PyPlumIO 0.6.4__tar.gz → 0.6.6__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 (152) hide show
  1. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/ci.yml +1 -1
  2. {pyplumio-0.6.4 → pyplumio-0.6.6}/PKG-INFO +5 -4
  3. {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/PKG-INFO +5 -4
  4. {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/requires.txt +3 -3
  5. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/_version.py +3 -3
  6. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/__init__.py +4 -4
  7. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/mixer.py +2 -2
  8. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/thermostat.py +2 -2
  9. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/protocol.py +17 -13
  10. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyproject.toml +6 -4
  11. {pyplumio-0.6.4 → pyplumio-0.6.6}/requirements_test.txt +3 -3
  12. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_mixer.py +1 -1
  13. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_thermostat.py +1 -1
  14. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_protocol.py +1 -0
  15. {pyplumio-0.6.4 → pyplumio-0.6.6}/.gitattributes +0 -0
  16. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/CODE_OF_CONDUCT.md +0 -0
  17. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  18. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  19. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/dependabot.yml +0 -0
  20. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/codeql.yml +0 -0
  21. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/deploy.yml +0 -0
  22. {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/documentation.yml +0 -0
  23. {pyplumio-0.6.4 → pyplumio-0.6.6}/.gitignore +0 -0
  24. {pyplumio-0.6.4 → pyplumio-0.6.6}/.pre-commit-config.yaml +0 -0
  25. {pyplumio-0.6.4 → pyplumio-0.6.6}/.qlty/qlty.toml +0 -0
  26. {pyplumio-0.6.4 → pyplumio-0.6.6}/.vscode/settings.json +0 -0
  27. {pyplumio-0.6.4 → pyplumio-0.6.6}/LICENSE +0 -0
  28. {pyplumio-0.6.4 → pyplumio-0.6.6}/MANIFEST.in +0 -0
  29. {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/SOURCES.txt +0 -0
  30. {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/dependency_links.txt +0 -0
  31. {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/top_level.txt +0 -0
  32. {pyplumio-0.6.4 → pyplumio-0.6.6}/README.md +0 -0
  33. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/Makefile +0 -0
  34. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/make.bat +0 -0
  35. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/callbacks.rst +0 -0
  36. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/conf.py +0 -0
  37. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/connecting.rst +0 -0
  38. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/frames.rst +0 -0
  39. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/index.rst +0 -0
  40. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/mixers_thermostats.rst +0 -0
  41. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/protocol.rst +0 -0
  42. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/reading.rst +0 -0
  43. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/schedules.rst +0 -0
  44. {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/writing.rst +0 -0
  45. {pyplumio-0.6.4 → pyplumio-0.6.6}/images/ecomax.png +0 -0
  46. {pyplumio-0.6.4 → pyplumio-0.6.6}/images/rs485.png +0 -0
  47. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/__init__.py +0 -0
  48. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/__main__.py +0 -0
  49. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/connection.py +0 -0
  50. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/const.py +0 -0
  51. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/data_types.py +0 -0
  52. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/ecomax.py +0 -0
  53. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/ecoster.py +0 -0
  54. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/exceptions.py +0 -0
  55. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/filters.py +0 -0
  56. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/__init__.py +0 -0
  57. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/messages.py +0 -0
  58. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/requests.py +0 -0
  59. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/responses.py +0 -0
  60. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/__init__.py +0 -0
  61. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/async_cache.py +0 -0
  62. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/event_manager.py +0 -0
  63. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/factory.py +0 -0
  64. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/task_manager.py +0 -0
  65. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/__init__.py +0 -0
  66. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/custom/__init__.py +0 -0
  67. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
  68. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/ecomax.py +0 -0
  69. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/mixer.py +0 -0
  70. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/thermostat.py +0 -0
  71. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/py.typed +0 -0
  72. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/stream.py +0 -0
  73. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/__init__.py +0 -0
  74. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/alerts.py +0 -0
  75. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/ecomax_parameters.py +0 -0
  76. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/frame_versions.py +0 -0
  77. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/mixer_parameters.py +0 -0
  78. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/network_info.py +0 -0
  79. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/product_info.py +0 -0
  80. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/program_version.py +0 -0
  81. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/regulator_data.py +0 -0
  82. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/regulator_data_schema.py +0 -0
  83. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/schedules.py +0 -0
  84. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/sensor_data.py +0 -0
  85. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/thermostat_parameters.py +0 -0
  86. {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/utils.py +0 -0
  87. {pyplumio-0.6.4 → pyplumio-0.6.6}/requirements.txt +0 -0
  88. {pyplumio-0.6.4 → pyplumio-0.6.6}/requirements_docs.txt +0 -0
  89. {pyplumio-0.6.4 → pyplumio-0.6.6}/setup.cfg +0 -0
  90. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/__init__.py +0 -0
  91. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/conftest.py +0 -0
  92. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/__init__.py +0 -0
  93. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_ecomax.py +0 -0
  94. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_ecoster.py +0 -0
  95. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_init.py +0 -0
  96. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_init.py +0 -0
  97. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_messages.py +0 -0
  98. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_requests.py +0 -0
  99. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_responses.py +0 -0
  100. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/__init__.py +0 -0
  101. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_async_cache.py +0 -0
  102. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_event_manager.py +0 -0
  103. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_factory.py +0 -0
  104. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_task_manager.py +0 -0
  105. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_uid.py +0 -0
  106. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/__init__.py +0 -0
  107. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/custom/__init__.py +0 -0
  108. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
  109. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/custom/test_init.py +0 -0
  110. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_ecomax.py +0 -0
  111. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_init.py +0 -0
  112. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_mixers.py +0 -0
  113. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_thermostats.py +0 -0
  114. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/ruff.toml +0 -0
  115. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/__init__.py +0 -0
  116. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_alerts.py +0 -0
  117. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_ecomax_parameters.py +0 -0
  118. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_frame_versions.py +0 -0
  119. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_mixer_parameters.py +0 -0
  120. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_product_info.py +0 -0
  121. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_schedules.py +0 -0
  122. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_connection.py +0 -0
  123. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_data_types.py +0 -0
  124. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_filters.py +0 -0
  125. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_init.py +0 -0
  126. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_main.py +0 -0
  127. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_stream.py +0 -0
  128. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_utils.py +0 -0
  129. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/messages/regulator_data.json +0 -0
  130. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/messages/sensor_data.json +0 -0
  131. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
  132. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/alerts.json +0 -0
  133. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/ecomax_control.json +0 -0
  134. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/ecomax_parameters.json +0 -0
  135. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/mixer_parameters.json +0 -0
  136. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
  137. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_mixer_parameter.json +0 -0
  138. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_schedule.json +0 -0
  139. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
  140. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/thermostat_parameters.json +0 -0
  141. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/alerts.json +0 -0
  142. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/device_available.json +0 -0
  143. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/ecomax_parameters.json +0 -0
  144. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/mixer_parameters.json +0 -0
  145. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/password.json +0 -0
  146. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/program_version.json +0 -0
  147. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/regulator_data_schema.json +0 -0
  148. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/schedules.json +0 -0
  149. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/thermostat_parameters.json +0 -0
  150. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/uid.json +0 -0
  151. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
  152. {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -14,7 +14,7 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
  strategy:
16
16
  matrix:
17
- python-version: ["3.10", "3.11", "3.12", "3.13"]
17
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
18
18
 
19
19
  steps:
20
20
  - uses: actions/checkout@v4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPlumIO
3
- Version: 0.6.4
3
+ Version: 0.6.6
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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
20
21
  Classifier: Topic :: Software Development :: Libraries
21
22
  Classifier: Topic :: Home Automation
22
23
  Requires-Python: >=3.10
@@ -25,14 +26,14 @@ License-File: LICENSE
25
26
  Requires-Dist: pyserial-asyncio==0.6
26
27
  Provides-Extra: test
27
28
  Requires-Dist: codespell==2.4.1; extra == "test"
28
- Requires-Dist: coverage==7.11.0; extra == "test"
29
+ Requires-Dist: coverage==7.11.3; extra == "test"
29
30
  Requires-Dist: freezegun==1.5.5; extra == "test"
30
31
  Requires-Dist: mypy==1.18.2; extra == "test"
31
32
  Requires-Dist: numpy<3.0.0,>=2.0.0; extra == "test"
32
33
  Requires-Dist: pyserial-asyncio-fast==0.16; extra == "test"
33
34
  Requires-Dist: pytest==8.4.2; extra == "test"
34
35
  Requires-Dist: pytest-asyncio==1.2.0; extra == "test"
35
- Requires-Dist: ruff==0.14.3; extra == "test"
36
+ Requires-Dist: ruff==0.14.4; extra == "test"
36
37
  Requires-Dist: tox==4.32.0; extra == "test"
37
38
  Requires-Dist: types-pyserial==3.5.0.20251001; extra == "test"
38
39
  Provides-Extra: docs
@@ -41,7 +42,7 @@ Requires-Dist: sphinx_rtd_theme==3.0.2; extra == "docs"
41
42
  Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
42
43
  Provides-Extra: dev
43
44
  Requires-Dist: pyplumio[docs,test]; extra == "dev"
44
- Requires-Dist: pre-commit==4.3.0; extra == "dev"
45
+ Requires-Dist: pre-commit==4.4.0; extra == "dev"
45
46
  Requires-Dist: tomli==2.3.0; extra == "dev"
46
47
  Dynamic: license-file
47
48
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPlumIO
3
- Version: 0.6.4
3
+ Version: 0.6.6
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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
20
21
  Classifier: Topic :: Software Development :: Libraries
21
22
  Classifier: Topic :: Home Automation
22
23
  Requires-Python: >=3.10
@@ -25,14 +26,14 @@ License-File: LICENSE
25
26
  Requires-Dist: pyserial-asyncio==0.6
26
27
  Provides-Extra: test
27
28
  Requires-Dist: codespell==2.4.1; extra == "test"
28
- Requires-Dist: coverage==7.11.0; extra == "test"
29
+ Requires-Dist: coverage==7.11.3; extra == "test"
29
30
  Requires-Dist: freezegun==1.5.5; extra == "test"
30
31
  Requires-Dist: mypy==1.18.2; extra == "test"
31
32
  Requires-Dist: numpy<3.0.0,>=2.0.0; extra == "test"
32
33
  Requires-Dist: pyserial-asyncio-fast==0.16; extra == "test"
33
34
  Requires-Dist: pytest==8.4.2; extra == "test"
34
35
  Requires-Dist: pytest-asyncio==1.2.0; extra == "test"
35
- Requires-Dist: ruff==0.14.3; extra == "test"
36
+ Requires-Dist: ruff==0.14.4; extra == "test"
36
37
  Requires-Dist: tox==4.32.0; extra == "test"
37
38
  Requires-Dist: types-pyserial==3.5.0.20251001; extra == "test"
38
39
  Provides-Extra: docs
@@ -41,7 +42,7 @@ Requires-Dist: sphinx_rtd_theme==3.0.2; extra == "docs"
41
42
  Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
42
43
  Provides-Extra: dev
43
44
  Requires-Dist: pyplumio[docs,test]; extra == "dev"
44
- Requires-Dist: pre-commit==4.3.0; extra == "dev"
45
+ Requires-Dist: pre-commit==4.4.0; extra == "dev"
45
46
  Requires-Dist: tomli==2.3.0; extra == "dev"
46
47
  Dynamic: license-file
47
48
 
@@ -2,7 +2,7 @@ pyserial-asyncio==0.6
2
2
 
3
3
  [dev]
4
4
  pyplumio[docs,test]
5
- pre-commit==4.3.0
5
+ pre-commit==4.4.0
6
6
  tomli==2.3.0
7
7
 
8
8
  [docs]
@@ -12,13 +12,13 @@ readthedocs-sphinx-search==0.3.2
12
12
 
13
13
  [test]
14
14
  codespell==2.4.1
15
- coverage==7.11.0
15
+ coverage==7.11.3
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.14.3
22
+ ruff==0.14.4
23
23
  tox==4.32.0
24
24
  types-pyserial==3.5.0.20251001
@@ -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.4'
32
- __version_tuple__ = version_tuple = (0, 6, 4)
31
+ __version__ = version = '0.6.6'
32
+ __version_tuple__ = version_tuple = (0, 6, 6)
33
33
 
34
- __commit_id__ = commit_id = 'gc17c7ed5e'
34
+ __commit_id__ = commit_id = 'g40bf0ee75'
@@ -131,7 +131,7 @@ class PhysicalDevice(Device, ABC):
131
131
  """Represents a physical device.
132
132
 
133
133
  Physical device have network address and can have multiple
134
- virtual devices associated with them via parent property.
134
+ logical devices associated with them via parent property.
135
135
  """
136
136
 
137
137
  __slots__ = ("address", "_network_info", "_frame_versions")
@@ -222,8 +222,8 @@ class PhysicalDevice(Device, ABC):
222
222
  return await create_instance(get_device_handler(device_type), cls=cls, **kwargs)
223
223
 
224
224
 
225
- class VirtualDevice(Device, ABC):
226
- """Represents a virtual device associated with physical device."""
225
+ class LogicalDevice(Device, ABC):
226
+ """Represents a logical device associated with physical device."""
227
227
 
228
228
  __slots__ = ("parent", "index")
229
229
 
@@ -258,7 +258,7 @@ def device_handler(
258
258
  __all__ = [
259
259
  "Device",
260
260
  "PhysicalDevice",
261
- "VirtualDevice",
261
+ "LogicalDevice",
262
262
  "device_hander",
263
263
  "get_device_handler",
264
264
  "is_known_device_type",
@@ -7,7 +7,7 @@ from collections.abc import Coroutine, Generator
7
7
  import logging
8
8
  from typing import Any
9
9
 
10
- from pyplumio.devices import VirtualDevice
10
+ from pyplumio.devices import LogicalDevice
11
11
  from pyplumio.helpers.event_manager import event_listener
12
12
  from pyplumio.parameters import ParameterValues
13
13
  from pyplumio.parameters.mixer import (
@@ -21,7 +21,7 @@ from pyplumio.structures.product_info import ATTR_PRODUCT, ProductInfo
21
21
  _LOGGER = logging.getLogger(__name__)
22
22
 
23
23
 
24
- class Mixer(VirtualDevice):
24
+ class Mixer(LogicalDevice):
25
25
  """Represents a mixer."""
26
26
 
27
27
  __slots__ = ()
@@ -7,7 +7,7 @@ from collections.abc import Coroutine, Generator
7
7
  import logging
8
8
  from typing import Any
9
9
 
10
- from pyplumio.devices import VirtualDevice
10
+ from pyplumio.devices import LogicalDevice
11
11
  from pyplumio.helpers.event_manager import event_listener
12
12
  from pyplumio.parameters import ParameterValues
13
13
  from pyplumio.parameters.thermostat import (
@@ -20,7 +20,7 @@ from pyplumio.parameters.thermostat import (
20
20
  _LOGGER = logging.getLogger()
21
21
 
22
22
 
23
- class Thermostat(VirtualDevice):
23
+ class Thermostat(LogicalDevice):
24
24
  """Represents a thermostat."""
25
25
 
26
26
  __slots__ = ()
@@ -231,16 +231,21 @@ class AsyncProtocol(Protocol, EventManager[PhysicalDevice]):
231
231
  self.frame_handler(reader=self.reader, writer=self.writer),
232
232
  name="frame_handler_task",
233
233
  )
234
- for device in self.data.values():
235
- device.dispatch_nowait(ATTR_CONNECTED, True)
234
+ self._mark_connected()
235
+ self.statistics.reset_transfer_statistics()
236
236
 
237
+ def _mark_connected(self) -> None:
238
+ """Mark connection as connected."""
237
239
  self.connected.set()
238
- self.statistics.reset_transfer_statistics()
240
+ self.network_info.server_status = True
239
241
  self.statistics.connected_since = datetime.now()
242
+ for device in self.data.values():
243
+ device.dispatch_nowait(ATTR_CONNECTED, True)
240
244
 
241
- async def _mark_disconnected(self) -> None:
242
- """Mark as protocol as disconnected."""
245
+ def _mark_disconnected(self) -> None:
246
+ """Mark connection as disconnected."""
243
247
  self.connected.clear()
248
+ self.network_info.server_status = False
244
249
  for device in self.data.values():
245
250
  device.dispatch_nowait(ATTR_CONNECTED, False)
246
251
 
@@ -254,20 +259,19 @@ class AsyncProtocol(Protocol, EventManager[PhysicalDevice]):
254
259
  async def connection_lost(self) -> None:
255
260
  """Close the connection and call connection lost callbacks."""
256
261
  if self.connected.is_set():
257
- await self._mark_disconnected()
258
- await asyncio.gather(*(callback() for callback in self.on_connection_lost))
262
+ self._mark_disconnected()
259
263
  await self._close_writer()
264
+ await asyncio.gather(*(callback() for callback in self.on_connection_lost))
260
265
 
261
266
  async def shutdown(self) -> None:
262
267
  """Shutdown the protocol and close the connection."""
263
- if self.connected.is_set():
264
- await self._mark_disconnected()
265
- await asyncio.gather(*(device.shutdown() for device in self.data.values()))
266
- await self._close_writer()
267
-
268
- self._clear_write_queue()
269
268
  self.cancel_tasks()
269
+ self._clear_write_queue()
270
270
  await self.wait_until_done()
271
+ if self.connected.is_set():
272
+ self._mark_disconnected()
273
+ await self._close_writer()
274
+ await asyncio.gather(*(device.shutdown() for device in self.data.values()))
271
275
 
272
276
  async def frame_handler(self, reader: FrameReader, writer: FrameWriter) -> None:
273
277
  """Handle frame reads and writes."""
@@ -19,6 +19,7 @@ classifiers = [
19
19
  "Programming Language :: Python :: 3.11",
20
20
  "Programming Language :: Python :: 3.12",
21
21
  "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
22
23
  "Topic :: Software Development :: Libraries",
23
24
  "Topic :: Home Automation",
24
25
  ]
@@ -35,14 +36,14 @@ dynamic = ["version"]
35
36
  [project.optional-dependencies]
36
37
  test = [
37
38
  "codespell==2.4.1",
38
- "coverage==7.11.0",
39
+ "coverage==7.11.3",
39
40
  "freezegun==1.5.5",
40
41
  "mypy==1.18.2",
41
42
  "numpy<3.0.0,>=2.0.0",
42
43
  "pyserial-asyncio-fast==0.16",
43
44
  "pytest==8.4.2",
44
45
  "pytest-asyncio==1.2.0",
45
- "ruff==0.14.3",
46
+ "ruff==0.14.4",
46
47
  "tox==4.32.0",
47
48
  "types-pyserial==3.5.0.20251001"
48
49
  ]
@@ -53,7 +54,7 @@ docs = [
53
54
  ]
54
55
  dev = [
55
56
  "pyplumio[test,docs]",
56
- "pre-commit==4.3.0",
57
+ "pre-commit==4.4.0",
57
58
  "tomli==2.3.0"
58
59
  ]
59
60
 
@@ -241,7 +242,7 @@ asyncio_default_fixture_loop_scope = "function"
241
242
  [tool.tox]
242
243
  legacy_tox_ini = """
243
244
  [tox]
244
- envlist = lint, type, py{310,311,312,313}
245
+ envlist = lint, type, py{310,311,312,313,314}
245
246
  isolated_build = True
246
247
  skip_missing_interpreters = True
247
248
  ignore_basepython_conflict = True
@@ -252,6 +253,7 @@ legacy_tox_ini = """
252
253
  3.11: py311
253
254
  3.12: py312
254
255
  3.13: py313, lint, type
256
+ 3.14: py314
255
257
 
256
258
  [testenv]
257
259
  deps =
@@ -1,13 +1,13 @@
1
1
  codespell==2.4.1
2
- coverage==7.11.0
2
+ coverage==7.11.3
3
3
  freezegun==1.5.5
4
4
  mypy==1.18.2
5
5
  numpy<3.0.0,>=2.0.0
6
- pre-commit==4.3.0
6
+ pre-commit==4.4.0
7
7
  pyserial-asyncio-fast==0.16
8
8
  pytest-asyncio==1.2.0
9
9
  pytest==8.4.2
10
- ruff==0.14.3
10
+ ruff==0.14.4
11
11
  tomli==2.3.0
12
12
  tox==4.32.0
13
13
  types-pyserial==3.5.0.20251001
@@ -1,4 +1,4 @@
1
- """Contains tests for the mixer virtual device."""
1
+ """Contains tests for the mixer logical device."""
2
2
 
3
3
  import asyncio
4
4
  import logging
@@ -1,4 +1,4 @@
1
- """Contains tests for the thermostat virtual device."""
1
+ """Contains tests for the thermostat logical device."""
2
2
 
3
3
  import asyncio
4
4
  from typing import Final
@@ -103,6 +103,7 @@ class TestAsyncProtocol:
103
103
  assert protocol.statistics.connected_since == NEVER
104
104
  protocol.connection_established(reader=mock_reader, writer=mock_writer)
105
105
  assert protocol.connected.is_set()
106
+ assert protocol.network_info.server_status is True
106
107
 
107
108
  # Test frame handler task was created.
108
109
  mock_frame_handler.assert_called_once_with(
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
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
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