nwp500-python 1.2.3__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nwp500_python-2.0.0/BREAKING_CHANGES_V3.md +122 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/CHANGELOG.rst +59 -0
- nwp500_python-2.0.0/MIGRATION.md +217 -0
- {nwp500_python-1.2.3/src/nwp500_python.egg-info → nwp500_python-2.0.0}/PKG-INFO +1 -1
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/DEVICE_STATUS_FIELDS.rst +16 -14
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/event_emitter_demo.py +7 -5
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/periodic_requests.py +1 -1
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/tou_schedule_example.py +6 -1
- nwp500_python-2.0.0/src/nwp500/__init__.py +160 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/models.py +109 -6
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/mqtt_client.py +8 -4
- {nwp500_python-1.2.3 → nwp500_python-2.0.0/src/nwp500_python.egg-info}/PKG-INFO +1 -1
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500_python.egg-info/SOURCES.txt +2 -0
- nwp500_python-1.2.3/src/nwp500/__init__.py +0 -102
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.coveragerc +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.github/copilot-instructions.md +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.github/workflows/ci.yml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.github/workflows/release.yml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.gitignore +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.pre-commit-config.yaml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/.readthedocs.yml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/AUTHORS.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/CONTRIBUTING.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/LICENSE.txt +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/Makefile +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/README.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/RELEASE.md +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/API_CLIENT.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/API_REFERENCE.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/AUTHENTICATION.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/AUTO_RECOVERY.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/AUTO_RECOVERY_QUICK.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/COMMAND_QUEUE.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/DEVELOPMENT.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/DEVICE_FEATURE_FIELDS.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/ENERGY_MONITORING.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/ERROR_CODES.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/EVENT_EMITTER.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/FIRMWARE_TRACKING.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/MQTT_CLIENT.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/MQTT_MESSAGES.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/Makefile +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/_static/.gitignore +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/authors.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/changelog.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/conf.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/contributing.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/index.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/license.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/openapi.yaml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/readme.rst +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/docs/requirements.txt +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/.ruff.toml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/README.md +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/anti_legionella_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/api_client_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/auth_constructor_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/authenticate.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/auto_recovery_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/combined_callbacks.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/command_queue_demo.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/device_feature_callback.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/device_status_callback.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/device_status_callback_debug.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/energy_usage_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/improved_auth_pattern.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/mask.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/mqtt_client_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/periodic_device_info.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/power_control_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/reconnection_demo.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/reservation_schedule_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/set_dhw_temperature_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/set_mode_example.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/simple_auto_recovery.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/simple_periodic_info.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/simple_periodic_status.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/test_api_client.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/test_mqtt_connection.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/test_mqtt_messaging.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/examples/test_periodic_minimal.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/pyproject.toml +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/scripts/format.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/scripts/lint.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/scripts/setup-dev.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/setup.cfg +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/setup.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/api_client.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/auth.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/cli.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/config.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/constants.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500/events.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500_python.egg-info/entry_points.txt +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500_python.egg-info/not-zip-safe +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500_python.egg-info/requires.txt +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/src/nwp500_python.egg-info/top_level.txt +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/tests/conftest.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/tests/test_api_helpers.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/tests/test_command_queue.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/tests/test_events.py +0 -0
- {nwp500_python-1.2.3 → nwp500_python-2.0.0}/tox.ini +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Breaking Changes for v3.0.0
|
|
2
|
+
|
|
3
|
+
This document outlines the breaking changes planned for nwp500-python v3.0.0.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Version 3.0.0 will be the first major version to include breaking changes since the library's initial release. The primary focus is removing deprecated functionality and improving type safety.
|
|
8
|
+
|
|
9
|
+
## Scheduled Removals
|
|
10
|
+
|
|
11
|
+
### OperationMode Enum Removal
|
|
12
|
+
|
|
13
|
+
**Target**: v3.0.0
|
|
14
|
+
**Current Status**: Deprecated in v2.0.0
|
|
15
|
+
**Migration Period**: v2.x series (minimum 6 months)
|
|
16
|
+
|
|
17
|
+
The original `OperationMode` enum will be completely removed and replaced with:
|
|
18
|
+
- `DhwOperationSetting` for user-configured mode preferences
|
|
19
|
+
- `CurrentOperationMode` for real-time operational states
|
|
20
|
+
|
|
21
|
+
#### Impact Assessment
|
|
22
|
+
- **High Impact**: Code using direct enum comparisons
|
|
23
|
+
- **Medium Impact**: Type hints and function signatures
|
|
24
|
+
- **Low Impact**: Display-only usage (`.name` attribute)
|
|
25
|
+
|
|
26
|
+
#### Required Actions
|
|
27
|
+
1. Replace all `OperationMode` imports with specific enum imports
|
|
28
|
+
2. Update enum comparisons to use appropriate enum type
|
|
29
|
+
3. Update type hints in function signatures
|
|
30
|
+
4. Remove any `OperationMode` references from custom code
|
|
31
|
+
|
|
32
|
+
#### Migration Tools Available
|
|
33
|
+
- `MIGRATION.md` - Comprehensive migration guide
|
|
34
|
+
- `migrate_operation_mode_usage()` - Programmatic guidance
|
|
35
|
+
- `enable_deprecation_warnings()` - Runtime warning system
|
|
36
|
+
- Updated documentation with new enum usage patterns
|
|
37
|
+
|
|
38
|
+
## Pre-3.0 Checklist
|
|
39
|
+
|
|
40
|
+
Before releasing v3.0.0, ensure:
|
|
41
|
+
|
|
42
|
+
### Code Removal
|
|
43
|
+
- [ ] Remove `OperationMode` enum class from `models.py`
|
|
44
|
+
- [ ] Remove `OperationMode` from package exports (`__init__.py`)
|
|
45
|
+
- [ ] Remove deprecation warning infrastructure
|
|
46
|
+
- [ ] Update all internal references to use new enums
|
|
47
|
+
|
|
48
|
+
### Documentation Updates
|
|
49
|
+
- [ ] Update all documentation to remove `OperationMode` references
|
|
50
|
+
- [ ] Update `MIGRATION.md` to reflect completed migration
|
|
51
|
+
- [ ] Update API documentation
|
|
52
|
+
- [ ] Update example scripts if any still reference old enum
|
|
53
|
+
|
|
54
|
+
### Testing
|
|
55
|
+
- [ ] Ensure all tests pass without `OperationMode`
|
|
56
|
+
- [ ] Add tests to verify enum removal
|
|
57
|
+
- [ ] Test that import errors are clear and helpful
|
|
58
|
+
- [ ] Validate all examples work with new enums only
|
|
59
|
+
|
|
60
|
+
### Communication
|
|
61
|
+
- [ ] Update CHANGELOG.rst with breaking changes
|
|
62
|
+
- [ ] Release notes highlighting breaking changes
|
|
63
|
+
- [ ] GitHub release with migration guidance
|
|
64
|
+
- [ ] Consider blog post or announcement for major users
|
|
65
|
+
|
|
66
|
+
## Timeline
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
v2.0.0 (Current)
|
|
70
|
+
├── OperationMode deprecated
|
|
71
|
+
├── New enums introduced
|
|
72
|
+
├── Migration tools provided
|
|
73
|
+
└── Backward compatibility maintained
|
|
74
|
+
|
|
75
|
+
v2.1.0 (Optional)
|
|
76
|
+
├── Optional deprecation warnings
|
|
77
|
+
├── Enhanced migration tools
|
|
78
|
+
└── Continued compatibility
|
|
79
|
+
|
|
80
|
+
v2.x.x (6+ months)
|
|
81
|
+
├── Migration period
|
|
82
|
+
├── User feedback collection
|
|
83
|
+
└── Migration assistance
|
|
84
|
+
|
|
85
|
+
v3.0.0 (Target)
|
|
86
|
+
├── OperationMode removed
|
|
87
|
+
├── Breaking changes implemented
|
|
88
|
+
└── Type safety improvements
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Rollback Plan
|
|
92
|
+
|
|
93
|
+
If breaking changes cause significant issues:
|
|
94
|
+
|
|
95
|
+
1. **Emergency Patch**: Revert breaking changes in v3.0.1
|
|
96
|
+
2. **Deprecation Extension**: Extend deprecation period to v4.0.0
|
|
97
|
+
3. **Enhanced Migration**: Provide additional migration tools
|
|
98
|
+
4. **Communication**: Clear messaging about timeline changes
|
|
99
|
+
|
|
100
|
+
## Version Support
|
|
101
|
+
|
|
102
|
+
- **v2.x**: Long-term support with security fixes
|
|
103
|
+
- **v3.x**: Current development branch
|
|
104
|
+
- **v1.x**: End-of-life (security fixes only if critical)
|
|
105
|
+
|
|
106
|
+
## Migration Support
|
|
107
|
+
|
|
108
|
+
Migration support will be available:
|
|
109
|
+
- **During v2.x**: Full backward compatibility + new enums
|
|
110
|
+
- **During v3.0 beta**: Migration warnings and testing
|
|
111
|
+
- **After v3.0**: Documentation and examples only
|
|
112
|
+
|
|
113
|
+
## Contact
|
|
114
|
+
|
|
115
|
+
For questions about breaking changes or migration assistance:
|
|
116
|
+
- File GitHub issues with "migration" label
|
|
117
|
+
- Reference `MIGRATION.md` for detailed guidance
|
|
118
|
+
- Use `migrate_operation_mode_usage()` for programmatic help
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
*This document will be updated as v3.0.0 approaches with more specific details and timelines.*
|
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
Version 2.0.0 (Unreleased)
|
|
6
|
+
==========================
|
|
7
|
+
|
|
8
|
+
**Breaking Changes (Planned for v3.0.0)**
|
|
9
|
+
|
|
10
|
+
- **DEPRECATION**: ``OperationMode`` enum is deprecated and will be removed in v3.0.0
|
|
11
|
+
|
|
12
|
+
- Use ``DhwOperationSetting`` for user-configured mode preferences (values 1-6)
|
|
13
|
+
- Use ``CurrentOperationMode`` for real-time operational states (values 0, 32, 64, 96)
|
|
14
|
+
- See ``MIGRATION.md`` for detailed migration guide
|
|
15
|
+
|
|
16
|
+
Added
|
|
17
|
+
-----
|
|
18
|
+
|
|
19
|
+
- **Enhanced Type Safety**: Split ``OperationMode`` into semantically distinct enums
|
|
20
|
+
|
|
21
|
+
- ``DhwOperationSetting``: User-configured mode preferences (HEAT_PUMP, ELECTRIC, ENERGY_SAVER, HIGH_DEMAND, VACATION, POWER_OFF)
|
|
22
|
+
- ``CurrentOperationMode``: Real-time operational states (STANDBY, HEAT_PUMP_MODE, HYBRID_EFFICIENCY_MODE, HYBRID_BOOST_MODE)
|
|
23
|
+
- Prevents accidental comparison of user preferences with real-time states
|
|
24
|
+
- Better IDE support with more specific enum types
|
|
25
|
+
|
|
26
|
+
- **Migration Support**: Comprehensive tools for smooth migration
|
|
27
|
+
|
|
28
|
+
- ``migrate_operation_mode_usage()`` helper function with programmatic guidance
|
|
29
|
+
- ``MIGRATION.md`` with step-by-step migration instructions
|
|
30
|
+
- Value mappings and common usage pattern examples
|
|
31
|
+
- Backward compatibility preservation during transition
|
|
32
|
+
|
|
33
|
+
- **Documentation Updates**: Updated all documentation to reflect new enum structure
|
|
34
|
+
|
|
35
|
+
- ``DEVICE_STATUS_FIELDS.rst`` updated with new enum types
|
|
36
|
+
- Code examples use new enums with proper imports
|
|
37
|
+
- Clear distinction between configuration vs real-time status
|
|
38
|
+
|
|
39
|
+
Changed
|
|
40
|
+
-------
|
|
41
|
+
|
|
42
|
+
- **DeviceStatus Model**: Updated to use specific enum types
|
|
43
|
+
|
|
44
|
+
- ``operationMode`` field now uses ``CurrentOperationMode`` type
|
|
45
|
+
- ``dhwOperationSetting`` field now uses ``DhwOperationSetting`` type
|
|
46
|
+
- Maintains backward compatibility through value preservation
|
|
47
|
+
|
|
48
|
+
- **Example Scripts**: Updated to demonstrate new enum usage
|
|
49
|
+
|
|
50
|
+
- ``event_emitter_demo.py`` updated to use ``CurrentOperationMode``
|
|
51
|
+
- Fixed incorrect enum references (HEAT_PUMP_ONLY → HEAT_PUMP_MODE)
|
|
52
|
+
- All examples remain functional with new type system
|
|
53
|
+
|
|
54
|
+
Deprecated
|
|
55
|
+
----------
|
|
56
|
+
|
|
57
|
+
- **OperationMode enum**: Will be removed in v3.0.0
|
|
58
|
+
|
|
59
|
+
- All functionality preserved for backward compatibility
|
|
60
|
+
- Migration guide available in ``MIGRATION.md``
|
|
61
|
+
- Helper function ``migrate_operation_mode_usage()`` provides guidance
|
|
62
|
+
- Original enum remains available during transition period
|
|
63
|
+
|
|
5
64
|
Version 1.2.2 (2025-10-17)
|
|
6
65
|
==========================
|
|
7
66
|
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Migration Guide: OperationMode → DhwOperationSetting & CurrentOperationMode
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
In version 2.x of nwp500-python, the `OperationMode` enum has been split into two more specific enums to improve code clarity and type safety:
|
|
6
|
+
|
|
7
|
+
- **`DhwOperationSetting`**: User-configured mode preferences (values 1-6)
|
|
8
|
+
- **`CurrentOperationMode`**: Real-time operational states (values 0, 32, 64, 96)
|
|
9
|
+
|
|
10
|
+
This change clarifies the distinction between "what mode the user has configured" vs "what the device is doing right now."
|
|
11
|
+
|
|
12
|
+
## Why This Change?
|
|
13
|
+
|
|
14
|
+
The original `OperationMode` enum mixed two different concepts:
|
|
15
|
+
1. **User preferences** (1-6): What heating mode should be used when heating is needed
|
|
16
|
+
2. **Real-time status** (0, 32, 64, 96): What the device is actively doing right now
|
|
17
|
+
|
|
18
|
+
This led to confusion and potential bugs. The new enums provide:
|
|
19
|
+
- **Type safety**: Can't accidentally compare user preferences with real-time states
|
|
20
|
+
- **Clarity**: Clear distinction between configuration and current operation
|
|
21
|
+
- **Better IDE support**: More specific autocomplete and type checking
|
|
22
|
+
|
|
23
|
+
## Migration Steps
|
|
24
|
+
|
|
25
|
+
### 1. Update Imports
|
|
26
|
+
|
|
27
|
+
**Before:**
|
|
28
|
+
```python
|
|
29
|
+
from nwp500 import OperationMode
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**After:**
|
|
33
|
+
```python
|
|
34
|
+
from nwp500 import DhwOperationSetting, CurrentOperationMode
|
|
35
|
+
# or keep the old import during transition:
|
|
36
|
+
from nwp500 import OperationMode, DhwOperationSetting, CurrentOperationMode
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Update DHW Operation Setting Comparisons
|
|
40
|
+
|
|
41
|
+
**Before:**
|
|
42
|
+
```python
|
|
43
|
+
if status.dhwOperationSetting == OperationMode.ENERGY_SAVER:
|
|
44
|
+
print("Device configured for Energy Saver mode")
|
|
45
|
+
|
|
46
|
+
if status.dhwOperationSetting == OperationMode.POWER_OFF:
|
|
47
|
+
print("Device is powered off")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**After:**
|
|
51
|
+
```python
|
|
52
|
+
if status.dhwOperationSetting == DhwOperationSetting.ENERGY_SAVER:
|
|
53
|
+
print("Device configured for Energy Saver mode")
|
|
54
|
+
|
|
55
|
+
if status.dhwOperationSetting == DhwOperationSetting.POWER_OFF:
|
|
56
|
+
print("Device is powered off")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. Update Operation Mode Comparisons
|
|
60
|
+
|
|
61
|
+
**Before:**
|
|
62
|
+
```python
|
|
63
|
+
if status.operationMode == OperationMode.STANDBY:
|
|
64
|
+
print("Device is idle")
|
|
65
|
+
|
|
66
|
+
if status.operationMode == OperationMode.HEAT_PUMP_MODE:
|
|
67
|
+
print("Heat pump is running")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**After:**
|
|
71
|
+
```python
|
|
72
|
+
if status.operationMode == CurrentOperationMode.STANDBY:
|
|
73
|
+
print("Device is idle")
|
|
74
|
+
|
|
75
|
+
if status.operationMode == CurrentOperationMode.HEAT_PUMP_MODE:
|
|
76
|
+
print("Heat pump is running")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 4. Update Type Hints
|
|
80
|
+
|
|
81
|
+
**Before:**
|
|
82
|
+
```python
|
|
83
|
+
def handle_mode_change(old_mode: OperationMode, new_mode: OperationMode):
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
def check_dhw_setting(setting: OperationMode) -> bool:
|
|
87
|
+
pass
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**After:**
|
|
91
|
+
```python
|
|
92
|
+
def handle_mode_change(old_mode: CurrentOperationMode, new_mode: CurrentOperationMode):
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
def check_dhw_setting(setting: DhwOperationSetting) -> bool:
|
|
96
|
+
pass
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 5. Update Command Sending Logic
|
|
100
|
+
|
|
101
|
+
**Before:**
|
|
102
|
+
```python
|
|
103
|
+
# Vacation mode check
|
|
104
|
+
if mode_id == OperationMode.VACATION.value:
|
|
105
|
+
# handle vacation days parameter
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**After:**
|
|
109
|
+
```python
|
|
110
|
+
# Vacation mode check
|
|
111
|
+
if mode_id == DhwOperationSetting.VACATION.value:
|
|
112
|
+
# handle vacation days parameter
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Value Mappings
|
|
116
|
+
|
|
117
|
+
### DhwOperationSetting (User Preferences)
|
|
118
|
+
```python
|
|
119
|
+
DhwOperationSetting.HEAT_PUMP = 1 # Heat Pump Only
|
|
120
|
+
DhwOperationSetting.ELECTRIC = 2 # Electric Only
|
|
121
|
+
DhwOperationSetting.ENERGY_SAVER = 3 # Energy Saver (default)
|
|
122
|
+
DhwOperationSetting.HIGH_DEMAND = 4 # High Demand
|
|
123
|
+
DhwOperationSetting.VACATION = 5 # Vacation Mode
|
|
124
|
+
DhwOperationSetting.POWER_OFF = 6 # Device Powered Off
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### CurrentOperationMode (Real-time States)
|
|
128
|
+
```python
|
|
129
|
+
CurrentOperationMode.STANDBY = 0 # Device idle
|
|
130
|
+
CurrentOperationMode.HEAT_PUMP_MODE = 32 # Heat pump active
|
|
131
|
+
CurrentOperationMode.HYBRID_EFFICIENCY_MODE = 64 # Energy Saver mode heating
|
|
132
|
+
CurrentOperationMode.HYBRID_BOOST_MODE = 96 # High Demand mode heating
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Common Migration Patterns
|
|
136
|
+
|
|
137
|
+
### Event Handlers
|
|
138
|
+
**Before:**
|
|
139
|
+
```python
|
|
140
|
+
def on_mode_change(old_mode: OperationMode, new_mode: OperationMode):
|
|
141
|
+
if new_mode == OperationMode.HEAT_PUMP_MODE:
|
|
142
|
+
print("Heat pump started")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**After:**
|
|
146
|
+
```python
|
|
147
|
+
def on_mode_change(old_mode: CurrentOperationMode, new_mode: CurrentOperationMode):
|
|
148
|
+
if new_mode == CurrentOperationMode.HEAT_PUMP_MODE:
|
|
149
|
+
print("Heat pump started")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Status Display Logic
|
|
153
|
+
**Before:**
|
|
154
|
+
```python
|
|
155
|
+
def get_device_status(status: DeviceStatus) -> dict:
|
|
156
|
+
return {
|
|
157
|
+
'mode': status.dhwOperationSetting.name, # User's setting
|
|
158
|
+
'active': status.operationMode != OperationMode.STANDBY, # Currently heating?
|
|
159
|
+
'powered_on': status.dhwOperationSetting != OperationMode.POWER_OFF
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**After:**
|
|
164
|
+
```python
|
|
165
|
+
def get_device_status(status: DeviceStatus) -> dict:
|
|
166
|
+
return {
|
|
167
|
+
'mode': status.dhwOperationSetting.name, # User's setting
|
|
168
|
+
'active': status.operationMode != CurrentOperationMode.STANDBY, # Currently heating?
|
|
169
|
+
'powered_on': status.dhwOperationSetting != DhwOperationSetting.POWER_OFF
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Backward Compatibility
|
|
174
|
+
|
|
175
|
+
The original `OperationMode` enum remains available for backward compatibility but is **deprecated**:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# Still works, but deprecated
|
|
179
|
+
from nwp500 import OperationMode
|
|
180
|
+
if status.dhwOperationSetting == OperationMode.ENERGY_SAVER:
|
|
181
|
+
pass
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Note**: The deprecated enum will be removed in a future major version (3.0+).
|
|
185
|
+
|
|
186
|
+
## Testing Your Migration
|
|
187
|
+
|
|
188
|
+
Use the migration helper to validate your changes:
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from nwp500 import migrate_operation_mode_usage
|
|
192
|
+
|
|
193
|
+
# Get migration guidance
|
|
194
|
+
guide = migrate_operation_mode_usage()
|
|
195
|
+
print(guide['migration_examples'])
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Timeline
|
|
199
|
+
|
|
200
|
+
- **Current (2.x)**: Both old and new enums available, old enum deprecated
|
|
201
|
+
- **Next minor (2.x+1)**: Deprecation warnings added
|
|
202
|
+
- **Future major (3.0)**: `OperationMode` enum removed
|
|
203
|
+
|
|
204
|
+
## Need Help?
|
|
205
|
+
|
|
206
|
+
- Check the [documentation](docs/DEVICE_STATUS_FIELDS.rst) for detailed explanations
|
|
207
|
+
- Use the `migrate_operation_mode_usage()` helper function for guidance
|
|
208
|
+
- Look at updated examples in the `examples/` directory
|
|
209
|
+
- File an issue if you encounter migration problems
|
|
210
|
+
|
|
211
|
+
## Benefits After Migration
|
|
212
|
+
|
|
213
|
+
1. **Type Safety**: Compiler/IDE catches enum mismatches
|
|
214
|
+
2. **Clarity**: Clear distinction between user preferences and device state
|
|
215
|
+
3. **Better Documentation**: Each enum has focused, specific documentation
|
|
216
|
+
4. **Future-Proof**: Easier to extend either enum independently
|
|
217
|
+
5. **Reduced Bugs**: Impossible to accidentally compare incompatible concepts
|
|
@@ -44,7 +44,7 @@ This document lists the fields found in the ``status`` object of device status m
|
|
|
44
44
|
- Sub error code providing additional error details. See ERROR_CODES.rst for details.
|
|
45
45
|
- None
|
|
46
46
|
* - ``operationMode``
|
|
47
|
-
-
|
|
47
|
+
- CurrentOperationMode
|
|
48
48
|
- None
|
|
49
49
|
- The current **actual operational state** of the device (what it's doing RIGHT NOW). Reports status values: 0=Standby, 32=Heat Pump active, 64=Energy Saver active, 96=High Demand active. See Operation Modes section below for the critical distinction between this and ``dhwOperationSetting``.
|
|
50
50
|
- None
|
|
@@ -229,9 +229,9 @@ This document lists the fields found in the ``status`` object of device status m
|
|
|
229
229
|
- Type of program reservation.
|
|
230
230
|
- None
|
|
231
231
|
* - ``dhwOperationSetting``
|
|
232
|
-
-
|
|
232
|
+
- DhwOperationSetting
|
|
233
233
|
- None
|
|
234
|
-
- User's configured DHW operation mode preference. This field uses the
|
|
234
|
+
- User's configured DHW operation mode preference. This field uses the ``DhwOperationSetting`` enum (separate from ``CurrentOperationMode``) and contains command mode values (1=HEAT_PUMP, 2=ELECTRIC, 3=ENERGY_SAVER, 4=HIGH_DEMAND, 5=VACATION, 6=POWER_OFF). When the device is powered off via the power-off command, this field will show 6 (POWER_OFF). This is how to distinguish between "powered off" vs "on but in standby". See the Operation Modes section below for details.
|
|
235
235
|
- None
|
|
236
236
|
* - ``temperatureType``
|
|
237
237
|
- integer
|
|
@@ -533,10 +533,10 @@ These two fields serve different purposes and it's critical to understand their
|
|
|
533
533
|
Field Definitions
|
|
534
534
|
^^^^^^^^^^^^^^^^^
|
|
535
535
|
|
|
536
|
-
**dhwOperationSetting** (
|
|
536
|
+
**dhwOperationSetting** (DhwOperationSetting enum with command values 1-6)
|
|
537
537
|
The user's **configured mode preference** - what heating mode the device should use when it needs to heat water. This is set via the ``dhw-mode`` command and persists until changed by the user or device.
|
|
538
538
|
|
|
539
|
-
* Type: ``
|
|
539
|
+
* Type: ``DhwOperationSetting`` enum
|
|
540
540
|
* Values:
|
|
541
541
|
|
|
542
542
|
* 1 = ``HEAT_PUMP`` (Heat Pump Only)
|
|
@@ -551,10 +551,10 @@ Field Definitions
|
|
|
551
551
|
* Meaning: "When heating is needed, use this mode" OR "I'm powered off" (if value is 6)
|
|
552
552
|
* Value 6 (``POWER_OFF``) indicates the device was powered off via the power-off command. This is how to distinguish between "powered off" and "on but idle".
|
|
553
553
|
|
|
554
|
-
**operationMode** (
|
|
554
|
+
**operationMode** (CurrentOperationMode enum with status values 0, 32, 64, 96)
|
|
555
555
|
The device's **current actual operational state** - what the device is doing RIGHT NOW. This reflects real-time operation and changes automatically based on whether the device is idle or actively heating.
|
|
556
556
|
|
|
557
|
-
* Type: ``
|
|
557
|
+
* Type: ``CurrentOperationMode`` enum
|
|
558
558
|
* Values:
|
|
559
559
|
|
|
560
560
|
* 0 = ``STANDBY`` (Idle, not heating)
|
|
@@ -661,11 +661,13 @@ For user-facing applications, follow these guidelines:
|
|
|
661
661
|
**Code Example**
|
|
662
662
|
.. code-block:: python
|
|
663
663
|
|
|
664
|
+
from nwp500.models import DeviceStatus, DhwOperationSetting, CurrentOperationMode
|
|
665
|
+
|
|
664
666
|
def format_mode_display(status: DeviceStatus) -> dict:
|
|
665
667
|
"""Format mode and status for UI display."""
|
|
666
668
|
|
|
667
669
|
# Check if device is powered off first
|
|
668
|
-
if status.dhwOperationSetting ==
|
|
670
|
+
if status.dhwOperationSetting == DhwOperationSetting.POWER_OFF:
|
|
669
671
|
return {
|
|
670
672
|
'configured_mode': 'Off',
|
|
671
673
|
'operational_state': 'Powered Off',
|
|
@@ -678,16 +680,16 @@ For user-facing applications, follow these guidelines:
|
|
|
678
680
|
configured_mode = status.dhwOperationSetting.name.replace('_', ' ').title()
|
|
679
681
|
|
|
680
682
|
# Current operational state
|
|
681
|
-
if status.operationMode ==
|
|
683
|
+
if status.operationMode == CurrentOperationMode.STANDBY:
|
|
682
684
|
operational_state = "Idle"
|
|
683
685
|
is_heating = False
|
|
684
|
-
elif status.operationMode ==
|
|
686
|
+
elif status.operationMode == CurrentOperationMode.HEAT_PUMP_MODE:
|
|
685
687
|
operational_state = "Heating (Heat Pump)"
|
|
686
688
|
is_heating = True
|
|
687
|
-
elif status.operationMode ==
|
|
689
|
+
elif status.operationMode == CurrentOperationMode.HYBRID_EFFICIENCY_MODE:
|
|
688
690
|
operational_state = "Heating (Energy Saver)"
|
|
689
691
|
is_heating = True
|
|
690
|
-
elif status.operationMode ==
|
|
692
|
+
elif status.operationMode == CurrentOperationMode.HYBRID_BOOST_MODE:
|
|
691
693
|
operational_state = "Heating (High Demand)"
|
|
692
694
|
is_heating = True
|
|
693
695
|
else:
|
|
@@ -712,9 +714,9 @@ For user-facing applications, follow these guidelines:
|
|
|
712
714
|
|
|
713
715
|
4. **operationMode changes automatically** - you cannot directly set this; it changes based on device operation
|
|
714
716
|
|
|
715
|
-
5. **
|
|
717
|
+
5. **Separate enum types provide clarity** - ``DhwOperationSetting`` (values 1-6) for user preferences, ``CurrentOperationMode`` (values 0/32/64/96) for real-time states
|
|
716
718
|
|
|
717
|
-
6. **Power off detection** - Check if ``dhwOperationSetting ==
|
|
719
|
+
6. **Power off detection** - Check if ``dhwOperationSetting == DhwOperationSetting.POWER_OFF`` to determine if device is powered off vs just idle
|
|
718
720
|
|
|
719
721
|
Technical Notes
|
|
720
722
|
---------------
|
|
@@ -29,7 +29,7 @@ logging.basicConfig(
|
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
from nwp500 import NavienAPIClient, NavienAuthClient, NavienMqttClient
|
|
32
|
-
from nwp500.models import DeviceStatus,
|
|
32
|
+
from nwp500.models import DeviceStatus, CurrentOperationMode
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
# Example 1: Multiple listeners for the same event
|
|
@@ -52,16 +52,18 @@ async def save_temperature_to_db(old_temp: float, new_temp: float):
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
# Example 2: Mode change handlers
|
|
55
|
-
def log_mode_change(old_mode:
|
|
55
|
+
def log_mode_change(old_mode: CurrentOperationMode, new_mode: CurrentOperationMode):
|
|
56
56
|
"""Log operation mode changes."""
|
|
57
57
|
print(f"🔄 [Mode] Changed from {old_mode.name} to {new_mode.name}")
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def optimize_on_mode_change(
|
|
60
|
+
def optimize_on_mode_change(
|
|
61
|
+
old_mode: CurrentOperationMode, new_mode: CurrentOperationMode
|
|
62
|
+
):
|
|
61
63
|
"""Optimization handler."""
|
|
62
|
-
if new_mode ==
|
|
64
|
+
if new_mode == CurrentOperationMode.HEAT_PUMP_MODE:
|
|
63
65
|
print("♻️ [Optimizer] Heat pump mode - maximum efficiency!")
|
|
64
|
-
elif new_mode ==
|
|
66
|
+
elif new_mode == CurrentOperationMode.HYBRID_BOOST_MODE:
|
|
65
67
|
print("⚡ [Optimizer] High demand mode - fast recovery!")
|
|
66
68
|
|
|
67
69
|
|
|
@@ -75,7 +75,7 @@ async def main():
|
|
|
75
75
|
print(f"\n--- Status Response #{status_count} ---")
|
|
76
76
|
print(f" Temperature: {status.dhwTemperature:.1f}°F")
|
|
77
77
|
print(f" Power: {status.currentInstPower:.1f}W")
|
|
78
|
-
print(f" Available Energy: {status.availableEnergyCapacity:.
|
|
78
|
+
print(f" Available Energy: {status.availableEnergyCapacity:.0f} Wh")
|
|
79
79
|
|
|
80
80
|
def on_device_feature(feature: DeviceFeature):
|
|
81
81
|
"""Callback receives parsed DeviceFeature objects."""
|
|
@@ -17,8 +17,13 @@ async def _wait_for_controller_serial(mqtt_client: NavienMqttClient, device) ->
|
|
|
17
17
|
if not feature_future.done():
|
|
18
18
|
feature_future.set_result(feature)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
# Subscribe to device feature messages first
|
|
21
|
+
await mqtt_client.subscribe_device_feature(device, capture_feature)
|
|
22
|
+
|
|
23
|
+
# Then request device info
|
|
21
24
|
await mqtt_client.request_device_info(device)
|
|
25
|
+
|
|
26
|
+
# Wait for the response
|
|
22
27
|
feature = await asyncio.wait_for(feature_future, timeout=15)
|
|
23
28
|
return feature.controllerSerialNumber
|
|
24
29
|
|