nwp500-python 7.3.1__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.3.1 → nwp500_python-7.3.2}/CHANGELOG.rst +21 -0
- {nwp500_python-7.3.1/src/nwp500_python.egg-info → nwp500_python-7.3.2}/PKG-INFO +1 -1
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/api_client.py +3 -2
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/auth.py +3 -2
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/__main__.py +2 -2
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/client.py +14 -13
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/subscriptions.py +6 -5
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/unit_system.py +17 -13
- {nwp500_python-7.3.1 → nwp500_python-7.3.2/src/nwp500_python.egg-info}/PKG-INFO +1 -1
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_unit_switching.py +6 -6
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.agent/workflows/pre-completion-testing.md +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.coveragerc +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.github/copilot-instructions.md +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.github/workflows/ci.yml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.github/workflows/release.yml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.gitignore +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.pre-commit-config.yaml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/.readthedocs.yml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/AUTHORS.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/CONTRIBUTING.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/LICENSE.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/Makefile +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/README.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/RELEASE.md +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/Makefile +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/_static/.gitignore +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/api/nwp500.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/authors.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/changelog.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/conf.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/configuration.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/development/contributing.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/development/history.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/enumerations.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/advanced_features_explained.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/authentication.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/auto_recovery.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/command_queue.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/energy_monitoring.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/event_system.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/home_assistant_integration.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/mqtt_diagnostics.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/reservations.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/scheduling_features.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/time_of_use.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/guides/unit_conversion.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/index.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/installation.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/license.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/openapi.yaml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/data_conversions.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/device_features.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/device_status.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/error_codes.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/mqtt_protocol.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/quick_reference.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/protocol/rest_api.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/api_client.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/auth_client.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/cli.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/device_control.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/events.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/exceptions.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/models.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/python_api/mqtt_client.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/quickstart.rst +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/docs/requirements.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/.ruff.toml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/README.md +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/air_filter_reset.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/anti_legionella.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/auto_recovery.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/combined_callbacks.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/demand_response.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/device_capabilities.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/device_status_debug.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/energy_analytics.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/error_code_demo.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/mqtt_diagnostics.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/power_control.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/recirculation_control.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/reconnection_demo.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/reservation_schedule.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/simple_auto_recovery.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/token_restoration.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/tou_openei.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/tou_schedule.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/advanced/water_reservation.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/beginner/01_authentication.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/beginner/02_list_devices.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/beginner/03_get_status.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/beginner/04_set_temperature.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/advanced_auth_patterns.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/command_queue.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/device_status_callback.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/error_handling.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/event_driven_control.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/improved_auth.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/legacy_auth_constructor.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/mqtt_realtime_monitoring.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/periodic_requests.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/set_mode.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/vacation_mode.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/mask.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/testing/periodic_device_info.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/testing/simple_periodic_info.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/testing/test_api_client.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/testing/test_mqtt_connection.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/testing/test_mqtt_messaging.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/testing/test_periodic_minimal.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/pyproject.toml +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/README.md +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/bump_version.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/diagnose_mqtt_connection.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/extract_changelog.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/format.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/lint.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/setup-dev.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/scripts/validate_version.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/setup.cfg +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/setup.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/__init__.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/__init__.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/commands.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/handlers.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/monitoring.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/output_formatters.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/rich_output.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/cli/token_storage.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/command_decorators.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/config.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/converters.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/device_capabilities.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/device_info_cache.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/encoding.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/enums.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/events.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/exceptions.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/factory.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/field_factory.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/models.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/__init__.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/command_queue.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/connection.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/control.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/diagnostics.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/periodic.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/reconnection.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt/utils.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/mqtt_events.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/py.typed +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/temperature.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/topic_builder.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500/utils.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/SOURCES.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/entry_points.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/not-zip-safe +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/requires.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/src/nwp500_python.egg-info/top_level.txt +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/conftest.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_api_helpers.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_auth.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_cli_basic.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_cli_commands.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_command_decorators.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_command_queue.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_device_capabilities.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_device_info_cache.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_events.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_exceptions.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_model_converters.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_models.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_mqtt_client_init.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_temperature_converters.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tests/test_utils.py +0 -0
- {nwp500_python-7.3.1 → nwp500_python-7.3.2}/tox.ini +0 -0
|
@@ -2,6 +2,27 @@
|
|
|
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
|
+
|
|
5
26
|
Version 7.3.1 (2026-01-25)
|
|
6
27
|
==========================
|
|
7
28
|
|
|
@@ -50,7 +50,7 @@ class NavienAPIClient:
|
|
|
50
50
|
auth_client: NavienAuthClient,
|
|
51
51
|
base_url: str = API_BASE_URL,
|
|
52
52
|
session: aiohttp.ClientSession | None = None,
|
|
53
|
-
unit_system: Literal["metric", "
|
|
53
|
+
unit_system: Literal["metric", "us_customary"] | None = None,
|
|
54
54
|
):
|
|
55
55
|
"""
|
|
56
56
|
Initialize Navien API client.
|
|
@@ -63,7 +63,8 @@ class NavienAPIClient:
|
|
|
63
63
|
provided)
|
|
64
64
|
unit_system: Preferred unit system:
|
|
65
65
|
- "metric": Celsius, LPM, Liters
|
|
66
|
-
- "
|
|
66
|
+
- "us_customary": Fahrenheit, GPM, Gallons
|
|
67
|
+
|
|
67
68
|
- None: Auto-detect from device (default)
|
|
68
69
|
|
|
69
70
|
Raises:
|
|
@@ -289,7 +289,7 @@ class NavienAuthClient:
|
|
|
289
289
|
session: aiohttp.ClientSession | None = None,
|
|
290
290
|
timeout: int = 30,
|
|
291
291
|
stored_tokens: AuthTokens | None = None,
|
|
292
|
-
unit_system: Literal["metric", "
|
|
292
|
+
unit_system: Literal["metric", "us_customary"] | None = None,
|
|
293
293
|
):
|
|
294
294
|
"""
|
|
295
295
|
Initialize the authentication client.
|
|
@@ -304,7 +304,8 @@ class NavienAuthClient:
|
|
|
304
304
|
If provided and valid, skips initial sign_in.
|
|
305
305
|
unit_system: Preferred unit system:
|
|
306
306
|
- "metric": Celsius, LPM, Liters
|
|
307
|
-
- "
|
|
307
|
+
- "us_customary": Fahrenheit, GPM, Gallons
|
|
308
|
+
|
|
308
309
|
- None: Auto-detect from device (default)
|
|
309
310
|
|
|
310
311
|
Note:
|
|
@@ -129,8 +129,8 @@ def async_command(f: Any) -> Any:
|
|
|
129
129
|
)
|
|
130
130
|
@click.option(
|
|
131
131
|
"--unit-system",
|
|
132
|
-
type=click.Choice(["metric", "
|
|
133
|
-
help="Unit system: metric (C/LPM/L) or
|
|
132
|
+
type=click.Choice(["metric", "us_customary"], case_sensitive=False),
|
|
133
|
+
help="Unit system: metric (C/LPM/L) or us_customary (F/GPM/gal)",
|
|
134
134
|
)
|
|
135
135
|
@click.option("-v", "--verbose", count=True, help="Increase verbosity")
|
|
136
136
|
@click.version_option(version=__version__)
|
|
@@ -16,7 +16,7 @@ import json
|
|
|
16
16
|
import logging
|
|
17
17
|
import uuid
|
|
18
18
|
from collections.abc import Callable
|
|
19
|
-
from typing import TYPE_CHECKING, Any,
|
|
19
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
20
20
|
|
|
21
21
|
from awscrt import mqtt
|
|
22
22
|
from awscrt.exceptions import AwsCrtError
|
|
@@ -31,15 +31,7 @@ from ..exceptions import (
|
|
|
31
31
|
MqttPublishError,
|
|
32
32
|
TokenRefreshError,
|
|
33
33
|
)
|
|
34
|
-
from ..unit_system import set_unit_system
|
|
35
|
-
|
|
36
|
-
if TYPE_CHECKING:
|
|
37
|
-
from ..models import (
|
|
38
|
-
Device,
|
|
39
|
-
DeviceFeature,
|
|
40
|
-
DeviceStatus,
|
|
41
|
-
EnergyUsageResponse,
|
|
42
|
-
)
|
|
34
|
+
from ..unit_system import UnitSystemType, set_unit_system
|
|
43
35
|
from .command_queue import MqttCommandQueue
|
|
44
36
|
from .connection import MqttConnection
|
|
45
37
|
from .control import MqttDeviceController
|
|
@@ -52,6 +44,14 @@ from .utils import (
|
|
|
52
44
|
PeriodicRequestType,
|
|
53
45
|
)
|
|
54
46
|
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
from ..models import (
|
|
49
|
+
Device,
|
|
50
|
+
DeviceFeature,
|
|
51
|
+
DeviceStatus,
|
|
52
|
+
EnergyUsageResponse,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
55
|
__author__ = "Emmanuel Levijarvi"
|
|
56
56
|
__copyright__ = "Emmanuel Levijarvi"
|
|
57
57
|
__license__ = "MIT"
|
|
@@ -136,7 +136,7 @@ class NavienMqttClient(EventEmitter):
|
|
|
136
136
|
self,
|
|
137
137
|
auth_client: NavienAuthClient,
|
|
138
138
|
config: MqttConnectionConfig | None = None,
|
|
139
|
-
unit_system:
|
|
139
|
+
unit_system: UnitSystemType = None,
|
|
140
140
|
):
|
|
141
141
|
"""
|
|
142
142
|
Initialize the MQTT client.
|
|
@@ -146,7 +146,8 @@ class NavienMqttClient(EventEmitter):
|
|
|
146
146
|
config: Optional connection configuration
|
|
147
147
|
unit_system: Preferred unit system:
|
|
148
148
|
- "metric": Celsius, LPM, Liters
|
|
149
|
-
- "
|
|
149
|
+
- "us_customary": Fahrenheit, GPM, Gallons
|
|
150
|
+
|
|
150
151
|
- None: Auto-detect from device (default)
|
|
151
152
|
|
|
152
153
|
Raises:
|
|
@@ -184,7 +185,7 @@ class NavienMqttClient(EventEmitter):
|
|
|
184
185
|
set_unit_system(unit_system)
|
|
185
186
|
|
|
186
187
|
self._auth_client = auth_client
|
|
187
|
-
self._unit_system:
|
|
188
|
+
self._unit_system: UnitSystemType = unit_system
|
|
188
189
|
self.config = config or MqttConnectionConfig()
|
|
189
190
|
|
|
190
191
|
# Session tracking
|
|
@@ -15,7 +15,7 @@ import asyncio
|
|
|
15
15
|
import json
|
|
16
16
|
import logging
|
|
17
17
|
from collections.abc import Callable
|
|
18
|
-
from typing import TYPE_CHECKING, Any
|
|
18
|
+
from typing import TYPE_CHECKING, Any
|
|
19
19
|
|
|
20
20
|
from awscrt import mqtt
|
|
21
21
|
from awscrt.exceptions import AwsCrtError
|
|
@@ -25,7 +25,7 @@ from ..events import EventEmitter
|
|
|
25
25
|
from ..exceptions import MqttNotConnectedError
|
|
26
26
|
from ..models import Device, DeviceFeature, DeviceStatus, EnergyUsageResponse
|
|
27
27
|
from ..topic_builder import MqttTopicBuilder
|
|
28
|
-
from ..unit_system import set_unit_system
|
|
28
|
+
from ..unit_system import UnitSystemType, set_unit_system
|
|
29
29
|
from .utils import redact_topic, topic_matches_pattern
|
|
30
30
|
|
|
31
31
|
if TYPE_CHECKING:
|
|
@@ -55,7 +55,7 @@ class MqttSubscriptionManager:
|
|
|
55
55
|
event_emitter: EventEmitter,
|
|
56
56
|
schedule_coroutine: Callable[[Any], None],
|
|
57
57
|
device_info_cache: MqttDeviceInfoCache | None = None,
|
|
58
|
-
unit_system:
|
|
58
|
+
unit_system: UnitSystemType = None,
|
|
59
59
|
):
|
|
60
60
|
"""
|
|
61
61
|
Initialize subscription manager.
|
|
@@ -67,14 +67,15 @@ class MqttSubscriptionManager:
|
|
|
67
67
|
schedule_coroutine: Function to schedule async tasks
|
|
68
68
|
device_info_cache: Optional MqttDeviceInfoCache for caching device
|
|
69
69
|
features
|
|
70
|
-
unit_system: Preferred unit system ("metric", "
|
|
70
|
+
unit_system: Preferred unit system ("metric", "us_customary",
|
|
71
|
+
or None)
|
|
71
72
|
"""
|
|
72
73
|
self._connection = connection
|
|
73
74
|
self._client_id = client_id
|
|
74
75
|
self._event_emitter = event_emitter
|
|
75
76
|
self._schedule_coroutine = schedule_coroutine
|
|
76
77
|
self._device_info_cache = device_info_cache
|
|
77
|
-
self._unit_system:
|
|
78
|
+
self._unit_system: UnitSystemType = unit_system
|
|
78
79
|
|
|
79
80
|
# Track subscriptions and handlers
|
|
80
81
|
self._subscriptions: dict[str, mqtt.QoS] = {}
|
|
@@ -22,16 +22,19 @@ __license__ = "MIT"
|
|
|
22
22
|
|
|
23
23
|
_logger = logging.getLogger(__name__)
|
|
24
24
|
|
|
25
|
+
# Type alias for unit system preference
|
|
26
|
+
UnitSystemType = Literal["metric", "us_customary"] | None
|
|
27
|
+
|
|
25
28
|
# Context variable to store the preferred unit system
|
|
26
29
|
# None means auto-detect from device
|
|
27
|
-
# "metric" means Celsius, "
|
|
30
|
+
# "metric" means Celsius, "us_customary" means Fahrenheit
|
|
28
31
|
_unit_system_context: contextvars.ContextVar[
|
|
29
|
-
Literal["metric", "
|
|
32
|
+
Literal["metric", "us_customary"] | None
|
|
30
33
|
] = contextvars.ContextVar("unit_system", default=None)
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
def set_unit_system(
|
|
34
|
-
unit_system: Literal["metric", "
|
|
37
|
+
unit_system: Literal["metric", "us_customary"] | None,
|
|
35
38
|
) -> None:
|
|
36
39
|
"""Set preferred unit system for temperature, flow, and volume conversions.
|
|
37
40
|
|
|
@@ -41,12 +44,12 @@ def set_unit_system(
|
|
|
41
44
|
Args:
|
|
42
45
|
unit_system: Preferred unit system:
|
|
43
46
|
- "metric": Use Celsius, LPM, and Liters
|
|
44
|
-
- "
|
|
47
|
+
- "us_customary": Use Fahrenheit, GPM, and Gallons
|
|
45
48
|
- None: Auto-detect from device's temperature_type (default)
|
|
46
49
|
|
|
47
50
|
Example:
|
|
48
51
|
>>> from nwp500 import set_unit_system
|
|
49
|
-
>>> set_unit_system("
|
|
52
|
+
>>> set_unit_system("us_customary")
|
|
50
53
|
>>> # All values now in F, GPM, Gallons
|
|
51
54
|
>>> set_unit_system(None) # Reset to auto-detect
|
|
52
55
|
|
|
@@ -57,13 +60,13 @@ def set_unit_system(
|
|
|
57
60
|
_unit_system_context.set(unit_system)
|
|
58
61
|
|
|
59
62
|
|
|
60
|
-
def get_unit_system() -> Literal["metric", "
|
|
63
|
+
def get_unit_system() -> Literal["metric", "us_customary"] | None:
|
|
61
64
|
"""Get the currently configured unit system preference.
|
|
62
65
|
|
|
63
66
|
Returns:
|
|
64
67
|
The current unit system preference:
|
|
65
68
|
- "metric": Celsius, LPM, Liters
|
|
66
|
-
- "
|
|
69
|
+
- "us_customary": Fahrenheit, GPM, Gallons
|
|
67
70
|
- None: Auto-detect from device (default)
|
|
68
71
|
"""
|
|
69
72
|
return _unit_system_context.get()
|
|
@@ -79,29 +82,29 @@ def reset_unit_system() -> None:
|
|
|
79
82
|
|
|
80
83
|
|
|
81
84
|
def unit_system_to_temperature_type(
|
|
82
|
-
unit_system: Literal["metric", "
|
|
85
|
+
unit_system: Literal["metric", "us_customary"] | None,
|
|
83
86
|
) -> TemperatureType | None:
|
|
84
87
|
"""Convert unit system preference to TemperatureType enum.
|
|
85
88
|
|
|
86
89
|
Args:
|
|
87
|
-
unit_system: Unit system preference ("metric", "
|
|
90
|
+
unit_system: Unit system preference ("metric", "us_customary", or None)
|
|
88
91
|
|
|
89
92
|
Returns:
|
|
90
93
|
- TemperatureType.CELSIUS for "metric"
|
|
91
|
-
- TemperatureType.FAHRENHEIT for "
|
|
94
|
+
- TemperatureType.FAHRENHEIT for "us_customary"
|
|
92
95
|
- None for None (auto-detect)
|
|
93
96
|
"""
|
|
94
97
|
match unit_system:
|
|
95
98
|
case "metric":
|
|
96
99
|
return TemperatureType.CELSIUS
|
|
97
|
-
case "
|
|
100
|
+
case "us_customary":
|
|
98
101
|
return TemperatureType.FAHRENHEIT
|
|
99
102
|
case None:
|
|
100
103
|
return None
|
|
101
104
|
|
|
102
105
|
|
|
103
106
|
def is_metric_preferred(
|
|
104
|
-
override: Literal["metric", "
|
|
107
|
+
override: Literal["metric", "us_customary"] | None = None,
|
|
105
108
|
) -> bool:
|
|
106
109
|
"""Check if metric (Celsius) is preferred.
|
|
107
110
|
|
|
@@ -113,7 +116,8 @@ def is_metric_preferred(
|
|
|
113
116
|
over the context-configured unit system.
|
|
114
117
|
|
|
115
118
|
Returns:
|
|
116
|
-
True if metric (Celsius) is preferred, False if
|
|
119
|
+
True if metric (Celsius) is preferred, False if us_customary
|
|
120
|
+
(Fahrenheit).
|
|
117
121
|
"""
|
|
118
122
|
# If override is provided, use it
|
|
119
123
|
if override is not None:
|
|
@@ -353,8 +353,8 @@ def test_unit_system_context_override_affects_field_units():
|
|
|
353
353
|
assert feature.get_field_unit("freeze_protection_temp_min") == " °C"
|
|
354
354
|
assert feature.get_field_unit("recirc_temperature_min") == " °C"
|
|
355
355
|
|
|
356
|
-
# Test 3: Override to
|
|
357
|
-
set_unit_system("
|
|
356
|
+
# Test 3: Override to us_customary - should return Fahrenheit units
|
|
357
|
+
set_unit_system("us_customary")
|
|
358
358
|
assert feature.get_field_unit("dhw_temperature_min") == " °F"
|
|
359
359
|
assert feature.get_field_unit("freeze_protection_temp_min") == " °F"
|
|
360
360
|
assert feature.get_field_unit("recirc_temperature_min") == " °F"
|
|
@@ -478,8 +478,8 @@ def test_unit_system_context_override_with_flow_rate_units():
|
|
|
478
478
|
set_unit_system("metric")
|
|
479
479
|
assert status.get_field_unit("current_dhw_flow_rate") == " LPM"
|
|
480
480
|
|
|
481
|
-
# Test 3: Override to
|
|
482
|
-
set_unit_system("
|
|
481
|
+
# Test 3: Override to us_customary - should return GPM units
|
|
482
|
+
set_unit_system("us_customary")
|
|
483
483
|
assert status.get_field_unit("current_dhw_flow_rate") == " GPM"
|
|
484
484
|
|
|
485
485
|
# Clean up
|
|
@@ -601,8 +601,8 @@ def test_unit_system_context_override_with_volume_units():
|
|
|
601
601
|
set_unit_system("metric")
|
|
602
602
|
assert status.get_field_unit("cumulated_dhw_flow_rate") == " L"
|
|
603
603
|
|
|
604
|
-
# Test 3: Override to
|
|
605
|
-
set_unit_system("
|
|
604
|
+
# Test 3: Override to us_customary - should return Gallons units
|
|
605
|
+
set_unit_system("us_customary")
|
|
606
606
|
assert status.get_field_unit("cumulated_dhw_flow_rate") == " gal"
|
|
607
607
|
|
|
608
608
|
# Clean up
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/legacy_auth_constructor.py
RENAMED
|
File without changes
|
{nwp500_python-7.3.1 → nwp500_python-7.3.2}/examples/intermediate/mqtt_realtime_monitoring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|