nwp500-python 9.4.0__tar.gz → 9.4.1__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 (228) hide show
  1. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/CHANGELOG.rst +14 -0
  2. {nwp500_python-9.4.0/src/nwp500_python.egg-info → nwp500_python-9.4.1}/PKG-INFO +1 -1
  3. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/explanation/tank-energy.rst +7 -7
  4. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/data_conversions.rst +1 -1
  5. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/models.rst +1 -1
  6. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/converters.py +1 -1
  7. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/reconnection.py +7 -0
  8. {nwp500_python-9.4.0 → nwp500_python-9.4.1/src/nwp500_python.egg-info}/PKG-INFO +1 -1
  9. nwp500_python-9.4.1/src/nwp500_python.egg-info/scm_version.json +8 -0
  10. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_reliability.py +39 -0
  11. nwp500_python-9.4.0/src/nwp500_python.egg-info/scm_version.json +0 -8
  12. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.coveragerc +0 -0
  13. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.github/RESOLVING_PR_COMMENTS.md +0 -0
  14. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.github/copilot-instructions.md +0 -0
  15. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.github/workflows/ci.yml +0 -0
  16. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.github/workflows/release.yml +0 -0
  17. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.gitignore +0 -0
  18. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.pre-commit-config.yaml +0 -0
  19. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/.readthedocs.yml +0 -0
  20. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/AUTHORS.rst +0 -0
  21. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/CONTRIBUTING.rst +0 -0
  22. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/LICENSE.txt +0 -0
  23. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/Makefile +0 -0
  24. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/README.rst +0 -0
  25. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/RELEASE.md +0 -0
  26. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/Makefile +0 -0
  27. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/_static/.gitignore +0 -0
  28. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/conf.py +0 -0
  29. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/explanation/advanced-features.rst +0 -0
  30. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/explanation/architecture.rst +0 -0
  31. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/explanation/index.rst +0 -0
  32. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/explanation/tou-recovery-cap.rst +0 -0
  33. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/explanation/unknown-values.rst +0 -0
  34. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/authenticate.rst +0 -0
  35. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/auto-recovery.rst +0 -0
  36. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/diagnose-mqtt.rst +0 -0
  37. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/home-assistant.rst +0 -0
  38. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/index.rst +0 -0
  39. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/maintenance.rst +0 -0
  40. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/manage-units.rst +0 -0
  41. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/monitor-status.rst +0 -0
  42. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/optimize-tou.rst +0 -0
  43. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/queue-commands.rst +0 -0
  44. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/schedule-operation.rst +0 -0
  45. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/how-to/track-energy.rst +0 -0
  46. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/index.rst +0 -0
  47. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/openapi.yaml +0 -0
  48. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/project/authors.rst +0 -0
  49. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/project/changelog.rst +0 -0
  50. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/project/contributing.rst +0 -0
  51. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/project/history.rst +0 -0
  52. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/project/license.rst +0 -0
  53. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/configuration.rst +0 -0
  54. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/enumerations.rst +0 -0
  55. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/index.rst +0 -0
  56. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/installation.rst +0 -0
  57. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/device_features.rst +0 -0
  58. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/device_status.rst +0 -0
  59. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/error_codes.rst +0 -0
  60. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/mqtt_protocol.rst +0 -0
  61. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/quick_reference.rst +0 -0
  62. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/protocol/rest_api.rst +0 -0
  63. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/api_client.rst +0 -0
  64. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/auth_client.rst +0 -0
  65. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/cli.rst +0 -0
  66. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/events.rst +0 -0
  67. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/exceptions.rst +0 -0
  68. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/reference/python_api/mqtt_client.rst +0 -0
  69. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/requirements.txt +0 -0
  70. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/docs/tutorials/getting-started.rst +0 -0
  71. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/.ruff.toml +0 -0
  72. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/README.md +0 -0
  73. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/air_filter_reset.py +0 -0
  74. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/anti_legionella.py +0 -0
  75. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/auto_recovery.py +0 -0
  76. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/combined_callbacks.py +0 -0
  77. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/demand_response.py +0 -0
  78. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/device_capabilities.py +0 -0
  79. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/device_status_debug.py +0 -0
  80. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/energy_analytics.py +0 -0
  81. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/error_code_demo.py +0 -0
  82. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/firmware_payload_capture.py +0 -0
  83. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/mqtt_diagnostics.py +0 -0
  84. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/power_control.py +0 -0
  85. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/recirculation_control.py +0 -0
  86. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/reconnection_demo.py +0 -0
  87. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/reservation_schedule.py +0 -0
  88. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/simple_auto_recovery.py +0 -0
  89. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/token_restoration.py +0 -0
  90. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/tou_openei.py +0 -0
  91. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/tou_schedule.py +0 -0
  92. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/advanced/water_reservation.py +0 -0
  93. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/beginner/01_authentication.py +0 -0
  94. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/beginner/02_list_devices.py +0 -0
  95. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/beginner/03_get_status.py +0 -0
  96. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/beginner/04_set_temperature.py +0 -0
  97. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/advanced_auth_patterns.py +0 -0
  98. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/command_queue.py +0 -0
  99. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/device_status_callback.py +0 -0
  100. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/error_handling.py +0 -0
  101. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/event_driven_control.py +0 -0
  102. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/improved_auth.py +0 -0
  103. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/legacy_auth_constructor.py +0 -0
  104. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/mqtt_realtime_monitoring.py +0 -0
  105. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/periodic_requests.py +0 -0
  106. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/set_mode.py +0 -0
  107. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/intermediate/vacation_mode.py +0 -0
  108. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/mask.py +0 -0
  109. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/testing/periodic_device_info.py +0 -0
  110. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/testing/simple_periodic_info.py +0 -0
  111. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/testing/test_api_client.py +0 -0
  112. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/testing/test_mqtt_connection.py +0 -0
  113. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/testing/test_mqtt_messaging.py +0 -0
  114. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/examples/testing/test_periodic_minimal.py +0 -0
  115. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/pyproject.toml +0 -0
  116. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/README.md +0 -0
  117. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/bump_version.py +0 -0
  118. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/diagnose_mqtt_connection.py +0 -0
  119. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/extract_changelog.py +0 -0
  120. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/format.py +0 -0
  121. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/lint.py +0 -0
  122. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/setup-dev.py +0 -0
  123. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/scripts/validate_version.py +0 -0
  124. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/setup.cfg +0 -0
  125. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/setup.py +0 -0
  126. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/__init__.py +0 -0
  127. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/_base.py +0 -0
  128. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/api_client.py +0 -0
  129. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/auth.py +0 -0
  130. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/__init__.py +0 -0
  131. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/__main__.py +0 -0
  132. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/handlers.py +0 -0
  133. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/monitoring.py +0 -0
  134. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/output_formatters.py +0 -0
  135. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/presentation.py +0 -0
  136. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/rich_output.py +0 -0
  137. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/cli/token_storage.py +0 -0
  138. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/command_decorators.py +0 -0
  139. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/config.py +0 -0
  140. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/device_capabilities.py +0 -0
  141. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/device_info_cache.py +0 -0
  142. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/encoding.py +0 -0
  143. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/enums.py +0 -0
  144. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/events.py +0 -0
  145. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/exceptions.py +0 -0
  146. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/factory.py +0 -0
  147. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/field_factory.py +0 -0
  148. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/__init__.py +0 -0
  149. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/_converters.py +0 -0
  150. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/device.py +0 -0
  151. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/diagnostics.py +0 -0
  152. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/energy.py +0 -0
  153. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/feature.py +0 -0
  154. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/firmware.py +0 -0
  155. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/mqtt_models.py +0 -0
  156. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/schedule.py +0 -0
  157. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/status.py +0 -0
  158. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/models/tou.py +0 -0
  159. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/__init__.py +0 -0
  160. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/_control_commands.py +0 -0
  161. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/_device_subscriptions.py +0 -0
  162. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/client.py +0 -0
  163. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/command_queue.py +0 -0
  164. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/connection.py +0 -0
  165. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/control.py +0 -0
  166. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/diagnostics.py +0 -0
  167. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/periodic.py +0 -0
  168. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/state_tracker.py +0 -0
  169. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/subscriptions.py +0 -0
  170. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/types.py +0 -0
  171. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt/utils.py +0 -0
  172. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/mqtt_events.py +0 -0
  173. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/openei.py +0 -0
  174. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/py.typed +0 -0
  175. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/reservations.py +0 -0
  176. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/temperature.py +0 -0
  177. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/topic_builder.py +0 -0
  178. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/tou_schedule.py +0 -0
  179. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/unit_system.py +0 -0
  180. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500/utils.py +0 -0
  181. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/SOURCES.txt +0 -0
  182. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
  183. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/entry_points.txt +0 -0
  184. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/not-zip-safe +0 -0
  185. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/requires.txt +0 -0
  186. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/scm_file_list.json +0 -0
  187. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/src/nwp500_python.egg-info/top_level.txt +0 -0
  188. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/conftest.py +0 -0
  189. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_api_helpers.py +0 -0
  190. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_app_queries.py +0 -0
  191. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_auth.py +0 -0
  192. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_auth_session_lifecycle.py +0 -0
  193. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_bug_fixes.py +0 -0
  194. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_canonical_schedule.py +0 -0
  195. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_cli_basic.py +0 -0
  196. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_cli_commands.py +0 -0
  197. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_cli_tristate_presentation.py +0 -0
  198. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_command_decorators.py +0 -0
  199. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_command_queue.py +0 -0
  200. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_device_capabilities.py +0 -0
  201. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_device_info_cache.py +0 -0
  202. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_device_rest_models.py +0 -0
  203. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_events.py +0 -0
  204. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_exceptions.py +0 -0
  205. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_model_converters.py +0 -0
  206. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_models.py +0 -0
  207. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_clean_session_resume.py +0 -0
  208. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_client_init.py +0 -0
  209. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_events.py +0 -0
  210. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_hypothesis.py +0 -0
  211. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_reconnection.py +0 -0
  212. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_mqtt_reconnection_storm.py +0 -0
  213. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_multi_device.py +0 -0
  214. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_openei.py +0 -0
  215. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_protocol_correctness.py +0 -0
  216. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_public_api.py +0 -0
  217. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_reservations.py +0 -0
  218. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_temperature_converters.py +0 -0
  219. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_threading_model.py +0 -0
  220. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_token_storage.py +0 -0
  221. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_tou_api.py +0 -0
  222. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_tou_schedule.py +0 -0
  223. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_unit_switching.py +0 -0
  224. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_unit_system_process_wide.py +0 -0
  225. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_utility_modules.py +0 -0
  226. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tests/test_utils.py +0 -0
  227. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/tox.ini +0 -0
  228. {nwp500_python-9.4.0 → nwp500_python-9.4.1}/uv.lock +0 -0
