nwp500-python 7.4.10__tar.gz → 8.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.github/workflows/ci.yml +4 -4
  2. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.github/workflows/release.yml +3 -3
  3. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.readthedocs.yml +1 -1
  4. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/CHANGELOG.rst +136 -2
  5. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/CONTRIBUTING.rst +1 -1
  6. nwp500_python-8.0.0/PKG-INFO +120 -0
  7. nwp500_python-8.0.0/README.rst +78 -0
  8. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/docs/conf.py +1 -1
  9. nwp500_python-7.4.10/docs/guides/advanced_features_explained.rst → nwp500_python-8.0.0/docs/explanation/advanced-features.rst +13 -19
  10. nwp500_python-8.0.0/docs/explanation/architecture.rst +81 -0
  11. nwp500_python-8.0.0/docs/explanation/index.rst +11 -0
  12. nwp500_python-7.4.10/docs/guides/auto_recovery.rst → nwp500_python-8.0.0/docs/how-to/auto-recovery.rst +2 -2
  13. nwp500_python-7.4.10/docs/guides/mqtt_diagnostics.rst → nwp500_python-8.0.0/docs/how-to/diagnose-mqtt.rst +34 -34
  14. nwp500_python-7.4.10/docs/guides/home_assistant_integration.rst → nwp500_python-8.0.0/docs/how-to/home-assistant.rst +6 -7
  15. nwp500_python-8.0.0/docs/how-to/index.rst +20 -0
  16. nwp500_python-8.0.0/docs/how-to/maintenance.rst +119 -0
  17. nwp500_python-7.4.10/docs/guides/unit_conversion.rst → nwp500_python-8.0.0/docs/how-to/manage-units.rst +5 -5
  18. nwp500_python-7.4.10/docs/guides/event_system.rst → nwp500_python-8.0.0/docs/how-to/monitor-status.rst +110 -123
  19. nwp500_python-7.4.10/docs/guides/time_of_use.rst → nwp500_python-8.0.0/docs/how-to/optimize-tou.rst +16 -16
  20. nwp500_python-7.4.10/docs/guides/command_queue.rst → nwp500_python-8.0.0/docs/how-to/queue-commands.rst +13 -16
  21. nwp500_python-7.4.10/docs/guides/scheduling.rst → nwp500_python-8.0.0/docs/how-to/schedule-operation.rst +119 -12
  22. nwp500_python-8.0.0/docs/how-to/track-energy.rst +333 -0
  23. nwp500_python-8.0.0/docs/index.rst +64 -0
  24. {nwp500_python-7.4.10/docs/development → nwp500_python-8.0.0/docs/project}/history.rst +14 -13
  25. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/configuration.rst +4 -4
  26. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/enumerations.rst +3 -4
  27. nwp500_python-8.0.0/docs/reference/index.rst +43 -0
  28. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/installation.rst +11 -7
  29. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/data_conversions.rst +6 -6
  30. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/device_features.rst +3 -3
  31. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/device_status.rst +2 -2
  32. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/error_codes.rst +1 -1
  33. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/mqtt_protocol.rst +1 -1
  34. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/quick_reference.rst +1 -1
  35. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/python_api/auth_client.rst +4 -4
  36. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/python_api/cli.rst +3 -3
  37. nwp500_python-8.0.0/docs/reference/python_api/events.rst +287 -0
  38. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/python_api/exceptions.rst +18 -18
  39. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/python_api/models.rst +157 -6
  40. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/python_api/mqtt_client.rst +374 -317
  41. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/docs/requirements.txt +2 -0
  42. nwp500_python-7.4.10/docs/quickstart.rst → nwp500_python-8.0.0/docs/tutorials/getting-started.rst +13 -14
  43. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/air_filter_reset.py +3 -3
  44. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/anti_legionella.py +4 -4
  45. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/combined_callbacks.py +3 -3
  46. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/demand_response.py +3 -3
  47. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/device_capabilities.py +2 -2
  48. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/device_status_debug.py +2 -2
  49. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/energy_analytics.py +1 -1
  50. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/firmware_payload_capture.py +4 -4
  51. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/mqtt_diagnostics.py +11 -13
  52. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/power_control.py +3 -3
  53. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/recirculation_control.py +4 -6
  54. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/reconnection_demo.py +7 -7
  55. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/reservation_schedule.py +2 -2
  56. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/token_restoration.py +1 -1
  57. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/tou_openei.py +1 -1
  58. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/tou_schedule.py +5 -5
  59. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/water_reservation.py +2 -2
  60. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/beginner/04_set_temperature.py +2 -2
  61. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/advanced_auth_patterns.py +1 -1
  62. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/command_queue.py +8 -8
  63. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/device_status_callback.py +2 -2
  64. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/error_handling.py +2 -2
  65. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/event_driven_control.py +30 -33
  66. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/improved_auth.py +1 -1
  67. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/mqtt_realtime_monitoring.py +3 -3
  68. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/periodic_requests.py +4 -4
  69. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/set_mode.py +2 -2
  70. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/vacation_mode.py +2 -2
  71. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/testing/periodic_device_info.py +2 -2
  72. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/testing/test_mqtt_messaging.py +3 -3
  73. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/pyproject.toml +3 -3
  74. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/setup.cfg +3 -3
  75. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/__init__.py +16 -0
  76. nwp500_python-8.0.0/src/nwp500/_base.py +78 -0
  77. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/api_client.py +4 -7
  78. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/auth.py +40 -69
  79. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/__init__.py +2 -0
  80. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/__main__.py +3 -1
  81. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/commands.py +2 -0
  82. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/handlers.py +31 -30
  83. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/monitoring.py +3 -3
  84. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/output_formatters.py +2 -0
  85. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/rich_output.py +2 -0
  86. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/cli/token_storage.py +4 -2
  87. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/command_decorators.py +2 -0
  88. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/config.py +3 -0
  89. nwp500_python-8.0.0/src/nwp500/converters.py +191 -0
  90. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/device_capabilities.py +6 -4
  91. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/device_info_cache.py +13 -11
  92. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/encoding.py +2 -0
  93. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/enums.py +2 -0
  94. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/events.py +15 -8
  95. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/exceptions.py +5 -3
  96. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/factory.py +2 -0
  97. nwp500_python-8.0.0/src/nwp500/models/__init__.py +96 -0
  98. nwp500_python-8.0.0/src/nwp500/models/_converters.py +77 -0
  99. nwp500_python-8.0.0/src/nwp500/models/device.py +59 -0
  100. nwp500_python-8.0.0/src/nwp500/models/energy.py +78 -0
  101. nwp500_python-8.0.0/src/nwp500/models/feature.py +411 -0
  102. nwp500_python-8.0.0/src/nwp500/models/mqtt_models.py +33 -0
  103. nwp500_python-8.0.0/src/nwp500/models/schedule.py +338 -0
  104. nwp500_python-8.0.0/src/nwp500/models/status.py +927 -0
  105. nwp500_python-8.0.0/src/nwp500/models/tou.py +162 -0
  106. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/__init__.py +2 -0
  107. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/client.py +386 -36
  108. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/connection.py +16 -8
  109. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/control.py +201 -20
  110. nwp500_python-8.0.0/src/nwp500/mqtt/state_tracker.py +162 -0
  111. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/subscriptions.py +334 -138
  112. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/utils.py +51 -0
  113. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt_events.py +55 -31
  114. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/reservations.py +15 -37
  115. nwp500_python-8.0.0/src/nwp500/topic_builder.py +70 -0
  116. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/utils.py +2 -0
  117. nwp500_python-8.0.0/src/nwp500_python.egg-info/PKG-INFO +120 -0
  118. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500_python.egg-info/SOURCES.txt +51 -37
  119. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500_python.egg-info/requires.txt +1 -1
  120. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_auth.py +22 -22
  121. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_cli_commands.py +69 -13
  122. nwp500_python-8.0.0/tests/test_multi_device.py +243 -0
  123. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_reservations.py +40 -42
  124. nwp500_python-7.4.10/PKG-INFO +0 -328
  125. nwp500_python-7.4.10/README.rst +0 -286
  126. nwp500_python-7.4.10/docs/api/nwp500.rst +0 -182
  127. nwp500_python-7.4.10/docs/guides/energy_monitoring.rst +0 -339
  128. nwp500_python-7.4.10/docs/index.rst +0 -161
  129. nwp500_python-7.4.10/docs/python_api/device_control.rst +0 -1188
  130. nwp500_python-7.4.10/docs/python_api/events.rst +0 -358
  131. nwp500_python-7.4.10/src/nwp500/converters.py +0 -543
  132. nwp500_python-7.4.10/src/nwp500/models.py +0 -1453
  133. nwp500_python-7.4.10/src/nwp500/topic_builder.py +0 -40
  134. nwp500_python-7.4.10/src/nwp500_python.egg-info/PKG-INFO +0 -328
  135. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.coveragerc +0 -0
  136. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.github/RESOLVING_PR_COMMENTS.md +0 -0
  137. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.github/copilot-instructions.md +0 -0
  138. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.gitignore +0 -0
  139. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/.pre-commit-config.yaml +0 -0
  140. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/AUTHORS.rst +0 -0
  141. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/LICENSE.txt +0 -0
  142. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/Makefile +0 -0
  143. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/RELEASE.md +0 -0
  144. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/docs/Makefile +0 -0
  145. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/docs/_static/.gitignore +0 -0
  146. /nwp500_python-7.4.10/docs/guides/authentication.rst → /nwp500_python-8.0.0/docs/how-to/authenticate.rst +0 -0
  147. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/docs/openapi.yaml +0 -0
  148. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/project}/authors.rst +0 -0
  149. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/project}/changelog.rst +0 -0
  150. {nwp500_python-7.4.10/docs/development → nwp500_python-8.0.0/docs/project}/contributing.rst +0 -0
  151. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/project}/license.rst +0 -0
  152. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/protocol/rest_api.rst +0 -0
  153. {nwp500_python-7.4.10/docs → nwp500_python-8.0.0/docs/reference}/python_api/api_client.rst +0 -0
  154. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/.ruff.toml +0 -0
  155. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/README.md +0 -0
  156. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/auto_recovery.py +0 -0
  157. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/error_code_demo.py +0 -0
  158. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/advanced/simple_auto_recovery.py +0 -0
  159. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/beginner/01_authentication.py +0 -0
  160. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/beginner/02_list_devices.py +0 -0
  161. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/beginner/03_get_status.py +0 -0
  162. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/intermediate/legacy_auth_constructor.py +0 -0
  163. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/mask.py +0 -0
  164. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/testing/simple_periodic_info.py +0 -0
  165. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/testing/test_api_client.py +0 -0
  166. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/testing/test_mqtt_connection.py +0 -0
  167. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/examples/testing/test_periodic_minimal.py +0 -0
  168. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/README.md +0 -0
  169. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/bump_version.py +0 -0
  170. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/diagnose_mqtt_connection.py +0 -0
  171. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/extract_changelog.py +0 -0
  172. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/format.py +0 -0
  173. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/lint.py +0 -0
  174. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/setup-dev.py +0 -0
  175. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/scripts/validate_version.py +0 -0
  176. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/setup.py +0 -0
  177. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/field_factory.py +0 -0
  178. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/command_queue.py +0 -0
  179. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/diagnostics.py +0 -0
  180. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/periodic.py +0 -0
  181. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/mqtt/reconnection.py +0 -0
  182. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/openei.py +0 -0
  183. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/py.typed +0 -0
  184. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/temperature.py +0 -0
  185. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500/unit_system.py +0 -0
  186. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
  187. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500_python.egg-info/entry_points.txt +0 -0
  188. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500_python.egg-info/not-zip-safe +0 -0
  189. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/src/nwp500_python.egg-info/top_level.txt +0 -0
  190. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/conftest.py +0 -0
  191. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_api_helpers.py +0 -0
  192. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_cli_basic.py +0 -0
  193. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_command_decorators.py +0 -0
  194. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_command_queue.py +0 -0
  195. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_device_capabilities.py +0 -0
  196. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_device_info_cache.py +0 -0
  197. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_events.py +0 -0
  198. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_exceptions.py +0 -0
  199. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_model_converters.py +0 -0
  200. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_models.py +0 -0
  201. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_mqtt_client_init.py +0 -0
  202. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_mqtt_hypothesis.py +0 -0
  203. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_openei.py +0 -0
  204. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_temperature_converters.py +0 -0
  205. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_tou_api.py +0 -0
  206. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_unit_switching.py +0 -0
  207. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tests/test_utils.py +0 -0
  208. {nwp500_python-7.4.10 → nwp500_python-8.0.0}/tox.ini +0 -0
