nwp500-python 6.0.2__tar.gz → 6.0.3__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.
Files changed (139) hide show
  1. nwp500_python-6.0.3/.agent/workflows/pre-completion-testing.md +73 -0
  2. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/CHANGELOG.rst +83 -0
  3. {nwp500_python-6.0.2/src/nwp500_python.egg-info → nwp500_python-6.0.3}/PKG-INFO +13 -106
  4. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/README.rst +11 -105
  5. nwp500_python-6.0.3/docs/api/nwp500.rst +157 -0
  6. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/configuration.rst +10 -58
  7. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/advanced_features_explained.rst +18 -18
  8. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/auto_recovery.rst +1 -1
  9. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/energy_monitoring.rst +26 -26
  10. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/event_system.rst +30 -30
  11. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/index.rst +15 -12
  12. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/data_conversions.rst +15 -10
  13. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/device_features.rst +6 -1
  14. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/device_status.rst +19 -14
  15. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/error_codes.rst +5 -1
  16. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/firmware_tracking.rst +37 -7
  17. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/mqtt_protocol.rst +12 -13
  18. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/protocol/rest_api.rst +6 -2
  19. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/constants.rst +1 -1
  20. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/events.rst +4 -4
  21. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/models.rst +150 -150
  22. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/mqtt_client.rst +40 -40
  23. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/quickstart.rst +4 -4
  24. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/combined_callbacks.py +11 -9
  25. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/device_feature_callback.py +19 -19
  26. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/device_status_callback.py +22 -20
  27. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/device_status_callback_debug.py +3 -3
  28. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/energy_usage_example.py +6 -6
  29. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/event_emitter_demo.py +4 -4
  30. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/improved_auth_pattern.py +3 -3
  31. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/mqtt_client_example.py +9 -9
  32. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/periodic_device_info.py +4 -4
  33. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/periodic_requests.py +6 -6
  34. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/power_control_example.py +5 -5
  35. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/reconnection_demo.py +1 -1
  36. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/reservation_schedule_example.py +2 -1
  37. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/set_dhw_temperature_example.py +6 -6
  38. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/set_mode_example.py +4 -4
  39. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/simple_auto_recovery.py +2 -2
  40. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/simple_periodic_info.py +1 -1
  41. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/simple_periodic_status.py +3 -1
  42. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/test_periodic_minimal.py +2 -2
  43. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/token_restoration_example.py +6 -5
  44. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/tou_openei_example.py +1 -1
  45. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/tou_schedule_example.py +6 -5
  46. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/scripts/bump_version.py +73 -39
  47. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/scripts/format.py +35 -15
  48. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/scripts/lint.py +35 -15
  49. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/scripts/setup-dev.py +15 -12
  50. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/setup.cfg +1 -0
  51. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/__init__.py +3 -3
  52. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/api_client.py +8 -6
  53. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/auth.py +75 -124
  54. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/cli/commands.py +3 -3
  55. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/cli/monitoring.py +2 -2
  56. nwp500_python-6.0.3/src/nwp500/models.py +479 -0
  57. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_client.py +25 -61
  58. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_subscriptions.py +31 -90
  59. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_utils.py +57 -0
  60. {nwp500_python-6.0.2 → nwp500_python-6.0.3/src/nwp500_python.egg-info}/PKG-INFO +13 -106
  61. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500_python.egg-info/SOURCES.txt +2 -0
  62. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500_python.egg-info/requires.txt +1 -0
  63. nwp500_python-6.0.2/src/nwp500/models.py +0 -983
  64. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.coveragerc +0 -0
  65. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.github/copilot-instructions.md +0 -0
  66. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.github/workflows/ci.yml +0 -0
  67. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.github/workflows/release.yml +0 -0
  68. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.gitignore +0 -0
  69. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.pre-commit-config.yaml +0 -0
  70. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/.readthedocs.yml +0 -0
  71. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/AUTHORS.rst +0 -0
  72. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/CONTRIBUTING.rst +0 -0
  73. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/LICENSE.txt +0 -0
  74. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/Makefile +0 -0
  75. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/RELEASE.md +0 -0
  76. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/Makefile +0 -0
  77. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/_static/.gitignore +0 -0
  78. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/authors.rst +0 -0
  79. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/changelog.rst +0 -0
  80. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/conf.py +0 -0
  81. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/development/contributing.rst +0 -0
  82. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/development/history.rst +0 -0
  83. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/command_queue.rst +0 -0
  84. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/reservations.rst +0 -0
  85. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/scheduling_features.rst +0 -0
  86. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/guides/time_of_use.rst +0 -0
  87. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/installation.rst +0 -0
  88. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/license.rst +0 -0
  89. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/openapi.yaml +0 -0
  90. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/api_client.rst +0 -0
  91. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/auth_client.rst +0 -0
  92. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/cli.rst +0 -0
  93. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/python_api/exceptions.rst +0 -0
  94. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/docs/requirements.txt +0 -0
  95. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/.ruff.toml +0 -0
  96. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/README.md +0 -0
  97. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/anti_legionella_example.py +0 -0
  98. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/api_client_example.py +0 -0
  99. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/auth_constructor_example.py +0 -0
  100. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/authenticate.py +0 -0
  101. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/auto_recovery_example.py +0 -0
  102. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/command_queue_demo.py +0 -0
  103. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/exception_handling_example.py +0 -0
  104. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/mask.py +0 -0
  105. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/test_api_client.py +0 -0
  106. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/test_mqtt_connection.py +0 -0
  107. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/examples/test_mqtt_messaging.py +0 -0
  108. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/pyproject.toml +0 -0
  109. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/scripts/README.md +0 -0
  110. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/scripts/validate_version.py +0 -0
  111. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/setup.py +0 -0
  112. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/cli/__init__.py +0 -0
  113. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/cli/__main__.py +0 -0
  114. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/cli/output_formatters.py +0 -0
  115. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/cli/token_storage.py +0 -0
  116. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/config.py +0 -0
  117. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/constants.py +0 -0
  118. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/encoding.py +0 -0
  119. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/events.py +0 -0
  120. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/exceptions.py +0 -0
  121. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_command_queue.py +0 -0
  122. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_connection.py +0 -0
  123. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_device_control.py +0 -0
  124. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_periodic.py +0 -0
  125. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/mqtt_reconnection.py +0 -0
  126. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/py.typed +0 -0
  127. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500/utils.py +0 -0
  128. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
  129. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500_python.egg-info/entry_points.txt +0 -0
  130. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500_python.egg-info/not-zip-safe +0 -0
  131. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/src/nwp500_python.egg-info/top_level.txt +0 -0
  132. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/conftest.py +0 -0
  133. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/test_api_helpers.py +0 -0
  134. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/test_auth.py +0 -0
  135. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/test_command_queue.py +0 -0
  136. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/test_events.py +0 -0
  137. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/test_exceptions.py +0 -0
  138. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tests/test_utils.py +0 -0
  139. {nwp500_python-6.0.2 → nwp500_python-6.0.3}/tox.ini +0 -0
