PyPlumIO 0.5.16__tar.gz → 0.5.18__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 (144) hide show
  1. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.pre-commit-config.yaml +2 -2
  2. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PKG-INFO +10 -10
  3. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/PKG-INFO +10 -10
  4. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/requires.txt +9 -9
  5. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/schedules.rst +3 -3
  6. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/_version.py +2 -2
  7. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/__init__.py +2 -2
  8. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/ecomax.py +2 -2
  9. pyplumio-0.5.18/pyplumio/helpers/factory.py +28 -0
  10. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/parameter.py +5 -6
  11. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/schedule.py +7 -8
  12. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/protocol.py +11 -8
  13. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/stream.py +2 -2
  14. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/ecomax_parameters.py +27 -38
  15. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/mixer_parameters.py +17 -16
  16. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/schedules.py +11 -10
  17. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/thermostat_parameters.py +20 -19
  18. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyproject.toml +9 -9
  19. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/requirements_docs.txt +1 -1
  20. pyplumio-0.5.18/requirements_test.txt +11 -0
  21. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_factory.py +7 -7
  22. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_parameter.py +4 -5
  23. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_schedule.py +4 -4
  24. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_devices.py +26 -13
  25. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_protocol.py +1 -1
  26. PyPlumIO-0.5.16/pyplumio/helpers/factory.py +0 -20
  27. PyPlumIO-0.5.16/requirements_test.txt +0 -11
  28. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.gitattributes +0 -0
  29. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/CODE_OF_CONDUCT.md +0 -0
  30. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  31. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  32. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/dependabot.yml +0 -0
  33. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/ci.yml +0 -0
  34. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/codeql-analysis.yml +0 -0
  35. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/deploy.yml +0 -0
  36. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/documentation.yml +0 -0
  37. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.gitignore +0 -0
  38. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.vscode/settings.json +0 -0
  39. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/LICENSE +0 -0
  40. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/MANIFEST.in +0 -0
  41. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/SOURCES.txt +0 -0
  42. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/dependency_links.txt +0 -0
  43. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/top_level.txt +0 -0
  44. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/README.md +0 -0
  45. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/Makefile +0 -0
  46. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/make.bat +0 -0
  47. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/callbacks.rst +0 -0
  48. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/conf.py +0 -0
  49. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/connecting.rst +0 -0
  50. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/index.rst +0 -0
  51. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/mixers_thermostats.rst +0 -0
  52. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/protocol.rst +0 -0
  53. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/reading.rst +0 -0
  54. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/writing.rst +0 -0
  55. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/images/ecomax.png +0 -0
  56. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/images/rs485.png +0 -0
  57. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/__init__.py +0 -0
  58. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/__main__.py +0 -0
  59. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/connection.py +0 -0
  60. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/const.py +0 -0
  61. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/ecoster.py +0 -0
  62. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/mixer.py +0 -0
  63. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/thermostat.py +0 -0
  64. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/exceptions.py +0 -0
  65. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/filters.py +0 -0
  66. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/__init__.py +0 -0
  67. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/messages.py +0 -0
  68. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/requests.py +0 -0
  69. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/responses.py +0 -0
  70. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/__init__.py +0 -0
  71. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/data_types.py +0 -0
  72. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/event_manager.py +0 -0
  73. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/task_manager.py +0 -0
  74. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/timeout.py +0 -0
  75. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/typing.py +0 -0
  76. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/uid.py +0 -0
  77. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/py.typed +0 -0
  78. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/__init__.py +0 -0
  79. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/alerts.py +0 -0
  80. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/boiler_load.py +0 -0
  81. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/boiler_power.py +0 -0
  82. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/fan_power.py +0 -0
  83. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/frame_versions.py +0 -0
  84. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/fuel_consumption.py +0 -0
  85. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/fuel_level.py +0 -0
  86. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/lambda_sensor.py +0 -0
  87. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/mixer_sensors.py +0 -0
  88. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/modules.py +0 -0
  89. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/network_info.py +0 -0
  90. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/output_flags.py +0 -0
  91. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/outputs.py +0 -0
  92. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/pending_alerts.py +0 -0
  93. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/product_info.py +0 -0
  94. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/program_version.py +0 -0
  95. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/regulator_data.py +0 -0
  96. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/regulator_data_schema.py +0 -0
  97. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/statuses.py +0 -0
  98. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/temperatures.py +0 -0
  99. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/thermostat_sensors.py +0 -0
  100. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/utils.py +0 -0
  101. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/requirements.txt +0 -0
  102. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/setup.cfg +0 -0
  103. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/__init__.py +0 -0
  104. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/conftest.py +0 -0
  105. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_init.py +0 -0
  106. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_messages.py +0 -0
  107. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_requests.py +0 -0
  108. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_responses.py +0 -0
  109. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/__init__.py +0 -0
  110. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_data_types.py +0 -0
  111. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_event_manager.py +0 -0
  112. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_task_manager.py +0 -0
  113. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_timeout.py +0 -0
  114. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_uid.py +0 -0
  115. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/ruff.toml +0 -0
  116. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_connection.py +0 -0
  117. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_filters.py +0 -0
  118. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_init.py +0 -0
  119. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_main.py +0 -0
  120. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_stream.py +0 -0
  121. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_utils.py +0 -0
  122. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/messages/regulator_data.json +0 -0
  123. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/messages/sensor_data.json +0 -0
  124. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/alerts.json +0 -0
  125. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/ecomax_control.json +0 -0
  126. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/ecomax_parameters.json +0 -0
  127. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/mixer_parameters.json +0 -0
  128. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
  129. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_mixer_parameter.json +0 -0
  130. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_schedule.json +0 -0
  131. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
  132. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/thermostat_parameters.json +0 -0
  133. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/alerts.json +0 -0
  134. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/device_available.json +0 -0
  135. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/ecomax_parameters.json +0 -0
  136. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/mixer_parameters.json +0 -0
  137. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/password.json +0 -0
  138. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/program_version.json +0 -0
  139. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/regulator_data_schema.json +0 -0
  140. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/schedules.json +0 -0
  141. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/thermostat_parameters.json +0 -0
  142. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/uid.json +0 -0
  143. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
  144. {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -2,7 +2,7 @@
2
2
  # See https://pre-commit.com/hooks.html for more hooks
3
3
  repos:
4
4
  - repo: https://github.com/astral-sh/ruff-pre-commit
5
- rev: v0.3.0
5
+ rev: v0.4.2
6
6
  hooks:
7
7
  - id: ruff
8
8
  args:
@@ -12,6 +12,6 @@ repos:
12
12
  hooks:
13
13
  - id: codespell
14
14
  - repo: https://github.com/pre-commit/mirrors-mypy
15
- rev: v1.8.0
15
+ rev: v1.10.0
16
16
  hooks:
17
17
  - id: mypy
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyPlumIO
3
- Version: 0.5.16
3
+ Version: 0.5.18
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,21 +25,21 @@ License-File: LICENSE
25
25
  Requires-Dist: pyserial-asyncio==0.6
26
26
  Provides-Extra: test
27
27
  Requires-Dist: codespell==2.2.6; extra == "test"
28
- Requires-Dist: coverage==7.4.3; extra == "test"
29
- Requires-Dist: mypy==1.8.0; extra == "test"
28
+ Requires-Dist: coverage==7.5.1; extra == "test"
29
+ Requires-Dist: mypy==1.10.0; extra == "test"
30
30
  Requires-Dist: pyserial-asyncio-fast==0.11; extra == "test"
31
- Requires-Dist: pytest==8.1.0; extra == "test"
32
- Requires-Dist: pytest-asyncio==0.23.5; extra == "test"
33
- Requires-Dist: ruff==0.3.0; extra == "test"
34
- Requires-Dist: tox==4.13.0; extra == "test"
35
- Requires-Dist: types-pyserial==3.5.0.20240205; extra == "test"
31
+ Requires-Dist: pytest==8.2.0; extra == "test"
32
+ Requires-Dist: pytest-asyncio==0.23.6; extra == "test"
33
+ Requires-Dist: ruff==0.4.3; extra == "test"
34
+ Requires-Dist: tox==4.15.0; extra == "test"
35
+ Requires-Dist: types-pyserial==3.5.0.20240311; extra == "test"
36
36
  Provides-Extra: docs
37
- Requires-Dist: sphinx==7.2.6; extra == "docs"
37
+ Requires-Dist: sphinx==7.3.7; extra == "docs"
38
38
  Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "docs"
39
39
  Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
40
40
  Provides-Extra: dev
41
41
  Requires-Dist: pyplumio[docs,test]; extra == "dev"
42
- Requires-Dist: pre-commit==3.6.2; extra == "dev"
42
+ Requires-Dist: pre-commit==3.7.0; extra == "dev"
43
43
  Requires-Dist: tomli==2.0.1; extra == "dev"
44
44
 
45
45
  # PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyPlumIO
3
- Version: 0.5.16
3
+ Version: 0.5.18
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,21 +25,21 @@ License-File: LICENSE
25
25
  Requires-Dist: pyserial-asyncio==0.6
26
26
  Provides-Extra: test
27
27
  Requires-Dist: codespell==2.2.6; extra == "test"
28
- Requires-Dist: coverage==7.4.3; extra == "test"
29
- Requires-Dist: mypy==1.8.0; extra == "test"
28
+ Requires-Dist: coverage==7.5.1; extra == "test"
29
+ Requires-Dist: mypy==1.10.0; extra == "test"
30
30
  Requires-Dist: pyserial-asyncio-fast==0.11; extra == "test"
31
- Requires-Dist: pytest==8.1.0; extra == "test"
32
- Requires-Dist: pytest-asyncio==0.23.5; extra == "test"
33
- Requires-Dist: ruff==0.3.0; extra == "test"
34
- Requires-Dist: tox==4.13.0; extra == "test"
35
- Requires-Dist: types-pyserial==3.5.0.20240205; extra == "test"
31
+ Requires-Dist: pytest==8.2.0; extra == "test"
32
+ Requires-Dist: pytest-asyncio==0.23.6; extra == "test"
33
+ Requires-Dist: ruff==0.4.3; extra == "test"
34
+ Requires-Dist: tox==4.15.0; extra == "test"
35
+ Requires-Dist: types-pyserial==3.5.0.20240311; extra == "test"
36
36
  Provides-Extra: docs
37
- Requires-Dist: sphinx==7.2.6; extra == "docs"
37
+ Requires-Dist: sphinx==7.3.7; extra == "docs"
38
38
  Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "docs"
39
39
  Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
40
40
  Provides-Extra: dev
41
41
  Requires-Dist: pyplumio[docs,test]; extra == "dev"
42
- Requires-Dist: pre-commit==3.6.2; extra == "dev"
42
+ Requires-Dist: pre-commit==3.7.0; extra == "dev"
43
43
  Requires-Dist: tomli==2.0.1; extra == "dev"
44
44
 
45
45
  # PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
@@ -2,21 +2,21 @@ pyserial-asyncio==0.6
2
2
 
3
3
  [dev]
4
4
  pyplumio[docs,test]
5
- pre-commit==3.6.2
5
+ pre-commit==3.7.0
6
6
  tomli==2.0.1
7
7
 
8
8
  [docs]
9
- sphinx==7.2.6
9
+ sphinx==7.3.7
10
10
  sphinx_rtd_theme==2.0.0
11
11
  readthedocs-sphinx-search==0.3.2
12
12
 
13
13
  [test]
14
14
  codespell==2.2.6
15
- coverage==7.4.3
16
- mypy==1.8.0
15
+ coverage==7.5.1
16
+ mypy==1.10.0
17
17
  pyserial-asyncio-fast==0.11
18
- pytest==8.1.0
19
- pytest-asyncio==0.23.5
20
- ruff==0.3.0
21
- tox==4.13.0
22
- types-pyserial==3.5.0.20240205
18
+ pytest==8.2.0
19
+ pytest-asyncio==0.23.6
20
+ ruff==0.4.3
21
+ tox==4.15.0
22
+ types-pyserial==3.5.0.20240311
@@ -55,7 +55,7 @@ switches back to daytime mode from 07:00 to 00:00.
55
55
  heating_schedule = schedules["heating"]
56
56
  heating_schedule.monday.set_off(start="00:00", end="07:00")
57
57
  heating_schedule.monday.set_on(start="07:00", end="00:00")
58
- heating_schedule.commit()
58
+ await heating_schedule.commit()
59
59
 
60
60
  For clarity sake, you might want to use ``STATE_NIGHT`` and
61
61
  ``STATE_DAY`` constants from ``pyplumio.helpers.schedule`` module.
@@ -99,7 +99,7 @@ Schedule object:
99
99
  weekday.set_off("07:00", "00:00")
100
100
 
101
101
  # Commit changes to the device.
102
- heating_schedule.commit()
102
+ await heating_schedule.commit()
103
103
 
104
104
  Schedule Examples
105
105
  -----------------
@@ -131,7 +131,7 @@ Schedule Examples
131
131
  # There will be no nighttime mode on sunday.
132
132
  heating_schedule.sunday.set_state(STATE_DAY)
133
133
 
134
- heating_schedule.commit()
134
+ await heating_schedule.commit()
135
135
 
136
136
 
137
137
  asyncio.run(main())
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.5.16'
16
- __version_tuple__ = version_tuple = (0, 5, 16)
15
+ __version__ = version = '0.5.18'
16
+ __version_tuple__ = version_tuple = (0, 5, 18)
@@ -11,7 +11,7 @@ from pyplumio.const import ATTR_FRAME_ERRORS, ATTR_LOADED, DeviceType, FrameType
11
11
  from pyplumio.exceptions import UnknownDeviceError
12
12
  from pyplumio.frames import DataFrameDescription, Frame, Request, get_frame_handler
13
13
  from pyplumio.helpers.event_manager import EventManager
14
- from pyplumio.helpers.factory import factory
14
+ from pyplumio.helpers.factory import create_instance
15
15
  from pyplumio.helpers.parameter import SET_RETRIES, Parameter
16
16
  from pyplumio.helpers.typing import ParameterValueType
17
17
  from pyplumio.structures.network_info import NetworkInfo
@@ -160,7 +160,7 @@ class AddressableDevice(Device, ABC):
160
160
 
161
161
  If value is not available before timeout, retry request.
162
162
  """
163
- request: Request = factory(
163
+ request: Request = await create_instance(
164
164
  get_frame_handler(frame_type), recipient=self.address
165
165
  )
166
166
 
@@ -28,7 +28,7 @@ from pyplumio.frames import (
28
28
  get_frame_handler,
29
29
  is_known_frame_type,
30
30
  )
31
- from pyplumio.helpers.factory import factory
31
+ from pyplumio.helpers.factory import create_instance
32
32
  from pyplumio.helpers.parameter import ParameterValues
33
33
  from pyplumio.helpers.schedule import Schedule, ScheduleDay
34
34
  from pyplumio.structures.alerts import ATTR_TOTAL_ALERTS
@@ -235,7 +235,7 @@ class EcoMAX(AddressableDevice):
235
235
  and not self._has_frame_version(frame_type, version)
236
236
  ):
237
237
  # We don't have this frame or it's version has changed.
238
- request: Request = factory(
238
+ request: Request = await create_instance(
239
239
  get_frame_handler(frame_type), recipient=self.address
240
240
  )
241
241
  self.queue.put_nowait(request)
@@ -0,0 +1,28 @@
1
+ """Contains a factory helper."""
2
+ from __future__ import annotations
3
+
4
+ import asyncio
5
+ import importlib
6
+ import logging
7
+ from types import ModuleType
8
+ from typing import Any
9
+
10
+ _LOGGER = logging.getLogger(__name__)
11
+
12
+
13
+ async def _load_module(module_name: str) -> ModuleType:
14
+ """Load a module by name."""
15
+ return await asyncio.get_running_loop().run_in_executor(
16
+ None, importlib.import_module, f".{module_name}", "pyplumio"
17
+ )
18
+
19
+
20
+ async def create_instance(class_path: str, **kwargs: Any) -> Any:
21
+ """Return a class instance from the class path."""
22
+ module_name, class_name = class_path.rsplit(".", 1)
23
+ try:
24
+ module = await _load_module(module_name)
25
+ return getattr(module, class_name)(**kwargs)
26
+ except Exception:
27
+ _LOGGER.error("Failed to load module (%s)", class_path)
28
+ raise
@@ -166,6 +166,10 @@ class Parameter(ABC):
166
166
  """Set parameter as no longer pending update."""
167
167
  self._pending_update = False
168
168
 
169
+ async def create_request(self) -> Request:
170
+ """Create a request to change the parameter."""
171
+ raise NotImplementedError
172
+
169
173
  async def set(self, value: ParameterValueType, retries: int = SET_RETRIES) -> bool:
170
174
  """Set a parameter value."""
171
175
  if (value := _normalize_parameter_value(value)) == self.values.value:
@@ -188,7 +192,7 @@ class Parameter(ABC):
188
192
  self.device.unsubscribe(self.description.name, self._confirm_update)
189
193
  return False
190
194
 
191
- await self.device.queue.put(self.request)
195
+ await self.device.queue.put(await self.create_request())
192
196
  await asyncio.sleep(SET_TIMEOUT)
193
197
  retries -= 1
194
198
 
@@ -223,11 +227,6 @@ class Parameter(ABC):
223
227
  """Return the unit of measurement."""
224
228
  return self.description.unit_of_measurement
225
229
 
226
- @property
227
- def request(self) -> Request:
228
- """Return request to change the parameter."""
229
- raise NotImplementedError
230
-
231
230
 
232
231
  class BinaryParameter(Parameter):
233
232
  """Represents binary device parameter."""
@@ -9,7 +9,7 @@ from typing import Final, Literal
9
9
 
10
10
  from pyplumio.const import STATE_OFF, STATE_ON
11
11
  from pyplumio.devices import AddressableDevice
12
- from pyplumio.helpers.factory import factory
12
+ from pyplumio.helpers.factory import create_instance
13
13
  from pyplumio.structures.schedules import collect_schedule_data
14
14
 
15
15
  TIME_FORMAT: Final = "%H:%M"
@@ -158,12 +158,11 @@ class Schedule(Iterable):
158
158
  self.saturday,
159
159
  ).__iter__()
160
160
 
161
- def commit(self) -> None:
161
+ async def commit(self) -> None:
162
162
  """Commit a weekly schedule to the device."""
163
- self.device.queue.put_nowait(
164
- factory(
165
- "frames.requests.SetScheduleRequest",
166
- recipient=self.device.address,
167
- data=collect_schedule_data(self.name, self.device),
168
- )
163
+ request = await create_instance(
164
+ "frames.requests.SetScheduleRequest",
165
+ recipient=self.device.address,
166
+ data=collect_schedule_data(self.name, self.device),
169
167
  )
168
+ await self.device.queue.put(request)
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
  from abc import ABC, abstractmethod
5
5
  import asyncio
6
6
  from collections.abc import Awaitable, Callable
7
- from functools import cache
8
7
  import logging
9
8
  from typing import cast
10
9
 
@@ -19,7 +18,7 @@ from pyplumio.exceptions import (
19
18
  from pyplumio.frames import Frame
20
19
  from pyplumio.frames.requests import StartMasterRequest
21
20
  from pyplumio.helpers.event_manager import EventManager
22
- from pyplumio.helpers.factory import factory
21
+ from pyplumio.helpers.factory import create_instance
23
22
  from pyplumio.stream import FrameReader, FrameWriter
24
23
  from pyplumio.structures.network_info import (
25
24
  EthernetParameters,
@@ -202,7 +201,9 @@ class AsyncProtocol(Protocol, EventManager):
202
201
  write_queue.task_done()
203
202
 
204
203
  if (response := await reader.read()) is not None:
205
- device = self.get_device_entry(response.sender)
204
+ device = await self.get_device_entry(
205
+ cast(DeviceType, response.sender)
206
+ )
206
207
  read_queue.put_nowait((device, response))
207
208
 
208
209
  except FrameDataError as e:
@@ -229,16 +230,18 @@ class AsyncProtocol(Protocol, EventManager):
229
230
  device.handle_frame(frame)
230
231
  read_queue.task_done()
231
232
 
232
- @cache
233
- def get_device_entry(self, device_type: DeviceType) -> AddressableDevice:
233
+ async def get_device_entry(self, device_type: DeviceType) -> AddressableDevice:
234
234
  """Set up device entry."""
235
235
  handler, name = get_device_handler_and_name(device_type)
236
- return self.data.setdefault(name, self._create_device_entry(name, handler))
236
+ if name not in self.data:
237
+ self.data[name] = await self._create_device_entry(name, handler)
237
238
 
238
- def _create_device_entry(self, name: str, handler: str) -> AddressableDevice:
239
+ return self.data[name]
240
+
241
+ async def _create_device_entry(self, name: str, handler: str) -> AddressableDevice:
239
242
  """Create device entry."""
240
243
  write_queue = self.queues[1]
241
- device: AddressableDevice = factory(
244
+ device: AddressableDevice = await create_instance(
242
245
  handler, queue=write_queue, network=self._network
243
246
  )
244
247
  device.dispatch_nowait(ATTR_CONNECTED, True)
@@ -9,7 +9,7 @@ from typing import Final
9
9
  from pyplumio.const import DeviceType
10
10
  from pyplumio.exceptions import ChecksumError, ReadError
11
11
  from pyplumio.frames import FRAME_START, Frame, bcc, get_frame_handler, struct_header
12
- from pyplumio.helpers.factory import factory
12
+ from pyplumio.helpers.factory import create_instance
13
13
  from pyplumio.helpers.timeout import timeout
14
14
 
15
15
  READER_TIMEOUT: Final = 10
@@ -132,7 +132,7 @@ class FrameReader:
132
132
  if payload[-2] != bcc(header + payload[:-2]):
133
133
  raise ChecksumError(f"Incorrect frame checksum ({payload[-2]})")
134
134
 
135
- frame: Frame = factory(
135
+ frame: Frame = await create_instance(
136
136
  get_frame_handler(frame_type=payload[0]),
137
137
  recipient=recipient,
138
138
  message=payload[1:-2],
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
 
4
4
  from collections.abc import Generator
5
5
  from dataclasses import dataclass
6
- from typing import Any, Final
6
+ from typing import Any, Final, cast
7
7
 
8
8
  from pyplumio.const import (
9
9
  ATTR_INDEX,
@@ -16,7 +16,7 @@ from pyplumio.const import (
16
16
  )
17
17
  from pyplumio.devices import AddressableDevice
18
18
  from pyplumio.frames import Request
19
- from pyplumio.helpers.factory import factory
19
+ from pyplumio.helpers.factory import create_instance
20
20
  from pyplumio.helpers.parameter import (
21
21
  BinaryParameter,
22
22
  BinaryParameterDescription,
@@ -44,6 +44,31 @@ class EcomaxParameter(Parameter):
44
44
  device: AddressableDevice
45
45
  description: EcomaxParameterDescription
46
46
 
47
+ async def create_request(self) -> Request:
48
+ """Create a request to change the parameter."""
49
+ if self.description.name == ATTR_ECOMAX_CONTROL:
50
+ cls = "frames.requests.EcomaxControlRequest"
51
+ data = {ATTR_VALUE: self.values.value}
52
+ elif self.description.name == ATTR_THERMOSTAT_PROFILE:
53
+ cls = "frames.requests.SetThermostatParameterRequest"
54
+ data = {
55
+ ATTR_INDEX: self._index,
56
+ ATTR_VALUE: self.values.value,
57
+ ATTR_OFFSET: 0,
58
+ ATTR_SIZE: 1,
59
+ }
60
+ else:
61
+ cls = "frames.requests.SetEcomaxParameterRequest"
62
+ data = {
63
+ ATTR_INDEX: self._index,
64
+ ATTR_VALUE: self.values.value,
65
+ }
66
+
67
+ return cast(
68
+ Request,
69
+ await create_instance(cls, recipient=self.device.address, data=data),
70
+ )
71
+
47
72
  async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
48
73
  """Set a parameter value."""
49
74
  if isinstance(value, (int, float)):
@@ -72,42 +97,6 @@ class EcomaxParameter(Parameter):
72
97
  self.values.max_value - self.description.offset
73
98
  ) * self.description.multiplier
74
99
 
75
- @property
76
- def request(self) -> Request:
77
- """Return request to change the parameter."""
78
- if self.description.name == ATTR_ECOMAX_CONTROL:
79
- request: Request = factory(
80
- "frames.requests.EcomaxControlRequest",
81
- recipient=self.device.address,
82
- data={
83
- ATTR_VALUE: self.values.value,
84
- },
85
- )
86
-
87
- elif self.description.name == ATTR_THERMOSTAT_PROFILE:
88
- request = factory(
89
- "frames.requests.SetThermostatParameterRequest",
90
- recipient=self.device.address,
91
- data={
92
- ATTR_INDEX: self._index,
93
- ATTR_VALUE: self.values.value,
94
- ATTR_OFFSET: 0,
95
- ATTR_SIZE: 1,
96
- },
97
- )
98
-
99
- else:
100
- request = factory(
101
- "frames.requests.SetEcomaxParameterRequest",
102
- recipient=self.device.address,
103
- data={
104
- ATTR_INDEX: self._index,
105
- ATTR_VALUE: self.values.value,
106
- },
107
- )
108
-
109
- return request
110
-
111
100
 
112
101
  class EcomaxBinaryParameter(BinaryParameter, EcomaxParameter):
113
102
  """Represents an ecoMAX binary parameter."""
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
 
4
4
  from collections.abc import Generator
5
5
  from dataclasses import dataclass
6
- from typing import TYPE_CHECKING, Any, Final
6
+ from typing import TYPE_CHECKING, Any, Final, cast
7
7
 
8
8
  from pyplumio.const import (
9
9
  ATTR_DEVICE_INDEX,
@@ -13,7 +13,7 @@ from pyplumio.const import (
13
13
  UnitOfMeasurement,
14
14
  )
15
15
  from pyplumio.frames import Request
16
- from pyplumio.helpers.factory import factory
16
+ from pyplumio.helpers.factory import create_instance
17
17
  from pyplumio.helpers.parameter import (
18
18
  BinaryParameter,
19
19
  BinaryParameterDescription,
@@ -42,6 +42,21 @@ class MixerParameter(Parameter):
42
42
  device: Mixer
43
43
  description: MixerParameterDescription
44
44
 
45
+ async def create_request(self) -> Request:
46
+ """Create a request to change the parameter."""
47
+ return cast(
48
+ Request,
49
+ await create_instance(
50
+ "frames.requests.SetMixerParameterRequest",
51
+ recipient=self.device.parent.address,
52
+ data={
53
+ ATTR_INDEX: self._index,
54
+ ATTR_VALUE: self.values.value,
55
+ ATTR_DEVICE_INDEX: self.device.index,
56
+ },
57
+ ),
58
+ )
59
+
45
60
  async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
46
61
  """Set a parameter value."""
47
62
  if isinstance(value, (int, float)):
@@ -70,20 +85,6 @@ class MixerParameter(Parameter):
70
85
  self.values.max_value - self.description.offset
71
86
  ) * self.description.multiplier
72
87
 
73
- @property
74
- def request(self) -> Request:
75
- """Return request to change the parameter."""
76
- request: Request = factory(
77
- "frames.requests.SetMixerParameterRequest",
78
- recipient=self.device.parent.address,
79
- data={
80
- ATTR_INDEX: self._index,
81
- ATTR_VALUE: self.values.value,
82
- ATTR_DEVICE_INDEX: self.device.index,
83
- },
84
- )
85
- return request
86
-
87
88
 
88
89
  class MixerBinaryParameter(BinaryParameter, MixerParameter):
89
90
  """Represents a mixer binary parameter."""
@@ -5,13 +5,13 @@ from collections.abc import Sequence
5
5
  from dataclasses import dataclass
6
6
  from functools import reduce
7
7
  from itertools import chain
8
- from typing import Any, Final
8
+ from typing import Any, Final, cast
9
9
 
10
10
  from pyplumio.const import ATTR_PARAMETER, ATTR_SCHEDULE, ATTR_SWITCH, ATTR_TYPE
11
11
  from pyplumio.devices import AddressableDevice, Device
12
12
  from pyplumio.exceptions import FrameDataError
13
13
  from pyplumio.frames import Request
14
- from pyplumio.helpers.factory import factory
14
+ from pyplumio.helpers.factory import create_instance
15
15
  from pyplumio.helpers.parameter import (
16
16
  BinaryParameter,
17
17
  BinaryParameterDescription,
@@ -81,16 +81,17 @@ class ScheduleParameter(Parameter):
81
81
 
82
82
  device: AddressableDevice
83
83
 
84
- @property
85
- def request(self) -> Request:
86
- """Return request to change the parameter."""
84
+ async def create_request(self) -> Request:
85
+ """Create a request to change the parameter."""
87
86
  schedule_name, _ = self.description.name.split("_schedule_", 1)
88
- request: Request = factory(
89
- "frames.requests.SetScheduleRequest",
90
- recipient=self.device.address,
91
- data=collect_schedule_data(schedule_name, self.device),
87
+ return cast(
88
+ Request,
89
+ await create_instance(
90
+ "frames.requests.SetScheduleRequest",
91
+ recipient=self.device.address,
92
+ data=collect_schedule_data(schedule_name, self.device),
93
+ ),
92
94
  )
93
- return request
94
95
 
95
96
 
96
97
  class ScheduleBinaryParameter(ScheduleParameter, BinaryParameter):
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
 
4
4
  from collections.abc import Generator
5
5
  from dataclasses import dataclass
6
- from typing import TYPE_CHECKING, Any, Final
6
+ from typing import TYPE_CHECKING, Any, Final, cast
7
7
 
8
8
  from pyplumio.const import (
9
9
  ATTR_INDEX,
@@ -14,7 +14,7 @@ from pyplumio.const import (
14
14
  )
15
15
  from pyplumio.devices import AddressableDevice
16
16
  from pyplumio.frames import Request
17
- from pyplumio.helpers.factory import factory
17
+ from pyplumio.helpers.factory import create_instance
18
18
  from pyplumio.helpers.parameter import (
19
19
  BinaryParameter,
20
20
  BinaryParameterDescription,
@@ -59,6 +59,24 @@ class ThermostatParameter(Parameter):
59
59
  self.offset = offset
60
60
  super().__init__(device, values, description, index)
61
61
 
62
+ async def create_request(self) -> Request:
63
+ """Create a request to change the parameter."""
64
+ return cast(
65
+ Request,
66
+ await create_instance(
67
+ "frames.requests.SetThermostatParameterRequest",
68
+ recipient=self.device.parent.address,
69
+ data={
70
+ # Increase the index by one to account for thermostat
71
+ # profile, which is being set at ecoMAX device level.
72
+ ATTR_INDEX: self._index + 1,
73
+ ATTR_VALUE: self.values.value,
74
+ ATTR_OFFSET: self.offset,
75
+ ATTR_SIZE: self.description.size,
76
+ },
77
+ ),
78
+ )
79
+
62
80
  async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
63
81
  """Set a parameter value."""
64
82
  if isinstance(value, (int, float)):
@@ -81,23 +99,6 @@ class ThermostatParameter(Parameter):
81
99
  """Return the maximum allowed value."""
82
100
  return self.values.max_value * self.description.multiplier
83
101
 
84
- @property
85
- def request(self) -> Request:
86
- """Return request to change the parameter."""
87
- request: Request = factory(
88
- "frames.requests.SetThermostatParameterRequest",
89
- recipient=self.device.parent.address,
90
- data={
91
- # Increase the index by one to account for thermostat
92
- # profile, which is being set at ecoMAX device level.
93
- ATTR_INDEX: self._index + 1,
94
- ATTR_VALUE: self.values.value,
95
- ATTR_OFFSET: self.offset,
96
- ATTR_SIZE: self.description.size,
97
- },
98
- )
99
- return request
100
-
101
102
 
102
103
  class ThermostatBinaryParameter(BinaryParameter, ThermostatParameter):
103
104
  """Represents a thermostat binary parameter."""
@@ -33,23 +33,23 @@ dynamic = ["version"]
33
33
  [project.optional-dependencies]
34
34
  test = [
35
35
  "codespell==2.2.6",
36
- "coverage==7.4.3",
37
- "mypy==1.8.0",
36
+ "coverage==7.5.1",
37
+ "mypy==1.10.0",
38
38
  "pyserial-asyncio-fast==0.11",
39
- "pytest==8.1.0",
40
- "pytest-asyncio==0.23.5",
41
- "ruff==0.3.0",
42
- "tox==4.13.0",
43
- "types-pyserial==3.5.0.20240205"
39
+ "pytest==8.2.0",
40
+ "pytest-asyncio==0.23.6",
41
+ "ruff==0.4.3",
42
+ "tox==4.15.0",
43
+ "types-pyserial==3.5.0.20240311"
44
44
  ]
45
45
  docs = [
46
- "sphinx==7.2.6",
46
+ "sphinx==7.3.7",
47
47
  "sphinx_rtd_theme==2.0.0",
48
48
  "readthedocs-sphinx-search==0.3.2"
49
49
  ]
50
50
  dev = [
51
51
  "pyplumio[test,docs]",
52
- "pre-commit==3.6.2",
52
+ "pre-commit==3.7.0",
53
53
  "tomli==2.0.1"
54
54
  ]
55
55
 
@@ -1,3 +1,3 @@
1
- sphinx==7.2.6
1
+ sphinx==7.3.7
2
2
  sphinx_rtd_theme==2.0.0
3
3
  readthedocs-sphinx-search==0.3.2