@@ -18,7 +18,7 @@ jobs:
18
18
  - name: Set up Python
19
19
  uses: actions/setup-python@v5
20
20
  with:
21
- python-version: '3.13'
21
+ python-version: '3.14'
22
22
 
23
23
  - name: Install tox
24
24
  run: |
@@ -37,7 +37,7 @@ jobs:
37
37
  - name: Set up Python
38
38
  uses: actions/setup-python@v5
39
39
  with:
40
- python-version: '3.13'
40
+ python-version: '3.14'
41
41
 
42
42
  - name: Install ruff
43
43
  run: |
@@ -52,7 +52,7 @@ jobs:
52
52
  runs-on: ubuntu-latest
53
53
  strategy:
54
54
  matrix:
55
- python-version: ['3.13', '3.14']
55
+ python-version: ['3.14']
56
56
 
57
57
  steps:
58
58
  - uses: actions/checkout@v4
@@ -87,7 +87,7 @@ jobs:
87
87
  - name: Set up Python
88
88
  uses: actions/setup-python@v5
89
89
  with:
90
- python-version: '3.13'
90
+ python-version: '3.14'
91
91
 
92
92
  - name: Install build dependencies
93
93
  run: |
@@ -18,7 +18,7 @@ jobs:
18
18
  - name: Set up Python