@@ -0,0 +1,73 @@
1
+ ---
2
+ description: Run linting and testing before completing tasks
3
+ ---
4
+
5
+ # Pre-Completion Testing Workflow
6
+
7
+ Before marking any code-related task as complete, you MUST run the following checks:
8
+
9
+ ## 1. Linting with Ruff
10
+
11
+ Run ruff to check for code style and quality issues:
12
+
13
+ ```bash
14
+ ruff check src/ tests/ examples/
15
+ ```
16
+
17
+ If there are any errors, fix them before proceeding. You can auto-fix many issues with:
18
+
19
+ ```bash
20
+ ruff check --fix src/ tests/ examples/
21
+ ```
22
+
23
+ ## 2. Format Check with Ruff
24
+
25
+ Verify code formatting is correct:
26
+
27
+ ```bash
28
+ ruff format --check src/ tests/ examples/
29
+ ```
30
+
31
+ If formatting issues are found, apply formatting:
32
+
33
+ ```bash
34
+ ruff format src/ tests/ examples/
35
+ ```
36
+
37
+ ## 3. Run Unit Tests
38
+
39
+ Execute the test suite to ensure no regressions:
40
+
41
+ ```bash
42
+ pytest tests/
43
+ ```
44
+
45
+ All tests must pass before completing the task.
46
+
47
+ ## 4. Type Checking (Optional but Recommended)
48
+
49
+ If you've modified type annotations or core logic, run mypy:
50
+
51
+ ```bash
52
+ mypy src/
53
+ ```
54
+
55
+ ## Summary
56
+
57
+ **Required before task completion:**
58
+ - ✅ Ruff linting passes (no errors)
59
+ - ✅ Ruff formatting check passes
60
+ - ✅ All pytest tests pass
61
+
62
+ **Recommended:**
63
+ - ✅ Mypy type checking passes (if types were modified)
64
+
65
+ ## Quick Command
66
+
67
+ You can run all checks with:
68
+
69
+ ```bash
70
+ ruff check src/ tests/ examples/ && ruff format --check src/ tests/ examples/ && pytest tests/
71
+ ```
72
+
73
+ **IMPORTANT**: Do not claim a task is complete without running these checks. If any check fails, fix the issues and re-run the checks.
@@ -2,6 +2,89 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ Version 6.0.3 (2025-11-20)
6
+ ==========================
7
+
8
+ **BREAKING CHANGES**: Migration from custom dataclass-based models to Pydantic BaseModel implementations with automatic field validation and alias handling.
9
+
10
+ Removed
11
+ -------
12
+
13
+ - Removed legacy dataclass implementations for models (DeviceInfo, Location, Device, FirmwareInfo, DeviceStatus, DeviceFeature, EnergyUsage*). All models now inherit from ``NavienBaseModel`` (Pydantic).
14
+ - Removed manual ``from_dict`` constructors relying on camelCase key mapping logic.
15
+ - Removed field metadata conversion system (``meta()`` + ``apply_field_conversions()``) in favor of Pydantic ``BeforeValidator`` pipeline.
16
+
17
+ Changed
18
+ -------
19
+
20
+ - Models now use snake_case attribute names consistently; camelCase keys from API/MQTT are mapped automatically via Pydantic ``alias_generator=to_camel``.
21
+ - Boolean device fields now validated via ``DeviceBool`` Annotated type (device value 2 -> True, 0/1 -> False) replacing manual conversion code.
22
+ - Temperature offset (+20), scale division (/10) and decicelsius-to-Fahrenheit conversions implemented with lightweight ``BeforeValidator`` functions (``Add20``, ``Div10``, ``DeciCelsiusToF``) instead of post-processing.
23
+ - Enum parsing now handled directly by Pydantic; unknown values default safely via explicit Field defaults instead of try/except conversion loops.
24
+ - Field names updated (examples & docs) to snake_case: e.g. ``operationMode`` -> ``operation_mode``, ``dhwTemperatureSetting`` -> ``dhw_temperature_setting``.
25
+ - API typo handled using Field alias (``heLowerOnTDiffempSetting`` -> ``he_lower_on_diff_temp_setting``) rather than custom dictionary mutation.
26
+ - DeviceStatus conversion now performed on parse instead of separate transformation step, improving performance and reducing memory copies.
27
+ - Improved validation error messages from Pydantic on malformed payloads.
28
+ - Simplified energy usage model accessors; removed manual percentage methods duplication.
29
+
30
+ Added
31
+ -----
32
+
33
+ - Introduced ``NavienBaseModel`` configuring alias generation, population by name, and ignoring unknown fields for forward compatibility.
34
+ - Added structured Annotated types: ``DeviceBool``, ``Add20``, ``Div10``, ``DeciCelsiusToF`` for declarative conversion definitions.
35
+ - Added consistent default enum values directly in field declarations (e.g. ``operation_mode=STANDBY``).
36
+
37
+ Migration Guide (v6.0.2 -> v6.0.3)
38
+ ----------------------------------
39
+
40
+ 1. Replace any imports of dataclass models with Pydantic versions (paths unchanged). No code change required if you only accessed attributes.
41
+ 2. Remove calls to ``Model.from_dict(data)``: Either use ``Model.model_validate(data)`` or continue calling ``from_dict`` where still provided (thin wrapper for backward compatibility on some classes). Preferred: ``DeviceStatus.model_validate(raw_payload)``.
42
+ 3. Update attribute access to snake_case. Common mappings:
43
+ - ``deviceInfo.macAddress`` -> ``device.device_info.mac_address``
44
+ - ``deviceStatus.operationMode`` -> ``status.operation_mode``
45
+ - ``deviceStatus.dhwTemperatureSetting`` -> ``status.dhw_temperature_setting``
46
+ - ``deviceStatus.currentInletTemperature`` -> ``status.current_inlet_temperature``
47
+ 4. Remove manual conversion code. Raw numeric values are converted automatically; stop adding +20 or dividing by 10 in user code.
48
+ 5. Stop performing boolean normalization (``value == 2``) manually; attributes already return proper bools.
49
+ 6. For enum handling, remove try/except wrappers; rely on defaulted fields (e.g. ``operation_mode`` defaults to ``STANDBY``).
50
+ 7. If you previously mutated raw payload keys to snake_case, eliminate that transformation step.
51
+ 8. If you logged intermediate converted dictionaries, you can access ``model.model_dump()`` for a fully converted representation.
52
+ 9. Replace any custom validation logic with Pydantic validators or continue using existing patterns; most prior validation code is now unnecessary.
53
+ 10. Energy usage: Access percentages via properties unchanged; object types now Pydantic models.
54
+
55
+ Quick Example
56
+ ~~~~~~~~~~~~~
57
+
58
+ .. code-block:: python
59
+
60
+ # OLD (v6.0.2)
61
+ raw = mqtt_payload["deviceStatus"]
62
+ converted = apply_field_conversions(DeviceStatus, raw)
63
+ status = DeviceStatus(**converted)
64
+ print(converted["dhwTemperatureSetting"] + 20) # manual offset
65
+
66
+ # NEW (v6.0.3)
67
+ status = DeviceStatus.model_validate(mqtt_payload["deviceStatus"])
68
+ print(status.dhw_temperature_setting) # already includes +20 offset
69
+
70
+ # OLD boolean and enum handling
71
+ is_heating = converted["currentHeatUse"] == 2
72
+ mode = CurrentOperationMode(converted["operationMode"]) if converted["operationMode"] in (0,32,64,96) else CurrentOperationMode.STANDBY
73
+
74
+ # NEW simplified
75
+ is_heating = status.current_heat_use
76
+ mode = status.operation_mode
77
+
78
+ Benefits
79
+ ~~~~~~~~
80
+
81
+ - Declarative conversions reduce 400+ lines of imperative transformation logic.
82
+ - Improved performance (single parse vs copy + transform).
83
+ - Automatic camelCase key mapping; less brittle than manual dict key copying.
84
+ - Rich validation errors for debugging malformed device messages.
85
+ - Cleaner, shorter model definitions with clearer intent.
86
+ - Easier extension: add new fields with conversion by combining Annotated + validator.
87
+
5
88
  Version 6.0.2 (2025-11-15)
