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.
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/ci.yml +1 -1
- {pyplumio-0.6.4 → pyplumio-0.6.6}/PKG-INFO +5 -4
- {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/PKG-INFO +5 -4
- {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/requires.txt +3 -3
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/_version.py +3 -3
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/__init__.py +4 -4
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/mixer.py +2 -2
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/thermostat.py +2 -2
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/protocol.py +17 -13
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyproject.toml +6 -4
- {pyplumio-0.6.4 → pyplumio-0.6.6}/requirements_test.txt +3 -3
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_mixer.py +1 -1
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_thermostat.py +1 -1
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_protocol.py +1 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.gitattributes +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/CODE_OF_CONDUCT.md +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/dependabot.yml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/codeql.yml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/deploy.yml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.github/workflows/documentation.yml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.gitignore +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.pre-commit-config.yaml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.qlty/qlty.toml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/.vscode/settings.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/LICENSE +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/MANIFEST.in +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/PyPlumIO.egg-info/top_level.txt +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/README.md +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/Makefile +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/make.bat +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/callbacks.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/conf.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/connecting.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/frames.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/index.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/mixers_thermostats.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/protocol.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/reading.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/schedules.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/docs/source/writing.rst +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/images/ecomax.png +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/images/rs485.png +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/__main__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/connection.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/const.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/data_types.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/ecomax.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/devices/ecoster.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/exceptions.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/filters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/messages.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/requests.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/frames/responses.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/async_cache.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/event_manager.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/factory.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/helpers/task_manager.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/ecomax.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/mixer.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/parameters/thermostat.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/py.typed +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/stream.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/alerts.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/ecomax_parameters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/frame_versions.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/mixer_parameters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/network_info.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/product_info.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/program_version.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/regulator_data.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/regulator_data_schema.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/schedules.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/sensor_data.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/structures/thermostat_parameters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/pyplumio/utils.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/requirements.txt +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/requirements_docs.txt +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/setup.cfg +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/conftest.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_ecomax.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_ecoster.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/devices/test_init.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_init.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_messages.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_requests.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/frames/test_responses.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_async_cache.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_event_manager.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_factory.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_task_manager.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/helpers/test_uid.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/custom/test_init.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_ecomax.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_init.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_mixers.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/parameters/test_thermostats.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/ruff.toml +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/__init__.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_alerts.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_ecomax_parameters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_frame_versions.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_mixer_parameters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_product_info.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/structures/test_schedules.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_connection.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_data_types.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_filters.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_init.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_main.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_stream.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/test_utils.py +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/messages/regulator_data.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/messages/sensor_data.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/alerts.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/ecomax_control.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/mixer_parameters.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_schedule.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/alerts.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/device_available.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/mixer_parameters.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/password.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/program_version.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/schedules.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/responses/uid.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {pyplumio-0.6.4 → pyplumio-0.6.6}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPlumIO
|
|
3
|
-
Version: 0.6.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 6,
|
|
31
|
+
__version__ = version = '0.6.6'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 6)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
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
|
-
|
|
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
|
|
226
|
-
"""Represents a
|
|
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
|
-
"
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
-
|
|
235
|
-
|
|
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.
|
|
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
|
-
|
|
242
|
-
"""Mark
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|