19
19
  uses: actions/setup-python@v5
20
20
  with:
21
- python-version: '3.13'
21
+ python-version: '3.14'
22
22
 
23
23
  - name: Install dependencies
24
24
  run: |
@@ -53,7 +53,7 @@ jobs:
53
53
  - name: Set up Python
54
54
  uses: actions/setup-python@v5
55
55
  with:
56
- python-version: '3.10'
56
+ python-version: '3.14'
57
57
 
58
58
  - name: Install build dependencies
59
59
  run: |
@@ -80,7 +80,7 @@ jobs:
80
80
  - name: Set up Python
81
81
  uses: actions/setup-python@v5
82
82
  with:
83
- python-version: '3.10'
83
+ python-version: '3.14'
84
84
 
85
85
  - name: Extract changelog for this version
86
86
  id: changelog
@@ -19,7 +19,7 @@ formats:
19
19
  build:
20
20
  os: ubuntu-22.04
21
21
  tools:
22
- python: "3.13"
22
+ python: "3.14"
23
23
 
24
24
  python:
25
25
  install:
@@ -2,6 +2,140 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ Unreleased (8.x)
6
+ ================
7
+
8
+ Bug Fixes
9
+ ---------
10
+ - **Fix MQTT reconnection after unexpected AWS hangup**: The
11
+ ``on_connection_resumed`` callback was missing the ``connection`` parameter
12
+ required by the AWS IoT SDK callback signature. The SDK calls
13
+ ``on_connection_resumed(connection, return_code, session_present, **kwargs)``,
14
+ but the handler only accepted ``(return_code, session_present)``. The
15
+ mismatched signature caused the callback to fail silently (exception swallowed
16
+ by the AWS CRT C layer), so ``self._connected`` was never restored to ``True``
17
+ after an ``AWS_ERROR_MQTT_UNEXPECTED_HANGUP``. As a result, the
18
+ ``connection_resumed`` event was never emitted, the reconnection loop ran
19
+ indefinitely, and device sensors became permanently unavailable until a manual
20
+ restart. (`#85 <https://github.com/eman/nwp500-python/issues/85>`_)
21
+
22
+ Features
23
+ --------
24
+ - **Multi-device support enhancements**: Improved support for accounts with multiple
25
+ Navilink devices by injecting device identity into models and events.
26
+
27
+ - Added ``mac_address`` field to ``DeviceStatus`` and ``DeviceFeature`` models.
28
+ - Added ``device_mac`` attribute to all device-specific MQTT events (temperature
29
+ changes, mode changes, power updates, errors, etc.).
30
+ - Updated ``DeviceStateTracker`` and ``MqttSubscriptionManager`` to propagate
31
+ device identity correctly.
32
+
33
+ **BREAKING CHANGES**: ``.on()`` event handler callbacks now receive a single typed
34
+ event dataclass instead of positional arguments. ``MqttDeviceController`` is no longer
35
+ accessible as ``.control`` on ``NavienMqttClient``; all control methods are now
36
+ available directly on the client.
37
+
38
+ Breaking Changes
39
+ ----------------
40
+ - **Typed event payloads**: All ``.on()`` event handler callbacks now receive a single
41
+ typed event dataclass instance. The dataclasses are exported from
42
+ ``nwp500.mqtt_events``.
43
+
44
+ .. code-block:: python
45
+
46
+ # OLD (removed)
47
+ mqtt.on("temperature_changed", lambda old, new: print(old, new))
48
+ mqtt.on("connection_resumed", lambda rc, sp: print(rc, sp))
49
+
50
+ # NEW
51
+ mqtt.on("temperature_changed", lambda e: print(e.old_temperature, e.new_temperature))
52
+ mqtt.on("connection_resumed", lambda e: print(e.return_code, e.session_present))
53
+
54
+ - **``MqttDeviceController`` no longer public**: ``NavienMqttClient`` no longer exposes
55
+ a ``.control`` attribute. All control methods are now available directly on the
56
+ client.
57
+
58
+ .. code-block:: python
59
+
60
+ # OLD (removed)
61
+ await mqtt.control.set_temperature(device, 50)
62
+
63
+ # NEW
64
+ await mqtt.set_temperature(device, 50)
65
+
66
+ Migration Guide (from 7.x.x)
67
+ ----------------------------
68
+ The following steps are recommended for a smooth migration, particularly for complex
69
+ integrations like Home Assistant:
70
+
71
+ 1. **Update Event Listeners**: Locate all ``mqtt.on()`` or ``mqtt.once()`` calls.
72
+ Update the callback signatures to accept a single argument (the event object) and
73
+ update the body to access fields via the object (e.g., ``event.new_temperature``
74
+ instead of ``new_val``).
75
+ 2. **Refactor Control Calls**: Remove ``.control`` from all device command invocations.
76
+ Instead of ``await mqtt.control.set_power(...)``, use ``await mqtt.set_power(...)``.
77
+ 3. **Handle Unit Conversions**: If your integration previously performed its own
78
+ conversions or relied on the library's eager conversion, note that
79
+ ``DeviceStatus`` fields like ``dhw_temperature`` are now properties. They return
80
+ values based on the global unit system context (``us_customary`` by default).
81
+
82
+ * **Home Assistant Tip**: To ensure your state tracking is immune to unit system
83
+ toggles within the library, use the new ``*_raw`` fields (e.g.,
84
+ ``status.dhw_temperature_raw``) for comparison logic, and use the properties
85
+ only for display or when a converted value is explicitly needed.
86
+ 4. **Remove ``from_dict()`` Calls**: The ``from_dict()`` method has been removed
87
+ from all models. Use ``model_validate()`` instead.
88
+
89
+ * **Note**: ``AuthenticationResponse.model_validate()`` now automatically handles
90
+ the ``"data": { ... }`` wrapper found in raw API responses.
91
+ 5. **Subpackage Imports**: While top-level imports from ``nwp500.models`` are
92
+ preserved, if you were importing from the internal ``nwp500.models`` module file
93
+ directly, you must update your imports to point to the new structured files
94
+ (e.g., ``nwp500.models.status``).
95
+
96
+ Added
97
+ -----
98
+ - **New control methods**: Nine previously unimplemented ``CommandCode`` values now have
99
+ full implementations: ``check_firmware``, ``commit_firmware``, ``reconnect_wifi``,
100
+ ``reset_wifi``, ``set_freeze_protection_temperature``, ``run_smart_diagnostic``,
101
+ ``enable_intelligent_reservation``, ``disable_intelligent_reservation``, and
102
+ ``set_water_program_reservation``.
103
+ - **Typed subscription methods**: ``subscribe_reservation``,
104
+ ``subscribe_weekly_reservation``, and ``subscribe_recirculation`` return typed
105
+ responses directly without requiring raw MQTT event handlers.
106
+ - **New protocol models**: ``WeeklyReservationSchedule``, ``WeeklyReservationEntry``,
107
+ ``RecirculationSchedule``, ``RecirculationScheduleEntry``, and ``OtaCommitPayload``.
108
+ - **``DeviceStateTracker``**: State change detection extracted into a dedicated class
109
+ in ``nwp500.mqtt.state_tracker`` with per-device tracking keyed by MAC address.
110
+ - **``MQTT_PROTOCOL_VERSION`` constant**: Protocol version is now a named constant in
111
+ ``nwp500.config`` rather than a hardcoded integer in the command payload builder.
112
+ - **``response_ack_topic()``**: New method on ``MqttTopicBuilder`` for control command
113
+ acknowledgement topics.
114
+
115
+ Changed
116
+ -------
117
+ - **Unit conversion redesign**: Temperature, flow rate, and volume fields in
118
+ ``DeviceStatus`` and ``DeviceFeature`` now store raw device values as ``*_raw: int``
119
+ fields and expose converted values via lazy computed properties. Conversion happens at
120
+ access time rather than during Pydantic deserialization, preserving the original
121
+ device value in all cases.
122
+ - **Models split into subpackage**: ``nwp500.models`` is now a package
123
+ (``nwp500/models/``) with modules for status, schedule, TOU, and MQTT models. Public
124
+ imports from ``nwp500.models`` are unchanged.
125
+ - **Topic building centralised**: All MQTT topic construction now goes through
126
+ ``MqttTopicBuilder``. Hardcoded topic strings removed from ``control.py``,
127
+ ``reservations.py``, and ``cli/handlers.py``.
128
+ - **``set_vacation_days`` delegates to ``set_dhw_mode``**: The method now calls
129
+ ``set_dhw_mode(device, DhwOperationSetting.VACATION, vacation_days=days)`` directly.
130
+ - **Per-device state tracking**: ``_previous_status`` changed from a single
131
+ ``DeviceStatus | None`` to a ``dict[str, DeviceStatus]`` keyed by MAC address,
132
+ preventing spurious state-change events when multiple devices are connected.
133
+ - **Unit system stored as instance variable**: ``NavienAPIClient``,
134
+ ``NavienMqttClient``, and ``NavienAuthClient`` no longer call ``set_unit_system()``
135
+ as a constructor side-effect.
136
+ - **``NavienBaseModel`` consolidated**: Duplicate definitions in ``auth.py`` and
137
+ ``models.py`` merged into a single definition in ``nwp500._base``.
138
+
5
139
  Version 7.4.10 (2026-04-13)