6
89
  ==========================
7
90
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nwp500-python
3
- Version: 6.0.2
3
+ Version: 6.0.3
4
4
  Summary: A library for controlling Navien NWP500 Water Heaters via NaviLink
5
5
  Home-page: https://github.com/eman/nwp500-python
6
6
  Author: Emmanuel Levijarvi
@@ -24,6 +24,7 @@ Description-Content-Type: text/x-rst; charset=UTF-8
24
24
  License-File: LICENSE.txt
25
25
  Requires-Dist: aiohttp>=3.8.0
26
26
  Requires-Dist: awsiotsdk>=1.26.0
27
+ Requires-Dist: pydantic>=2.0.0
27
28
  Provides-Extra: testing
28
29
  Requires-Dist: setuptools; extra == "testing"
29
30
  Requires-Dist: pytest; extra == "testing"
@@ -52,19 +53,15 @@ A Python library for monitoring and controlling the Navien NWP500 Heat Pump Wate
52
53
 
53
54
  Features
54
55
  ========
56
+ * Monitor status (temperature, power, charge %)
57
+ * Set target water temperature
58
+ * Change operation mode
59
+ * Optional scheduling (reservations)
60
+ * Optional time-of-use settings
61
+ * Periodic high-temp cycle info
62
+ * Access detailed status fields
55
63
 
