nwp500-python 7.4.6__tar.gz → 7.4.7__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 (188) hide show
  1. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.github/workflows/ci.yml +4 -4
  2. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.gitignore +6 -0
  3. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/CHANGELOG.rst +26 -0
  4. {nwp500_python-7.4.6/src/nwp500_python.egg-info → nwp500_python-7.4.7}/PKG-INFO +1 -1
  5. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/api/nwp500.rst +8 -0
  6. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/advanced_features_explained.rst +1 -1
  7. nwp500_python-7.4.7/docs/guides/scheduling.rst +681 -0
  8. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/time_of_use.rst +163 -155
  9. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/index.rst +1 -2
  10. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/openapi.yaml +231 -0
  11. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/cli.rst +85 -31
  12. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/device_control.rst +1 -2
  13. nwp500_python-7.4.7/examples/advanced/tou_openei.py +121 -0
  14. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/pyproject.toml +5 -2
  15. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/__init__.py +11 -0
  16. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/api_client.py +104 -1
  17. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/__init__.py +6 -0
  18. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/__main__.py +294 -5
  19. nwp500_python-7.4.7/src/nwp500/cli/handlers.py +1131 -0
  20. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/rich_output.py +364 -0
  21. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/encoding.py +88 -33
  22. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/models.py +126 -0
  23. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/control.py +2 -2
  24. nwp500_python-7.4.7/src/nwp500/openei.py +213 -0
  25. {nwp500_python-7.4.6 → nwp500_python-7.4.7/src/nwp500_python.egg-info}/PKG-INFO +1 -1
  26. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500_python.egg-info/SOURCES.txt +4 -6
  27. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_api_helpers.py +44 -7
  28. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_models.py +133 -1
  29. nwp500_python-7.4.7/tests/test_openei.py +219 -0
  30. nwp500_python-7.4.7/tests/test_tou_api.py +262 -0
  31. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tox.ini +1 -7
  32. nwp500_python-7.4.6/.agent/workflows/pre-completion-testing.md +0 -73
  33. nwp500_python-7.4.6/.bandit +0 -3
  34. nwp500_python-7.4.6/docs/guides/reservations.rst +0 -721
  35. nwp500_python-7.4.6/docs/guides/scheduling_features.rst +0 -406
  36. nwp500_python-7.4.6/examples/advanced/tou_openei.py +0 -328
  37. nwp500_python-7.4.6/package-lock.json +0 -6
  38. nwp500_python-7.4.6/package.json +0 -1
  39. nwp500_python-7.4.6/src/nwp500/cli/handlers.py +0 -564
  40. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.coveragerc +0 -0
  41. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.github/RESOLVING_PR_COMMENTS.md +0 -0
  42. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.github/copilot-instructions.md +0 -0
  43. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.github/workflows/release.yml +0 -0
  44. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.pre-commit-config.yaml +0 -0
  45. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/.readthedocs.yml +0 -0
  46. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/AUTHORS.rst +0 -0
  47. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/CONTRIBUTING.rst +0 -0
  48. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/LICENSE.txt +0 -0
  49. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/Makefile +0 -0
  50. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/README.rst +0 -0
  51. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/RELEASE.md +0 -0
  52. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/Makefile +0 -0
  53. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/_static/.gitignore +0 -0
  54. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/authors.rst +0 -0
  55. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/changelog.rst +0 -0
  56. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/conf.py +0 -0
  57. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/configuration.rst +0 -0
  58. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/development/contributing.rst +0 -0
  59. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/development/history.rst +0 -0
  60. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/enumerations.rst +0 -0
  61. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/authentication.rst +0 -0
  62. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/auto_recovery.rst +0 -0
  63. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/command_queue.rst +0 -0
  64. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/energy_monitoring.rst +0 -0
  65. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/event_system.rst +0 -0
  66. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/home_assistant_integration.rst +0 -0
  67. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/mqtt_diagnostics.rst +0 -0
  68. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/guides/unit_conversion.rst +0 -0
  69. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/installation.rst +0 -0
  70. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/license.rst +0 -0
  71. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/data_conversions.rst +0 -0
  72. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/device_features.rst +0 -0
  73. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/device_status.rst +0 -0
  74. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/error_codes.rst +0 -0
  75. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/mqtt_protocol.rst +0 -0
  76. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/quick_reference.rst +0 -0
  77. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/protocol/rest_api.rst +0 -0
  78. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/api_client.rst +0 -0
  79. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/auth_client.rst +0 -0
  80. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/events.rst +0 -0
  81. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/exceptions.rst +0 -0
  82. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/models.rst +0 -0
  83. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/python_api/mqtt_client.rst +0 -0
  84. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/quickstart.rst +0 -0
  85. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/docs/requirements.txt +0 -0
  86. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/.ruff.toml +0 -0
  87. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/README.md +0 -0
  88. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/air_filter_reset.py +0 -0
  89. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/anti_legionella.py +0 -0
  90. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/auto_recovery.py +0 -0
  91. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/combined_callbacks.py +0 -0
  92. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/demand_response.py +0 -0
  93. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/device_capabilities.py +0 -0
  94. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/device_status_debug.py +0 -0
  95. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/energy_analytics.py +0 -0
  96. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/error_code_demo.py +0 -0
  97. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/mqtt_diagnostics.py +0 -0
  98. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/power_control.py +0 -0
  99. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/recirculation_control.py +0 -0
  100. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/reconnection_demo.py +0 -0
  101. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/reservation_schedule.py +0 -0
  102. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/simple_auto_recovery.py +0 -0
  103. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/token_restoration.py +0 -0
  104. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/tou_schedule.py +0 -0
  105. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/advanced/water_reservation.py +0 -0
  106. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/beginner/01_authentication.py +0 -0
  107. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/beginner/02_list_devices.py +0 -0
  108. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/beginner/03_get_status.py +0 -0
  109. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/beginner/04_set_temperature.py +0 -0
  110. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/advanced_auth_patterns.py +0 -0
  111. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/command_queue.py +0 -0
  112. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/device_status_callback.py +0 -0
  113. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/error_handling.py +0 -0
  114. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/event_driven_control.py +0 -0
  115. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/improved_auth.py +0 -0
  116. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/legacy_auth_constructor.py +0 -0
  117. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/mqtt_realtime_monitoring.py +0 -0
  118. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/periodic_requests.py +0 -0
  119. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/set_mode.py +0 -0
  120. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/intermediate/vacation_mode.py +0 -0
  121. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/mask.py +0 -0
  122. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/testing/periodic_device_info.py +0 -0
  123. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/testing/simple_periodic_info.py +0 -0
  124. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/testing/test_api_client.py +0 -0
  125. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/testing/test_mqtt_connection.py +0 -0
  126. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/testing/test_mqtt_messaging.py +0 -0
  127. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/examples/testing/test_periodic_minimal.py +0 -0
  128. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/README.md +0 -0
  129. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/bump_version.py +0 -0
  130. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/diagnose_mqtt_connection.py +0 -0
  131. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/extract_changelog.py +0 -0
  132. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/format.py +0 -0
  133. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/lint.py +0 -0
  134. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/setup-dev.py +0 -0
  135. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/scripts/validate_version.py +0 -0
  136. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/setup.cfg +0 -0
  137. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/setup.py +0 -0
  138. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/auth.py +0 -0
  139. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/commands.py +0 -0
  140. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/monitoring.py +0 -0
  141. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/output_formatters.py +0 -0
  142. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/cli/token_storage.py +0 -0
  143. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/command_decorators.py +0 -0
  144. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/config.py +0 -0
  145. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/converters.py +0 -0
  146. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/device_capabilities.py +0 -0
  147. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/device_info_cache.py +0 -0
  148. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/enums.py +0 -0
  149. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/events.py +0 -0
  150. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/exceptions.py +0 -0
  151. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/factory.py +0 -0
  152. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/field_factory.py +0 -0
  153. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/__init__.py +0 -0
  154. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/client.py +0 -0
  155. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/command_queue.py +0 -0
  156. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/connection.py +0 -0
  157. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/diagnostics.py +0 -0
  158. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/periodic.py +0 -0
  159. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/reconnection.py +0 -0
  160. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/subscriptions.py +0 -0
  161. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt/utils.py +0 -0
  162. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/mqtt_events.py +0 -0
  163. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/py.typed +0 -0
  164. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/temperature.py +0 -0
  165. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/topic_builder.py +0 -0
  166. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/unit_system.py +0 -0
  167. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500/utils.py +0 -0
  168. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
  169. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500_python.egg-info/entry_points.txt +0 -0
  170. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500_python.egg-info/not-zip-safe +0 -0
  171. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500_python.egg-info/requires.txt +0 -0
  172. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/src/nwp500_python.egg-info/top_level.txt +0 -0
  173. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/conftest.py +0 -0
  174. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_auth.py +0 -0
  175. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_cli_basic.py +0 -0
  176. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_cli_commands.py +0 -0
  177. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_command_decorators.py +0 -0
  178. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_command_queue.py +0 -0
  179. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_device_capabilities.py +0 -0
  180. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_device_info_cache.py +0 -0
  181. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_events.py +0 -0
  182. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_exceptions.py +0 -0
  183. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_model_converters.py +0 -0
  184. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_mqtt_client_init.py +0 -0
  185. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_mqtt_hypothesis.py +0 -0
  186. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_temperature_converters.py +0 -0
  187. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_unit_switching.py +0 -0
  188. {nwp500_python-7.4.6 → nwp500_python-7.4.7}/tests/test_utils.py +0 -0
