nwp500-python 7.2.3__tar.gz → 7.3.2__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-7.2.3 → nwp500_python-7.3.2}/CHANGELOG.rst +227 -114
- {nwp500_python-7.2.3/src/nwp500_python.egg-info → nwp500_python-7.3.2}/PKG-INFO +1 -1
- nwp500_python-7.3.2/docs/guides/home_assistant_integration.rst +371 -0
- nwp500_python-7.3.2/docs/guides/unit_conversion.rst +663 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/index.rst +8 -6
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/device_status.rst +20 -20
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/__init__.py +9 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/api_client.py +16 -4
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/auth.py +24 -10
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/__main__.py +27 -3
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/handlers.py +3 -2
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/output_formatters.py +49 -14
- nwp500_python-7.3.2/src/nwp500/converters.py +481 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/encoding.py +3 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/events.py +3 -2
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/field_factory.py +27 -9
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/models.py +252 -115
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/client.py +32 -16
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/connection.py +23 -9
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/subscriptions.py +12 -1
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/utils.py +2 -1
- nwp500_python-7.3.2/src/nwp500/temperature.py +373 -0
- nwp500_python-7.3.2/src/nwp500/unit_system.py +132 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2/src/nwp500_python.egg-info}/PKG-INFO +1 -1
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/SOURCES.txt +4 -0
- nwp500_python-7.3.2/tests/conftest.py +118 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_mqtt_client_init.py +41 -37
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_temperature_converters.py +24 -0
- nwp500_python-7.3.2/tests/test_unit_switching.py +609 -0
- nwp500_python-7.2.3/src/nwp500/converters.py +0 -165
- nwp500_python-7.2.3/src/nwp500/temperature.py +0 -187
- nwp500_python-7.2.3/tests/conftest.py +0 -10
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.agent/workflows/pre-completion-testing.md +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.coveragerc +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.github/copilot-instructions.md +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.github/workflows/ci.yml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.github/workflows/release.yml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.gitignore +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.pre-commit-config.yaml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/.readthedocs.yml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/AUTHORS.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/CONTRIBUTING.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/LICENSE.txt +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/Makefile +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/README.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/RELEASE.md +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/Makefile +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/_static/.gitignore +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/api/nwp500.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/authors.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/changelog.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/conf.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/configuration.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/development/contributing.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/development/history.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/enumerations.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/advanced_features_explained.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/authentication.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/auto_recovery.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/command_queue.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/energy_monitoring.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/event_system.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/mqtt_diagnostics.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/reservations.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/scheduling_features.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/guides/time_of_use.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/installation.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/license.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/openapi.yaml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/data_conversions.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/device_features.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/error_codes.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/mqtt_protocol.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/quick_reference.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/protocol/rest_api.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/api_client.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/auth_client.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/cli.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/device_control.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/events.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/exceptions.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/models.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/python_api/mqtt_client.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/quickstart.rst +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/docs/requirements.txt +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/.ruff.toml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/README.md +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/air_filter_reset.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/anti_legionella.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/auto_recovery.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/combined_callbacks.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/demand_response.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/device_capabilities.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/device_status_debug.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/energy_analytics.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/error_code_demo.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/mqtt_diagnostics.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/power_control.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/recirculation_control.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/reconnection_demo.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/reservation_schedule.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/simple_auto_recovery.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/token_restoration.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/tou_openei.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/tou_schedule.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/advanced/water_reservation.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/beginner/01_authentication.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/beginner/02_list_devices.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/beginner/03_get_status.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/beginner/04_set_temperature.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/advanced_auth_patterns.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/command_queue.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/device_status_callback.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/error_handling.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/event_driven_control.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/improved_auth.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/legacy_auth_constructor.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/mqtt_realtime_monitoring.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/periodic_requests.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/set_mode.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/intermediate/vacation_mode.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/mask.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/testing/periodic_device_info.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/testing/simple_periodic_info.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/testing/test_api_client.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/testing/test_mqtt_connection.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/testing/test_mqtt_messaging.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/examples/testing/test_periodic_minimal.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/pyproject.toml +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/README.md +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/bump_version.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/diagnose_mqtt_connection.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/extract_changelog.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/format.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/lint.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/setup-dev.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/scripts/validate_version.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/setup.cfg +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/setup.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/__init__.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/commands.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/monitoring.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/rich_output.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/cli/token_storage.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/command_decorators.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/config.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/device_capabilities.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/device_info_cache.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/enums.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/exceptions.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/factory.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/__init__.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/command_queue.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/control.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/diagnostics.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/periodic.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt/reconnection.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/mqtt_events.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/py.typed +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/topic_builder.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500/utils.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/entry_points.txt +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/not-zip-safe +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/requires.txt +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/top_level.txt +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_api_helpers.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_auth.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_cli_basic.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_cli_commands.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_command_decorators.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_command_queue.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_device_capabilities.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_device_info_cache.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_events.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_exceptions.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_model_converters.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_models.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tests/test_utils.py +0 -0
- {nwp500_python-7.2.3 → nwp500_python-7.3.2}/tox.ini +0 -0
|
@@ -2,21 +2,134 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
Version 7.3.2 (2026-01-25)
|
|
6
|
+
==========================
|
|
7
|
+
|
|
8
|
+
Changed
|
|
9
|
+
-------
|
|
10
|
+
- **Unit System Consistency**: Removed deprecated ``"imperial"`` unit system identifier in favor of ``"us_customary"`` for Home Assistant compatibility
|
|
11
|
+
|
|
12
|
+
- Changed all references from ``UnitSystem.IMPERIAL`` to ``UnitSystem.US_CUSTOMARY``
|
|
13
|
+
- Updated ``set_unit_system()`` and related functions to use ``"us_customary"`` exclusively
|
|
14
|
+
- ``"metric"`` remains unchanged for Metric conversions
|
|
15
|
+
- Affects API client, MQTT client, and CLI unit system handling
|
|
16
|
+
- Improves consistency with Home Assistant naming conventions
|
|
17
|
+
|
|
18
|
+
Fixed
|
|
19
|
+
-----
|
|
20
|
+
- **Unit System Consolidation**: Consolidated duplicate ``UnitSystemType`` type alias definitions into single canonical definition in ``unit_system.py``
|
|
21
|
+
|
|
22
|
+
- Removed redundant type definitions from multiple modules
|
|
23
|
+
- Improved code maintainability and consistency
|
|
24
|
+
- All unit system operations now reference centralized type definition
|
|
25
|
+
|
|
26
|
+
Version 7.3.1 (2026-01-25)
|
|
27
|
+
==========================
|
|
28
|
+
|
|
29
|
+
Fixed
|
|
30
|
+
-----
|
|
31
|
+
- **MQTT Client Initialization**: Removed overly strict token validity check from ``NavienMqttClient.__init__()``
|
|
32
|
+
|
|
33
|
+
- The strict token validity check prevented creating MQTT clients with restored tokens that may have expired between application restarts
|
|
34
|
+
- However, ``NavienMqttClient.connect()`` already handles token refresh automatically, making the check redundant
|
|
35
|
+
- This change allows integrations to create MQTT clients with expired tokens and let connect() handle validation
|
|
36
|
+
- Simplifies application code by removing duplicate token refresh calls
|
|
37
|
+
- Enables proper handling of restored authentication sessions
|
|
38
|
+
- Fixes MQTT connection failures when using stored tokens across application restarts
|
|
39
|
+
|
|
40
|
+
Version 7.3.0 (2026-01-19)
|
|
41
|
+
==========================
|
|
42
|
+
|
|
43
|
+
Added
|
|
44
|
+
-----
|
|
45
|
+
- **Dynamic Unit Conversion**: All temperature, flow, and volume measurements now dynamically convert based on user's region preference (Metric/Imperial)
|
|
46
|
+
|
|
47
|
+
- Temperature fields convert between Celsius and Fahrenheit using standard formulas
|
|
48
|
+
- Flow rate fields convert between LPM (Liters Per Minute) and GPM (Gallons Per Minute)
|
|
49
|
+
- Volume fields convert between Liters and Gallons
|
|
50
|
+
- Available devices and regions determine conversion support (validated at runtime)
|
|
51
|
+
- ``get_field_unit()`` method retrieves the correct unit suffix for any field
|
|
52
|
+
- All conversions use Pydantic ``WrapValidator`` for transparent, automatic conversion
|
|
53
|
+
- Comprehensive documentation in ``docs/guides/unit_conversion.rst``
|
|
54
|
+
- Example usage:
|
|
55
|
+
|
|
56
|
+
.. code-block:: python
|
|
57
|
+
|
|
58
|
+
# Get converted value with unit
|
|
59
|
+
temp_f = device_status.flow_rate_target # Returns Fahrenheit if region prefers imperial
|
|
60
|
+
unit = device_status.get_field_unit("flow_rate_target") # Returns "°F" or "°C"
|
|
61
|
+
|
|
62
|
+
# All conversions are transparent - values automatically convert to preferred units
|
|
63
|
+
flow_gpm = device_status.flow_rate_current # GPM if imperial, LPM if metric
|
|
64
|
+
volume_gal = device_status.tank_volume # Gallons if imperial, Liters if metric
|
|
65
|
+
|
|
66
|
+
- Supported conversion fields:
|
|
67
|
+
|
|
68
|
+
- **Temperature**: ``flow_rate_target``, ``flow_rate_current``, ``in_water_temp``, ``out_water_temp``, ``set_temp``, ``in_temp``, ``out_temp``, etc.
|
|
69
|
+
- **Flow Rate**: ``flow_rate_target``, ``flow_rate_current``
|
|
70
|
+
- **Volume**: ``tank_volume`` and related storage fields
|
|
71
|
+
|
|
72
|
+
- Integration patterns for Home Assistant, CLI, and custom integrations documented
|
|
73
|
+
|
|
74
|
+
- **Unit System Override**: Allow applications and CLI users to override the device's temperature preference and explicitly specify Metric or Imperial units
|
|
75
|
+
|
|
76
|
+
- Library-level: Add optional ``unit_system`` parameter to ``NavienAuthClient``, ``NavienMqttClient``, and ``NavienAPIClient`` initialization
|
|
77
|
+
- Set once at initialization; applies to all subsequent data conversions
|
|
78
|
+
- Accepts: ``"metric"`` (Celsius/LPM/Liters), ``"imperial"`` (Fahrenheit/GPM/Gallons), or ``None`` (auto-detect from device)
|
|
79
|
+
- Decouples unit preference from device configuration - users can override what the device is set to
|
|
80
|
+
- Uses context variables for thread-safe and async-safe unit system management
|
|
81
|
+
- Example usage:
|
|
82
|
+
|
|
83
|
+
.. code-block:: python
|
|
84
|
+
|
|
85
|
+
# Library initialization
|
|
86
|
+
from nwp500 import NavienAuthClient, set_unit_system
|
|
87
|
+
auth = NavienAuthClient(email, password, unit_system="metric")
|
|
88
|
+
|
|
89
|
+
# Or set after initialization
|
|
90
|
+
set_unit_system("imperial")
|
|
91
|
+
device_status = await mqtt.request_device_status(device)
|
|
92
|
+
# Values now in F, GPM, gallons regardless of device setting
|
|
93
|
+
|
|
94
|
+
- CLI-level: Add ``--unit-system`` flag for per-command override
|
|
95
|
+
- Example: ``nwp-cli status --unit-system metric``
|
|
96
|
+
- Defaults to device's setting if not specified
|
|
97
|
+
- New exported functions:
|
|
98
|
+
- ``set_unit_system(unit_system)`` - Set the preferred unit system
|
|
99
|
+
- ``get_unit_system()`` - Get the current unit system preference
|
|
100
|
+
- ``reset_unit_system()`` - Reset to auto-detect mode
|
|
101
|
+
|
|
102
|
+
Fixed
|
|
103
|
+
-----
|
|
104
|
+
- **MQTT Unit System Override Bug**: Fixed unit_system CLI flag not applying to device status values
|
|
105
|
+
|
|
106
|
+
- **Issue**: Running ``nwp-cli --unit-system metric status`` displayed values in device's native format (imperial) with metric unit strings (e.g., "104.9 °C" instead of "40.5 °C")
|
|
107
|
+
- **Root Cause**: MQTT callbacks from AWS CRT execute on different threads where context variables are not set. Since Python's context variables are task-local, the unit_system preference was not visible to validators
|
|
108
|
+
- **Solution**: Store unit_system in ``NavienMqttClient`` and ``MqttSubscriptionManager``. Before parsing MQTT messages, explicitly set the context variable in message handlers to ensure validators use the correct unit system regardless of thread context
|
|
109
|
+
- **Result**: Values and units now correctly convert when ``--unit-system`` override is specified
|
|
110
|
+
- **Testing**: All 393 tests pass including new unit system context override tests
|
|
111
|
+
|
|
112
|
+
- **Type Annotation Quotes**: Removed unnecessary quoted type annotations (UP037 violations)
|
|
113
|
+
|
|
114
|
+
- With ``from __future__ import annotations``, explicit string quotes are redundant
|
|
115
|
+
- Updated ``from_dict()`` methods in ``UserInfo``, ``AuthTokens``, ``AuthenticationResponse``, ``DeviceStatus``, ``DeviceFeature``, and ``EnergyUsageResponse``
|
|
116
|
+
- Improves code clarity and passes modern linting standards
|
|
117
|
+
|
|
5
118
|
Version 7.2.3 (2026-01-15)
|
|
6
119
|
==========================
|
|
7
120
|
|
|
8
121
|
Added
|
|
9
122
|
-----
|
|
10
123
|
- **Daily Energy Breakdown by Month**: New ``--month`` option for energy command to show daily energy data for a specific month
|
|
11
|
-
|
|
124
|
+
|
|
12
125
|
.. code-block:: bash
|
|
13
|
-
|
|
126
|
+
|
|
14
127
|
# Daily breakdown for a single month
|
|
15
128
|
nwp-cli energy --year 2025 --month 12
|
|
16
|
-
|
|
129
|
+
|
|
17
130
|
# Monthly summary for multiple months (existing)
|
|
18
131
|
nwp-cli energy --year 2025 --months 10,11,12
|
|
19
|
-
|
|
132
|
+
|
|
20
133
|
- Displays daily energy consumption, efficiency, and heat source breakdown
|
|
21
134
|
- Rich formatted output with progress bars and color-coded efficiency percentages
|
|
22
135
|
- Plain text fallback for non-Rich environments
|
|
@@ -25,25 +138,25 @@ Added
|
|
|
25
138
|
Fixed
|
|
26
139
|
-----
|
|
27
140
|
- **Documentation**: Fixed all warnings and broken cross-references in documentation
|
|
28
|
-
|
|
141
|
+
|
|
29
142
|
- Fixed docstring formatting in field_factory.py module
|
|
30
143
|
- Fixed broken cross-reference links in enumerations.rst, mqtt_diagnostics.rst, cli.rst, and models.rst
|
|
31
144
|
- Fixed invalid JSON syntax in code examples (removed invalid [...] and ... tokens)
|
|
32
145
|
- Suppressed duplicate object description warnings from re-exported classes
|
|
33
|
-
|
|
146
|
+
|
|
34
147
|
- **CLI Documentation**: Updated documentation for all 19 CLI commands
|
|
35
|
-
|
|
148
|
+
|
|
36
149
|
- Added missing device-info command documentation
|
|
37
150
|
- Added --raw flag documentation for status, info, and device-info commands
|
|
38
151
|
- Added --month option documentation to energy command
|
|
39
152
|
- Clarified mutually exclusive options (--months vs --month)
|
|
40
|
-
|
|
153
|
+
|
|
41
154
|
- **RST Title Hierarchy**: Fixed title level inconsistencies in device_control.rst
|
|
42
155
|
|
|
43
156
|
- **Read the Docs Configuration**: Updated Python version requirement to 3.13 in Read the Docs config
|
|
44
157
|
|
|
45
158
|
- **CI Test Failures**: Fixed ``ModuleNotFoundError`` when running tests without CLI dependencies installed
|
|
46
|
-
|
|
159
|
+
|
|
47
160
|
- Wrapped CLI module imports in try-except blocks in test modules
|
|
48
161
|
- Tests are skipped gracefully when optional dependencies (click, rich) are not installed
|
|
49
162
|
- Allows pytest to run without CLI extra, while supporting full test suite with tox
|
|
@@ -59,7 +172,7 @@ Version 7.2.2 (2025-12-25)
|
|
|
59
172
|
Fixed
|
|
60
173
|
-----
|
|
61
174
|
- **TOU Status Always Showing False**: Fixed ``touStatus`` field always reporting ``False`` regardless of actual device state
|
|
62
|
-
|
|
175
|
+
|
|
63
176
|
- Root cause: Version 7.2.1 incorrectly changed ``touStatus`` to use device-specific 1/2 encoding, but the device uses standard 0/1 encoding
|
|
64
177
|
- Solution: Use Python's built-in ``bool()`` for ``touStatus`` field (handles 0=False, 1=True naturally)
|
|
65
178
|
- Updated documentation in ``docs/protocol/quick_reference.rst`` to note ``touStatus`` exception
|
|
@@ -72,21 +185,21 @@ Version 7.2.1 (2025-12-25)
|
|
|
72
185
|
Added
|
|
73
186
|
-----
|
|
74
187
|
- **CLI Command**: New ``device-info`` command to retrieve basic device information from REST API
|
|
75
|
-
|
|
188
|
+
|
|
76
189
|
.. code-block:: bash
|
|
77
|
-
|
|
190
|
+
|
|
78
191
|
# Get basic device info (DeviceInfo model)
|
|
79
192
|
python3 -m nwp500.cli device-info
|
|
80
193
|
python3 -m nwp500.cli device-info --raw
|
|
81
194
|
|
|
82
195
|
- **ConnectionStatus Enum**: New ``ConnectionStatus`` enum for device cloud connection state
|
|
83
|
-
|
|
196
|
+
|
|
84
197
|
- ``ConnectionStatus.DISCONNECTED`` = 1 - Device offline/not connected
|
|
85
198
|
- ``ConnectionStatus.CONNECTED`` = 2 - Device online and reachable
|
|
86
199
|
- Used in ``DeviceInfo.connected`` field with automatic validation
|
|
87
200
|
|
|
88
201
|
- **InstallType Enum**: New ``InstallType`` enum for device installation classification
|
|
89
|
-
|
|
202
|
+
|
|
90
203
|
- ``InstallType.RESIDENTIAL`` = "R" - Residential use
|
|
91
204
|
- ``InstallType.COMMERCIAL`` = "C" - Commercial use
|
|
92
205
|
- Used in ``DeviceInfo.install_type`` field with automatic validation
|
|
@@ -96,7 +209,7 @@ Added
|
|
|
96
209
|
|
|
97
210
|
Changed
|
|
98
211
|
-------
|
|
99
|
-
- **DeviceInfo Model**:
|
|
212
|
+
- **DeviceInfo Model**:
|
|
100
213
|
- ``connected`` field now uses ``ConnectionStatus`` enum instead of plain int
|
|
101
214
|
- ``install_type`` field now uses ``InstallType`` enum instead of plain string
|
|
102
215
|
|
|
@@ -112,12 +225,12 @@ Changed
|
|
|
112
225
|
Removed
|
|
113
226
|
-------
|
|
114
227
|
- **constants.py Module**: Removed empty ``constants.py`` module. ``CommandCode`` enum was already moved to ``enums.py`` in version 4.2.0.
|
|
115
|
-
|
|
228
|
+
|
|
116
229
|
.. code-block:: python
|
|
117
|
-
|
|
230
|
+
|
|
118
231
|
# OLD (removed)
|
|
119
232
|
from nwp500.constants import CommandCode
|
|
120
|
-
|
|
233
|
+
|
|
121
234
|
# NEW (use this)
|
|
122
235
|
from nwp500.enums import CommandCode
|
|
123
236
|
|
|
@@ -140,20 +253,20 @@ Removed
|
|
|
140
253
|
|
|
141
254
|
# OLD (removed)
|
|
142
255
|
from nwp500 import DeviceCapabilityChecker, DeviceInfoCache
|
|
143
|
-
|
|
256
|
+
|
|
144
257
|
# NEW
|
|
145
258
|
from nwp500 import MqttDeviceCapabilityChecker, MqttDeviceInfoCache
|
|
146
259
|
|
|
147
|
-
**Rationale**: The original names were too generic. These classes are specifically designed
|
|
148
|
-
for MQTT client functionality (auto-fetching device info, caching, capability checking).
|
|
149
|
-
The new names make it clear they're MQTT-specific implementations, leaving room for future
|
|
260
|
+
**Rationale**: The original names were too generic. These classes are specifically designed
|
|
261
|
+
for MQTT client functionality (auto-fetching device info, caching, capability checking).
|
|
262
|
+
The new names make it clear they're MQTT-specific implementations, leaving room for future
|
|
150
263
|
REST API versions if needed.
|
|
151
264
|
|
|
152
265
|
**Migration**: Simple find-and-replace:
|
|
153
|
-
|
|
266
|
+
|
|
154
267
|
- ``DeviceCapabilityChecker`` → ``MqttDeviceCapabilityChecker``
|
|
155
268
|
- ``DeviceInfoCache`` → ``MqttDeviceInfoCache``
|
|
156
|
-
|
|
269
|
+
|
|
157
270
|
All functionality remains identical - only the class names changed.
|
|
158
271
|
|
|
159
272
|
Added
|
|
@@ -165,7 +278,7 @@ Added
|
|
|
165
278
|
|
|
166
279
|
# Create both API and MQTT clients in one call
|
|
167
280
|
from nwp500 import create_navien_clients
|
|
168
|
-
|
|
281
|
+
|
|
169
282
|
async with create_navien_clients(email, password) as (api_client, mqtt_client):
|
|
170
283
|
devices = await api_client.get_devices()
|
|
171
284
|
await mqtt_client.connect()
|
|
@@ -183,10 +296,10 @@ Added
|
|
|
183
296
|
.. code-block:: python
|
|
184
297
|
|
|
185
298
|
from nwp500 import VolumeCode
|
|
186
|
-
|
|
299
|
+
|
|
187
300
|
# Enum values: VOLUME_50GAL = 65, VOLUME_65GAL = 66, VOLUME_80GAL = 67
|
|
188
301
|
# Human-readable text available in VOLUME_CODE_TEXT dict
|
|
189
|
-
|
|
302
|
+
|
|
190
303
|
- Maps device codes to actual tank capacities (50, 65, 80 gallons)
|
|
191
304
|
- Used in ``DeviceFeature.volume_code`` field with automatic validation
|
|
192
305
|
- Exported from main package for convenience
|
|
@@ -254,7 +367,7 @@ Changed
|
|
|
254
367
|
from nwp500.mqtt_client import NavienMqttClient
|
|
255
368
|
from nwp500.mqtt_diagnostics import MqttDiagnosticsCollector
|
|
256
369
|
from nwp500.mqtt_utils import MqttConnectionConfig
|
|
257
|
-
|
|
370
|
+
|
|
258
371
|
# NEW imports (preferred)
|
|
259
372
|
from nwp500.mqtt import NavienMqttClient, MqttDiagnosticsCollector, MqttConnectionConfig
|
|
260
373
|
# OR import from main package (recommended)
|
|
@@ -285,12 +398,12 @@ Changed
|
|
|
285
398
|
- Renamed and moved 35+ example scripts for better discoverability
|
|
286
399
|
- Updated ``examples/README.md`` with 'Getting Started' guide and categorized index
|
|
287
400
|
- Added 01-04 beginner series for smooth onboarding:
|
|
288
|
-
|
|
401
|
+
|
|
289
402
|
- ``beginner/01_authentication.py`` - Basic authentication patterns
|
|
290
403
|
- ``beginner/02_list_devices.py`` - Retrieving device information
|
|
291
404
|
- ``beginner/03_get_status.py`` - Getting device status
|
|
292
405
|
- ``beginner/04_set_temperature.py`` - Basic device control
|
|
293
|
-
|
|
406
|
+
|
|
294
407
|
- Intermediate examples: event-driven control, error handling, MQTT monitoring
|
|
295
408
|
- Advanced examples: demand response, recirculation, TOU schedules, diagnostics
|
|
296
409
|
- Testing examples: connection testing, periodic updates, minimal examples
|
|
@@ -427,18 +540,18 @@ Fixed
|
|
|
427
540
|
Version 7.0.0 (2025-12-17)
|
|
428
541
|
==========================
|
|
429
542
|
|
|
430
|
-
**BREAKING CHANGES**:
|
|
543
|
+
**BREAKING CHANGES**:
|
|
431
544
|
- Minimum Python version raised to 3.13
|
|
432
545
|
- Enumerations refactored for type safety and consistency
|
|
433
546
|
|
|
434
547
|
Removed
|
|
435
548
|
-------
|
|
436
549
|
- **Python 3.9-3.12 Support**: Minimum Python version is now 3.13
|
|
437
|
-
|
|
550
|
+
|
|
438
551
|
Home Assistant has deprecated Python 3.12 support, making Python 3.13 the de facto minimum for this ecosystem.
|
|
439
|
-
|
|
552
|
+
|
|
440
553
|
Python 3.13 features and improvements:
|
|
441
|
-
|
|
554
|
+
|
|
442
555
|
- **Experimental free-threaded mode** (PEP 703): Optional GIL removal for true parallelism
|
|
443
556
|
- **JIT compiler** (PEP 744): Just-in-time compilation for performance improvements
|
|
444
557
|
- **Better error messages**: Enhanced suggestions for NameError, AttributeError, and import errors
|
|
@@ -447,16 +560,16 @@ Removed
|
|
|
447
560
|
- PEP 695: New type parameter syntax for generics
|
|
448
561
|
- PEP 701: f-string improvements
|
|
449
562
|
- Built-in ``datetime.UTC`` constant
|
|
450
|
-
|
|
563
|
+
|
|
451
564
|
If you need Python 3.12 support, use version 6.1.x of this library.
|
|
452
565
|
|
|
453
566
|
- **CommandCode moved**: Import from ``nwp500.enums`` instead of ``nwp500.constants``
|
|
454
|
-
|
|
567
|
+
|
|
455
568
|
.. code-block:: python
|
|
456
|
-
|
|
569
|
+
|
|
457
570
|
# OLD (removed)
|
|
458
571
|
from nwp500.constants import CommandCode
|
|
459
|
-
|
|
572
|
+
|
|
460
573
|
# NEW
|
|
461
574
|
from nwp500.enums import CommandCode
|
|
462
575
|
# OR
|
|
@@ -466,14 +579,14 @@ Added
|
|
|
466
579
|
-----
|
|
467
580
|
|
|
468
581
|
- **Python 3.12+ Optimizations**: Leverage latest Python features
|
|
469
|
-
|
|
582
|
+
|
|
470
583
|
- PEP 695: New type parameter syntax (``def func[T](...)`` instead of ``TypeVar``)
|
|
471
584
|
- Use ``datetime.UTC`` constant instead of ``datetime.timezone.utc``
|
|
472
585
|
- Native union syntax (``X | Y`` instead of ``Union[X, Y]``)
|
|
473
586
|
- Cleaner generic type annotations throughout codebase
|
|
474
587
|
|
|
475
588
|
- **Enumerations Module (``src/nwp500/enums.py``)**: Comprehensive type-safe enums for device control and status
|
|
476
|
-
|
|
589
|
+
|
|
477
590
|
- Status value enums: ``OnOffFlag``, ``Operation``, ``DhwOperationSetting``, ``CurrentOperationMode``, ``HeatSource``, ``DREvent``, ``WaterLevel``, ``FilterChange``, ``RecirculationMode``
|
|
478
591
|
- Time of Use enums: ``TouWeekType``, ``TouRateType``
|
|
479
592
|
- Device capability enums: ``CapabilityFlag``, ``TemperatureType``, ``DeviceType``
|
|
@@ -488,7 +601,7 @@ Changed
|
|
|
488
601
|
-------
|
|
489
602
|
|
|
490
603
|
- **Command Code Constants**: Migrated from ``constants.py`` to ``CommandCode`` enum in ``enums.py``
|
|
491
|
-
|
|
604
|
+
|
|
492
605
|
- ``ANTI_LEGIONELLA_ENABLE`` → ``CommandCode.ANTI_LEGIONELLA_ON``
|
|
493
606
|
- ``ANTI_LEGIONELLA_DISABLE`` → ``CommandCode.ANTI_LEGIONELLA_OFF``
|
|
494
607
|
- ``TOU_ENABLE`` → ``CommandCode.TOU_ON``
|
|
@@ -497,19 +610,19 @@ Changed
|
|
|
497
610
|
- All command constants now use consistent naming in ``CommandCode`` enum
|
|
498
611
|
|
|
499
612
|
- **Model Enumerations**: Updated type annotations for clarity and type safety
|
|
500
|
-
|
|
613
|
+
|
|
501
614
|
- ``TemperatureUnit`` → ``TemperatureType`` (matches device protocol field names)
|
|
502
615
|
- All capability flags (e.g., ``power_use``, ``dhw_use``) now use ``CapabilityFlag`` type
|
|
503
616
|
- ``MqttRequest.device_type`` now accepts ``Union[DeviceType, int]`` for flexibility
|
|
504
617
|
|
|
505
618
|
- **Model Serialization**: Enums automatically serialize to human-readable names
|
|
506
|
-
|
|
619
|
+
|
|
507
620
|
- `model_dump()` converts enums to names (e.g., `DhwOperationSetting.HEAT_PUMP` → `"HEAT_PUMP"`)
|
|
508
621
|
- CLI and other consumers benefit from automatic enum name serialization
|
|
509
622
|
- Text mappings available for custom formatting (e.g., `DHW_OPERATION_TEXT[enum]` → "Heat Pump Only")
|
|
510
623
|
|
|
511
624
|
- **Documentation**: Comprehensive updates across protocol and API documentation
|
|
512
|
-
|
|
625
|
+
|
|
513
626
|
- ``docs/guides/time_of_use.rst``: Clarified TOU override status behavior (1=OFF/override active, 2=ON/normal operation)
|
|
514
627
|
- ``docs/protocol/data_conversions.rst``: Updated TOU field descriptions with correct enum values
|
|
515
628
|
- ``docs/protocol/device_features.rst``: Added capability flag pattern explanation (2=supported, 1=not supported)
|
|
@@ -517,14 +630,14 @@ Changed
|
|
|
517
630
|
- ``docs/python_api/models.rst``: Updated model field type annotations
|
|
518
631
|
|
|
519
632
|
- **Examples**: Updated to use new enums for type-safe device control
|
|
520
|
-
|
|
633
|
+
|
|
521
634
|
- ``examples/anti_legionella_example.py``: Uses ``CommandCode`` enum
|
|
522
635
|
- ``examples/device_feature_callback.py``: Uses capability enums
|
|
523
636
|
- ``examples/event_emitter_demo.py``: Uses status enums
|
|
524
637
|
- ``examples/mqtt_diagnostics_example.py``: Uses command enums
|
|
525
638
|
|
|
526
639
|
- **CLI Code Cleanup**: Refactored JSON formatting to use shared utility function
|
|
527
|
-
|
|
640
|
+
|
|
528
641
|
- Extracted repeated `json.dumps()` calls to `format_json_output()` helper
|
|
529
642
|
- Cleaner code with consistent formatting across all commands
|
|
530
643
|
|
|
@@ -572,7 +685,7 @@ Changed
|
|
|
572
685
|
|
|
573
686
|
# OLD (removed)
|
|
574
687
|
build_reservation_entry(..., param=120)
|
|
575
|
-
|
|
688
|
+
|
|
576
689
|
# NEW
|
|
577
690
|
build_reservation_entry(..., temperature_f=140.0)
|
|
578
691
|
|
|
@@ -583,7 +696,7 @@ Changed
|
|
|
583
696
|
|
|
584
697
|
# OLD (removed)
|
|
585
698
|
await mqtt.set_dhw_temperature(device, 120)
|
|
586
|
-
|
|
699
|
+
|
|
587
700
|
# NEW
|
|
588
701
|
await mqtt.set_dhw_temperature(device, 140.0)
|
|
589
702
|
|
|
@@ -604,7 +717,7 @@ Added
|
|
|
604
717
|
.. code-block:: python
|
|
605
718
|
|
|
606
719
|
from nwp500 import fahrenheit_to_half_celsius
|
|
607
|
-
|
|
720
|
+
|
|
608
721
|
param = fahrenheit_to_half_celsius(140.0) # Returns 120
|
|
609
722
|
|
|
610
723
|
Fixed
|
|
@@ -644,7 +757,7 @@ Fixed
|
|
|
644
757
|
|
|
645
758
|
- **Example Code**: Fixed ``device_status_callback.py`` example to use snake_case attribute names consistently
|
|
646
759
|
- **Field Descriptions**: Clarified distinctions between similar fields:
|
|
647
|
-
|
|
760
|
+
|
|
648
761
|
- ``dhw_temperature_setting`` vs ``dhw_target_temperature_setting`` descriptions
|
|
649
762
|
- ``freeze_protection_temp`` descriptions differ between DeviceStatus and DeviceFeature
|
|
650
763
|
- ``eco_use`` descriptions differ between DeviceStatus (current state) and DeviceFeature (capability)
|
|
@@ -656,7 +769,7 @@ Fixed
|
|
|
656
769
|
-----
|
|
657
770
|
|
|
658
771
|
- **CRITICAL Temperature Conversion Bug**: Corrected temperature conversion formula for 8 sensor fields that were displaying values ~100°F higher than expected. The v6.0.4 change incorrectly used division by 5 (pentacelsius) instead of division by 10 (decicelsius) for these fields:
|
|
659
|
-
|
|
772
|
+
|
|
660
773
|
- ``tank_upper_temperature`` - Water tank upper sensor
|
|
661
774
|
- ``tank_lower_temperature`` - Water tank lower sensor
|
|
662
775
|
- ``discharge_temperature`` - Compressor discharge temperature (refrigerant)
|
|
@@ -665,13 +778,13 @@ Fixed
|
|
|
665
778
|
- ``ambient_temperature`` - Ambient air temperature at heat pump
|
|
666
779
|
- ``target_super_heat`` - Target superheat setpoint
|
|
667
780
|
- ``current_super_heat`` - Measured superheat value
|
|
668
|
-
|
|
781
|
+
|
|
669
782
|
**Impact**: These fields now correctly display temperatures in expected ranges:
|
|
670
|
-
|
|
783
|
+
|
|
671
784
|
- Tank temperatures: ~120°F (close to DHW temperature, not ~220°F)
|
|
672
785
|
- Discharge temperature: 120-180°F (not 220-280°F)
|
|
673
786
|
- Suction, evaporator, ambient: Now showing physically realistic values
|
|
674
|
-
|
|
787
|
+
|
|
675
788
|
**Technical details**: Changed from ``PentaCelsiusToF`` (÷5) back to ``DeciCelsiusToF`` (÷10). The correct formula is ``(raw_value / 10.0) * 9/5 + 32``.
|
|
676
789
|
|
|
677
790
|
Changed
|
|
@@ -686,7 +799,7 @@ Fixed
|
|
|
686
799
|
-----
|
|
687
800
|
|
|
688
801
|
- **Temperature Conversion Accuracy**: Corrected temperature conversion logic based on analysis of the decompiled mobile application. Previous conversions used approximations; new logic uses exact formulas from the app:
|
|
689
|
-
|
|
802
|
+
|
|
690
803
|
- Replaced ``Add20`` validator with ``HalfCelsiusToF`` for fields transmitted as half-degrees Celsius
|
|
691
804
|
- Replaced ``DeciCelsiusToF`` with ``PentaCelsiusToF`` for fields scaled by factor of 5
|
|
692
805
|
- Affects multiple temperature sensor readings for improved accuracy
|
|
@@ -818,32 +931,32 @@ Removed
|
|
|
818
931
|
-------
|
|
819
932
|
|
|
820
933
|
- **Constructor Callbacks**: Removed ``on_connection_interrupted`` and ``on_connection_resumed`` constructor parameters from ``NavienMqttClient``
|
|
821
|
-
|
|
934
|
+
|
|
822
935
|
.. code-block:: python
|
|
823
|
-
|
|
936
|
+
|
|
824
937
|
# OLD (removed in v6.0.0)
|
|
825
938
|
mqtt_client = NavienMqttClient(
|
|
826
939
|
auth_client,
|
|
827
940
|
on_connection_interrupted=on_interrupted,
|
|
828
941
|
on_connection_resumed=on_resumed,
|
|
829
942
|
)
|
|
830
|
-
|
|
943
|
+
|
|
831
944
|
# NEW (use event emitter pattern)
|
|
832
945
|
mqtt_client = NavienMqttClient(auth_client)
|
|
833
946
|
mqtt_client.on("connection_interrupted", on_interrupted)
|
|
834
947
|
mqtt_client.on("connection_resumed", on_resumed)
|
|
835
948
|
|
|
836
949
|
- **Backward Compatibility Re-exports**: Removed exception re-exports from ``api_client`` and ``auth`` modules
|
|
837
|
-
|
|
950
|
+
|
|
838
951
|
.. code-block:: python
|
|
839
|
-
|
|
952
|
+
|
|
840
953
|
# OLD (removed in v6.0.0)
|
|
841
954
|
from nwp500.api_client import APIError
|
|
842
955
|
from nwp500.auth import AuthenticationError, TokenRefreshError
|
|
843
|
-
|
|
956
|
+
|
|
844
957
|
# NEW (import from exceptions module)
|
|
845
958
|
from nwp500.exceptions import APIError, AuthenticationError, TokenRefreshError
|
|
846
|
-
|
|
959
|
+
|
|
847
960
|
# OR (import from package root - recommended)
|
|
848
961
|
from nwp500 import APIError, AuthenticationError, TokenRefreshError
|
|
849
962
|
|
|
@@ -854,7 +967,7 @@ Changed
|
|
|
854
967
|
-------
|
|
855
968
|
|
|
856
969
|
- **Migration Benefits**:
|
|
857
|
-
|
|
970
|
+
|
|
858
971
|
- Multiple listeners per event (not just one callback)
|
|
859
972
|
- Consistent API with other events (temperature_changed, mode_changed, etc.)
|
|
860
973
|
- Dynamic listener management (add/remove listeners at runtime)
|
|
@@ -877,7 +990,7 @@ Fixed
|
|
|
877
990
|
-----
|
|
878
991
|
|
|
879
992
|
- **MQTT Future Cancellation**: Fixed InvalidStateError exceptions during disconnect
|
|
880
|
-
|
|
993
|
+
|
|
881
994
|
- Added asyncio.shield() to protect concurrent.futures.Future objects from cancellation
|
|
882
995
|
- Applied consistent cancellation handling across all MQTT operations (connect, disconnect, subscribe, unsubscribe, publish)
|
|
883
996
|
- AWS CRT callbacks can now complete independently without raising InvalidStateError
|
|
@@ -905,7 +1018,7 @@ Changed
|
|
|
905
1018
|
Version 5.0.0 (2025-10-27)
|
|
906
1019
|
==========================
|
|
907
1020
|
|
|
908
|
-
**BREAKING CHANGES**: This release introduces a comprehensive enterprise exception architecture.
|
|
1021
|
+
**BREAKING CHANGES**: This release introduces a comprehensive enterprise exception architecture.
|
|
909
1022
|
See migration guide below for details on updating your code.
|
|
910
1023
|
|
|
911
1024
|
Added
|
|
@@ -915,10 +1028,10 @@ Added
|
|
|
915
1028
|
|
|
916
1029
|
- Created ``exceptions.py`` module with comprehensive exception hierarchy
|
|
917
1030
|
- Added ``Nwp500Error`` as base exception for all library errors
|
|
918
|
-
- Added MQTT-specific exceptions: ``MqttError``, ``MqttConnectionError``, ``MqttNotConnectedError``,
|
|
1031
|
+
- Added MQTT-specific exceptions: ``MqttError``, ``MqttConnectionError``, ``MqttNotConnectedError``,
|
|
919
1032
|
``MqttPublishError``, ``MqttSubscriptionError``, ``MqttCredentialsError``
|
|
920
1033
|
- Added validation exceptions: ``ValidationError``, ``ParameterValidationError``, ``RangeValidationError``
|
|
921
|
-
- Added device exceptions: ``DeviceError``, ``DeviceNotFoundError``, ``DeviceOfflineError``,
|
|
1034
|
+
- Added device exceptions: ``DeviceError``, ``DeviceNotFoundError``, ``DeviceOfflineError``,
|
|
922
1035
|
``DeviceOperationError``
|
|
923
1036
|
- All exceptions now include ``error_code``, ``details``, and ``retriable`` attributes
|
|
924
1037
|
- Added ``to_dict()`` method to all exceptions for structured logging
|
|
@@ -946,7 +1059,7 @@ Migration Guide (v4.x to v5.0)
|
|
|
946
1059
|
|
|
947
1060
|
**Breaking Changes Summary**:
|
|
948
1061
|
|
|
949
|
-
The library now uses specific exception types instead of generic ``RuntimeError`` and ``ValueError``.
|
|
1062
|
+
The library now uses specific exception types instead of generic ``RuntimeError`` and ``ValueError``.
|
|
950
1063
|
This improves error handling but requires updates to exception handling code.
|
|
951
1064
|
|
|
952
1065
|
**1. MQTT Connection Errors**
|
|
@@ -962,7 +1075,7 @@ This improves error handling but requires updates to exception handling code.
|
|
|
962
1075
|
|
|
963
1076
|
# NEW CODE (v5.0+)
|
|
964
1077
|
from nwp500 import MqttNotConnectedError, MqttError
|
|
965
|
-
|
|
1078
|
+
|
|
966
1079
|
try:
|
|
967
1080
|
await mqtt_client.request_device_status(device)
|
|
968
1081
|
except MqttNotConnectedError:
|
|
@@ -985,7 +1098,7 @@ This improves error handling but requires updates to exception handling code.
|
|
|
985
1098
|
|
|
986
1099
|
# NEW CODE (v5.0+)
|
|
987
1100
|
from nwp500 import RangeValidationError, ValidationError
|
|
988
|
-
|
|
1101
|
+
|
|
989
1102
|
try:
|
|
990
1103
|
set_vacation_mode(device, days=35)
|
|
991
1104
|
except RangeValidationError as e:
|
|
@@ -1009,7 +1122,7 @@ This improves error handling but requires updates to exception handling code.
|
|
|
1009
1122
|
|
|
1010
1123
|
# NEW CODE (v5.0+)
|
|
1011
1124
|
from nwp500 import MqttCredentialsError
|
|
1012
|
-
|
|
1125
|
+
|
|
1013
1126
|
try:
|
|
1014
1127
|
mqtt_client = NavienMqttClient(auth_client)
|
|
1015
1128
|
except MqttCredentialsError as e:
|
|
@@ -1023,14 +1136,14 @@ This improves error handling but requires updates to exception handling code.
|
|
|
1023
1136
|
|
|
1024
1137
|
# NEW CODE (v5.0+) - catch all library exceptions
|
|
1025
1138
|
from nwp500 import Nwp500Error
|
|
1026
|
-
|
|
1139
|
+
|
|
1027
1140
|
try:
|
|
1028
1141
|
# Any library operation
|
|
1029
1142
|
await mqtt_client.request_device_status(device)
|
|
1030
1143
|
except Nwp500Error as e:
|
|
1031
1144
|
# All nwp500 exceptions inherit from Nwp500Error
|
|
1032
1145
|
logger.error(f"Library error: {e.to_dict()}")
|
|
1033
|
-
|
|
1146
|
+
|
|
1034
1147
|
# Check if retriable
|
|
1035
1148
|
if e.retriable:
|
|
1036
1149
|
await retry_operation()
|
|
@@ -1042,7 +1155,7 @@ All exceptions now include structured information:
|
|
|
1042
1155
|
.. code-block:: python
|
|
1043
1156
|
|
|
1044
1157
|
from nwp500 import MqttPublishError
|
|
1045
|
-
|
|
1158
|
+
|
|
1046
1159
|
try:
|
|
1047
1160
|
await mqtt_client.publish(topic, payload)
|
|
1048
1161
|
except MqttPublishError as e:
|
|
@@ -1055,10 +1168,10 @@ All exceptions now include structured information:
|
|
|
1055
1168
|
# 'details': {},
|
|
1056
1169
|
# 'retriable': True
|
|
1057
1170
|
# }
|
|
1058
|
-
|
|
1171
|
+
|
|
1059
1172
|
# Log for monitoring/alerting
|
|
1060
1173
|
logger.error("Publish failed", extra=error_info)
|
|
1061
|
-
|
|
1174
|
+
|
|
1062
1175
|
# Implement retry logic
|
|
1063
1176
|
if e.retriable:
|
|
1064
1177
|
await asyncio.sleep(1)
|
|
@@ -1116,7 +1229,7 @@ Added
|
|
|
1116
1229
|
-----
|
|
1117
1230
|
|
|
1118
1231
|
- **MQTT Reconnection**: Two-tier reconnection strategy with unlimited retries
|
|
1119
|
-
|
|
1232
|
+
|
|
1120
1233
|
- Implemented quick reconnection (attempts 1-9) for fast recovery from transient network issues
|
|
1121
1234
|
- Implemented deep reconnection (every 10th attempt) with full connection rebuild and credential refresh
|
|
1122
1235
|
- Changed default ``max_reconnect_attempts`` from 10 to -1 (unlimited retries)
|
|
@@ -1132,7 +1245,7 @@ Improved
|
|
|
1132
1245
|
--------
|
|
1133
1246
|
|
|
1134
1247
|
- **Exception Handling**: Replaced 25 catch-all exception handlers with specific exception types
|
|
1135
|
-
|
|
1248
|
+
|
|
1136
1249
|
- ``mqtt_client.py``: Uses ``AwsCrtError``, ``AuthenticationError``, ``TokenRefreshError``, ``RuntimeError``, ``ValueError``, ``TypeError``, ``AttributeError``
|
|
1137
1250
|
- ``mqtt_reconnection.py``: Uses ``AwsCrtError``, ``RuntimeError``, ``ValueError``, ``TypeError``
|
|
1138
1251
|
- ``mqtt_connection.py``: Uses ``AwsCrtError``, ``RuntimeError``, ``ValueError``
|
|
@@ -1142,7 +1255,7 @@ Improved
|
|
|
1142
1255
|
- Added exception handling guidelines to ``.github/copilot-instructions.md``
|
|
1143
1256
|
|
|
1144
1257
|
- **Code Quality**: Multiple readability and safety improvements
|
|
1145
|
-
|
|
1258
|
+
|
|
1146
1259
|
- Simplified nested conditions by extracting to local variables
|
|
1147
1260
|
- Added ``hasattr()`` checks before accessing ``AwsCrtError.name`` attribute
|
|
1148
1261
|
- Optimized ``resubscribe_all()`` to break after first failure per topic (reduces redundant error logs)
|
|
@@ -1153,7 +1266,7 @@ Fixed
|
|
|
1153
1266
|
-----
|
|
1154
1267
|
|
|
1155
1268
|
- **MQTT Reconnection**: Eliminated duplicate "Connection interrupted" log messages
|
|
1156
|
-
|
|
1269
|
+
|
|
1157
1270
|
- Removed duplicate logging from ``mqtt_client.py`` (kept in ``mqtt_reconnection.py``)
|
|
1158
1271
|
|
|
1159
1272
|
Version 3.1.4 (2025-10-26)
|
|
@@ -1163,7 +1276,7 @@ Fixed
|
|
|
1163
1276
|
-----
|
|
1164
1277
|
|
|
1165
1278
|
- **MQTT Reconnection**: Fixed MQTT reconnection failures due to expired AWS credentials
|
|
1166
|
-
|
|
1279
|
+
|
|
1167
1280
|
- Added AWS credential expiration tracking (``_aws_expires_at`` field in ``AuthTokens``)
|
|
1168
1281
|
- Added ``are_aws_credentials_expired`` property to check AWS credential validity
|
|
1169
1282
|
- Modified ``ensure_valid_token()`` to prioritize AWS credential expiration check
|
|
@@ -1180,7 +1293,7 @@ Fixed
|
|
|
1180
1293
|
-----
|
|
1181
1294
|
|
|
1182
1295
|
- **MQTT Reconnection**: Improved MQTT reconnection reliability with active reconnection
|
|
1183
|
-
|
|
1296
|
+
|
|
1184
1297
|
- **Breaking Internal Change**: ``MqttReconnectionHandler`` now requires ``reconnect_func`` parameter (not Optional)
|
|
1185
1298
|
- Implemented active reconnection that always recreates MQTT connection on interruption
|
|
1186
1299
|
- Removed unreliable passive fallback to AWS IoT SDK automatic reconnection
|
|
@@ -1199,7 +1312,7 @@ Fixed
|
|
|
1199
1312
|
-----
|
|
1200
1313
|
|
|
1201
1314
|
- **Authentication**: Fixed 401 authentication errors with automatic token refresh
|
|
1202
|
-
|
|
1315
|
+
|
|
1203
1316
|
- Add automatic token refresh on 401 Unauthorized responses in API client
|
|
1204
1317
|
- Preserve AWS credentials when refreshing tokens (required for MQTT)
|
|
1205
1318
|
- Save refreshed tokens to cache after successful API calls
|
|
@@ -1216,7 +1329,7 @@ Fixed
|
|
|
1216
1329
|
-----
|
|
1217
1330
|
|
|
1218
1331
|
- **MQTT Client**: Fixed connection interrupted callback signature for AWS SDK
|
|
1219
|
-
|
|
1332
|
+
|
|
1220
1333
|
- Updated callback to match latest AWS IoT SDK signature: ``(connection, error, **kwargs)``
|
|
1221
1334
|
- Fixed type annotations in ``MqttConnection`` for proper type checking
|
|
1222
1335
|
- Resolves mypy type checking errors and ensures AWS SDK compatibility
|
|
@@ -1228,14 +1341,14 @@ Version 3.0.0 (Unreleased)
|
|
|
1228
1341
|
**Breaking Changes**
|
|
1229
1342
|
|
|
1230
1343
|
- **REMOVED**: ``OperationMode`` enum has been removed
|
|
1231
|
-
|
|
1344
|
+
|
|
1232
1345
|
- This enum was deprecated in v2.0.0 and has now been fully removed
|
|
1233
1346
|
- Use ``DhwOperationSetting`` for user-configured mode preferences (values 1-6)
|
|
1234
1347
|
- Use ``CurrentOperationMode`` for real-time operational states (values 0, 32, 64, 96)
|
|
1235
1348
|
- Migration was supported throughout the v2.x series
|
|
1236
1349
|
|
|
1237
1350
|
- **REMOVED**: Migration helper functions and deprecation infrastructure
|
|
1238
|
-
|
|
1351
|
+
|
|
1239
1352
|
- Removed ``migrate_operation_mode_usage()`` function
|
|
1240
1353
|
- Removed ``enable_deprecation_warnings()`` function
|
|
1241
1354
|
- Removed migration documentation files (MIGRATION.md, BREAKING_CHANGES_V3.md)
|
|
@@ -1248,7 +1361,7 @@ Version 2.0.0 (Unreleased)
|
|
|
1248
1361
|
|
|
1249
1362
|
- **DEPRECATION**: ``OperationMode`` enum is deprecated and will be removed in v3.0.0
|
|
1250
1363
|
|
|
1251
|
-
|
|
1364
|
+
|
|
1252
1365
|
- Use ``DhwOperationSetting`` for user-configured mode preferences (values 1-6)
|
|
1253
1366
|
- Use ``CurrentOperationMode`` for real-time operational states (values 0, 32, 64, 96)
|
|
1254
1367
|
- See ``MIGRATION.md`` for detailed migration guide
|
|
@@ -1325,7 +1438,7 @@ Added
|
|
|
1325
1438
|
- Standardized ruff configuration across all environments
|
|
1326
1439
|
- Eliminates "passes locally but fails in CI" issues
|
|
1327
1440
|
- Cross-platform support (Linux, macOS, Windows, containers)
|
|
1328
|
-
|
|
1441
|
+
|
|
1329
1442
|
- All MQTT operations (connect, disconnect, subscribe, unsubscribe, publish) use ``asyncio.wrap_future()`` to convert AWS SDK Futures to asyncio Futures
|
|
1330
1443
|
- Eliminates "blocking I/O detected" warnings in Home Assistant and other async applications
|
|
1331
1444
|
- Fully compatible with async event loops without blocking other operations
|
|
@@ -1336,7 +1449,7 @@ Added
|
|
|
1336
1449
|
- Updated documentation with non-blocking implementation details
|
|
1337
1450
|
|
|
1338
1451
|
- **Event Emitter Pattern (Phase 1)**: Event-driven architecture for device state changes
|
|
1339
|
-
|
|
1452
|
+
|
|
1340
1453
|
- ``EventEmitter`` base class with multiple listeners per event
|
|
1341
1454
|
- Async and sync handler support
|
|
1342
1455
|
- Priority-based execution order (higher priority executes first)
|
|
@@ -1354,7 +1467,7 @@ Added
|
|
|
1354
1467
|
- Documentation: ``EVENT_EMITTER.rst``, ``EVENT_QUICK_REFERENCE.rst``, ``EVENT_ARCHITECTURE.rst``
|
|
1355
1468
|
|
|
1356
1469
|
- **Authentication**: Simplified constructor-based authentication
|
|
1357
|
-
|
|
1470
|
+
|
|
1358
1471
|
- ``NavienAuthClient`` now requires ``user_id`` and ``password`` in constructor
|
|
1359
1472
|
- Automatic authentication when entering async context manager
|
|
1360
1473
|
- No need to call ``sign_in()`` manually
|
|
@@ -1363,7 +1476,7 @@ Added
|
|
|
1363
1476
|
- Updated all documentation with new authentication examples
|
|
1364
1477
|
|
|
1365
1478
|
- **MQTT Command Queue**: Automatic command queuing when disconnected
|
|
1366
|
-
|
|
1479
|
+
|
|
1367
1480
|
- Commands sent while disconnected are automatically queued
|
|
1368
1481
|
- Queue processed in FIFO order when connection is restored
|
|
1369
1482
|
- Configurable queue size (default: 100 commands)
|
|
@@ -1376,7 +1489,7 @@ Added
|
|
|
1376
1489
|
- Documentation: ``COMMAND_QUEUE.rst``
|
|
1377
1490
|
|
|
1378
1491
|
- **MQTT Reconnection**: Automatic reconnection with exponential backoff
|
|
1379
|
-
|
|
1492
|
+
|
|
1380
1493
|
- Automatic reconnection on connection interruption
|
|
1381
1494
|
- Configurable exponential backoff (default: 1s, 2s, 4s, 8s, ... up to 120s)
|
|
1382
1495
|
- Configurable max attempts (default: 10)
|
|
@@ -1388,7 +1501,7 @@ Added
|
|
|
1388
1501
|
- Documentation: Added reconnection section to MQTT_CLIENT.rst
|
|
1389
1502
|
|
|
1390
1503
|
- **MQTT Client**: Complete implementation of real-time device communication
|
|
1391
|
-
|
|
1504
|
+
|
|
1392
1505
|
- WebSocket MQTT connection to AWS IoT Core
|
|
1393
1506
|
- Device subscription and message handling
|
|
1394
1507
|
- Status request methods (device info, device status)
|
|
@@ -1397,7 +1510,7 @@ Added
|
|
|
1397
1510
|
- Connection lifecycle management (connect, disconnect, reconnect)
|
|
1398
1511
|
|
|
1399
1512
|
- **Device Control**: Fully implemented and verified control commands
|
|
1400
|
-
|
|
1513
|
+
|
|
1401
1514
|
- Power control (on/off) with correct command codes
|
|
1402
1515
|
- DHW mode control (Heat Pump, Electric, Energy Saver, High Demand)
|
|
1403
1516
|
- DHW temperature control with 20°F offset handling
|
|
@@ -1405,7 +1518,7 @@ Added
|
|
|
1405
1518
|
- Helper method for display-value temperature control
|
|
1406
1519
|
|
|
1407
1520
|
- **Typed Callbacks**: 100% coverage of all MQTT response types
|
|
1408
|
-
|
|
1521
|
+
|
|
1409
1522
|
- ``subscribe_device_status()`` - Automatic parsing of status messages into ``DeviceStatus`` objects
|
|
1410
1523
|
- ``subscribe_device_feature()`` - Automatic parsing of feature messages into ``DeviceFeature`` objects
|
|
1411
1524
|
- ``subscribe_energy_usage()`` - Automatic parsing of energy usage responses into ``EnergyUsageResponse`` objects
|
|
@@ -1414,7 +1527,7 @@ Added
|
|
|
1414
1527
|
- Example scripts demonstrating usage patterns
|
|
1415
1528
|
|
|
1416
1529
|
- **Energy Usage API (EMS)**: Historical energy consumption data
|
|
1417
|
-
|
|
1530
|
+
|
|
1418
1531
|
- ``request_energy_usage()`` - Query daily energy usage for specified month(s)
|
|
1419
1532
|
- ``EnergyUsageResponse`` dataclass with daily breakdown
|
|
1420
1533
|
- ``EnergyUsageTotal`` with percentage calculations
|
|
@@ -1426,7 +1539,7 @@ Added
|
|
|
1426
1539
|
- Efficiency percentage calculations
|
|
1427
1540
|
|
|
1428
1541
|
- **Data Models**: Comprehensive type-safe models
|
|
1429
|
-
|
|
1542
|
+
|
|
1430
1543
|
- ``DeviceStatus`` dataclass with 125 sensor and operational fields
|
|
1431
1544
|
- ``DeviceFeature`` dataclass with 46 capability and configuration fields
|
|
1432
1545
|
- ``EnergyUsageResponse`` dataclass for historical energy data
|
|
@@ -1439,7 +1552,7 @@ Added
|
|
|
1439
1552
|
- Authentication tokens and user info
|
|
1440
1553
|
|
|
1441
1554
|
- **API Client**: High-level REST API client
|
|
1442
|
-
|
|
1555
|
+
|
|
1443
1556
|
- Device listing and information retrieval
|
|
1444
1557
|
- Firmware information queries
|
|
1445
1558
|
- Time-of-Use (TOU) schedule management
|
|
@@ -1448,7 +1561,7 @@ Added
|
|
|
1448
1561
|
- Automatic session management
|
|
1449
1562
|
|
|
1450
1563
|
- **Authentication**: AWS Cognito integration
|
|
1451
|
-
|
|
1564
|
+
|
|
1452
1565
|
- Sign-in with email/password
|
|
1453
1566
|
- Access token management
|
|
1454
1567
|
- Token refresh functionality
|
|
@@ -1456,7 +1569,7 @@ Added
|
|
|
1456
1569
|
- Async context manager support
|
|
1457
1570
|
|
|
1458
1571
|
- **Documentation**: Complete protocol and API documentation
|
|
1459
|
-
|
|
1572
|
+
|
|
1460
1573
|
- MQTT message format specifications
|
|
1461
1574
|
- Energy usage query API documentation (EMS data)
|
|
1462
1575
|
- API client usage guide
|
|
@@ -1468,7 +1581,7 @@ Added
|
|
|
1468
1581
|
- Complete energy data reference (ENERGY_DATA_SUMMARY.md)
|
|
1469
1582
|
|
|
1470
1583
|
- **Examples**: Production-ready example scripts
|
|
1471
|
-
|
|
1584
|
+
|
|
1472
1585
|
- ``device_status_callback.py`` - Real-time status monitoring with typed callbacks
|
|
1473
1586
|
- ``device_feature_callback.py`` - Device capabilities and firmware info
|
|
1474
1587
|
- ``combined_callbacks.py`` - Both status and feature callbacks together
|
|
@@ -1481,7 +1594,7 @@ Changed
|
|
|
1481
1594
|
-------
|
|
1482
1595
|
|
|
1483
1596
|
- **Breaking**: Python version requirement updated to 3.9+
|
|
1484
|
-
|
|
1597
|
+
|
|
1485
1598
|
- Minimum Python version is now 3.9 (was 3.8)
|
|
1486
1599
|
- Migrated to native type hints (PEP 585): ``dict[str, Any]`` instead of ``Dict[str, Any]``
|
|
1487
1600
|
- Removed ``typing.Dict``, ``typing.List``, ``typing.Deque`` imports
|
|
@@ -1490,7 +1603,7 @@ Changed
|
|
|
1490
1603
|
- Updated ruff target-version to py39
|
|
1491
1604
|
|
|
1492
1605
|
- **Breaking**: ``NavienAuthClient`` constructor signature
|
|
1493
|
-
|
|
1606
|
+
|
|
1494
1607
|
- Now requires ``user_id`` and ``password`` as first parameters
|
|
1495
1608
|
- Old: ``NavienAuthClient()`` then ``await client.sign_in(email, password)``
|
|
1496
1609
|
- New: ``NavienAuthClient(email, password)`` - authentication is automatic
|
|
@@ -1499,7 +1612,7 @@ Changed
|
|
|
1499
1612
|
- All documentation updated with new examples
|
|
1500
1613
|
|
|
1501
1614
|
- **Documentation**: Major updates across all files
|
|
1502
|
-
|
|
1615
|
+
|
|
1503
1616
|
- Fixed all RST formatting issues (title underlines, tables)
|
|
1504
1617
|
- Updated authentication examples in 8 documentation files
|
|
1505
1618
|
- Fixed broken documentation links (local file paths)
|
|
@@ -1514,7 +1627,7 @@ Fixed
|
|
|
1514
1627
|
-----
|
|
1515
1628
|
|
|
1516
1629
|
- **Critical Bug**: Thread-safe reconnection task creation from MQTT callbacks
|
|
1517
|
-
|
|
1630
|
+
|
|
1518
1631
|
- Fixed ``RuntimeError: no running event loop`` when connection is interrupted
|
|
1519
1632
|
- Fixed ``RuntimeWarning: coroutine '_reconnect_with_backoff' was never awaited``
|
|
1520
1633
|
- Connection interruption callbacks run in separate threads without event loops
|
|
@@ -1524,7 +1637,7 @@ Fixed
|
|
|
1524
1637
|
- Ensures reconnection tasks are properly awaited and executed
|
|
1525
1638
|
|
|
1526
1639
|
- **Critical Bug**: Thread-safe event emission from MQTT callbacks
|
|
1527
|
-
|
|
1640
|
+
|
|
1528
1641
|
- Fixed ``RuntimeError: no running event loop in thread 'Dummy-1'``
|
|
1529
1642
|
- MQTT callbacks run in separate threads created by AWS IoT SDK
|
|
1530
1643
|
- Implemented ``_schedule_coroutine()`` method for thread-safe scheduling
|
|
@@ -1534,7 +1647,7 @@ Fixed
|
|
|
1534
1647
|
- All event emissions now work correctly from any thread
|
|
1535
1648
|
|
|
1536
1649
|
- **Bug**: Incorrect method parameter passing in temperature control
|
|
1537
|
-
|
|
1650
|
+
|
|
1538
1651
|
- Fixed ``set_dhw_temperature_display()`` calling ``set_dhw_temperature()`` with wrong parameters
|
|
1539
1652
|
- Was passing individual parameters (``device_id``, ``device_type``, ``additional_value``)
|
|
1540
1653
|
- Now correctly passes ``Device`` object as expected by method signature
|
|
@@ -1542,14 +1655,14 @@ Fixed
|
|
|
1542
1655
|
- Updated docstrings to match actual method signatures
|
|
1543
1656
|
|
|
1544
1657
|
- **Enhancement**: Anonymized MAC addresses in documentation
|
|
1545
|
-
|
|
1658
|
+
|
|
1546
1659
|
- Replaced all occurrences of real MAC address (``04786332fca0``) with placeholder (``aabbccddeeff``)
|
|
1547
1660
|
- Updated ``API_CLIENT.rst``, ``MQTT_CLIENT.rst``, ``MQTT_MESSAGES.rst``
|
|
1548
1661
|
- Updated built HTML documentation files
|
|
1549
1662
|
- Protects privacy in public documentation
|
|
1550
1663
|
|
|
1551
1664
|
- **Critical Bug**: Device control command codes
|
|
1552
|
-
|
|
1665
|
+
|
|
1553
1666
|
- Fixed incorrect command code usage causing unintended power-off
|
|
1554
1667
|
- Power-off now uses command code ``33554433``
|
|
1555
1668
|
- Power-on now uses command code ``33554434``
|
|
@@ -1557,7 +1670,7 @@ Fixed
|
|
|
1557
1670
|
- Discovered through network traffic analysis of official app
|
|
1558
1671
|
|
|
1559
1672
|
- **Critical Bug**: MQTT topic pattern matching with wildcards
|
|
1560
|
-
|
|
1673
|
+
|
|
1561
1674
|
- Fixed ``_topic_matches_pattern()`` to correctly handle ``#`` wildcard
|
|
1562
1675
|
- Topics now match when message arrives on base topic (e.g., ``cmd/52/device/res``)
|
|
1563
1676
|
- Topics also match subtopics (e.g., ``cmd/52/device/res/extra``)
|
|
@@ -1565,21 +1678,21 @@ Fixed
|
|
|
1565
1678
|
- Enables callbacks to receive messages correctly
|
|
1566
1679
|
|
|
1567
1680
|
- **Bug**: Missing ``OperationMode.STANDBY`` enum value
|
|
1568
|
-
|
|
1681
|
+
|
|
1569
1682
|
- Added ``STANDBY = 0`` to ``OperationMode`` enum
|
|
1570
1683
|
- Device reports mode 0 when tank is fully charged and no heating is needed
|
|
1571
1684
|
- Added graceful fallback for unknown enum values
|
|
1572
1685
|
- Prevents ``ValueError`` when parsing device status
|
|
1573
1686
|
|
|
1574
1687
|
- **Bug**: Insufficient topic subscriptions
|
|
1575
|
-
|
|
1688
|
+
|
|
1576
1689
|
- Examples now subscribe to broader topic patterns
|
|
1577
1690
|
- Subscribe to ``cmd/{device_type}/{device_topic}/#`` to catch all command messages
|
|
1578
1691
|
- Subscribe to ``evt/{device_type}/{device_topic}/#`` to catch all event messages
|
|
1579
1692
|
- Ensures all device responses are received
|
|
1580
1693
|
|
|
1581
1694
|
- **Enhancement**: Robust enum conversion with fallbacks
|
|
1582
|
-
|
|
1695
|
+
|
|
1583
1696
|
- Added try/except blocks for all enum conversions in ``DeviceStatus.from_dict()``
|
|
1584
1697
|
- Added try/except blocks for all enum conversions in ``DeviceFeature.from_dict()``
|
|
1585
1698
|
- Unknown operation modes default to ``STANDBY``
|
|
@@ -1592,7 +1705,7 @@ Verified
|
|
|
1592
1705
|
--------
|
|
1593
1706
|
|
|
1594
1707
|
- **Device Control**: Real-world testing with Navien NWP500 device
|
|
1595
|
-
|
|
1708
|
+
|
|
1596
1709
|
- Successfully changed DHW mode from Heat Pump to Energy Saver
|
|
1597
1710
|
- Successfully changed DHW mode from Energy Saver to High Demand
|
|
1598
1711
|
- Successfully changed DHW temperature (discovered 20°F offset between message and display)
|