56
- * **Device Monitoring**: Access real-time status information including temperatures, power consumption, and tank charge level
57
- * **Temperature Control**: Set target water temperature (90-151°F)
58
- * **Operation Mode Control**: Switch between Heat Pump, Energy Saver, High Demand, Electric, and Vacation modes
59
- * **Reservation Management**: Schedule automatic temperature and mode changes
60
- * **Time of Use (TOU)**: Configure energy pricing schedules for demand response
61
- * **Anti-Legionella Protection**: Monitor periodic disinfection cycles (140°F heating)
62
- * **Comprehensive Status Data**: Access to 70+ device status fields including compressor status, heater status, flow rates, and more
63
- * **MQTT Protocol Support**: Low-level MQTT communication with Navien devices
64
- * **Non-Blocking Async Operations**: Fully compatible with async event loops (Home Assistant safe)
65
- * **Automatic Reconnection**: Reconnects automatically with exponential backoff during network interruptions
66
- * **Command Queuing**: Commands sent while disconnected are queued and sent automatically when reconnected
67
- * **Data Models**: Type-safe data classes with automatic unit conversions
64
+ * Async friendly
68
65
 
69
66
  Quick Start
70
67
  ===========
@@ -158,8 +155,8 @@ The library includes a command line interface for quick monitoring and device in
158
155
  **Available CLI Options:**