@@ -39,13 +39,13 @@ jobs:
39
39
  with:
40
40
  python-version: '3.13'
41
41
 
42
- - name: Install tox
42
+ - name: Install ruff
43
43
  run: |
44
44
  python -m pip install --upgrade pip
45
- python -m pip install tox
45
+ python -m pip install ruff
46
46
 
47
- - name: Run bandit
48
- run: tox -e bandit
47
+ - name: Run security checks (ruff bandit)
48
+ run: ruff check --select S src/
49
49
 
50
50
  test:
51
51
  name: Test on Python ${{ matrix.python-version }}
@@ -62,3 +62,9 @@ venv*/
62
62
  .secrets
63
63
  reference/*
64
64
  resources/*
65
+
66
+ # Tool caches
67
+ .mypy_cache/
68
+ .ruff_cache/
69
+ .bandit
70
+ .agent/
@@ -2,6 +2,32 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ Version 7.4.7 (2026-02-17)
6
+ ==========================
7
+
8
+ Added
9
+ -----
10
+ - **OpenEI Client Module**: New ``OpenEIClient`` async client (``nwp500.openei``) for browsing utility rate plans from the OpenEI API by zip code. Supports listing utilities, filtering rate plans, and fetching plan details. API key read from ``OPENEI_API_KEY`` environment variable.
11
+ - **Convert TOU API**: ``NavienAPIClient.convert_tou()`` sends raw OpenEI rate data to the Navien backend for server-side conversion into device-ready TOU schedules with season/week bitfields and scaled pricing.
12
+ - **Update TOU API**: ``NavienAPIClient.update_tou()`` applies a converted TOU rate plan to a device, matching the mobile app's ``PUT /device/tou`` endpoint.
13
+ - **ConvertedTOUPlan Model**: New Pydantic model for parsed ``convert_tou()`` results (utility, name, schedule).
14
+ - **CLI ``tou rates``**: Browse utilities and rate plans for a zip code (``nwp500 tou rates 94903``).
15
+ - **CLI ``tou plan``**: View converted rate plan details with decoded pricing (``nwp500 tou plan 94903 "EV Rate A"``).
16
+ - **CLI ``tou apply``**: Apply a rate plan to the water heater with optional ``--enable`` flag to activate TOU via MQTT.
17
+ - **CLI Reservations Table Output**: ``nwp-cli reservations get`` now displays reservations as a formatted table by default with global status indicator (ENABLED/DISABLED). Use ``--json`` flag for JSON output.
18
+ - **CLI ``anti-legionella set-period``**: New subcommand to change the Anti-Legionella cycle period (1-30 days) without toggling the feature. Use ``nwp-cli anti-legionella set-period 7`` to update cycle period.
19
+
20
+ Changed
21
+ -------
22
+ - **``examples/advanced/tou_openei.py``**: Rewritten to use the new ``OpenEIClient`` and ``convert_tou()``/``update_tou()`` library methods instead of inline OpenEI API calls and client-side conversion.
23
+
24
+ Fixed
25
+ -----
26
+ - **Week Bitfield Encoding (CRITICAL)**: Fixed MGPP week bitfield encoding to match NaviLink APK protocol. Sunday is now correctly bit 7 (128), Monday bit 6 (64), ..., Saturday bit 1 (2); bit 0 is unused. Affects all reservation and TOU schedule operations. Verified against reference captures.
27
+ - **Enable/Disable Convention**: Fixed reservation and TOU enable/disable flags to use standard device boolean convention (1=OFF, 2=ON) instead of inverted logic. This aligns with other device binary sensors and matches app behavior. Global reservation status now correctly shows DISABLED when ``reservationUse=1``.
28
+ - **Reservation Set Command Timeout**: Fixed ``reservations set`` subscription pattern that had extra wildcards preventing response matching. Command now receives confirmations correctly.
29
+ - **Intermittent Fetch Bug**: Tightened MQTT topic filter for reservation fetch from ``/res/`` to ``/res/rsv/`` with content validation to prevent false matches on unrelated response messages.
30
+
5
31
  Version 7.4.6 (2026-02-13)
6
32
  ==========================
7
33
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nwp500-python
3
- Version: 7.4.6
3
+ Version: 7.4.7
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
@@ -133,6 +133,14 @@ nwp500.mqtt\_events module
133
133
  :show-inheritance:
134
134
  :undoc-members:
135
135
 
136
+ nwp500.openei module
137
+ --------------------
138
+
139
+ .. automodule:: nwp500.openei
140
+ :members:
141
+ :show-inheritance:
142
+ :undoc-members:
143
+
136
144
  nwp500.temperature module
137
145
  -------------------------
138
146
 
@@ -499,5 +499,5 @@ See Also
499
499
 
500
500
  * :doc:`../protocol/data_conversions` - Temperature field conversions (HalfCelsiusToF, DeciCelsiusToF)
501
501
  * :doc:`../protocol/device_status` - Complete device status field reference
502
- * :doc:`scheduling_features` - Reservation and TOU integration points
502
+ * :doc:`scheduling` - Scheduling and automation guide
503
503
  * :doc:`../python_api/models` - DeviceStatus model field definitions