@@ -5,6 +5,20 @@ Changelog
5
5
  Unreleased
6
6
  ==========
7
7
 
8
+ Version 9.4.1 (2026-09-17)
9
+ ==========================
10
+
11
+ Fixed
12
+ -----
13
+ - **The reconnect attempt counter never reset after a successful quick or
14
+ deep reconnect.** Both build a new connection, so the SDK never calls
15
+ ``on_connection_resumed``, the only place the counter was reset. Each
16
+ later interruption started where the last one stopped: its first delay
17
+ was longer and it reached the deep-reconnect threshold sooner. A
18
+ long-running client saw the first delay grow from about 1 s to 12 s
19
+ over five daily AWS IoT disconnects. The counter now resets whenever the
20
+ backoff loop ends connected.
21
+
8
22
  Version 9.4.0 (2026-09-12)
9
23
  ==========================
10
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nwp500-python
3
- Version: 9.4.0
3
+ Version: 9.4.1
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
@@ -3,7 +3,7 @@ Tank Energy
3
3
  ===========
4
4
 
5
5
  The NWP500 reports two energy figures, ``totalEnergyCapacity`` and
6
- ``availableEnergyCapacity``. Both names mislead, and before v10.0 this
6
+ ``availableEnergyCapacity``. Both names mislead, and before v9.3.0 this
7
7
  library also scaled them wrongly. This page explains what they