6
140
  ===========================
7
141
 
@@ -205,7 +339,7 @@ Breaking Changes
205
339
  .. code-block:: python
206
340
 
207
341
  # OLD (hardcoded 95-150°F)
208
- await mqtt.control.set_dhw_temperature(device, temperature_f=140.0)
342
+ await mqtt.set_dhw_temperature(device, temperature_f=140.0)
209
343
  entry = build_reservation_entry(
210
344
  enabled=True,
211
345
  days=["Monday"],
@@ -217,7 +351,7 @@ Breaking Changes
217
351
 
218
352
  # NEW (device-provided limits, unit-aware)
219
353
  # Temperature value automatically uses user's preferred unit
220
- await mqtt.control.set_dhw_temperature(device, 140.0)
354
+ await mqtt.set_dhw_temperature(device, 140.0)
221
355
 
222
356
  # Device features provide min/max in user's preferred unit
223
357
  features = await device_info_cache.get(device.device_info.mac_address)
@@ -135,7 +135,7 @@ Follow a clear exception hierarchy with consistent naming:
135
135
  .. code-block:: python
136
136
 
137
137
  try:
138
- await mqtt_client.control.set_temperature(device, 150)
138
+ await mqtt_client.set_temperature(device, 150)
139
139
  except MqttNotConnectedError:
140
140
  # Handle specific case: not connected
141
141
  print("Connect to device first")
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: nwp500-python
3
+ Version: 8.0.0
4
+ Summary: A library for controlling Navien NWP500 Water Heaters via NaviLink
5
+ Home-page: https://github.com/eman/nwp500-python
6
+ Author: Emmanuel Levijarvi
7
+ Author-email: emansl@gmail.com
8
+ License: MIT
9
+ Project-URL: Documentation, https://nwp500-python.readthedocs.io/en/latest/
10
+ Project-URL: Source, https://github.com/eman/nwp500-python
11
+ Project-URL: Tracker, https://github.com/eman/nwp500-python/issues
12
+ Platform: any
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Requires-Python: >=3.14
19
+ Description-Content-Type: text/x-rst; charset=UTF-8
20
+ License-File: LICENSE.txt
21
+ Requires-Dist: aiohttp>=3.13.5
22
+ Requires-Dist: awsiotsdk>=1.29.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Provides-Extra: cli
25
+ Requires-Dist: click>=8.3.0; extra == "cli"
26
+ Requires-Dist: rich>=14.3.0; extra == "cli"
27
+ Provides-Extra: testing
28
+ Requires-Dist: setuptools; extra == "testing"
29
+ Requires-Dist: pytest; extra == "testing"
30
+ Requires-Dist: pytest-cov; extra == "testing"
31
+ Requires-Dist: pytest-asyncio; extra == "testing"
32
+ Requires-Dist: hypothesis; extra == "testing"
33
+ Provides-Extra: dev
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Requires-Dist: pyright>=1.1.0; extra == "dev"
36
+ Requires-Dist: setuptools; extra == "dev"
37
+ Requires-Dist: pytest; extra == "dev"
38
+ Requires-Dist: pytest-cov; extra == "dev"
39
+ Requires-Dist: pytest-asyncio; extra == "dev"
40
+ Requires-Dist: hypothesis; extra == "dev"
41
+ Dynamic: license-file
42
+
43
+ =============
44
+ nwp500-python
45
+ =============
46
+
47
+ |PyPI-v| |Python-versions| |CI-status| |Docs-status| |Code-style| |License|
48
+
49
+ Python library for Navien NWP500 Heat Pump Water Heater
50
+ ========================================================
51
+
52
+ A complete Python library for monitoring and controlling the Navien NWP500 Heat Pump Water Heater through the Navilink cloud service.
53
+
54
+ * **Documentation:** https://nwp500-python.readthedocs.io/
55
+ * **Source:** https://github.com/eman/nwp500-python
56
+
57
+ Features
58
+ ========
59
+ * **Complete Interface:** Full support for both REST API and real-time MQTT (AWS IoT).
60
+ * **Monitoring:** Real-time tracking of temperature, power usage, tank charge, and component status.
61
+ * **Control:** Remote control of target temperatures, operation modes, and vacation settings.
62
+ * **Advanced Features:** Native support for reservations, time-of-use (TOU) optimization, and anti-legionella cycles.
63
+ * **Type-Safe:** Built with Pydantic for robust data validation and unit handling.
64
+ * **Async/Await:** Modern asyncio-based implementation for high-performance integration.
65
+
66
+ Getting Started
67
+ ===============
68
+
69
+ .. code-block:: bash
70
+
71
+ pip install nwp500-python
72
+
73
+ Quick Example
74
+ -------------
75
+
76
+ .. code-block:: python
77
+
78
+ from nwp500 import NavienAuthClient, NavienAPIClient
79
+
80
+ async with NavienAuthClient("email@example.com", "password") as auth:
81
+ api = NavienAPIClient(auth)
82
+ devices = await api.list_devices()
83
+
84
+ if devices:
85
+ device = devices[0]
86
+ print(f"Temperature: {device.status.dhw_temperature}°F")
87
+ await api.set_device_temperature(device, 130)
88
+
89
+ Documentation
90
+ =============
91
+
92
+ The documentation follows the `Diátaxis <https://diataxis.fr/>`_ framework:
93
+
94
+ * `Tutorials <https://nwp500-python.readthedocs.io/en/latest/tutorials/getting-started.html>`_: Start here if you're new to the library.
95
+ * `How-to Guides <https://nwp500-python.readthedocs.io/en/latest/how-to/index.html>`_: Practical step-by-step recipes for specific tasks.
96
+ * `Reference <https://nwp500-python.readthedocs.io/en/latest/reference/index.html>`_: Technical descriptions of the API, models, and protocol.
97
+ * `Explanation <https://nwp500-python.readthedocs.io/en/latest/explanation/index.html>`_: Understanding-oriented deep dives into the library's design and advanced features.
98
+
99
+ Contributing
100
+ ============
101
+
102
+ We welcome contributions! Please see our `Contributing Guide <https://nwp500-python.readthedocs.io/en/latest/project/contributing.html>`_ for more details.
103
+
104
+ License
105
+ =======
106
+
107
+ This project is licensed under the MIT License. See the `LICENSE.txt <https://github.com/eman/nwp500-python/blob/main/LICENSE.txt>`_ file for details.
108
+
109
+ .. |PyPI-v| image:: https://img.shields.io/pypi/v/nwp500-python.svg
110
+ :target: https://pypi.org/project/nwp500-python/
111
+ .. |Python-versions| image:: https://img.shields.io/pypi/pyversions/nwp500-python.svg
112
+ :target: https://pypi.org/project/nwp500-python/
113
+ .. |CI-status| image:: https://github.com/eman/nwp500-python/actions/workflows/ci.yml/badge.svg
114
+ :target: https://github.com/eman/nwp500-python/actions/workflows/ci.yml
115
+ .. |Docs-status| image:: https://readthedocs.org/projects/nwp500-python/badge/?version=latest
116
+ :target: https://nwp500-python.readthedocs.io/en/latest/?badge=latest
117
+ .. |Code-style| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
118
+ :target: https://github.com/astral-sh/ruff
119
+ .. |License| image:: https://img.shields.io/pypi/l/nwp500-python.svg
120
+ :target: https://opensource.org/licenses/MIT
@@ -0,0 +1,78 @@
1
+ =============
2
+ nwp500-python
3
+ =============
4
+
5
+ |PyPI-v| |Python-versions| |CI-status| |Docs-status| |Code-style| |License|
6
+
7
+ Python library for Navien NWP500 Heat Pump Water Heater
8
+ ========================================================
9
+
10
+ A complete Python library for monitoring and controlling the Navien NWP500 Heat Pump Water Heater through the Navilink cloud service.
11
+
12
+ * **Documentation:** https://nwp500-python.readthedocs.io/
13
+ * **Source:** https://github.com/eman/nwp500-python
14
+
15
+ Features
16
+ ========
17
+ * **Complete Interface:** Full support for both REST API and real-time MQTT (AWS IoT).
18
+ * **Monitoring:** Real-time tracking of temperature, power usage, tank charge, and component status.
19
+ * **Control:** Remote control of target temperatures, operation modes, and vacation settings.
20
+ * **Advanced Features:** Native support for reservations, time-of-use (TOU) optimization, and anti-legionella cycles.
21
+ * **Type-Safe:** Built with Pydantic for robust data validation and unit handling.
22
+ * **Async/Await:** Modern asyncio-based implementation for high-performance integration.
23
+
24
+ Getting Started
25
+ ===============
26
+
27
+ .. code-block:: bash
28
+
29
+ pip install nwp500-python
30
+
31
+ Quick Example
32
+ -------------
33
+
34
+ .. code-block:: python
35
+
36
+ from nwp500 import NavienAuthClient, NavienAPIClient
37
+
38
+ async with NavienAuthClient("email@example.com", "password") as auth:
39
+ api = NavienAPIClient(auth)
40
+ devices = await api.list_devices()
41
+
42
+ if devices:
43
+ device = devices[0]
44
+ print(f"Temperature: {device.status.dhw_temperature}°F")
45
+ await api.set_device_temperature(device, 130)
46
+
47
+ Documentation
48
+ =============
49
+
50
+ The documentation follows the `Diátaxis <https://diataxis.fr/>`_ framework:
51
+
52
+ * `Tutorials <https://nwp500-python.readthedocs.io/en/latest/tutorials/getting-started.html>`_: Start here if you're new to the library.
53
+ * `How-to Guides <https://nwp500-python.readthedocs.io/en/latest/how-to/index.html>`_: Practical step-by-step recipes for specific tasks.
54
+ * `Reference <https://nwp500-python.readthedocs.io/en/latest/reference/index.html>`_: Technical descriptions of the API, models, and protocol.
55
+ * `Explanation <https://nwp500-python.readthedocs.io/en/latest/explanation/index.html>`_: Understanding-oriented deep dives into the library's design and advanced features.
56
+
57
+ Contributing
58
+ ============
59
+
60
+ We welcome contributions! Please see our `Contributing Guide <https://nwp500-python.readthedocs.io/en/latest/project/contributing.html>`_ for more details.
61
+
62
+ License
63
+ =======
64
+
65
+ This project is licensed under the MIT License. See the `LICENSE.txt <https://github.com/eman/nwp500-python/blob/main/LICENSE.txt>`_ file for details.
66
+
67
+ .. |PyPI-v| image:: https://img.shields.io/pypi/v/nwp500-python.svg
68
+ :target: https://pypi.org/project/nwp500-python/
69
+ .. |Python-versions| image:: https://img.shields.io/pypi/pyversions/nwp500-python.svg
70
+ :target: https://pypi.org/project/nwp500-python/
71
+ .. |CI-status| image:: https://github.com/eman/nwp500-python/actions/workflows/ci.yml/badge.svg
72
+ :target: https://github.com/eman/nwp500-python/actions/workflows/ci.yml
73
+ .. |Docs-status| image:: https://readthedocs.org/projects/nwp500-python/badge/?version=latest
74
+ :target: https://nwp500-python.readthedocs.io/en/latest/?badge=latest
75
+ .. |Code-style| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
76
+ :target: https://github.com/astral-sh/ruff
77
+ .. |License| image:: https://img.shields.io/pypi/l/nwp500-python.svg
78
+ :target: https://opensource.org/licenses/MIT
@@ -33,7 +33,7 @@ try: # for Sphinx >= 1.7
33
33
  except ImportError:
34
34
  from sphinx import apidoc
35
35
 
36
- output_dir = os.path.join(__location__, "api")
36
+ output_dir = os.path.join(__location__, "reference", "api")
37
37
  module_dir = os.path.join(__location__, "../src/nwp500")
38
38
  try:
39
39
  shutil.rmtree(output_dir)
@@ -1,16 +1,16 @@
1
- Advanced Features Explained: Weather-Responsive Heating, Demand Response, and Tank Stratification
2
- ==================================================================================================
1
+ Weather Response, Demand Response, and Tank Stratification
2
+ ===========================================================
3
3
 
4
- This document provides comprehensive technical documentation for three advanced NWP500 features.
4
+ This document covers three advanced NWP500 features.
5
5
 
6
6
  Overview of Advanced Features
7
7
  -----------------------------
8
8
 
9
- The NWP500 heat pump water heater implements sophisticated algorithms for grid integration, environmental responsiveness, and efficiency optimization:
9
+ The NWP500 heat pump water heater implements algorithms for grid integration, environmental responsiveness, and efficiency optimization:
10
10
 
11
11
  1. **Weather-Responsive Heating** - Adjusts heating strategy based on ambient temperature conditions
12
12
  2. **Demand Response Integration** - Responds to grid signals for demand/response events (CTA-2045)
13
- 3. **Tank Stratification Optimization** - Uses dual temperature sensors for enhanced heating efficiency
13
+ 3. **Tank Stratification Optimization** - Uses dual temperature sensors for improved heating efficiency
14
14
 
15
15
  Weather-Responsive Heating
16
16
  ==========================
@@ -18,7 +18,7 @@ Weather-Responsive Heating
18
18
  Feature Overview
19
19
  ----------------
20
20
 
21
- The device continuously monitors ambient air temperature to optimize heat pump performance and adjust heating strategies. This enables the system to maintain comfort while adapting to seasonal conditions automatically.
21
+ The device continuously monitors ambient air temperature to optimize heat pump performance and adjust heating strategies based on seasonal conditions.
22
22
 
23
23
  Technical Implementation
24
24
  ------------------------
@@ -109,7 +109,7 @@ The ``outsideTemperature`` field is transmitted in the device status update. Pyt
109
109
  .. code-block:: python
110
110
 
111
111
  # From device status updates
112
- status = await mqtt_client.control.request_device_status()
112
+ status = await mqtt_client.request_device_status()
113
113
 
114
114
  # Access ambient temperature data
115
115
  outdoor_temp = status.outside_temperature # Raw integer value
@@ -230,12 +230,6 @@ Implementation in Device Firmware
230
230
  3. **Grid Stability**: Participate in demand response events, earn utility incentives
231
231
  4. **Cost Reduction**: Shift heating to low-price periods automatically
232
232
 
233
- Utility Integration Requirements
234
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235
-
236
- To use demand response with your NWP500:
237
-
238
-
239
233
  Tank Temperature Sensors
240
234
  ------------------------
241
235
 
@@ -389,7 +383,7 @@ Monitoring Stratification from Python
389
383
  async def monitor_stratification(mqtt_client: NavienMQTTClient, device_id: str):
390
384
  """Monitor tank stratification quality"""
391
385
 
392
- status = await mqtt_client.control.request_device_status(device_id)
386
+ status = await mqtt_client.request_device_status(device_id)
393
387
 
394
388
  upper_temp = status.tank_upper_temperature # float in °F
395
389
  lower_temp = status.tank_lower_temperature # float in °F
@@ -470,7 +464,7 @@ The NWP500 uses **half-degrees Celsius** encoding for temperature fields.
470
464
 
471
465
  **Related Documentation**:
472
466
 
473
- See :doc:`../protocol/data_conversions` for complete field conversion reference and formula applications.
467
+ See :doc:`../reference/protocol/data_conversions` for complete field conversion reference and formula applications.
474
468
 
475
469
  Summary and Recommendations
476
470
  ============================
@@ -497,7 +491,7 @@ Summary and Recommendations
497
491
  See Also
498
492
  --------
499
493
 
500
- * :doc:`../protocol/data_conversions` - Temperature field conversions (HalfCelsiusToF, DeciCelsiusToF)
501
- * :doc:`../protocol/device_status` - Complete device status field reference
502
- * :doc:`scheduling` - Scheduling and automation guide
503
- * :doc:`../python_api/models` - DeviceStatus model field definitions
494
+ * :doc:`../reference/protocol/data_conversions` - Temperature field conversions (HalfCelsiusToF, DeciCelsiusToF)
495
+ * :doc:`../reference/protocol/device_status` - Complete device status field reference
496
+ * :doc:`../how-to/schedule-operation` - Scheduling and automation guide
497
+ * :doc:`../reference/python_api/models` - DeviceStatus model field definitions
@@ -0,0 +1,81 @@
1
+ ============
2
+ Architecture
3
+ ============
4
+
5
+ This document explains the high-level architecture of the ``nwp500-python`` library and how it interacts with the Navien Smart Control cloud platform.
6
+
7
+ System Overview
8
+ ===============
9
+
10
+ The library acts as a bridge between your Python application and the Navien NWP500 Heat Pump Water Heater. Communication happens through two primary channels:
11
+
12
+ 1. **REST API**: Used for authentication, account management, and listing devices.
13
+ 2. **MQTT (AWS IoT)**: Used for real-time monitoring and control of the device.
14
+
15
+ Component Diagram
16
+ =================
17
+
18
+ .. code-block:: text
19
+
20
+ +-------------------+ +------------------------+
21
+ | | | |
22
+ | Your Application | | Navien Smart Control |
23
+ | | | (Cloud) |
24
+ +---------+---------+ +-----------+------------+
25
+ | |
26
+ | +-------------+ |
27
+ +------>| Auth Client |<------+ (Sign-in/Tokens)
28
+ | +-------------+ |
29
+ | |
30
+ | +-------------+ |
31
+ +------>| API Client |<------+ (REST API)
32
+ | +-------------+ |
33
+ | |
34
+ | +-------------+ |
35
+ +------>| MQTT Client |<------+ (AWS IoT Core)
36
+ +-------------+
37
+
38
+ Core Components
39
+ ===============
40
+
41
+ Authentication Client
42
+ ---------------------
43
+
44
+ The ``NavienAuthClient`` is responsible for managing credentials and tokens. It performs the initial sign-in to obtain:
45
+ * A JWT access token for REST API requests.
46
+ * AWS IoT credentials (identity ID, session token, etc.) for MQTT connection.
47
+
48
+ REST API Client
49
+ ---------------
50
+
51
+ The ``NavienAPIClient`` provides methods for "heavy" or infrequent operations, such as:
52
+ * Retrieving the list of devices.
53
+ * Getting detailed device information.
54
+ * Accessing historical energy data.
55
+
56
+ MQTT Client
57
+ -----------
58
+
59
+ The ``NavienMqttClient`` is the heart of real-time interaction. It maintains a persistent connection to AWS IoT Core and handles:
60
+ * Subscribing to device status updates.
61
+ * Publishing control commands (e.g., setting temperature).
62
+ * Parsing incoming hex-encoded payloads into structured data models.
63
+
64
+ Data Models
65
+ ===========
66
+
67
+ The library uses **Pydantic** for all data models. This ensures:
68
+ * **Type Safety**: All fields have explicit types.
69
+ * **Validation**: Incoming data is validated against expected formats.
70
+ * **Unit Handling**: Temperatures and other units are automatically converted to appropriate scales (e.g., Fahrenheit).
71
+
72
+ Event System
73
+ ============
74
+
75
+ The library implements an asynchronous event system. You can subscribe to various events (e.g., status updates, connection changes) and provide callback functions that will be executed when those events occur.
76
+
77
+ See Also
78
+ ========
79
+
80
+ * :doc:`advanced-features` - Deep dive into TOU, reservations, and more.
81
+ * :doc:`../reference/protocol/mqtt_protocol` - Low-level details of the MQTT messaging.
@@ -0,0 +1,11 @@
1
+ ===========
2
+ Explanation
3
+ ===========
4
+
5
+ Understanding-oriented deep dives into the library's design and advanced features.
6
+
7
+ .. toctree::
8
+ :maxdepth: 1
9
+
10
+ advanced-features
11
+ architecture
@@ -127,7 +127,7 @@ Refresh authentication tokens before retrying (handles token expiry).
127
127
  await mqtt_client.subscribe_device_status(device, on_status)
128
128
  await mqtt_client.start_periodic_requests(device)
129
129
 
130
- **Pros:** Handles token expiry, more robust
130
+ **Pros:** Handles token expiry, more reliable
131
131
 
132
132
  **Cons:** More complex, need to manage client lifecycle
133
133
 
@@ -453,4 +453,4 @@ For production use, **use Strategy 4 (Exponential Backoff)** via the ``Resilient
453
453
  * Subscription restoration
454
454
  * Configurable limits and delays
455
455
 
456
- This ensures your application stays connected even during extended network outages.
456
+ Your application will stay connected even through extended network outages.