PyPlumIO 0.6.2__tar.gz → 0.6.4__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 (153) hide show
  1. {pyplumio-0.6.2 → pyplumio-0.6.4}/.pre-commit-config.yaml +1 -1
  2. {pyplumio-0.6.2 → pyplumio-0.6.4}/PKG-INFO +5 -5
  3. {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/PKG-INFO +5 -5
  4. {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/requires.txt +4 -4
  5. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/frames.rst +4 -26
  6. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/_version.py +3 -3
  7. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/connection.py +7 -7
  8. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/__init__.py +20 -14
  9. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/ecomax.py +16 -12
  10. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/__init__.py +2 -2
  11. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/ecomax.py +3 -1
  12. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/protocol.py +68 -99
  13. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/stream.py +6 -5
  14. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/network_info.py +23 -21
  15. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/schedules.py +1 -1
  16. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/sensor_data.py +1 -3
  17. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/utils.py +6 -4
  18. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyproject.toml +4 -4
  19. {pyplumio-0.6.2 → pyplumio-0.6.4}/requirements_test.txt +4 -4
  20. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/conftest.py +1 -1
  21. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_ecomax.py +6 -6
  22. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_ecoster.py +1 -1
  23. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_init.py +3 -1
  24. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_init.py +9 -9
  25. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_mixers.py +3 -1
  26. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_thermostats.py +3 -1
  27. pyplumio-0.6.4/tests/test_protocol.py +257 -0
  28. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_stream.py +2 -2
  29. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/device_available.json +4 -4
  30. pyplumio-0.6.2/tests/test_protocol.py +0 -469
  31. {pyplumio-0.6.2 → pyplumio-0.6.4}/.gitattributes +0 -0
  32. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/CODE_OF_CONDUCT.md +0 -0
  33. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  34. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  35. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/dependabot.yml +0 -0
  36. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/ci.yml +0 -0
  37. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/codeql.yml +0 -0
  38. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/deploy.yml +0 -0
  39. {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/documentation.yml +0 -0
  40. {pyplumio-0.6.2 → pyplumio-0.6.4}/.gitignore +0 -0
  41. {pyplumio-0.6.2 → pyplumio-0.6.4}/.qlty/qlty.toml +0 -0
  42. {pyplumio-0.6.2 → pyplumio-0.6.4}/.vscode/settings.json +0 -0
  43. {pyplumio-0.6.2 → pyplumio-0.6.4}/LICENSE +0 -0
  44. {pyplumio-0.6.2 → pyplumio-0.6.4}/MANIFEST.in +0 -0
  45. {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/SOURCES.txt +0 -0
  46. {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/dependency_links.txt +0 -0
  47. {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/top_level.txt +0 -0
  48. {pyplumio-0.6.2 → pyplumio-0.6.4}/README.md +0 -0
  49. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/Makefile +0 -0
  50. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/make.bat +0 -0
  51. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/callbacks.rst +0 -0
  52. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/conf.py +0 -0
  53. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/connecting.rst +0 -0
  54. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/index.rst +0 -0
  55. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/mixers_thermostats.rst +0 -0
  56. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/protocol.rst +0 -0
  57. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/reading.rst +0 -0
  58. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/schedules.rst +0 -0
  59. {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/writing.rst +0 -0
  60. {pyplumio-0.6.2 → pyplumio-0.6.4}/images/ecomax.png +0 -0
  61. {pyplumio-0.6.2 → pyplumio-0.6.4}/images/rs485.png +0 -0
  62. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/__init__.py +0 -0
  63. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/__main__.py +0 -0
  64. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/const.py +0 -0
  65. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/data_types.py +0 -0
  66. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/ecoster.py +0 -0
  67. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/mixer.py +0 -0
  68. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/thermostat.py +0 -0
  69. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/exceptions.py +0 -0
  70. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/filters.py +0 -0
  71. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/__init__.py +0 -0
  72. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/messages.py +0 -0
  73. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/requests.py +0 -0
  74. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/responses.py +0 -0
  75. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/__init__.py +0 -0
  76. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/async_cache.py +0 -0
  77. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/event_manager.py +0 -0
  78. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/factory.py +0 -0
  79. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/task_manager.py +0 -0
  80. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/custom/__init__.py +0 -0
  81. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
  82. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/mixer.py +0 -0
  83. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/thermostat.py +0 -0
  84. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/py.typed +0 -0
  85. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/__init__.py +0 -0
  86. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/alerts.py +0 -0
  87. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/ecomax_parameters.py +0 -0
  88. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/frame_versions.py +0 -0
  89. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/mixer_parameters.py +0 -0
  90. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/product_info.py +0 -0
  91. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/program_version.py +0 -0
  92. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/regulator_data.py +0 -0
  93. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/regulator_data_schema.py +0 -0
  94. {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/thermostat_parameters.py +0 -0
  95. {pyplumio-0.6.2 → pyplumio-0.6.4}/requirements.txt +0 -0
  96. {pyplumio-0.6.2 → pyplumio-0.6.4}/requirements_docs.txt +0 -0
  97. {pyplumio-0.6.2 → pyplumio-0.6.4}/setup.cfg +0 -0
  98. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/__init__.py +0 -0
  99. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/__init__.py +0 -0
  100. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_mixer.py +0 -0
  101. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_thermostat.py +0 -0
  102. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_init.py +0 -0
  103. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_messages.py +0 -0
  104. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_requests.py +0 -0
  105. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_responses.py +0 -0
  106. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/__init__.py +0 -0
  107. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_async_cache.py +0 -0
  108. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_event_manager.py +0 -0
  109. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_factory.py +0 -0
  110. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_task_manager.py +0 -0
  111. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_uid.py +0 -0
  112. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/__init__.py +0 -0
  113. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/custom/__init__.py +0 -0
  114. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
  115. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/custom/test_init.py +0 -0
  116. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_ecomax.py +0 -0
  117. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/ruff.toml +0 -0
  118. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/__init__.py +0 -0
  119. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_alerts.py +0 -0
  120. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_ecomax_parameters.py +0 -0
  121. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_frame_versions.py +0 -0
  122. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_mixer_parameters.py +0 -0
  123. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_product_info.py +0 -0
  124. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_schedules.py +0 -0
  125. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_connection.py +0 -0
  126. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_data_types.py +0 -0
  127. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_filters.py +0 -0
  128. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_init.py +0 -0
  129. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_main.py +0 -0
  130. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_utils.py +0 -0
  131. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/messages/regulator_data.json +0 -0
  132. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/messages/sensor_data.json +0 -0
  133. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
  134. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/alerts.json +0 -0
  135. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/ecomax_control.json +0 -0
  136. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/ecomax_parameters.json +0 -0
  137. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/mixer_parameters.json +0 -0
  138. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
  139. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_mixer_parameter.json +0 -0
  140. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_schedule.json +0 -0
  141. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
  142. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/thermostat_parameters.json +0 -0
  143. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/alerts.json +0 -0
  144. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/ecomax_parameters.json +0 -0
  145. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/mixer_parameters.json +0 -0
  146. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/password.json +0 -0
  147. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/program_version.json +0 -0
  148. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/regulator_data_schema.json +0 -0
  149. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/schedules.json +0 -0
  150. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/thermostat_parameters.json +0 -0
  151. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/uid.json +0 -0
  152. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
  153. {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -3,7 +3,7 @@
3
3
  # See https://pre-commit.com/hooks.html for more hooks
4
4
  repos:
5
5
  - repo: https://github.com/astral-sh/ruff-pre-commit
6
- rev: v0.14.0
6
+ rev: v0.14.4
7
7
  hooks:
8
8
  - id: ruff
9
9
  args:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPlumIO
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
5
5
  Author-email: Denis Paavilainen <denpa@denpa.pro>
6
6
  License: MIT License
@@ -25,15 +25,15 @@ License-File: LICENSE
25
25
  Requires-Dist: pyserial-asyncio==0.6
26
26
  Provides-Extra: test
27
27
  Requires-Dist: codespell==2.4.1; extra == "test"
28
- Requires-Dist: coverage==7.10.7; extra == "test"
28
+ Requires-Dist: coverage==7.11.0; extra == "test"
29
29
  Requires-Dist: freezegun==1.5.5; extra == "test"
30
30
  Requires-Dist: mypy==1.18.2; extra == "test"
31
31
  Requires-Dist: numpy<3.0.0,>=2.0.0; extra == "test"
32
32
  Requires-Dist: pyserial-asyncio-fast==0.16; extra == "test"
33
33
  Requires-Dist: pytest==8.4.2; extra == "test"
34
34
  Requires-Dist: pytest-asyncio==1.2.0; extra == "test"
35
- Requires-Dist: ruff==0.13.3; extra == "test"
36
- Requires-Dist: tox==4.30.3; extra == "test"
35
+ Requires-Dist: ruff==0.14.3; extra == "test"
36
+ Requires-Dist: tox==4.32.0; extra == "test"
37
37
  Requires-Dist: types-pyserial==3.5.0.20251001; extra == "test"
38
38
  Provides-Extra: docs
39
39
  Requires-Dist: sphinx==8.1.3; extra == "docs"
@@ -42,7 +42,7 @@ Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
42
42
  Provides-Extra: dev
43
43
  Requires-Dist: pyplumio[docs,test]; extra == "dev"
44
44
  Requires-Dist: pre-commit==4.3.0; extra == "dev"
45
- Requires-Dist: tomli==2.2.1; extra == "dev"
45
+ Requires-Dist: tomli==2.3.0; extra == "dev"
46
46
  Dynamic: license-file
47
47
 
48
48
  # PyPlumIO is a native ecoNET library for Plum ecoMAX controllers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPlumIO
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
5
5
  Author-email: Denis Paavilainen <denpa@denpa.pro>
6
6
  License: MIT License
@@ -25,15 +25,15 @@ License-File: LICENSE
25
25
  Requires-Dist: pyserial-asyncio==0.6
26
26
  Provides-Extra: test
27
27
  Requires-Dist: codespell==2.4.1; extra == "test"
28
- Requires-Dist: coverage==7.10.7; extra == "test"
28
+ Requires-Dist: coverage==7.11.0; extra == "test"
29
29
  Requires-Dist: freezegun==1.5.5; extra == "test"
30
30
  Requires-Dist: mypy==1.18.2; extra == "test"
31
31
  Requires-Dist: numpy<3.0.0,>=2.0.0; extra == "test"
32
32
  Requires-Dist: pyserial-asyncio-fast==0.16; extra == "test"
33
33
  Requires-Dist: pytest==8.4.2; extra == "test"
34
34
  Requires-Dist: pytest-asyncio==1.2.0; extra == "test"
35
- Requires-Dist: ruff==0.13.3; extra == "test"
36
- Requires-Dist: tox==4.30.3; extra == "test"
35
+ Requires-Dist: ruff==0.14.3; extra == "test"
36
+ Requires-Dist: tox==4.32.0; extra == "test"
37
37
  Requires-Dist: types-pyserial==3.5.0.20251001; extra == "test"
38
38
  Provides-Extra: docs
39
39
  Requires-Dist: sphinx==8.1.3; extra == "docs"
@@ -42,7 +42,7 @@ Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
42
42
  Provides-Extra: dev
43
43
  Requires-Dist: pyplumio[docs,test]; extra == "dev"
44
44
  Requires-Dist: pre-commit==4.3.0; extra == "dev"
45
- Requires-Dist: tomli==2.2.1; extra == "dev"
45
+ Requires-Dist: tomli==2.3.0; extra == "dev"
46
46
  Dynamic: license-file
47
47
 
48
48
  # PyPlumIO is a native ecoNET library for Plum ecoMAX controllers
@@ -3,7 +3,7 @@ pyserial-asyncio==0.6
3
3
  [dev]
4
4
  pyplumio[docs,test]
5
5
  pre-commit==4.3.0
6
- tomli==2.2.1
6
+ tomli==2.3.0
7
7
 
8
8
  [docs]
9
9
  sphinx==8.1.3
@@ -12,13 +12,13 @@ readthedocs-sphinx-search==0.3.2
12
12
 
13
13
  [test]
14
14
  codespell==2.4.1
15
- coverage==7.10.7
15
+ coverage==7.11.0
16
16
  freezegun==1.5.5
17
17
  mypy==1.18.2
18
18
  numpy<3.0.0,>=2.0.0
19
19
  pyserial-asyncio-fast==0.16
20
20
  pytest==8.4.2
21
21
  pytest-asyncio==1.2.0
22
- ruff==0.13.3
23
- tox==4.30.3
22
+ ruff==0.14.3
23
+ tox==4.32.0
24
24
  types-pyserial==3.5.0.20251001
@@ -568,6 +568,8 @@ Message
568
568
  Handler
569
569
  ^^^^^^^
570
570
 
571
+ .. autoclass:: pyplumio.structures.frame_versions.FrameVersionsStructure
572
+
571
573
  .. autoclass:: pyplumio.structures.regulator_data.RegulatorDataStructure
572
574
 
573
575
  SensorData
@@ -697,30 +699,6 @@ Message
697
699
  Handlers
698
700
  ^^^^^^^^
699
701
 
700
- .. autoclass:: pyplumio.structures.outputs.OutputsStructure
701
-
702
- .. autoclass:: pyplumio.structures.output_flags.OutputFlagsStructure
703
-
704
- .. autoclass:: pyplumio.structures.temperatures.TemperaturesStructure
705
-
706
- .. autoclass:: pyplumio.structures.statuses.StatusesStructure
707
-
708
- .. autoclass:: pyplumio.structures.pending_alerts.PendingAlertsStructure
709
-
710
- .. autoclass:: pyplumio.structures.fuel_level.FuelLevelStructure
711
-
712
- .. autoclass:: pyplumio.structures.fan_power.FanPowerStructure
713
-
714
- .. autoclass:: pyplumio.structures.boiler_load.BoilerLoadStructure
715
-
716
- .. autoclass:: pyplumio.structures.boiler_power.BoilerPowerStructure
717
-
718
- .. autoclass:: pyplumio.structures.fuel_consumption.FuelConsumptionStructure
719
-
720
- .. autoclass:: pyplumio.structures.modules.ModulesStructure
721
-
722
- .. autoclass:: pyplumio.structures.lambda_sensor.LambdaSensorStructure
723
-
724
- .. autoclass:: pyplumio.structures.thermostat_sensors.ThermostatSensorsStructure
702
+ .. autoclass:: pyplumio.structures.frame_versions.FrameVersionsStructure
725
703
 
726
- .. autoclass:: pyplumio.structures.mixer_sensors.MixerSensorsStructure
704
+ .. autoclass:: pyplumio.structures.sensor_data.SensorDataStructure
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.6.2'
32
- __version_tuple__ = version_tuple = (0, 6, 2)
31
+ __version__ = version = '0.6.4'
32
+ __version_tuple__ = version_tuple = (0, 6, 4)
33
33
 
34
- __commit_id__ = commit_id = 'g4f707ffa0'
34
+ __commit_id__ = commit_id = 'gc17c7ed5e'
@@ -19,8 +19,8 @@ from pyplumio.utils import timeout
19
19
 
20
20
  _LOGGER = logging.getLogger(__name__)
21
21
 
22
- CONNECT_TIMEOUT: Final = 5
23
- RECONNECT_TIMEOUT: Final = 20
22
+ TRY_CONNECT_FOR_SECONDS: Final = 5
23
+ RECONNECT_AFTER_SECONDS: Final = 20
24
24
 
25
25
  try:
26
26
  import serial_asyncio_fast as pyserial_asyncio
@@ -88,9 +88,9 @@ class Connection(ABC, TaskManager):
88
88
  except ConnectionFailedError:
89
89
  _LOGGER.error(
90
90
  "Can't connect to the device, retrying in %.1f seconds",
91
- RECONNECT_TIMEOUT,
91
+ RECONNECT_AFTER_SECONDS,
92
92
  )
93
- await asyncio.sleep(RECONNECT_TIMEOUT)
93
+ await asyncio.sleep(RECONNECT_AFTER_SECONDS)
94
94
  self.create_task(self._reconnect(), name="reconnect_task")
95
95
 
96
96
  async def connect(self) -> None:
@@ -126,7 +126,7 @@ class Connection(ABC, TaskManager):
126
126
  """Return connection options."""
127
127
  return self._options
128
128
 
129
- @timeout(CONNECT_TIMEOUT)
129
+ @timeout(TRY_CONNECT_FOR_SECONDS)
130
130
  @abstractmethod
131
131
  async def _open_connection(
132
132
  self,
@@ -162,7 +162,7 @@ class TcpConnection(Connection):
162
162
  f"TcpConnection(host={self.host}, port={self.port}, options={self.options})"
163
163
  )
164
164
 
165
- @timeout(CONNECT_TIMEOUT)
165
+ @timeout(TRY_CONNECT_FOR_SECONDS)
166
166
  async def _open_connection(
167
167
  self,
168
168
  ) -> tuple[asyncio.StreamReader, asyncio.StreamWriter]:
@@ -203,7 +203,7 @@ class SerialConnection(Connection):
203
203
  f"options={self.options})"
204
204
  )
205
205
 
206
- @timeout(CONNECT_TIMEOUT)
206
+ @timeout(TRY_CONNECT_FOR_SECONDS)
207
207
  async def _open_connection(
208
208
  self,
209
209
  ) -> tuple[asyncio.StreamReader, asyncio.StreamWriter]:
@@ -52,14 +52,18 @@ def get_device_handler(device_type: int) -> str:
52
52
  class Device(ABC, EventManager):
53
53
  """Represents a device."""
54
54
 
55
- __slots__ = ("queue",)
55
+ __slots__ = ("_write_queue",)
56
56
 
57
- queue: asyncio.Queue[Frame]
57
+ _write_queue: asyncio.Queue[Frame]
58
58
 
59
- def __init__(self, queue: asyncio.Queue[Frame]) -> None:
59
+ def __init__(self, write_queue: asyncio.Queue[Frame]) -> None:
60
60
  """Initialize a new device."""
61
61
  super().__init__()
62
- self.queue = queue
62
+ self._write_queue = write_queue
63
+
64
+ def queue_send(self, frame: Frame) -> None:
65
+ """Send frame to the write queue."""
66
+ self._write_queue.put_nowait(frame)
63
67
 
64
68
  async def set(
65
69
  self,
@@ -130,17 +134,19 @@ class PhysicalDevice(Device, ABC):
130
134
  virtual devices associated with them via parent property.
131
135
  """
132
136
 
133
- __slots__ = ("address", "_network", "_frame_versions")
137
+ __slots__ = ("address", "_network_info", "_frame_versions")
134
138
 
135
139
  address: ClassVar[int]
136
140
 
137
- _network: NetworkInfo
141
+ _network_info: NetworkInfo
138
142
  _frame_versions: dict[int, int]
139
143
 
140
- def __init__(self, queue: asyncio.Queue[Frame], network: NetworkInfo) -> None:
144
+ def __init__(
145
+ self, write_queue: asyncio.Queue[Frame], network_info: NetworkInfo
146
+ ) -> None:
141
147
  """Initialize a new physical device."""
142
- super().__init__(queue)
143
- self._network = network
148
+ super().__init__(write_queue)
149
+ self._network_info = network_info
144
150
  self._frame_versions = {}
145
151
 
146
152
  @event_listener(filter=on_change)
@@ -167,7 +173,7 @@ class PhysicalDevice(Device, ABC):
167
173
  """Request frame version from the device."""
168
174
  _LOGGER.debug("Updating frame %s to version %i", repr(frame_type), version)
169
175
  request = await Request.create(frame_type, recipient=self.address)
170
- self.queue.put_nowait(request)
176
+ self.queue_send(request)
171
177
 
172
178
  def has_frame_version(self, frame_type: FrameType | int, version: int) -> bool:
173
179
  """Return True if frame data is up to date, False otherwise."""
@@ -199,7 +205,7 @@ class PhysicalDevice(Device, ABC):
199
205
  initial_retries = retries
200
206
  while retries > 0:
201
207
  try:
202
- self.queue.put_nowait(request)
208
+ self.queue_send(request)
203
209
  return await self.get(name, timeout=timeout)
204
210
  except asyncio.TimeoutError:
205
211
  retries -= 1
@@ -211,7 +217,7 @@ class PhysicalDevice(Device, ABC):
211
217
  )
212
218
 
213
219
  @classmethod
214
- async def create(cls, device_type: int, **kwargs: Any) -> PhysicalDevice:
220
+ async def create(cls, device_type: DeviceType, **kwargs: Any) -> PhysicalDevice:
215
221
  """Create a physical device handler object."""
216
222
  return await create_instance(get_device_handler(device_type), cls=cls, **kwargs)
217
223
 
@@ -225,10 +231,10 @@ class VirtualDevice(Device, ABC):
225
231
  index: int
226
232
 
227
233
  def __init__(
228
- self, queue: asyncio.Queue[Frame], parent: PhysicalDevice, index: int = 0
234
+ self, write_queue: asyncio.Queue[Frame], parent: PhysicalDevice, index: int = 0
229
235
  ) -> None:
230
236
  """Initialize a new sub-device."""
231
- super().__init__(queue)
237
+ super().__init__(write_queue)
232
238
  self.parent = parent
233
239
  self.index = index
234
240
 
@@ -42,7 +42,7 @@ from pyplumio.structures.ecomax_parameters import (
42
42
  ATTR_ECOMAX_PARAMETERS,
43
43
  )
44
44
  from pyplumio.structures.mixer_parameters import ATTR_MIXER_PARAMETERS
45
- from pyplumio.structures.network_info import ATTR_NETWORK, NetworkInfo
45
+ from pyplumio.structures.network_info import ATTR_NETWORK_INFO, NetworkInfo
46
46
  from pyplumio.structures.product_info import ATTR_PRODUCT, ProductInfo
47
47
  from pyplumio.structures.regulator_data_schema import ATTR_REGDATA_SCHEMA
48
48
  from pyplumio.structures.schedules import (
@@ -121,7 +121,7 @@ REQUIRED_KEYS: tuple[DataKey, ...] = (
121
121
 
122
122
  REQUIRED_TYPES = [frame_type for _, frame_type in REQUIRED_KEYS]
123
123
 
124
- SETUP_TIMEOUT: Final = 60.0
124
+ WAIT_FOR_SETUP_SECONDS: Final = 60.0
125
125
 
126
126
 
127
127
  @device_handler(DeviceType.ECOMAX)
@@ -132,34 +132,38 @@ class EcoMAX(PhysicalDevice):
132
132
 
133
133
  _fuel_meter: FuelMeter
134
134
 
135
- def __init__(self, queue: asyncio.Queue[Frame], network: NetworkInfo) -> None:
135
+ def __init__(
136
+ self, write_queue: asyncio.Queue[Frame], network_info: NetworkInfo
137
+ ) -> None:
136
138
  """Initialize a new ecoMAX controller."""
137
- super().__init__(queue, network)
139
+ super().__init__(write_queue, network_info)
138
140
  self._fuel_meter = FuelMeter()
139
141
 
140
142
  def handle_frame(self, frame: Frame) -> None:
141
143
  """Handle frame received from the ecoMAX device."""
142
144
  if isinstance(frame, Request) and (
143
- response := frame.response(data={ATTR_NETWORK: self._network})
145
+ response := frame.response(data={ATTR_NETWORK_INFO: self._network_info})
144
146
  ):
145
- self.queue.put_nowait(response)
147
+ self.queue_send(response)
146
148
 
147
149
  super().handle_frame(frame)
148
150
 
149
151
  def _mixers(self, indexes: Iterable[int]) -> Generator[Mixer]:
150
- """Iterate through the mixer indexes.
152
+ """Iterate through indexes and yield a Mixer instance.
151
153
 
152
154
  For each index, return or create an instance of the mixer class.
153
155
  Once done, dispatch the 'mixers' event without waiting.
154
156
  """
155
157
  mixers: dict[int, Mixer] = self._data.setdefault(ATTR_MIXERS, {})
156
158
  for index in indexes:
157
- yield mixers.setdefault(index, Mixer(self.queue, parent=self, index=index))
159
+ yield mixers.setdefault(
160
+ index, Mixer(self._write_queue, parent=self, index=index)
161
+ )
158
162
 
159
163
  return self.dispatch_nowait(ATTR_MIXERS, mixers)
160
164
 
161
165
  def _thermostats(self, indexes: Iterable[int]) -> Generator[Thermostat]:
162
- """Iterate through the thermostat indexes.
166
+ """Iterate through indexes and yield a Thermostat instance.
163
167
 
164
168
  For each index, return or create an instance of the thermostat
165
169
  class. Once done, dispatch the 'thermostats' event without
@@ -168,7 +172,7 @@ class EcoMAX(PhysicalDevice):
168
172
  thermostats: dict[int, Thermostat] = self._data.setdefault(ATTR_THERMOSTATS, {})
169
173
  for index in indexes:
170
174
  yield thermostats.setdefault(
171
- index, Thermostat(self.queue, parent=self, index=index)
175
+ index, Thermostat(self._write_queue, parent=self, index=index)
172
176
  )
173
177
 
174
178
  return self.dispatch_nowait(ATTR_THERMOSTATS, thermostats)
@@ -220,11 +224,11 @@ class EcoMAX(PhysicalDevice):
220
224
  _LOGGER.debug("Setting up device entry")
221
225
 
222
226
  try:
223
- await self.wait_for(ATTR_SENSORS, timeout=SETUP_TIMEOUT)
227
+ await self.wait_for(ATTR_SENSORS, timeout=WAIT_FOR_SETUP_SECONDS)
224
228
  except asyncio.TimeoutError:
225
229
  _LOGGER.error(
226
230
  "Could not setup device entry; no response from device for %u seconds",
227
- SETUP_TIMEOUT,
231
+ WAIT_FOR_SETUP_SECONDS,
228
232
  )
229
233
  return False
230
234
 
@@ -204,7 +204,7 @@ class Parameter(ABC):
204
204
  self._values = replace(self._values, value=value)
205
205
  request = await self.create_request()
206
206
  if self.description.optimistic:
207
- await self.device.queue.put(request)
207
+ self.device.queue_send(request)
208
208
  return True
209
209
 
210
210
  self.update_done.clear()
@@ -233,7 +233,7 @@ class Parameter(ABC):
233
233
 
234
234
  async def _send_update_request(self, request: Request, timeout: float) -> bool:
235
235
  """Send update request to the remote and confirm the result."""
236
- await self.device.queue.put(request)
236
+ self.device.queue_send(request)
237
237
  with suppress(asyncio.TimeoutError):
238
238
  # Wait for the update to be done
239
239
  await asyncio.wait_for(self.update_done.wait(), timeout=timeout)
@@ -435,7 +435,9 @@ PARAMETER_TYPES: dict[ProductType, list[EcomaxParameterDescription]] = {
435
435
  name="feeder_calibration",
436
436
  ),
437
437
  EcomaxNumberDescription(
438
- name="fuel_factor",
438
+ name="fuel_tank_capacity",
439
+ step=50.0,
440
+ unit_of_measurement=UnitOfMeasurement.KILOGRAMS,
439
441
  ),
440
442
  EcomaxNumberDescription(
441
443
  name="fuel_calorific_value",