8
8
  actually measure and shows the evidence for the correction.
9
9
 
@@ -33,7 +33,7 @@ The short version
33
33
  whenever the setpoint moves.
34
34
 
35
35
  Both are raw counts of 4 Wh each, not Watt-hours. Library versions before
36
- 10.0 multiplied by 10, overstating tank energy by 2.5x.
36
+ 9.3.0 multiplied by 10, overstating tank energy by 2.5x.
37
37
 
38
38
  Both are also measured **from the setpoint**, so both describe potential
39
39
  rather than content: move the setpoint and both change while the water in
@@ -226,7 +226,7 @@ coefficient of performance:
226
226
  * - 4 Wh/count (corrected)
227
227
  - 2.89
228
228
  - Normal for a heat pump water heater
229
- * - 10 Wh/count (pre-10.0)
229
+ * - 10 Wh/count (pre-9.3.0)
230
230
  - 7.02
231
231
  - Physically impossible
232
232
 
@@ -236,7 +236,7 @@ A heat pump water heater in a 72 degF room runs at a COP of roughly 2 to
236
236
  This argument is worth stating separately because it needs no tank
237
237
  volume, specific heat or stratification model - only the device's own
238
238
  reported energy and its own reported power. It cannot tell you what the
239
- quantum *is*, but it rules out the pre-10.0 value regardless of anything
239
+ quantum *is*, but it rules out the pre-9.3.0 value regardless of anything
240
240
  assumed elsewhere on this page.