159
156
 
160
157
  * ``--status``: Print current device status as JSON. Can be combined with control commands to see updated status.
161
- * ``--device-info``: Print comprehensive device information (firmware, model, capabilities) via MQTT as JSON and exit
162
- * ``--device-feature``: Print device capabilities and feature settings via MQTT as JSON and exit
158
+ * ``--device-info``: Print comprehensive device information (firmware, model, capabilities) as JSON and exit
159
+ * ``--device-feature``: Print device capabilities and feature settings as JSON and exit
163
160
  * ``--power-on``: Turn the device on and display response
164
161
  * ``--power-off``: Turn the device off and display response
165
162
  * ``--set-mode MODE``: Set operation mode and display response. Valid modes: heat-pump, energy-saver, high-demand, electric, vacation, standby
@@ -200,63 +197,10 @@ The library provides access to comprehensive device status information:
200
197
  * Cumulative operation time
201
198
  * Flow rates
202
199
 
203
- Operation Modes
204
- ===============
205
-
206
- .. list-table:: Operation Modes
207
- :header-rows: 1
208
- :widths: 25 10 65
209
-
210
- * - Mode
211
- - ID
212
- - Description
213
- * - Heat Pump Mode
214
- - 1
215
- - Most energy-efficient mode using only the heat pump. Longest recovery time.
216
- * - Electric Mode
217
- - 2
218
- - Fastest recovery using only electric heaters. Least energy-efficient.
219
- * - Energy Saver Mode
220
- - 3
221
- - Default mode. Balances efficiency and recovery time using both heat pump and electric heater.
222
- * - High Demand Mode
223
- - 4
224
- - Uses electric heater more frequently for faster recovery time.
225
- * - Vacation Mode
226
- - 5
227
- - Suspends heating to save energy during extended absences.
228
-
229
- **Important:** When you set a mode, you're configuring the ``dhwOperationSetting`` (what mode to use when heating). The device's current operational state is reported in ``operationMode`` (0=Standby, 32=Heat Pump active, 64=Energy Saver active, 96=High Demand active).
230
-
231
- MQTT Protocol
232
- =============
233
-
234
- The library supports low-level MQTT communication with Navien devices:
235
-
236
- **Control Topics**
237
- * ``cmd/{deviceType}/{deviceId}/ctrl`` - Send control commands
238
- * ``cmd/{deviceType}/{deviceId}/ctrl/rsv/rd`` - Manage reservations
239
- * ``cmd/{deviceType}/{deviceId}/ctrl/tou/rd`` - Time of Use settings
240
- * ``cmd/{deviceType}/{deviceId}/st`` - Request status updates
241
-
242
- **Control Commands**
243
- * Power control (on/off)
244
- * DHW mode changes (including vacation mode)
245
- * Temperature settings
246
- * Reservation management (scheduled mode/temperature changes)
247
- * Time of Use (TOU) pricing schedules
248
-
249
- **Status Requests**
250
- * Device information
251
- * General device status
252
- * Energy usage queries
253
- * Reservation information
254
- * TOU settings
255
-
256
200
  Documentation
257
201
  =============
258
202
 
259
- For detailed information on device status fields, MQTT protocol, authentication, and more, see the complete documentation at https://nwp500-python.readthedocs.io/
203
+ Full docs: https://nwp500-python.readthedocs.io/
260
204
 
261
205
  Data Models
262
206
  ===========
