PyPlumIO 0.6.5__tar.gz → 0.6.7__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.5 → pyplumio-0.6.7}/.github/workflows/ci.yml +1 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/PKG-INFO +8 -7
- {pyplumio-0.6.5 → pyplumio-0.6.7}/PyPlumIO.egg-info/PKG-INFO +8 -7
- {pyplumio-0.6.5 → pyplumio-0.6.7}/PyPlumIO.egg-info/SOURCES.txt +0 -2
- {pyplumio-0.6.5 → pyplumio-0.6.7}/PyPlumIO.egg-info/requires.txt +6 -6
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/_version.py +3 -3
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/connection.py +3 -2
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/devices/__init__.py +5 -6
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/devices/ecomax.py +7 -5
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/devices/mixer.py +5 -5
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/devices/thermostat.py +3 -3
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/filters.py +14 -9
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/frames/__init__.py +53 -39
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/frames/messages.py +3 -3
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/frames/requests.py +15 -10
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/frames/responses.py +10 -10
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/helpers/async_cache.py +2 -2
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/helpers/event_manager.py +61 -31
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/parameters/custom/__init__.py +1 -2
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/protocol.py +1 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/__init__.py +7 -9
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/regulator_data.py +3 -3
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/utils.py +28 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyproject.toml +9 -7
- {pyplumio-0.6.5 → pyplumio-0.6.7}/requirements_test.txt +6 -6
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/devices/test_ecomax.py +1 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/devices/test_init.py +1 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/devices/test_mixer.py +1 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/devices/test_thermostat.py +1 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/frames/test_init.py +2 -13
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/frames/test_requests.py +64 -36
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/helpers/test_event_manager.py +25 -4
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_filters.py +15 -1
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_protocol.py +3 -3
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_utils.py +31 -0
- pyplumio-0.6.5/pyplumio/helpers/factory.py +0 -36
- pyplumio-0.6.5/tests/helpers/test_factory.py +0 -41
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.gitattributes +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/CODE_OF_CONDUCT.md +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/dependabot.yml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/workflows/codeql.yml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/workflows/deploy.yml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.github/workflows/documentation.yml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.gitignore +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.pre-commit-config.yaml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.qlty/qlty.toml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/.vscode/settings.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/LICENSE +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/MANIFEST.in +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/PyPlumIO.egg-info/top_level.txt +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/README.md +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/Makefile +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/make.bat +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/callbacks.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/conf.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/connecting.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/frames.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/index.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/mixers_thermostats.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/protocol.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/reading.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/schedules.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/docs/source/writing.rst +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/images/ecomax.png +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/images/rs485.png +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/__main__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/const.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/data_types.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/devices/ecoster.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/exceptions.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/helpers/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/helpers/task_manager.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/parameters/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/parameters/ecomax.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/parameters/mixer.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/parameters/thermostat.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/py.typed +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/stream.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/alerts.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/ecomax_parameters.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/frame_versions.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/mixer_parameters.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/network_info.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/product_info.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/program_version.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/regulator_data_schema.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/schedules.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/sensor_data.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/pyplumio/structures/thermostat_parameters.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/requirements.txt +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/requirements_docs.txt +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/setup.cfg +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/conftest.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/devices/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/devices/test_ecoster.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/frames/test_messages.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/frames/test_responses.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/helpers/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/helpers/test_async_cache.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/helpers/test_task_manager.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/helpers/test_uid.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/custom/test_init.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/test_ecomax.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/test_init.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/test_mixers.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/parameters/test_thermostats.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/ruff.toml +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/__init__.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/test_alerts.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/test_ecomax_parameters.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/test_frame_versions.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/test_mixer_parameters.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/test_product_info.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/structures/test_schedules.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_connection.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_data_types.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_init.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_main.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/test_stream.py +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/messages/regulator_data.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/messages/sensor_data.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/alerts.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/ecomax_control.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/mixer_parameters.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/set_schedule.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/alerts.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/device_available.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/mixer_parameters.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/password.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/program_version.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/schedules.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/responses/uid.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {pyplumio-0.6.5 → pyplumio-0.6.7}/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.7
|
|
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.
|
|
29
|
+
Requires-Dist: coverage==7.12.0; extra == "test"
|
|
29
30
|
Requires-Dist: freezegun==1.5.5; extra == "test"
|
|
30
|
-
Requires-Dist: mypy==1.
|
|
31
|
+
Requires-Dist: mypy==1.19.0; 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
|
-
Requires-Dist: pytest==
|
|
34
|
-
Requires-Dist: pytest-asyncio==1.
|
|
35
|
-
Requires-Dist: ruff==0.14.
|
|
34
|
+
Requires-Dist: pytest==9.0.1; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-asyncio==1.3.0; extra == "test"
|
|
36
|
+
Requires-Dist: ruff==0.14.7; 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.5.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.7
|
|
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.
|
|
29
|
+
Requires-Dist: coverage==7.12.0; extra == "test"
|
|
29
30
|
Requires-Dist: freezegun==1.5.5; extra == "test"
|
|
30
|
-
Requires-Dist: mypy==1.
|
|
31
|
+
Requires-Dist: mypy==1.19.0; 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
|
-
Requires-Dist: pytest==
|
|
34
|
-
Requires-Dist: pytest-asyncio==1.
|
|
35
|
-
Requires-Dist: ruff==0.14.
|
|
34
|
+
Requires-Dist: pytest==9.0.1; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-asyncio==1.3.0; extra == "test"
|
|
36
|
+
Requires-Dist: ruff==0.14.7; 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.5.0; extra == "dev"
|
|
45
46
|
Requires-Dist: tomli==2.3.0; extra == "dev"
|
|
46
47
|
Dynamic: license-file
|
|
47
48
|
|
|
@@ -61,7 +61,6 @@ pyplumio/frames/responses.py
|
|
|
61
61
|
pyplumio/helpers/__init__.py
|
|
62
62
|
pyplumio/helpers/async_cache.py
|
|
63
63
|
pyplumio/helpers/event_manager.py
|
|
64
|
-
pyplumio/helpers/factory.py
|
|
65
64
|
pyplumio/helpers/task_manager.py
|
|
66
65
|
pyplumio/parameters/__init__.py
|
|
67
66
|
pyplumio/parameters/ecomax.py
|
|
@@ -106,7 +105,6 @@ tests/frames/test_responses.py
|
|
|
106
105
|
tests/helpers/__init__.py
|
|
107
106
|
tests/helpers/test_async_cache.py
|
|
108
107
|
tests/helpers/test_event_manager.py
|
|
109
|
-
tests/helpers/test_factory.py
|
|
110
108
|
tests/helpers/test_task_manager.py
|
|
111
109
|
tests/helpers/test_uid.py
|
|
112
110
|
tests/parameters/__init__.py
|
|
@@ -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.5.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.
|
|
15
|
+
coverage==7.12.0
|
|
16
16
|
freezegun==1.5.5
|
|
17
|
-
mypy==1.
|
|
17
|
+
mypy==1.19.0
|
|
18
18
|
numpy<3.0.0,>=2.0.0
|
|
19
19
|
pyserial-asyncio-fast==0.16
|
|
20
|
-
pytest==
|
|
21
|
-
pytest-asyncio==1.
|
|
22
|
-
ruff==0.14.
|
|
20
|
+
pytest==9.0.1
|
|
21
|
+
pytest-asyncio==1.3.0
|
|
22
|
+
ruff==0.14.7
|
|
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.7'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 7)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g6d0ba3b08'
|
|
@@ -7,6 +7,7 @@ import asyncio
|
|
|
7
7
|
from collections.abc import AsyncGenerator
|
|
8
8
|
from contextlib import asynccontextmanager
|
|
9
9
|
import logging
|
|
10
|
+
from types import MappingProxyType
|
|
10
11
|
from typing import Any, Final
|
|
11
12
|
|
|
12
13
|
from serial import EIGHTBITS, PARITY_NONE, STOPBITS_ONE
|
|
@@ -122,9 +123,9 @@ class Connection(ABC, TaskManager):
|
|
|
122
123
|
return self._protocol
|
|
123
124
|
|
|
124
125
|
@property
|
|
125
|
-
def options(self) ->
|
|
126
|
+
def options(self) -> MappingProxyType[str, Any]:
|
|
126
127
|
"""Return connection options."""
|
|
127
|
-
return self._options
|
|
128
|
+
return MappingProxyType(self._options)
|
|
128
129
|
|
|
129
130
|
@timeout(TRY_CONNECT_FOR_SECONDS)
|
|
130
131
|
@abstractmethod
|
|
@@ -14,10 +14,9 @@ from pyplumio.exceptions import RequestError, UnknownDeviceError
|
|
|
14
14
|
from pyplumio.filters import on_change
|
|
15
15
|
from pyplumio.frames import Frame, Request, is_known_frame_type
|
|
16
16
|
from pyplumio.helpers.event_manager import EventManager, event_listener
|
|
17
|
-
from pyplumio.helpers.factory import create_instance
|
|
18
17
|
from pyplumio.parameters import Numeric, Parameter
|
|
19
18
|
from pyplumio.structures.network_info import NetworkInfo
|
|
20
|
-
from pyplumio.utils import to_camelcase
|
|
19
|
+
from pyplumio.utils import create_instance, to_camelcase
|
|
21
20
|
|
|
22
21
|
_LOGGER = logging.getLogger(__name__)
|
|
23
22
|
|
|
@@ -131,7 +130,7 @@ class PhysicalDevice(Device, ABC):
|
|
|
131
130
|
"""Represents a physical device.
|
|
132
131
|
|
|
133
132
|
Physical device have network address and can have multiple
|
|
134
|
-
|
|
133
|
+
logical devices associated with them via parent property.
|
|
135
134
|
"""
|
|
136
135
|
|
|
137
136
|
__slots__ = ("address", "_network_info", "_frame_versions")
|
|
@@ -222,8 +221,8 @@ class PhysicalDevice(Device, ABC):
|
|
|
222
221
|
return await create_instance(get_device_handler(device_type), cls=cls, **kwargs)
|
|
223
222
|
|
|
224
223
|
|
|
225
|
-
class
|
|
226
|
-
"""Represents a
|
|
224
|
+
class LogicalDevice(Device, ABC):
|
|
225
|
+
"""Represents a logical device associated with physical device."""
|
|
227
226
|
|
|
228
227
|
__slots__ = ("parent", "index")
|
|
229
228
|
|
|
@@ -258,7 +257,7 @@ def device_handler(
|
|
|
258
257
|
__all__ = [
|
|
259
258
|
"Device",
|
|
260
259
|
"PhysicalDevice",
|
|
261
|
-
"
|
|
260
|
+
"LogicalDevice",
|
|
262
261
|
"device_hander",
|
|
263
262
|
"get_device_handler",
|
|
264
263
|
"is_known_device_type",
|
|
@@ -43,7 +43,7 @@ from pyplumio.structures.ecomax_parameters import (
|
|
|
43
43
|
)
|
|
44
44
|
from pyplumio.structures.mixer_parameters import ATTR_MIXER_PARAMETERS
|
|
45
45
|
from pyplumio.structures.network_info import ATTR_NETWORK_INFO, NetworkInfo
|
|
46
|
-
from pyplumio.structures.product_info import ATTR_PRODUCT
|
|
46
|
+
from pyplumio.structures.product_info import ATTR_PRODUCT
|
|
47
47
|
from pyplumio.structures.regulator_data_schema import ATTR_REGDATA_SCHEMA
|
|
48
48
|
from pyplumio.structures.schedules import (
|
|
49
49
|
ATTR_SCHEDULES,
|
|
@@ -142,7 +142,9 @@ class EcoMAX(PhysicalDevice):
|
|
|
142
142
|
def handle_frame(self, frame: Frame) -> None:
|
|
143
143
|
"""Handle frame received from the ecoMAX device."""
|
|
144
144
|
if isinstance(frame, Request) and (
|
|
145
|
-
response := frame.
|
|
145
|
+
response := frame.create_response(
|
|
146
|
+
data={ATTR_NETWORK_INFO: self._network_info}
|
|
147
|
+
)
|
|
146
148
|
):
|
|
147
149
|
self.queue_send(response)
|
|
148
150
|
|
|
@@ -253,10 +255,10 @@ class EcoMAX(PhysicalDevice):
|
|
|
253
255
|
) -> bool:
|
|
254
256
|
"""Update ecoMAX parameters and dispatch the events."""
|
|
255
257
|
_LOGGER.debug("Received device parameters")
|
|
256
|
-
product_info
|
|
258
|
+
product_info = await self.get(ATTR_PRODUCT)
|
|
257
259
|
parameter_types = await get_ecomax_parameter_types(product_info)
|
|
258
260
|
|
|
259
|
-
def _ecomax_parameter_events() -> Generator[Coroutine]:
|
|
261
|
+
def _ecomax_parameter_events() -> Generator[Coroutine[Any, Any, None]]:
|
|
260
262
|
"""Get dispatch calls for ecoMAX parameter events."""
|
|
261
263
|
for index, values in parameters:
|
|
262
264
|
try:
|
|
@@ -333,7 +335,7 @@ class EcoMAX(PhysicalDevice):
|
|
|
333
335
|
) -> bool:
|
|
334
336
|
"""Update schedule parameters and dispatch the events."""
|
|
335
337
|
|
|
336
|
-
def _schedule_parameter_events() -> Generator[Coroutine]:
|
|
338
|
+
def _schedule_parameter_events() -> Generator[Coroutine[Any, Any, None]]:
|
|
337
339
|
"""Get dispatch calls for schedule parameter events."""
|
|
338
340
|
for index, values in parameters:
|
|
339
341
|
description = SCHEDULE_PARAMETERS[index]
|
|
@@ -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 (
|
|
@@ -16,12 +16,12 @@ from pyplumio.parameters.mixer import (
|
|
|
16
16
|
MixerSwitchDescription,
|
|
17
17
|
get_mixer_parameter_types,
|
|
18
18
|
)
|
|
19
|
-
from pyplumio.structures.product_info import ATTR_PRODUCT
|
|
19
|
+
from pyplumio.structures.product_info import ATTR_PRODUCT
|
|
20
20
|
|
|
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__ = ()
|
|
@@ -41,10 +41,10 @@ class Mixer(VirtualDevice):
|
|
|
41
41
|
) -> bool:
|
|
42
42
|
"""Update mixer parameters and dispatch the events."""
|
|
43
43
|
_LOGGER.debug("Received mixer %i parameters", self.index)
|
|
44
|
-
product_info
|
|
44
|
+
product_info = await self.parent.get(ATTR_PRODUCT)
|
|
45
45
|
parameter_types = get_mixer_parameter_types(product_info)
|
|
46
46
|
|
|
47
|
-
def _mixer_parameter_events() -> Generator[Coroutine]:
|
|
47
|
+
def _mixer_parameter_events() -> Generator[Coroutine[Any, Any, None]]:
|
|
48
48
|
"""Get dispatch calls for mixer parameter events."""
|
|
49
49
|
for index, values in parameters:
|
|
50
50
|
try:
|
|
@@ -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__ = ()
|
|
@@ -42,7 +42,7 @@ class Thermostat(VirtualDevice):
|
|
|
42
42
|
_LOGGER.debug("Received thermostat %i parameters", self.index)
|
|
43
43
|
parameter_types = get_thermostat_parameter_types()
|
|
44
44
|
|
|
45
|
-
def _thermostat_parameter_events() -> Generator[Coroutine]:
|
|
45
|
+
def _thermostat_parameter_events() -> Generator[Coroutine[Any, Any, None]]:
|
|
46
46
|
"""Get dispatch calls for thermostat parameter events."""
|
|
47
47
|
for index, values in parameters:
|
|
48
48
|
description = parameter_types[index]
|
|
@@ -69,7 +69,7 @@ DEFAULT_TOLERANCE: Final = 1e-6
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
@overload
|
|
72
|
-
def is_close(old: Parameter, new: Parameter
|
|
72
|
+
def is_close(old: Parameter, new: Parameter) -> bool: ...
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
@overload
|
|
@@ -79,9 +79,7 @@ def is_close(
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
@overload
|
|
82
|
-
def is_close(
|
|
83
|
-
old: SupportsComparison, new: SupportsComparison, *, tolerance: None = None
|
|
84
|
-
) -> bool: ...
|
|
82
|
+
def is_close(old: SupportsComparison, new: SupportsComparison) -> bool: ...
|
|
85
83
|
|
|
86
84
|
|
|
87
85
|
def is_close(
|
|
@@ -100,6 +98,9 @@ def is_close(
|
|
|
100
98
|
return old.__eq__(new)
|
|
101
99
|
|
|
102
100
|
|
|
101
|
+
_SubtractableT = TypeVar("_SubtractableT", list, SupportsSubtraction)
|
|
102
|
+
|
|
103
|
+
|
|
103
104
|
@overload
|
|
104
105
|
def diffence_between(old: list, new: list) -> list: ...
|
|
105
106
|
|
|
@@ -110,9 +111,7 @@ def diffence_between(
|
|
|
110
111
|
) -> SupportsSubtraction: ...
|
|
111
112
|
|
|
112
113
|
|
|
113
|
-
def diffence_between(
|
|
114
|
-
old: SupportsSubtraction | list, new: SupportsSubtraction | list
|
|
115
|
-
) -> SupportsSubtraction | list | None:
|
|
114
|
+
def diffence_between(old: _SubtractableT, new: _SubtractableT) -> Any:
|
|
116
115
|
"""Return a difference between values."""
|
|
117
116
|
if isinstance(old, list) and isinstance(new, list):
|
|
118
117
|
return [x for x in new if x not in old]
|
|
@@ -120,7 +119,7 @@ def diffence_between(
|
|
|
120
119
|
if isinstance(old, SupportsSubtraction) and isinstance(new, SupportsSubtraction):
|
|
121
120
|
return new.__sub__(old)
|
|
122
121
|
|
|
123
|
-
return
|
|
122
|
+
return NotImplemented
|
|
124
123
|
|
|
125
124
|
|
|
126
125
|
_Numeric: TypeAlias = float | int | Decimal | Number
|
|
@@ -172,6 +171,11 @@ class Filter(ABC):
|
|
|
172
171
|
|
|
173
172
|
return NotImplemented
|
|
174
173
|
|
|
174
|
+
@property
|
|
175
|
+
def __name__(self) -> str:
|
|
176
|
+
"""Return a callback name."""
|
|
177
|
+
return self._callback.__name__
|
|
178
|
+
|
|
175
179
|
@abstractmethod
|
|
176
180
|
async def __call__(self, new_value: Any) -> Any:
|
|
177
181
|
"""Set a new value for the callback."""
|
|
@@ -536,7 +540,8 @@ class _Delta(ComparisonFilter):
|
|
|
536
540
|
if self.is_undefined() or not is_close(self.value, new_value):
|
|
537
541
|
old_value = self.value
|
|
538
542
|
self.value = new_value
|
|
539
|
-
|
|
543
|
+
difference = diffence_between(old_value, new_value)
|
|
544
|
+
if difference is not NotImplemented:
|
|
540
545
|
return await self._callback(difference)
|
|
541
546
|
|
|
542
547
|
|
|
@@ -10,8 +10,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Final, TypeVar
|
|
|
10
10
|
|
|
11
11
|
from pyplumio.const import DeviceType, FrameType
|
|
12
12
|
from pyplumio.exceptions import UnknownFrameError
|
|
13
|
-
from pyplumio.
|
|
14
|
-
from pyplumio.utils import ensure_dict, to_camelcase
|
|
13
|
+
from pyplumio.utils import create_instance, ensure_dict, to_camelcase
|
|
15
14
|
|
|
16
15
|
if TYPE_CHECKING:
|
|
17
16
|
from pyplumio.structures import Structure
|
|
@@ -243,11 +242,29 @@ class Frame(ABC):
|
|
|
243
242
|
"""Decode a frame message."""
|
|
244
243
|
|
|
245
244
|
|
|
245
|
+
def frame_handler(
|
|
246
|
+
frame_type: FrameType, structure: type[Structure] | None = None
|
|
247
|
+
) -> Callable[[type[_FrameT]], type[_FrameT]]:
|
|
248
|
+
"""Specify frame type for the frame class."""
|
|
249
|
+
|
|
250
|
+
def wrapper(cls: type[_FrameT]) -> type[_FrameT]:
|
|
251
|
+
"""Wrap the frame class."""
|
|
252
|
+
setattr(cls, "frame_type", frame_type)
|
|
253
|
+
if structure and issubclass(cls, Response):
|
|
254
|
+
setattr(cls, "structures", (structure,))
|
|
255
|
+
|
|
256
|
+
return cls
|
|
257
|
+
|
|
258
|
+
return wrapper
|
|
259
|
+
|
|
260
|
+
|
|
246
261
|
class Request(Frame):
|
|
247
262
|
"""Represents a request."""
|
|
248
263
|
|
|
249
264
|
__slots__ = ()
|
|
250
265
|
|
|
266
|
+
response: ClassVar[type[Response]]
|
|
267
|
+
|
|
251
268
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
|
252
269
|
"""Create a frame message."""
|
|
253
270
|
return bytearray()
|
|
@@ -256,38 +273,47 @@ class Request(Frame):
|
|
|
256
273
|
"""Decode a frame message."""
|
|
257
274
|
return {}
|
|
258
275
|
|
|
259
|
-
def
|
|
260
|
-
"""
|
|
276
|
+
def create_response(self, **kwargs: Any) -> Response | None:
|
|
277
|
+
"""Create response frame."""
|
|
278
|
+
if hasattr(self, "response"):
|
|
279
|
+
return self.response(recipient=self.sender, **kwargs)
|
|
280
|
+
|
|
261
281
|
return None
|
|
262
282
|
|
|
283
|
+
def validate_response(self, response: Response) -> bool:
|
|
284
|
+
"""Validate if response is valid for the request."""
|
|
285
|
+
if not hasattr(self, "response"):
|
|
286
|
+
raise NotImplementedError
|
|
263
287
|
|
|
264
|
-
|
|
265
|
-
|
|
288
|
+
if isinstance(response, self.response):
|
|
289
|
+
return True
|
|
266
290
|
|
|
267
|
-
|
|
291
|
+
return False
|
|
268
292
|
|
|
269
|
-
def create_message(self, data: dict[str, Any]) -> bytearray:
|
|
270
|
-
"""Create a frame message."""
|
|
271
|
-
return bytearray()
|
|
272
293
|
|
|
273
|
-
|
|
274
|
-
"""Decode a frame message."""
|
|
275
|
-
return {}
|
|
294
|
+
_RequestT = TypeVar("_RequestT", bound=Request)
|
|
276
295
|
|
|
277
296
|
|
|
278
|
-
|
|
279
|
-
|
|
297
|
+
def expect_response(
|
|
298
|
+
response: type[Response],
|
|
299
|
+
) -> Callable[[type[_RequestT]], type[_RequestT]]:
|
|
300
|
+
"""Assign response to the request class."""
|
|
280
301
|
|
|
281
|
-
|
|
302
|
+
def wrapper(cls: type[_RequestT]) -> type[_RequestT]:
|
|
303
|
+
"""Wrap the request class."""
|
|
304
|
+
setattr(cls, "response", response)
|
|
305
|
+
return cls
|
|
282
306
|
|
|
307
|
+
return wrapper
|
|
283
308
|
|
|
284
|
-
|
|
285
|
-
|
|
309
|
+
|
|
310
|
+
class Response(Frame):
|
|
311
|
+
"""Represents a response."""
|
|
286
312
|
|
|
287
313
|
__slots__ = ("_structures",)
|
|
288
314
|
|
|
289
315
|
container: ClassVar[str]
|
|
290
|
-
structures: ClassVar[list[type[Structure]]]
|
|
316
|
+
structures: ClassVar[list[type[Structure]]] = []
|
|
291
317
|
|
|
292
318
|
_structures: list[Structure]
|
|
293
319
|
|
|
@@ -302,9 +328,7 @@ class Structured(Frame):
|
|
|
302
328
|
**kwargs: Any,
|
|
303
329
|
) -> None:
|
|
304
330
|
"""Initialize a new structured frame."""
|
|
305
|
-
|
|
306
|
-
self._structures = [structure(self) for structure in self.structures]
|
|
307
|
-
|
|
331
|
+
self._structures = [structure(self) for structure in self.structures]
|
|
308
332
|
super().__init__(
|
|
309
333
|
recipient, sender, econet_type, econet_version, message, data, **kwargs
|
|
310
334
|
)
|
|
@@ -330,28 +354,18 @@ class Structured(Frame):
|
|
|
330
354
|
return data
|
|
331
355
|
|
|
332
356
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
) -> Callable[[type[_FrameT]], type[_FrameT]]:
|
|
336
|
-
"""Specify frame type for the frame class."""
|
|
337
|
-
|
|
338
|
-
def wrapper(cls: type[_FrameT]) -> type[_FrameT]:
|
|
339
|
-
"""Wrap the frame class."""
|
|
340
|
-
setattr(cls, "frame_type", frame_type)
|
|
341
|
-
if structure and issubclass(cls, Structured):
|
|
342
|
-
setattr(cls, "structures", (structure,))
|
|
343
|
-
|
|
344
|
-
return cls
|
|
357
|
+
class Message(Response):
|
|
358
|
+
"""Represents a message."""
|
|
345
359
|
|
|
346
|
-
|
|
360
|
+
__slots__ = ()
|
|
347
361
|
|
|
348
362
|
|
|
349
|
-
|
|
363
|
+
_ResponseT = TypeVar("_ResponseT", bound=Response)
|
|
350
364
|
|
|
351
365
|
|
|
352
366
|
def contains(
|
|
353
367
|
*structures: type[Structure], container: str | None = None
|
|
354
|
-
) -> Callable[[type[
|
|
368
|
+
) -> Callable[[type[_ResponseT]], type[_ResponseT]]:
|
|
355
369
|
"""Decorate frame class with structure.
|
|
356
370
|
|
|
357
371
|
Indicate which structures need to be used for encoding/decoding
|
|
@@ -359,7 +373,7 @@ def contains(
|
|
|
359
373
|
a single key.
|
|
360
374
|
"""
|
|
361
375
|
|
|
362
|
-
def wrapper(cls: type[
|
|
376
|
+
def wrapper(cls: type[_ResponseT]) -> type[_ResponseT]:
|
|
363
377
|
"""Wrap the frame class."""
|
|
364
378
|
setattr(cls, "structures", structures)
|
|
365
379
|
if container:
|
|
@@ -375,9 +389,9 @@ __all__ = [
|
|
|
375
389
|
"Request",
|
|
376
390
|
"Response",
|
|
377
391
|
"Message",
|
|
378
|
-
"Structured",
|
|
379
392
|
"bcc",
|
|
380
393
|
"contains",
|
|
394
|
+
"expect_response",
|
|
381
395
|
"frame_handler",
|
|
382
396
|
"get_frame_handler",
|
|
383
397
|
"is_known_frame_type",
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from pyplumio.const import ATTR_SENSORS, FrameType
|
|
6
|
-
from pyplumio.frames import Message,
|
|
6
|
+
from pyplumio.frames import Message, contains, frame_handler
|
|
7
7
|
from pyplumio.structures.frame_versions import FrameVersionsStructure
|
|
8
8
|
from pyplumio.structures.regulator_data import RegulatorDataStructure
|
|
9
9
|
from pyplumio.structures.sensor_data import SensorDataStructure
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@frame_handler(FrameType.MESSAGE_REGULATOR_DATA, structure=RegulatorDataStructure)
|
|
13
|
-
class RegulatorDataMessage(
|
|
13
|
+
class RegulatorDataMessage(Message):
|
|
14
14
|
"""Represents a regulator data message."""
|
|
15
15
|
|
|
16
16
|
__slots__ = ()
|
|
@@ -18,7 +18,7 @@ class RegulatorDataMessage(Structured, Message):
|
|
|
18
18
|
|
|
19
19
|
@frame_handler(FrameType.MESSAGE_SENSOR_DATA)
|
|
20
20
|
@contains(FrameVersionsStructure, SensorDataStructure, container=ATTR_SENSORS)
|
|
21
|
-
class SensorDataMessage(
|
|
21
|
+
class SensorDataMessage(Message):
|
|
22
22
|
"""Represents a sensor data message."""
|
|
23
23
|
|
|
24
24
|
__slots__ = ()
|