241
241
 
242
242
  .. _two branches:
@@ -403,8 +403,8 @@ the heat capacity is 156 Wh per degF:
403
403
  drawable_Wh = 156 * (tank_mean_temperature - your_floor_degF)
404
404
 
405
405
 
406
- Migrating from before v10.0
407
- ===========================
406
+ Migrating from before v9.3.0
407
+ ============================
408
408
 
409
409
  .. list-table::
410
410
  :header-rows: 1
@@ -429,7 +429,7 @@ rename that is missed fails immediately with ``AttributeError`` instead
429
429
  of silently returning a number 2.5x too large.
430
430
 
431
431
  If you logged these values historically, the stored series needs
432
- rescaling by 0.4 to be comparable with values from v10.0 onward.
432
+ rescaling by 0.4 to be comparable with values from v9.3.0 onward.
433
433
 
434
434
 
435
435
  See also
@@ -367,7 +367,7 @@ Power and Energy Fields
367
367
  candidate implying a water volume below the nameplate. Two further
368
368
  checks agree -- 183 heating recoveries give 4.11 Wh/count by a
369
369
  noisier route, and the same recoveries imply a heat-pump COP of 2.89.
370
- The library uses 4.0. Versions before 10.0 used 10, which overstated
370
+ The library uses 4.0. Versions before 9.3.0 used 10, which overstated
371
371
  reported tank energy by 2.5x and implied a physically impossible COP
372
372
  of 7.0. See :doc:`../../explanation/tank-energy`.
373
373
 
@@ -263,7 +263,7 @@ Complete real-time device status with 100+ fields.
263
263
 
264
264
  .. warning::