@@ -267,12 +211,6 @@ The library includes type-safe data models with automatic unit conversions:
267
211
  * **DeviceFeature**: Device capabilities, firmware versions, and configuration limits
268
212
  * **OperationMode**: Enumeration of available operation modes
269
213
  * **TemperatureUnit**: Celsius/Fahrenheit handling
270
- * **MqttRequest/MqttCommand**: MQTT message structures
271
-
272
- Temperature conversions are handled automatically:
273
- * DHW temperatures: ``raw_value + 20`` (°F)
274
- * Heat pump temperatures: ``raw_value / 10.0`` (°F)
275
- * Ambient temperature: ``(raw_value * 9/5) + 32`` (°F)
276
214
 
277
215
  Requirements
278
216
  ============
@@ -284,37 +222,6 @@ Requirements
284
222
  * pydantic >= 2.0.0
285
223
  * awsiotsdk >= 1.21.0
286
224
 
287
- Development
288
- ===========
289
- To set up a development environment:
290
-
291
- .. code-block:: bash
292
-
293
- # Clone the repository
294
- git clone https://github.com/eman/nwp500-python.git
295
- cd nwp500-python
296
-
297
- # Install in development mode
298
- pip install -e .
299
-
300
- # Run tests
301
- pytest
302
-
303
- **Linting and CI Consistency**
304
-
305
- To ensure your local linting matches CI exactly:
306
-
307
- .. code-block:: bash
308
-
309
- # Install tox (recommended)
310
- pip install tox
311
-
312
- # Run linting exactly as CI does
313
- tox -e lint
314
-
315
- # Auto-fix and format
316
- tox -e format
317
-
318
225
  License
319
226
  =======
320
227
 
@@ -13,19 +13,15 @@ A Python library for monitoring and controlling the Navien NWP500 Heat Pump Wate
13
13
 
14
14
  Features
15
15
  ========
16
+ * Monitor status (temperature, power, charge %)
17
+ * Set target water temperature
18
+ * Change operation mode
19
+ * Optional scheduling (reservations)
20
+ * Optional time-of-use settings
21
+ * Periodic high-temp cycle info
22
+ * Access detailed status fields
16
23
 
17
- * **Device Monitoring**: Access real-time status information including temperatures, power consumption, and tank charge level
18
- * **Temperature Control**: Set target water temperature (90-151°F)
19
- * **Operation Mode Control**: Switch between Heat Pump, Energy Saver, High Demand, Electric, and Vacation modes
20
- * **Reservation Management**: Schedule automatic temperature and mode changes
21
- * **Time of Use (TOU)**: Configure energy pricing schedules for demand response
22
- * **Anti-Legionella Protection**: Monitor periodic disinfection cycles (140°F heating)
23
- * **Comprehensive Status Data**: Access to 70+ device status fields including compressor status, heater status, flow rates, and more
24
- * **MQTT Protocol Support**: Low-level MQTT communication with Navien devices
25
- * **Non-Blocking Async Operations**: Fully compatible with async event loops (Home Assistant safe)
26
- * **Automatic Reconnection**: Reconnects automatically with exponential backoff during network interruptions
27
- * **Command Queuing**: Commands sent while disconnected are queued and sent automatically when reconnected
28
- * **Data Models**: Type-safe data classes with automatic unit conversions
24
+ * Async friendly
29
25
 
30
26
  Quick Start
31
27
  ===========
@@ -119,8 +115,8 @@ The library includes a command line interface for quick monitoring and device in
119
115
  **Available CLI Options:**
120
116
 
121
117
  * ``--status``: Print current device status as JSON. Can be combined with control commands to see updated status.
122
- * ``--device-info``: Print comprehensive device information (firmware, model, capabilities) via MQTT as JSON and exit
123
- * ``--device-feature``: Print device capabilities and feature settings via MQTT as JSON and exit
118
+ * ``--device-info``: Print comprehensive device information (firmware, model, capabilities) as JSON and exit
119
+ * ``--device-feature``: Print device capabilities and feature settings as JSON and exit
124
120
  * ``--power-on``: Turn the device on and display response
125
121
  * ``--power-off``: Turn the device off and display response
126
122
  * ``--set-mode MODE``: Set operation mode and display response. Valid modes: heat-pump, energy-saver, high-demand, electric, vacation, standby
