PyPlumIO 0.5.15__tar.gz → 0.5.17__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.5.15 → pyplumio-0.5.17}/.pre-commit-config.yaml +2 -2
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/PKG-INFO +10 -10
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/PyPlumIO.egg-info/PKG-INFO +10 -10
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/PyPlumIO.egg-info/requires.txt +9 -9
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/_version.py +2 -2
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/connection.py +10 -22
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/devices/__init__.py +2 -2
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/devices/ecomax.py +16 -9
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/frames/__init__.py +1 -1
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/frames/messages.py +2 -2
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/frames/requests.py +17 -17
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/frames/responses.py +14 -14
- pyplumio-0.5.17/pyplumio/helpers/factory.py +23 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/parameter.py +5 -6
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/schedule.py +2 -3
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/protocol.py +10 -8
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/stream.py +2 -2
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/alerts.py +7 -1
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/ecomax_parameters.py +34 -35
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/mixer_parameters.py +17 -16
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/schedules.py +11 -10
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/thermostat_parameters.py +20 -19
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyproject.toml +9 -9
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/requirements_docs.txt +1 -1
- pyplumio-0.5.17/requirements_test.txt +11 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/frames/test_init.py +2 -2
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_factory.py +7 -7
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_parameter.py +4 -5
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_schedule.py +3 -4
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_connection.py +5 -8
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_devices.py +35 -12
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_protocol.py +1 -1
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/alerts.json +1 -1
- PyPlumIO-0.5.15/pyplumio/helpers/factory.py +0 -20
- PyPlumIO-0.5.15/requirements_test.txt +0 -11
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.gitattributes +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/CODE_OF_CONDUCT.md +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/dependabot.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/workflows/ci.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/workflows/codeql-analysis.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/workflows/deploy.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.github/workflows/documentation.yml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.gitignore +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/.vscode/settings.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/LICENSE +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/MANIFEST.in +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/PyPlumIO.egg-info/top_level.txt +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/README.md +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/Makefile +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/make.bat +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/callbacks.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/conf.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/connecting.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/index.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/mixers_thermostats.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/protocol.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/reading.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/schedules.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/docs/source/writing.rst +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/images/ecomax.png +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/images/rs485.png +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/__init__.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/__main__.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/const.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/devices/ecoster.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/devices/mixer.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/devices/thermostat.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/exceptions.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/filters.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/__init__.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/data_types.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/event_manager.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/task_manager.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/timeout.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/typing.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/helpers/uid.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/py.typed +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/__init__.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/boiler_load.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/boiler_power.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/fan_power.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/frame_versions.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/fuel_consumption.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/fuel_level.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/lambda_sensor.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/mixer_sensors.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/modules.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/network_info.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/output_flags.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/outputs.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/pending_alerts.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/product_info.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/program_version.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/regulator_data.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/regulator_data_schema.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/statuses.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/temperatures.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/structures/thermostat_sensors.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/pyplumio/utils.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/requirements.txt +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/setup.cfg +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/__init__.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/conftest.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/frames/test_messages.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/frames/test_requests.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/frames/test_responses.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/__init__.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_data_types.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_event_manager.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_task_manager.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_timeout.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/helpers/test_uid.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/ruff.toml +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_filters.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_init.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_main.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_stream.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/test_utils.py +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/messages/regulator_data.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/messages/sensor_data.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/alerts.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/ecomax_control.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/mixer_parameters.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/set_schedule.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/device_available.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/mixer_parameters.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/password.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/program_version.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/schedules.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/responses/uid.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {PyPlumIO-0.5.15 → pyplumio-0.5.17}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -2,7 +2,7 @@
|
|
2
2
|
# See https://pre-commit.com/hooks.html for more hooks
|
3
3
|
repos:
|
4
4
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
5
|
-
rev: v0.
|
5
|
+
rev: v0.4.2
|
6
6
|
hooks:
|
7
7
|
- id: ruff
|
8
8
|
args:
|
@@ -12,6 +12,6 @@ repos:
|
|
12
12
|
hooks:
|
13
13
|
- id: codespell
|
14
14
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
15
|
-
rev: v1.
|
15
|
+
rev: v1.10.0
|
16
16
|
hooks:
|
17
17
|
- id: mypy
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: PyPlumIO
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.17
|
4
4
|
Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
5
5
|
Author-email: Denis Paavilainen <denpa@denpa.pro>
|
6
6
|
License: MIT License
|
@@ -25,21 +25,21 @@ License-File: LICENSE
|
|
25
25
|
Requires-Dist: pyserial-asyncio==0.6
|
26
26
|
Provides-Extra: test
|
27
27
|
Requires-Dist: codespell==2.2.6; extra == "test"
|
28
|
-
Requires-Dist: coverage==7.
|
29
|
-
Requires-Dist: mypy==1.
|
28
|
+
Requires-Dist: coverage==7.5.0; extra == "test"
|
29
|
+
Requires-Dist: mypy==1.9.0; extra == "test"
|
30
30
|
Requires-Dist: pyserial-asyncio-fast==0.11; extra == "test"
|
31
|
-
Requires-Dist: pytest==8.
|
32
|
-
Requires-Dist: pytest-asyncio==0.23.
|
33
|
-
Requires-Dist: ruff==0.2
|
34
|
-
Requires-Dist: tox==4.
|
35
|
-
Requires-Dist: types-pyserial==3.5.0.
|
31
|
+
Requires-Dist: pytest==8.2.0; extra == "test"
|
32
|
+
Requires-Dist: pytest-asyncio==0.23.6; extra == "test"
|
33
|
+
Requires-Dist: ruff==0.4.2; extra == "test"
|
34
|
+
Requires-Dist: tox==4.15.0; extra == "test"
|
35
|
+
Requires-Dist: types-pyserial==3.5.0.20240311; extra == "test"
|
36
36
|
Provides-Extra: docs
|
37
|
-
Requires-Dist: sphinx==7.
|
37
|
+
Requires-Dist: sphinx==7.3.7; extra == "docs"
|
38
38
|
Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "docs"
|
39
39
|
Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
|
40
40
|
Provides-Extra: dev
|
41
41
|
Requires-Dist: pyplumio[docs,test]; extra == "dev"
|
42
|
-
Requires-Dist: pre-commit==3.
|
42
|
+
Requires-Dist: pre-commit==3.7.0; extra == "dev"
|
43
43
|
Requires-Dist: tomli==2.0.1; extra == "dev"
|
44
44
|
|
45
45
|
# PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: PyPlumIO
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.17
|
4
4
|
Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
5
5
|
Author-email: Denis Paavilainen <denpa@denpa.pro>
|
6
6
|
License: MIT License
|
@@ -25,21 +25,21 @@ License-File: LICENSE
|
|
25
25
|
Requires-Dist: pyserial-asyncio==0.6
|
26
26
|
Provides-Extra: test
|
27
27
|
Requires-Dist: codespell==2.2.6; extra == "test"
|
28
|
-
Requires-Dist: coverage==7.
|
29
|
-
Requires-Dist: mypy==1.
|
28
|
+
Requires-Dist: coverage==7.5.0; extra == "test"
|
29
|
+
Requires-Dist: mypy==1.9.0; extra == "test"
|
30
30
|
Requires-Dist: pyserial-asyncio-fast==0.11; extra == "test"
|
31
|
-
Requires-Dist: pytest==8.
|
32
|
-
Requires-Dist: pytest-asyncio==0.23.
|
33
|
-
Requires-Dist: ruff==0.2
|
34
|
-
Requires-Dist: tox==4.
|
35
|
-
Requires-Dist: types-pyserial==3.5.0.
|
31
|
+
Requires-Dist: pytest==8.2.0; extra == "test"
|
32
|
+
Requires-Dist: pytest-asyncio==0.23.6; extra == "test"
|
33
|
+
Requires-Dist: ruff==0.4.2; extra == "test"
|
34
|
+
Requires-Dist: tox==4.15.0; extra == "test"
|
35
|
+
Requires-Dist: types-pyserial==3.5.0.20240311; extra == "test"
|
36
36
|
Provides-Extra: docs
|
37
|
-
Requires-Dist: sphinx==7.
|
37
|
+
Requires-Dist: sphinx==7.3.7; extra == "docs"
|
38
38
|
Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "docs"
|
39
39
|
Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
|
40
40
|
Provides-Extra: dev
|
41
41
|
Requires-Dist: pyplumio[docs,test]; extra == "dev"
|
42
|
-
Requires-Dist: pre-commit==3.
|
42
|
+
Requires-Dist: pre-commit==3.7.0; extra == "dev"
|
43
43
|
Requires-Dist: tomli==2.0.1; extra == "dev"
|
44
44
|
|
45
45
|
# PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
@@ -2,21 +2,21 @@ pyserial-asyncio==0.6
|
|
2
2
|
|
3
3
|
[dev]
|
4
4
|
pyplumio[docs,test]
|
5
|
-
pre-commit==3.
|
5
|
+
pre-commit==3.7.0
|
6
6
|
tomli==2.0.1
|
7
7
|
|
8
8
|
[docs]
|
9
|
-
sphinx==7.
|
9
|
+
sphinx==7.3.7
|
10
10
|
sphinx_rtd_theme==2.0.0
|
11
11
|
readthedocs-sphinx-search==0.3.2
|
12
12
|
|
13
13
|
[test]
|
14
14
|
codespell==2.2.6
|
15
|
-
coverage==7.
|
16
|
-
mypy==1.
|
15
|
+
coverage==7.5.0
|
16
|
+
mypy==1.9.0
|
17
17
|
pyserial-asyncio-fast==0.11
|
18
|
-
pytest==8.
|
19
|
-
pytest-asyncio==0.23.
|
20
|
-
ruff==0.2
|
21
|
-
tox==4.
|
22
|
-
types-pyserial==3.5.0.
|
18
|
+
pytest==8.2.0
|
19
|
+
pytest-asyncio==0.23.6
|
20
|
+
ruff==0.4.2
|
21
|
+
tox==4.15.0
|
22
|
+
types-pyserial==3.5.0.20240311
|
@@ -10,6 +10,7 @@ from typing import Any, Final, cast
|
|
10
10
|
from serial import EIGHTBITS, PARITY_NONE, STOPBITS_ONE, SerialException
|
11
11
|
|
12
12
|
from pyplumio.exceptions import ConnectionFailedError
|
13
|
+
from pyplumio.helpers.task_manager import TaskManager
|
13
14
|
from pyplumio.helpers.timeout import timeout
|
14
15
|
from pyplumio.protocol import AsyncProtocol, Protocol
|
15
16
|
|
@@ -26,13 +27,12 @@ except ImportError:
|
|
26
27
|
import serial_asyncio as pyserial_asyncio
|
27
28
|
|
28
29
|
|
29
|
-
class Connection(ABC):
|
30
|
+
class Connection(ABC, TaskManager):
|
30
31
|
"""Represents a connection.
|
31
32
|
|
32
33
|
All specific connection classes MUST be inherited from this class.
|
33
34
|
"""
|
34
35
|
|
35
|
-
_closing: bool
|
36
36
|
_protocol: Protocol
|
37
37
|
_reconnect_on_failure: bool
|
38
38
|
_kwargs: MutableMapping[str, Any]
|
@@ -44,13 +44,13 @@ class Connection(ABC):
|
|
44
44
|
**kwargs: Any,
|
45
45
|
) -> None:
|
46
46
|
"""Initialize a new connection."""
|
47
|
+
super().__init__()
|
47
48
|
if protocol is None:
|
48
49
|
protocol = AsyncProtocol()
|
49
50
|
|
50
51
|
if reconnect_on_failure:
|
51
|
-
protocol.on_connection_lost.add(self.
|
52
|
+
protocol.on_connection_lost.add(self._reconnect)
|
52
53
|
|
53
|
-
self._closing = False
|
54
54
|
self._reconnect_on_failure = reconnect_on_failure
|
55
55
|
self._protocol = protocol
|
56
56
|
self._kwargs = kwargs
|
@@ -76,29 +76,20 @@ class Connection(ABC):
|
|
76
76
|
await self._open_connection(),
|
77
77
|
)
|
78
78
|
self.protocol.connection_established(reader, writer)
|
79
|
-
except (
|
80
|
-
|
81
|
-
SerialException,
|
82
|
-
asyncio.TimeoutError,
|
83
|
-
) as connection_error:
|
84
|
-
raise ConnectionFailedError from connection_error
|
79
|
+
except (OSError, SerialException, asyncio.TimeoutError) as err:
|
80
|
+
raise ConnectionFailedError from err
|
85
81
|
|
86
82
|
async def _reconnect(self) -> None:
|
87
83
|
"""Try to connect and reconnect on failure."""
|
88
84
|
try:
|
89
|
-
|
85
|
+
await self._connect()
|
90
86
|
except ConnectionFailedError:
|
91
|
-
await self._connection_lost()
|
92
|
-
|
93
|
-
async def _connection_lost(self) -> None:
|
94
|
-
"""Resume connection on the connection loss."""
|
95
|
-
if not self._closing:
|
96
87
|
_LOGGER.error(
|
97
88
|
"Can't connect to the device, retrying in %.1f seconds",
|
98
89
|
RECONNECT_TIMEOUT,
|
99
90
|
)
|
100
91
|
await asyncio.sleep(RECONNECT_TIMEOUT)
|
101
|
-
|
92
|
+
self.create_task(self._reconnect())
|
102
93
|
|
103
94
|
async def connect(self) -> None:
|
104
95
|
"""Open the connection.
|
@@ -106,14 +97,11 @@ class Connection(ABC):
|
|
106
97
|
Initialize a connection via connect or reconnect
|
107
98
|
routines, depending on '_reconnect_on_failure' property.
|
108
99
|
"""
|
109
|
-
if self._reconnect_on_failure
|
110
|
-
await self._reconnect()
|
111
|
-
else:
|
112
|
-
await self._connect()
|
100
|
+
await (self._reconnect if self._reconnect_on_failure else self._connect)()
|
113
101
|
|
114
102
|
async def close(self) -> None:
|
115
103
|
"""Close the connection."""
|
116
|
-
self.
|
104
|
+
self.cancel_tasks()
|
117
105
|
await self.protocol.shutdown()
|
118
106
|
|
119
107
|
@property
|
@@ -11,7 +11,7 @@ from pyplumio.const import ATTR_FRAME_ERRORS, ATTR_LOADED, DeviceType, FrameType
|
|
11
11
|
from pyplumio.exceptions import UnknownDeviceError
|
12
12
|
from pyplumio.frames import DataFrameDescription, Frame, Request, get_frame_handler
|
13
13
|
from pyplumio.helpers.event_manager import EventManager
|
14
|
-
from pyplumio.helpers.factory import
|
14
|
+
from pyplumio.helpers.factory import create_instance
|
15
15
|
from pyplumio.helpers.parameter import SET_RETRIES, Parameter
|
16
16
|
from pyplumio.helpers.typing import ParameterValueType
|
17
17
|
from pyplumio.structures.network_info import NetworkInfo
|
@@ -160,7 +160,7 @@ class AddressableDevice(Device, ABC):
|
|
160
160
|
|
161
161
|
If value is not available before timeout, retry request.
|
162
162
|
"""
|
163
|
-
request: Request =
|
163
|
+
request: Request = await create_instance(
|
164
164
|
get_frame_handler(frame_type), recipient=self.address
|
165
165
|
)
|
166
166
|
|
@@ -28,7 +28,7 @@ from pyplumio.frames import (
|
|
28
28
|
get_frame_handler,
|
29
29
|
is_known_frame_type,
|
30
30
|
)
|
31
|
-
from pyplumio.helpers.factory import
|
31
|
+
from pyplumio.helpers.factory import create_instance
|
32
32
|
from pyplumio.helpers.parameter import ParameterValues
|
33
33
|
from pyplumio.helpers.schedule import Schedule, ScheduleDay
|
34
34
|
from pyplumio.structures.alerts import ATTR_TOTAL_ALERTS
|
@@ -235,7 +235,7 @@ class EcoMAX(AddressableDevice):
|
|
235
235
|
and not self._has_frame_version(frame_type, version)
|
236
236
|
):
|
237
237
|
# We don't have this frame or it's version has changed.
|
238
|
-
request: Request =
|
238
|
+
request: Request = await create_instance(
|
239
239
|
get_frame_handler(frame_type), recipient=self.address
|
240
240
|
)
|
241
241
|
self.queue.put_nowait(request)
|
@@ -346,16 +346,23 @@ class EcoMAX(AddressableDevice):
|
|
346
346
|
|
347
347
|
return True
|
348
348
|
|
349
|
-
async def _add_ecomax_control_parameter(self, mode:
|
349
|
+
async def _add_ecomax_control_parameter(self, mode: DeviceState) -> None:
|
350
350
|
"""Create ecoMAX control parameter instance and dispatch an event."""
|
351
|
+
description = ECOMAX_CONTROL_PARAMETER
|
352
|
+
name = description.name
|
353
|
+
values = ParameterValues(
|
354
|
+
value=int(mode != DeviceState.OFF), min_value=0, max_value=1
|
355
|
+
)
|
356
|
+
|
357
|
+
if name in self.data:
|
358
|
+
parameter: EcomaxBinaryParameter = self.data[name]
|
359
|
+
parameter.values = values
|
360
|
+
return await self.dispatch(name, parameter)
|
361
|
+
|
351
362
|
await self.dispatch(
|
352
|
-
|
363
|
+
name,
|
353
364
|
EcomaxBinaryParameter(
|
354
|
-
device=self,
|
355
|
-
description=ECOMAX_CONTROL_PARAMETER,
|
356
|
-
values=ParameterValues(
|
357
|
-
value=int(mode != DeviceState.OFF), min_value=0, max_value=1
|
358
|
-
),
|
365
|
+
device=self, description=ECOMAX_CONTROL_PARAMETER, values=values
|
359
366
|
),
|
360
367
|
)
|
361
368
|
|
@@ -35,7 +35,7 @@ class RegulatorDataMessage(Message):
|
|
35
35
|
|
36
36
|
__slots__ = ()
|
37
37
|
|
38
|
-
frame_type: ClassVar[FrameType
|
38
|
+
frame_type: ClassVar[FrameType] = FrameType.MESSAGE_REGULATOR_DATA
|
39
39
|
|
40
40
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
41
41
|
"""Decode a frame message."""
|
@@ -47,7 +47,7 @@ class SensorDataMessage(Message):
|
|
47
47
|
|
48
48
|
__slots__ = ()
|
49
49
|
|
50
|
-
frame_type: ClassVar[FrameType
|
50
|
+
frame_type: ClassVar[FrameType] = FrameType.MESSAGE_SENSOR_DATA
|
51
51
|
|
52
52
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
53
53
|
"""Decode a frame message."""
|
@@ -24,7 +24,7 @@ class ProgramVersionRequest(Request):
|
|
24
24
|
|
25
25
|
__slots__ = ()
|
26
26
|
|
27
|
-
frame_type: ClassVar[FrameType
|
27
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_PROGRAM_VERSION
|
28
28
|
|
29
29
|
def response(self, **kwargs: Any) -> Response | None:
|
30
30
|
"""Return a response frame."""
|
@@ -36,7 +36,7 @@ class CheckDeviceRequest(Request):
|
|
36
36
|
|
37
37
|
__slots__ = ()
|
38
38
|
|
39
|
-
frame_type: ClassVar[FrameType
|
39
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_CHECK_DEVICE
|
40
40
|
|
41
41
|
def response(self, **kwargs: Any) -> Response | None:
|
42
42
|
"""Return a response frame."""
|
@@ -48,7 +48,7 @@ class UIDRequest(Request):
|
|
48
48
|
|
49
49
|
__slots__ = ()
|
50
50
|
|
51
|
-
frame_type: ClassVar[FrameType
|
51
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_UID
|
52
52
|
|
53
53
|
|
54
54
|
class PasswordRequest(Request):
|
@@ -56,7 +56,7 @@ class PasswordRequest(Request):
|
|
56
56
|
|
57
57
|
__slots__ = ()
|
58
58
|
|
59
|
-
frame_type: ClassVar[FrameType
|
59
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_PASSWORD
|
60
60
|
|
61
61
|
|
62
62
|
class EcomaxParametersRequest(Request):
|
@@ -67,7 +67,7 @@ class EcomaxParametersRequest(Request):
|
|
67
67
|
|
68
68
|
__slots__ = ()
|
69
69
|
|
70
|
-
frame_type: ClassVar[FrameType
|
70
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_ECOMAX_PARAMETERS
|
71
71
|
|
72
72
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
73
73
|
"""Create a frame message."""
|
@@ -83,7 +83,7 @@ class MixerParametersRequest(Request):
|
|
83
83
|
|
84
84
|
__slots__ = ()
|
85
85
|
|
86
|
-
frame_type: ClassVar[FrameType
|
86
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_MIXER_PARAMETERS
|
87
87
|
|
88
88
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
89
89
|
"""Create a frame message."""
|
@@ -99,7 +99,7 @@ class ThermostatParametersRequest(Request):
|
|
99
99
|
|
100
100
|
__slots__ = ()
|
101
101
|
|
102
|
-
frame_type: ClassVar[FrameType
|
102
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_THERMOSTAT_PARAMETERS
|
103
103
|
|
104
104
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
105
105
|
"""Create a frame message."""
|
@@ -111,7 +111,7 @@ class RegulatorDataSchemaRequest(Request):
|
|
111
111
|
|
112
112
|
__slots__ = ()
|
113
113
|
|
114
|
-
frame_type: ClassVar[FrameType
|
114
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_REGULATOR_DATA_SCHEMA
|
115
115
|
|
116
116
|
|
117
117
|
class SetEcomaxParameterRequest(Request):
|
@@ -122,7 +122,7 @@ class SetEcomaxParameterRequest(Request):
|
|
122
122
|
|
123
123
|
__slots__ = ()
|
124
124
|
|
125
|
-
frame_type: ClassVar[FrameType
|
125
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_SET_ECOMAX_PARAMETER
|
126
126
|
|
127
127
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
128
128
|
"""Create a frame message."""
|
@@ -140,7 +140,7 @@ class SetMixerParameterRequest(Request):
|
|
140
140
|
|
141
141
|
__slots__ = ()
|
142
142
|
|
143
|
-
frame_type: ClassVar[FrameType
|
143
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_SET_MIXER_PARAMETER
|
144
144
|
|
145
145
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
146
146
|
"""Create a frame message."""
|
@@ -168,7 +168,7 @@ class SetThermostatParameterRequest(Request):
|
|
168
168
|
|
169
169
|
__slots__ = ()
|
170
170
|
|
171
|
-
frame_type: ClassVar[FrameType
|
171
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_SET_THERMOSTAT_PARAMETER
|
172
172
|
|
173
173
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
174
174
|
"""Create a frame message."""
|
@@ -191,7 +191,7 @@ class EcomaxControlRequest(Request):
|
|
191
191
|
|
192
192
|
__slots__ = ()
|
193
193
|
|
194
|
-
frame_type: ClassVar[FrameType
|
194
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_ECOMAX_CONTROL
|
195
195
|
|
196
196
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
197
197
|
"""Create a frame message."""
|
@@ -210,7 +210,7 @@ class StartMasterRequest(Request):
|
|
210
210
|
|
211
211
|
__slots__ = ()
|
212
212
|
|
213
|
-
frame_type: ClassVar[FrameType
|
213
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_START_MASTER
|
214
214
|
|
215
215
|
|
216
216
|
class StopMasterRequest(Request):
|
@@ -222,7 +222,7 @@ class StopMasterRequest(Request):
|
|
222
222
|
|
223
223
|
__slots__ = ()
|
224
224
|
|
225
|
-
frame_type: ClassVar[FrameType
|
225
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_STOP_MASTER
|
226
226
|
|
227
227
|
|
228
228
|
class AlertsRequest(Request):
|
@@ -234,7 +234,7 @@ class AlertsRequest(Request):
|
|
234
234
|
|
235
235
|
__slots__ = ()
|
236
236
|
|
237
|
-
frame_type: ClassVar[FrameType
|
237
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_ALERTS
|
238
238
|
|
239
239
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
240
240
|
"""Create a frame message."""
|
@@ -246,7 +246,7 @@ class SchedulesRequest(Request):
|
|
246
246
|
|
247
247
|
__slots__ = ()
|
248
248
|
|
249
|
-
frame_type: ClassVar[FrameType
|
249
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_SCHEDULES
|
250
250
|
|
251
251
|
|
252
252
|
class SetScheduleRequest(Request):
|
@@ -254,7 +254,7 @@ class SetScheduleRequest(Request):
|
|
254
254
|
|
255
255
|
__slots__ = ()
|
256
256
|
|
257
|
-
frame_type: ClassVar[FrameType
|
257
|
+
frame_type: ClassVar[FrameType] = FrameType.REQUEST_SET_SCHEDULE
|
258
258
|
|
259
259
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
260
260
|
"""Create a frame message."""
|
@@ -24,7 +24,7 @@ class ProgramVersionResponse(Response):
|
|
24
24
|
|
25
25
|
__slots__ = ()
|
26
26
|
|
27
|
-
frame_type: ClassVar[FrameType
|
27
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_PROGRAM_VERSION
|
28
28
|
|
29
29
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
30
30
|
"""Create a frame message."""
|
@@ -43,7 +43,7 @@ class DeviceAvailableResponse(Response):
|
|
43
43
|
|
44
44
|
__slots__ = ()
|
45
45
|
|
46
|
-
frame_type: ClassVar[FrameType
|
46
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_DEVICE_AVAILABLE
|
47
47
|
|
48
48
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
49
49
|
"""Create a frame message."""
|
@@ -62,7 +62,7 @@ class UIDResponse(Response):
|
|
62
62
|
|
63
63
|
__slots__ = ()
|
64
64
|
|
65
|
-
frame_type: ClassVar[FrameType
|
65
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_UID
|
66
66
|
|
67
67
|
def create_message(self, data: dict[str, Any]) -> bytearray:
|
68
68
|
"""Create a frame message."""
|
@@ -81,7 +81,7 @@ class PasswordResponse(Response):
|
|
81
81
|
|
82
82
|
__slots__ = ()
|
83
83
|
|
84
|
-
frame_type: ClassVar[FrameType
|
84
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_PASSWORD
|
85
85
|
|
86
86
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
87
87
|
"""Decode a frame message."""
|
@@ -97,7 +97,7 @@ class EcomaxParametersResponse(Response):
|
|
97
97
|
|
98
98
|
__slots__ = ()
|
99
99
|
|
100
|
-
frame_type: ClassVar[FrameType
|
100
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_ECOMAX_PARAMETERS
|
101
101
|
|
102
102
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
103
103
|
"""Decode a frame message."""
|
@@ -112,7 +112,7 @@ class MixerParametersResponse(Response):
|
|
112
112
|
|
113
113
|
__slots__ = ()
|
114
114
|
|
115
|
-
frame_type: ClassVar[FrameType
|
115
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_MIXER_PARAMETERS
|
116
116
|
|
117
117
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
118
118
|
"""Decode a frame message."""
|
@@ -127,7 +127,7 @@ class ThermostatParametersResponse(Response):
|
|
127
127
|
|
128
128
|
__slots__ = ()
|
129
129
|
|
130
|
-
frame_type: ClassVar[FrameType
|
130
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_THERMOSTAT_PARAMETERS
|
131
131
|
|
132
132
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
133
133
|
"""Decode a frame message."""
|
@@ -143,7 +143,7 @@ class RegulatorDataSchemaResponse(Response):
|
|
143
143
|
|
144
144
|
__slots__ = ()
|
145
145
|
|
146
|
-
frame_type: ClassVar[FrameType
|
146
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_REGULATOR_DATA_SCHEMA
|
147
147
|
|
148
148
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
149
149
|
"""Decode a frame message."""
|
@@ -159,7 +159,7 @@ class SetEcomaxParameterResponse(Response):
|
|
159
159
|
|
160
160
|
__slots__ = ()
|
161
161
|
|
162
|
-
frame_type: ClassVar[FrameType
|
162
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_SET_ECOMAX_PARAMETER
|
163
163
|
|
164
164
|
|
165
165
|
class SetMixerParameterResponse(Response):
|
@@ -171,7 +171,7 @@ class SetMixerParameterResponse(Response):
|
|
171
171
|
|
172
172
|
__slots__ = ()
|
173
173
|
|
174
|
-
frame_type: ClassVar[FrameType
|
174
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_SET_MIXER_PARAMETER
|
175
175
|
|
176
176
|
|
177
177
|
class SetThermostatParameterResponse(Response):
|
@@ -183,7 +183,7 @@ class SetThermostatParameterResponse(Response):
|
|
183
183
|
|
184
184
|
__slots__ = ()
|
185
185
|
|
186
|
-
frame_type: ClassVar[FrameType
|
186
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_SET_THERMOSTAT_PARAMETER
|
187
187
|
|
188
188
|
|
189
189
|
class EcomaxControlResponse(Response):
|
@@ -195,7 +195,7 @@ class EcomaxControlResponse(Response):
|
|
195
195
|
|
196
196
|
__slots__ = ()
|
197
197
|
|
198
|
-
frame_type: ClassVar[FrameType
|
198
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_ECOMAX_CONTROL
|
199
199
|
|
200
200
|
|
201
201
|
class AlertsResponse(Response):
|
@@ -203,7 +203,7 @@ class AlertsResponse(Response):
|
|
203
203
|
|
204
204
|
__slots__ = ()
|
205
205
|
|
206
|
-
frame_type: ClassVar[FrameType
|
206
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_ALERTS
|
207
207
|
|
208
208
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
209
209
|
"""Decode a frame message."""
|
@@ -215,7 +215,7 @@ class SchedulesResponse(Response):
|
|
215
215
|
|
216
216
|
__slots__ = ()
|
217
217
|
|
218
|
-
frame_type: ClassVar[FrameType
|
218
|
+
frame_type: ClassVar[FrameType] = FrameType.RESPONSE_SCHEDULES
|
219
219
|
|
220
220
|
def decode_message(self, message: bytearray) -> dict[str, Any]:
|
221
221
|
"""Decode a frame message."""
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"""Contains a factory helper."""
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import asyncio
|
5
|
+
from importlib import import_module
|
6
|
+
import logging
|
7
|
+
from typing import Any
|
8
|
+
|
9
|
+
_LOGGER = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
async def create_instance(class_path: str, **kwargs: Any) -> Any:
|
13
|
+
"""Return a class instance from the class path."""
|
14
|
+
loop = asyncio.get_running_loop()
|
15
|
+
module_name, class_name = class_path.rsplit(".", 1)
|
16
|
+
try:
|
17
|
+
module = await loop.run_in_executor(
|
18
|
+
None, import_module, "." + module_name, "pyplumio"
|
19
|
+
)
|
20
|
+
return getattr(module, class_name)(**kwargs)
|
21
|
+
except Exception:
|
22
|
+
_LOGGER.error("Failed to load module (%s)", class_path)
|
23
|
+
raise
|
@@ -166,6 +166,10 @@ class Parameter(ABC):
|
|
166
166
|
"""Set parameter as no longer pending update."""
|
167
167
|
self._pending_update = False
|
168
168
|
|
169
|
+
async def create_request(self) -> Request:
|
170
|
+
"""Create a request to change the parameter."""
|
171
|
+
raise NotImplementedError
|
172
|
+
|
169
173
|
async def set(self, value: ParameterValueType, retries: int = SET_RETRIES) -> bool:
|
170
174
|
"""Set a parameter value."""
|
171
175
|
if (value := _normalize_parameter_value(value)) == self.values.value:
|
@@ -188,7 +192,7 @@ class Parameter(ABC):
|
|
188
192
|
self.device.unsubscribe(self.description.name, self._confirm_update)
|
189
193
|
return False
|
190
194
|
|
191
|
-
await self.device.queue.put(self.
|
195
|
+
await self.device.queue.put(await self.create_request())
|
192
196
|
await asyncio.sleep(SET_TIMEOUT)
|
193
197
|
retries -= 1
|
194
198
|
|
@@ -223,11 +227,6 @@ class Parameter(ABC):
|
|
223
227
|
"""Return the unit of measurement."""
|
224
228
|
return self.description.unit_of_measurement
|
225
229
|
|
226
|
-
@property
|
227
|
-
def request(self) -> Request:
|
228
|
-
"""Return request to change the parameter."""
|
229
|
-
raise NotImplementedError
|
230
|
-
|
231
230
|
|
232
231
|
class BinaryParameter(Parameter):
|
233
232
|
"""Represents binary device parameter."""
|
@@ -9,7 +9,7 @@ from typing import Final, Literal
|
|
9
9
|
|
10
10
|
from pyplumio.const import STATE_OFF, STATE_ON
|
11
11
|
from pyplumio.devices import AddressableDevice
|
12
|
-
from pyplumio.
|
12
|
+
from pyplumio.frames.requests import SetScheduleRequest
|
13
13
|
from pyplumio.structures.schedules import collect_schedule_data
|
14
14
|
|
15
15
|
TIME_FORMAT: Final = "%H:%M"
|
@@ -161,8 +161,7 @@ class Schedule(Iterable):
|
|
161
161
|
def commit(self) -> None:
|
162
162
|
"""Commit a weekly schedule to the device."""
|
163
163
|
self.device.queue.put_nowait(
|
164
|
-
|
165
|
-
"frames.requests.SetScheduleRequest",
|
164
|
+
SetScheduleRequest(
|
166
165
|
recipient=self.device.address,
|
167
166
|
data=collect_schedule_data(self.name, self.device),
|
168
167
|
)
|