265
265
  These replace ``total_energy_capacity`` and
266
- ``available_energy_capacity``, which were **removed** in v10.0. The
266
+ ``available_energy_capacity``, which were **removed** in v9.3.0. The
267
267
  old names were misleading -- ``available_energy_capacity`` is the
268
268
  energy *needed*, not the energy available -- and both were scaled
269
269
  2.5x too large. For energy you can actually draw, see
@@ -45,7 +45,7 @@ __all__ = [
45
45
  #: p90 4.45), agreeing to within 2% by a noisier route
46
46
  #: * the same recoveries imply a heat pump COP of 2.89 at 4 Wh/count
47
47
  #:
48
- #: Library versions before 10.0 used 10 Wh/count, which overstated reported
48
+ #: Library versions before 9.3.0 used 10 Wh/count, which overstated reported
49
49
  #: tank energy by 2.5x and implied a physically impossible COP of 7.0.
50
50
  #:
51
51
  #: See ``docs/explanation/tank-energy.rst`` for the full derivation.
@@ -347,6 +347,13 @@ class MqttReconnectionHandler:
347
347
  f"Error during reconnection attempt: {e}", exc_info=True
348
348
  )
349
349
 
350
+ # A successful quick or deep reconnect builds a new connection, so
351
+ # the SDK never calls on_connection_resumed for it. Reset the
352
+ # counter here, or every later interruption starts with a longer
353
+ # backoff and an earlier deep reconnect than the first one did.
354
+ if self._is_connected_func():
355
+ self._reconnect_attempts = 0
356
+
350
357
  # Check final state: report failure when retries are exhausted
351
358
  # (limited mode) or a fatal error stopped the loop.
352
359
  attempts_exhausted = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nwp500-python
3
- Version: 9.4.0
3
+ Version: 9.4.1
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
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "9.4.1",
3
+ "distance": 0,
4
+ "node": "g36a97ba8f8ce20912973b352fe380686a4f46ad1",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-17"
8
+ }
@@ -231,6 +231,45 @@ class TestReconnectLoopExceptionHandling:
231
231
  assert all(d <= config.max_reconnect_delay for d in sleeps)
232
232
  assert all(d > 0 for d in sleeps)
233
233
 
234
+ @pytest.mark.asyncio
235
+ @pytest.mark.parametrize("deep", [False, True])
236
+ async def test_successful_reconnect_resets_attempt_count(self, deep):
237
+ """Regression: a quick or deep reconnect makes a new connection, so
238
+ on_connection_resumed never fires and the counter kept growing
239
+ across interruptions, lengthening each later backoff."""
240
+ connected = False
241
+ attempts = []
242
+
243
+ async def reconnect():
244
+ nonlocal connected
245
+ attempts.append(1)
246
+ # Fail the first try of each interruption, then succeed.
247
+ if len(attempts) % 2 == 0:
248
+ connected = True
249
+ return
250
+ raise MqttNotConnectedError("down")
251
+
252
+ kwargs = {"deep_reconnect_func": reconnect} if deep else {}
253
+ config = _fast_config(
254
+ max_reconnect_attempts=-1,
255
+ deep_reconnect_threshold=1,
256
+ )
257
+ handler = _make_handler(
258
+ config,
259
+ lambda: connected,
260
+ reconnect,
261
+ **kwargs,
262
+ )
263
+ handler.enable()
264
+
265
+ for _ in range(3):
266
+ connected = False
267
+ await handler._reconnect_with_backoff()
268
+ assert connected
269
+ assert handler.attempt_count == 0
270
+
271
+ assert len(attempts) == 6
272
+
234
273
 
235
274
  class TestDisconnectDuringInterruption:
236
275
  """disconnect() must fully shut down even when not connected."""
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "9.4.0",
3
- "distance": 0,
4
- "node": "g14ff7fc4c8672df4b22b6ec222f49a67fcf78a50",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-09-13"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes