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.
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.pre-commit-config.yaml +1 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/PKG-INFO +5 -5
- {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/PKG-INFO +5 -5
- {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/requires.txt +4 -4
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/frames.rst +4 -26
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/_version.py +3 -3
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/connection.py +7 -7
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/__init__.py +20 -14
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/ecomax.py +16 -12
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/__init__.py +2 -2
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/ecomax.py +3 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/protocol.py +68 -99
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/stream.py +6 -5
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/network_info.py +23 -21
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/schedules.py +1 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/sensor_data.py +1 -3
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/utils.py +6 -4
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyproject.toml +4 -4
- {pyplumio-0.6.2 → pyplumio-0.6.4}/requirements_test.txt +4 -4
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/conftest.py +1 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_ecomax.py +6 -6
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_ecoster.py +1 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_init.py +3 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_init.py +9 -9
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_mixers.py +3 -1
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_thermostats.py +3 -1
- pyplumio-0.6.4/tests/test_protocol.py +257 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_stream.py +2 -2
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/device_available.json +4 -4
- pyplumio-0.6.2/tests/test_protocol.py +0 -469
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.gitattributes +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/CODE_OF_CONDUCT.md +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/dependabot.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/ci.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/codeql.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/deploy.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.github/workflows/documentation.yml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.gitignore +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.qlty/qlty.toml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/.vscode/settings.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/LICENSE +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/MANIFEST.in +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/PyPlumIO.egg-info/top_level.txt +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/README.md +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/Makefile +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/make.bat +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/callbacks.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/conf.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/connecting.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/index.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/mixers_thermostats.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/protocol.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/reading.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/schedules.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/docs/source/writing.rst +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/images/ecomax.png +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/images/rs485.png +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/__main__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/const.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/data_types.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/ecoster.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/mixer.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/devices/thermostat.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/exceptions.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/filters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/messages.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/requests.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/frames/responses.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/async_cache.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/event_manager.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/factory.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/helpers/task_manager.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/mixer.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/parameters/thermostat.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/py.typed +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/alerts.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/ecomax_parameters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/frame_versions.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/mixer_parameters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/product_info.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/program_version.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/regulator_data.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/regulator_data_schema.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/pyplumio/structures/thermostat_parameters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/requirements.txt +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/requirements_docs.txt +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/setup.cfg +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_mixer.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/devices/test_thermostat.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_init.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_messages.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_requests.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/frames/test_responses.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_async_cache.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_event_manager.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_factory.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_task_manager.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/helpers/test_uid.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/custom/test_init.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/parameters/test_ecomax.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/ruff.toml +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/__init__.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_alerts.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_ecomax_parameters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_frame_versions.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_mixer_parameters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_product_info.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/structures/test_schedules.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_connection.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_data_types.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_filters.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_init.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_main.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/test_utils.py +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/messages/regulator_data.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/messages/sensor_data.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/alerts.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/ecomax_control.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/mixer_parameters.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_schedule.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/alerts.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/mixer_parameters.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/password.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/program_version.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/schedules.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/responses/uid.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {pyplumio-0.6.2 → pyplumio-0.6.4}/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.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.
|
|
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.
|
|
36
|
-
Requires-Dist: tox==4.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
36
|
-
Requires-Dist: tox==4.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
23
|
-
tox==4.
|
|
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.
|
|
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.
|
|
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.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 6,
|
|
31
|
+
__version__ = version = '0.6.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 4)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
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
|
-
|
|
23
|
-
|
|
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
|
-
|
|
91
|
+
RECONNECT_AFTER_SECONDS,
|
|
92
92
|
)
|
|
93
|
-
await asyncio.sleep(
|
|
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(
|
|
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(
|
|
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(
|
|
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__ = ("
|
|
55
|
+
__slots__ = ("_write_queue",)
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
_write_queue: asyncio.Queue[Frame]
|
|
58
58
|
|
|
59
|
-
def __init__(self,
|
|
59
|
+
def __init__(self, write_queue: asyncio.Queue[Frame]) -> None:
|
|
60
60
|
"""Initialize a new device."""
|
|
61
61
|
super().__init__()
|
|
62
|
-
self.
|
|
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", "
|
|
137
|
+
__slots__ = ("address", "_network_info", "_frame_versions")
|
|
134
138
|
|
|
135
139
|
address: ClassVar[int]
|
|
136
140
|
|
|
137
|
-
|
|
141
|
+
_network_info: NetworkInfo
|
|
138
142
|
_frame_versions: dict[int, int]
|
|
139
143
|
|
|
140
|
-
def __init__(
|
|
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__(
|
|
143
|
-
self.
|
|
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.
|
|
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.
|
|
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:
|
|
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,
|
|
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__(
|
|
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
|
|
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
|
-
|
|
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__(
|
|
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__(
|
|
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={
|
|
145
|
+
response := frame.response(data={ATTR_NETWORK_INFO: self._network_info})
|
|
144
146
|
):
|
|
145
|
-
self.
|
|
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
|
|
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(
|
|
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
|
|
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.
|
|
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=
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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="
|
|
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",
|