@@ -161,63 +157,10 @@ The library provides access to comprehensive device status information:
161
157
  * Cumulative operation time
162
158
  * Flow rates
163
159
 
164
- Operation Modes
165
- ===============
166
-
167
- .. list-table:: Operation Modes
168
- :header-rows: 1
169
- :widths: 25 10 65
170
-
171
- * - Mode
172
- - ID
173
- - Description
174
- * - Heat Pump Mode
175
- - 1
176
- - Most energy-efficient mode using only the heat pump. Longest recovery time.
177
- * - Electric Mode
178
- - 2
179
- - Fastest recovery using only electric heaters. Least energy-efficient.
180
- * - Energy Saver Mode
181
- - 3
182
- - Default mode. Balances efficiency and recovery time using both heat pump and electric heater.
183
- * - High Demand Mode
184
- - 4
185
- - Uses electric heater more frequently for faster recovery time.
186
- * - Vacation Mode
187
- - 5
188
- - Suspends heating to save energy during extended absences.
189
-
190
- **Important:** When you set a mode, you're configuring the ``dhwOperationSetting`` (what mode to use when heating). The device's current operational state is reported in ``operationMode`` (0=Standby, 32=Heat Pump active, 64=Energy Saver active, 96=High Demand active).
191
-
192
- MQTT Protocol
193
- =============
194
-
195
- The library supports low-level MQTT communication with Navien devices:
196
-
197
- **Control Topics**
198
- * ``cmd/{deviceType}/{deviceId}/ctrl`` - Send control commands
199
- * ``cmd/{deviceType}/{deviceId}/ctrl/rsv/rd`` - Manage reservations
200
- * ``cmd/{deviceType}/{deviceId}/ctrl/tou/rd`` - Time of Use settings
201
- * ``cmd/{deviceType}/{deviceId}/st`` - Request status updates
202
-
203
- **Control Commands**
204
- * Power control (on/off)
205
- * DHW mode changes (including vacation mode)
206
- * Temperature settings
207
- * Reservation management (scheduled mode/temperature changes)
208
- * Time of Use (TOU) pricing schedules
209
-
210
- **Status Requests**
211
- * Device information
212
- * General device status
213
- * Energy usage queries
214
- * Reservation information
215
- * TOU settings
216
-
217
160
  Documentation
218
161
  =============
219
162
 
220
- For detailed information on device status fields, MQTT protocol, authentication, and more, see the complete documentation at https://nwp500-python.readthedocs.io/
163
+ Full docs: https://nwp500-python.readthedocs.io/
221
164
 
222
165
  Data Models
223
166
  ===========
@@ -228,12 +171,6 @@ The library includes type-safe data models with automatic unit conversions:
228
171
  * **DeviceFeature**: Device capabilities, firmware versions, and configuration limits
229
172
  * **OperationMode**: Enumeration of available operation modes
230
173
  * **TemperatureUnit**: Celsius/Fahrenheit handling
231
- * **MqttRequest/MqttCommand**: MQTT message structures
232
-
233
- Temperature conversions are handled automatically:
234
- * DHW temperatures: ``raw_value + 20`` (°F)
235
- * Heat pump temperatures: ``raw_value / 10.0`` (°F)
236
- * Ambient temperature: ``(raw_value * 9/5) + 32`` (°F)
237
174
 
238
175
  Requirements
239
176
  ============
@@ -245,37 +182,6 @@ Requirements
245
182
  * pydantic >= 2.0.0
246
183
  * awsiotsdk >= 1.21.0
247
184
 
248
- Development
249
- ===========
250
- To set up a development environment:
251
-
252
- .. code-block:: bash
253
-
254
- # Clone the repository
255
- git clone https://github.com/eman/nwp500-python.git
256
- cd nwp500-python
257
-
258
- # Install in development mode
259
- pip install -e .
260
-
261
- # Run tests
262
- pytest
263
-
264
- **Linting and CI Consistency**
265
-
266
- To ensure your local linting matches CI exactly:
267
-
268
- .. code-block:: bash
269
-
270
- # Install tox (recommended)
271
- pip install tox
272
-
273
- # Run linting exactly as CI does
274
- tox -e lint
275
-
276
- # Auto-fix and format
277
- tox -e format
278
-
279
185
  License
280
186
  =======
281
187
 
@@ -0,0 +1,157 @@
1
+ nwp500 package
2
+ ==============
3
+
4
+ Subpackages
5
+ -----------
6
+
7
+ .. toctree::
8
+ :maxdepth: 4
9
+
10
+ nwp500.cli
11
+
12
+ Submodules
13
+ ----------
14
+
15
+ nwp500.api\_client module
16
+ -------------------------
17
+
18
+ .. automodule:: nwp500.api_client
19
+ :members:
20
+ :show-inheritance:
21
+ :undoc-members:
22
+
23
+ nwp500.auth module
24
+ ------------------
25
+
26
+ .. automodule:: nwp500.auth
27
+ :members:
28
+ :show-inheritance:
29
+ :undoc-members:
30
+
31
+ nwp500.config module
32
+ --------------------
33
+
34
+ .. automodule:: nwp500.config
35
+ :members:
36
+ :show-inheritance:
37
+ :undoc-members:
38
+
39
+ nwp500.constants module
40
+ -----------------------
41
+
42
+ .. automodule:: nwp500.constants
43
+ :members:
44
+ :show-inheritance:
45
+ :undoc-members:
46
+
47
+ nwp500.encoding module
48
+ ----------------------
49
+
50
+ .. automodule:: nwp500.encoding
51
+ :members:
52
+ :show-inheritance:
53
+ :undoc-members:
54
+
55
+ nwp500.events module
56
+ --------------------
57
+
58
+ .. automodule:: nwp500.events
59
+ :members:
60
+ :show-inheritance:
61
+ :undoc-members:
62
+
63
+ nwp500.exceptions module
64
+ ------------------------
65
+
66
+ .. automodule:: nwp500.exceptions
67
+ :members:
68
+ :show-inheritance:
69
+ :undoc-members:
70
+
71
+ nwp500.models module
72
+ --------------------
73
+
74
+ .. automodule:: nwp500.models
75
+ :members:
76
+ :show-inheritance:
77
+ :undoc-members:
78
+
79
+ nwp500.mqtt\_client module
80
+ --------------------------
81
+
82
+ .. automodule:: nwp500.mqtt_client
83
+ :members:
84
+ :show-inheritance:
85
+ :undoc-members:
86
+
87
+ nwp500.mqtt\_command\_queue module
88
+ ----------------------------------
89
+
90
+ .. automodule:: nwp500.mqtt_command_queue
91
+ :members:
92
+ :show-inheritance:
93
+ :undoc-members:
94
+
95
+ nwp500.mqtt\_connection module
96
+ ------------------------------
97
+
98
+ .. automodule:: nwp500.mqtt_connection
99
+ :members:
100
+ :show-inheritance:
101
+ :undoc-members:
102
+
103
+ nwp500.mqtt\_device\_control module
104
+ -----------------------------------
105
+
106
+ .. automodule:: nwp500.mqtt_device_control
107
+ :members:
108
+ :show-inheritance:
109
+ :undoc-members:
110
+
111
+ nwp500.mqtt\_periodic module
112
+ ----------------------------
113
+
114
+ .. automodule:: nwp500.mqtt_periodic
115
+ :members:
116
+ :show-inheritance:
117
+ :undoc-members:
118
+
119
+ nwp500.mqtt\_reconnection module
120
+ --------------------------------
121
+
122
+ .. automodule:: nwp500.mqtt_reconnection
123
+ :members:
124
+ :show-inheritance:
125
+ :undoc-members:
126
+
127
+ nwp500.mqtt\_subscriptions module
128
+ ---------------------------------
129
+
130
+ .. automodule:: nwp500.mqtt_subscriptions
131
+ :members:
132
+ :show-inheritance:
133
+ :undoc-members:
134
+
135
+ nwp500.mqtt\_utils module
136
+ -------------------------
137
+
138
+ .. automodule:: nwp500.mqtt_utils
139
+ :members:
140
+ :show-inheritance:
141
+ :undoc-members:
142
+
143
+ nwp500.utils module
144
+ -------------------
145
+
146
+ .. automodule:: nwp500.utils
147
+ :members:
148
+ :show-inheritance:
149
+ :undoc-members:
150
+
151
+ Module contents
152
+ ---------------
153
+
154
+ .. automodule:: nwp500
155
+ :members:
156
+ :show-inheritance:
157
+ :undoc-members: