PyPlumIO 0.6.7__tar.gz → 0.6.8__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.7 → pyplumio-0.6.8}/.pre-commit-config.yaml +2 -2
- {pyplumio-0.6.7 → pyplumio-0.6.8}/PKG-INFO +7 -7
- {pyplumio-0.6.7 → pyplumio-0.6.8}/PyPlumIO.egg-info/PKG-INFO +7 -7
- {pyplumio-0.6.7 → pyplumio-0.6.8}/PyPlumIO.egg-info/requires.txt +6 -6
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/_version.py +3 -3
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/connection.py +19 -13
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyproject.toml +6 -6
- pyplumio-0.6.8/requirements.txt +1 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/requirements_test.txt +5 -5
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_connection.py +29 -36
- pyplumio-0.6.7/requirements.txt +0 -1
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.gitattributes +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/CODE_OF_CONDUCT.md +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/dependabot.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/workflows/ci.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/workflows/codeql.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/workflows/deploy.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.github/workflows/documentation.yml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.gitignore +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.qlty/qlty.toml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/.vscode/settings.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/LICENSE +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/MANIFEST.in +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/PyPlumIO.egg-info/top_level.txt +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/README.md +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/Makefile +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/make.bat +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/callbacks.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/conf.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/connecting.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/frames.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/index.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/mixers_thermostats.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/protocol.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/reading.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/schedules.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/docs/source/writing.rst +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/images/ecomax.png +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/images/rs485.png +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/__main__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/const.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/data_types.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/devices/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/devices/ecomax.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/devices/ecoster.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/devices/mixer.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/devices/thermostat.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/exceptions.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/filters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/frames/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/frames/messages.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/frames/requests.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/frames/responses.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/helpers/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/helpers/async_cache.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/helpers/event_manager.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/helpers/task_manager.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/parameters/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/parameters/ecomax.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/parameters/mixer.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/parameters/thermostat.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/protocol.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/py.typed +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/stream.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/alerts.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/ecomax_parameters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/frame_versions.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/mixer_parameters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/network_info.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/product_info.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/program_version.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/regulator_data.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/regulator_data_schema.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/schedules.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/sensor_data.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/structures/thermostat_parameters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/pyplumio/utils.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/requirements_docs.txt +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/setup.cfg +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/conftest.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/devices/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/devices/test_ecomax.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/devices/test_ecoster.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/devices/test_init.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/devices/test_mixer.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/devices/test_thermostat.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/frames/test_init.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/frames/test_messages.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/frames/test_requests.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/frames/test_responses.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/helpers/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/helpers/test_async_cache.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/helpers/test_event_manager.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/helpers/test_task_manager.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/helpers/test_uid.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/custom/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/custom/test_init.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/test_ecomax.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/test_init.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/test_mixers.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/parameters/test_thermostats.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/ruff.toml +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/__init__.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/test_alerts.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/test_ecomax_parameters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/test_frame_versions.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/test_mixer_parameters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/test_product_info.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/structures/test_schedules.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_data_types.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_filters.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_init.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_main.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_protocol.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_stream.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/test_utils.py +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/messages/regulator_data.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/messages/sensor_data.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/alerts.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/ecomax_control.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/mixer_parameters.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/set_schedule.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/alerts.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/device_available.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/mixer_parameters.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/password.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/program_version.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/schedules.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/responses/uid.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {pyplumio-0.6.7 → pyplumio-0.6.8}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# See https://pre-commit.com/hooks.html for more hooks
|
|
4
4
|
repos:
|
|
5
5
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
6
|
-
rev: v0.14.
|
|
6
|
+
rev: v0.14.10
|
|
7
7
|
hooks:
|
|
8
8
|
- id: ruff
|
|
9
9
|
args:
|
|
@@ -13,6 +13,6 @@ repos:
|
|
|
13
13
|
hooks:
|
|
14
14
|
- id: codespell
|
|
15
15
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
16
|
-
rev: v1.
|
|
16
|
+
rev: v1.19.1
|
|
17
17
|
hooks:
|
|
18
18
|
- id: mypy
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPlumIO
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
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
|
|
@@ -23,17 +23,17 @@ Classifier: Topic :: Home Automation
|
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
-
Requires-Dist: pyserial-asyncio==0.
|
|
26
|
+
Requires-Dist: pyserial-asyncio-fast==0.16
|
|
27
27
|
Provides-Extra: test
|
|
28
28
|
Requires-Dist: codespell==2.4.1; extra == "test"
|
|
29
|
-
Requires-Dist: coverage==7.
|
|
29
|
+
Requires-Dist: coverage==7.13.0; extra == "test"
|
|
30
30
|
Requires-Dist: freezegun==1.5.5; extra == "test"
|
|
31
|
-
Requires-Dist: mypy==1.19.
|
|
31
|
+
Requires-Dist: mypy==1.19.1; extra == "test"
|
|
32
32
|
Requires-Dist: numpy<3.0.0,>=2.0.0; extra == "test"
|
|
33
33
|
Requires-Dist: pyserial-asyncio-fast==0.16; extra == "test"
|
|
34
|
-
Requires-Dist: pytest==9.0.
|
|
34
|
+
Requires-Dist: pytest==9.0.2; extra == "test"
|
|
35
35
|
Requires-Dist: pytest-asyncio==1.3.0; extra == "test"
|
|
36
|
-
Requires-Dist: ruff==0.14.
|
|
36
|
+
Requires-Dist: ruff==0.14.10; extra == "test"
|
|
37
37
|
Requires-Dist: tox==4.32.0; extra == "test"
|
|
38
38
|
Requires-Dist: types-pyserial==3.5.0.20251001; extra == "test"
|
|
39
39
|
Provides-Extra: docs
|
|
@@ -42,7 +42,7 @@ Requires-Dist: sphinx_rtd_theme==3.0.2; extra == "docs"
|
|
|
42
42
|
Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
|
|
43
43
|
Provides-Extra: dev
|
|
44
44
|
Requires-Dist: pyplumio[docs,test]; extra == "dev"
|
|
45
|
-
Requires-Dist: pre-commit==4.5.
|
|
45
|
+
Requires-Dist: pre-commit==4.5.1; extra == "dev"
|
|
46
46
|
Requires-Dist: tomli==2.3.0; extra == "dev"
|
|
47
47
|
Dynamic: license-file
|
|
48
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPlumIO
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
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
|
|
@@ -23,17 +23,17 @@ Classifier: Topic :: Home Automation
|
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
-
Requires-Dist: pyserial-asyncio==0.
|
|
26
|
+
Requires-Dist: pyserial-asyncio-fast==0.16
|
|
27
27
|
Provides-Extra: test
|
|
28
28
|
Requires-Dist: codespell==2.4.1; extra == "test"
|
|
29
|
-
Requires-Dist: coverage==7.
|
|
29
|
+
Requires-Dist: coverage==7.13.0; extra == "test"
|
|
30
30
|
Requires-Dist: freezegun==1.5.5; extra == "test"
|
|
31
|
-
Requires-Dist: mypy==1.19.
|
|
31
|
+
Requires-Dist: mypy==1.19.1; extra == "test"
|
|
32
32
|
Requires-Dist: numpy<3.0.0,>=2.0.0; extra == "test"
|
|
33
33
|
Requires-Dist: pyserial-asyncio-fast==0.16; extra == "test"
|
|
34
|
-
Requires-Dist: pytest==9.0.
|
|
34
|
+
Requires-Dist: pytest==9.0.2; extra == "test"
|
|
35
35
|
Requires-Dist: pytest-asyncio==1.3.0; extra == "test"
|
|
36
|
-
Requires-Dist: ruff==0.14.
|
|
36
|
+
Requires-Dist: ruff==0.14.10; extra == "test"
|
|
37
37
|
Requires-Dist: tox==4.32.0; extra == "test"
|
|
38
38
|
Requires-Dist: types-pyserial==3.5.0.20251001; extra == "test"
|
|
39
39
|
Provides-Extra: docs
|
|
@@ -42,7 +42,7 @@ Requires-Dist: sphinx_rtd_theme==3.0.2; extra == "docs"
|
|
|
42
42
|
Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
|
|
43
43
|
Provides-Extra: dev
|
|
44
44
|
Requires-Dist: pyplumio[docs,test]; extra == "dev"
|
|
45
|
-
Requires-Dist: pre-commit==4.5.
|
|
45
|
+
Requires-Dist: pre-commit==4.5.1; extra == "dev"
|
|
46
46
|
Requires-Dist: tomli==2.3.0; extra == "dev"
|
|
47
47
|
Dynamic: license-file
|
|
48
48
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
pyserial-asyncio==0.
|
|
1
|
+
pyserial-asyncio-fast==0.16
|
|
2
2
|
|
|
3
3
|
[dev]
|
|
4
4
|
pyplumio[docs,test]
|
|
5
|
-
pre-commit==4.5.
|
|
5
|
+
pre-commit==4.5.1
|
|
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.13.0
|
|
16
16
|
freezegun==1.5.5
|
|
17
|
-
mypy==1.19.
|
|
17
|
+
mypy==1.19.1
|
|
18
18
|
numpy<3.0.0,>=2.0.0
|
|
19
19
|
pyserial-asyncio-fast==0.16
|
|
20
|
-
pytest==9.0.
|
|
20
|
+
pytest==9.0.2
|
|
21
21
|
pytest-asyncio==1.3.0
|
|
22
|
-
ruff==0.14.
|
|
22
|
+
ruff==0.14.10
|
|
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.8'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 8)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gbde57b4a1'
|
|
@@ -11,6 +11,7 @@ from types import MappingProxyType
|
|
|
11
11
|
from typing import Any, Final
|
|
12
12
|
|
|
13
13
|
from serial import EIGHTBITS, PARITY_NONE, STOPBITS_ONE
|
|
14
|
+
import serial_asyncio_fast
|
|
14
15
|
|
|
15
16
|
from pyplumio.devices import PhysicalDevice
|
|
16
17
|
from pyplumio.exceptions import ConnectionFailedError
|
|
@@ -23,13 +24,6 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
23
24
|
TRY_CONNECT_FOR_SECONDS: Final = 5
|
|
24
25
|
RECONNECT_AFTER_SECONDS: Final = 20
|
|
25
26
|
|
|
26
|
-
try:
|
|
27
|
-
import serial_asyncio_fast as pyserial_asyncio
|
|
28
|
-
|
|
29
|
-
_LOGGER.info("Using pyserial-asyncio-fast in place of pyserial-asyncio")
|
|
30
|
-
except ImportError:
|
|
31
|
-
import serial_asyncio as pyserial_asyncio # type: ignore[no-redef]
|
|
32
|
-
|
|
33
27
|
|
|
34
28
|
class Connection(ABC, TaskManager):
|
|
35
29
|
"""Represents a connection.
|
|
@@ -37,11 +31,12 @@ class Connection(ABC, TaskManager):
|
|
|
37
31
|
All specific connection classes MUST be inherited from this class.
|
|
38
32
|
"""
|
|
39
33
|
|
|
40
|
-
__slots__ = ("_protocol", "_reconnect_on_failure", "_options")
|
|
34
|
+
__slots__ = ("_protocol", "_reconnect_on_failure", "_options", "_retries")
|
|
41
35
|
|
|
42
36
|
_protocol: Protocol
|
|
43
37
|
_reconnect_on_failure: bool
|
|
44
38
|
_options: dict[str, Any]
|
|
39
|
+
_retries: int
|
|
45
40
|
|
|
46
41
|
def __init__(
|
|
47
42
|
self,
|
|
@@ -60,6 +55,7 @@ class Connection(ABC, TaskManager):
|
|
|
60
55
|
self._reconnect_on_failure = reconnect_on_failure
|
|
61
56
|
self._protocol = protocol
|
|
62
57
|
self._options = options
|
|
58
|
+
self._retries = 0
|
|
63
59
|
|
|
64
60
|
async def __aenter__(self) -> Connection:
|
|
65
61
|
"""Provide an entry point for the context manager."""
|
|
@@ -86,11 +82,21 @@ class Connection(ABC, TaskManager):
|
|
|
86
82
|
"""Try to connect and reconnect on failure."""
|
|
87
83
|
try:
|
|
88
84
|
await self._connect()
|
|
85
|
+
if self._retries > 0:
|
|
86
|
+
_LOGGER.info(
|
|
87
|
+
"Connection to device restored after %i retries", self._retries
|
|
88
|
+
)
|
|
89
|
+
self._retries = 0
|
|
89
90
|
except ConnectionFailedError:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
if self._retries == 0:
|
|
92
|
+
_LOGGER.error(
|
|
93
|
+
(
|
|
94
|
+
"Unable to connect to the device. Connection we be retried "
|
|
95
|
+
"automatically every %i seconds in background."
|
|
96
|
+
),
|
|
97
|
+
RECONNECT_AFTER_SECONDS,
|
|
98
|
+
)
|
|
99
|
+
self._retries += 1
|
|
94
100
|
await asyncio.sleep(RECONNECT_AFTER_SECONDS)
|
|
95
101
|
self.create_task(self._reconnect(), name="reconnect_task")
|
|
96
102
|
|
|
@@ -209,7 +215,7 @@ class SerialConnection(Connection):
|
|
|
209
215
|
self,
|
|
210
216
|
) -> tuple[asyncio.StreamReader, asyncio.StreamWriter]:
|
|
211
217
|
"""Open the connection and return reader and writer objects."""
|
|
212
|
-
return await
|
|
218
|
+
return await serial_asyncio_fast.open_serial_connection(
|
|
213
219
|
url=self.url,
|
|
214
220
|
baudrate=self.baudrate,
|
|
215
221
|
bytesize=EIGHTBITS,
|
|
@@ -24,7 +24,7 @@ classifiers = [
|
|
|
24
24
|
"Topic :: Home Automation",
|
|
25
25
|
]
|
|
26
26
|
dependencies = [
|
|
27
|
-
"pyserial-asyncio==0.
|
|
27
|
+
"pyserial-asyncio-fast==0.16"
|
|
28
28
|
]
|
|
29
29
|
dynamic = ["version"]
|
|
30
30
|
|
|
@@ -36,14 +36,14 @@ dynamic = ["version"]
|
|
|
36
36
|
[project.optional-dependencies]
|
|
37
37
|
test = [
|
|
38
38
|
"codespell==2.4.1",
|
|
39
|
-
"coverage==7.
|
|
39
|
+
"coverage==7.13.0",
|
|
40
40
|
"freezegun==1.5.5",
|
|
41
|
-
"mypy==1.19.
|
|
41
|
+
"mypy==1.19.1",
|
|
42
42
|
"numpy<3.0.0,>=2.0.0",
|
|
43
43
|
"pyserial-asyncio-fast==0.16",
|
|
44
|
-
"pytest==9.0.
|
|
44
|
+
"pytest==9.0.2",
|
|
45
45
|
"pytest-asyncio==1.3.0",
|
|
46
|
-
"ruff==0.14.
|
|
46
|
+
"ruff==0.14.10",
|
|
47
47
|
"tox==4.32.0",
|
|
48
48
|
"types-pyserial==3.5.0.20251001"
|
|
49
49
|
]
|
|
@@ -54,7 +54,7 @@ docs = [
|
|
|
54
54
|
]
|
|
55
55
|
dev = [
|
|
56
56
|
"pyplumio[test,docs]",
|
|
57
|
-
"pre-commit==4.5.
|
|
57
|
+
"pre-commit==4.5.1",
|
|
58
58
|
"tomli==2.3.0"
|
|
59
59
|
]
|
|
60
60
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyserial-asyncio-fast==0.16
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
codespell==2.4.1
|
|
2
|
-
coverage==7.
|
|
2
|
+
coverage==7.13.0
|
|
3
3
|
freezegun==1.5.5
|
|
4
|
-
mypy==1.19.
|
|
4
|
+
mypy==1.19.1
|
|
5
5
|
numpy<3.0.0,>=2.0.0
|
|
6
|
-
pre-commit==4.5.
|
|
6
|
+
pre-commit==4.5.1
|
|
7
7
|
pyserial-asyncio-fast==0.16
|
|
8
|
+
pytest==9.0.2
|
|
8
9
|
pytest-asyncio==1.3.0
|
|
9
|
-
|
|
10
|
-
ruff==0.14.7
|
|
10
|
+
ruff==0.14.10
|
|
11
11
|
tomli==2.3.0
|
|
12
12
|
tox==4.32.0
|
|
13
13
|
types-pyserial==3.5.0.20251001
|
|
@@ -3,40 +3,24 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from asyncio import StreamReader, StreamWriter
|
|
6
|
-
from importlib import reload
|
|
7
6
|
import logging
|
|
8
|
-
import
|
|
9
|
-
from typing import Any, Final
|
|
7
|
+
from typing import Final
|
|
10
8
|
from unittest.mock import AsyncMock, Mock, patch
|
|
11
9
|
|
|
12
10
|
import pytest
|
|
13
11
|
from serial import EIGHTBITS, PARITY_NONE, STOPBITS_ONE
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
from pyplumio.connection import (
|
|
14
|
+
RECONNECT_AFTER_SECONDS,
|
|
15
|
+
Connection,
|
|
16
|
+
SerialConnection,
|
|
17
|
+
TcpConnection,
|
|
18
|
+
)
|
|
17
19
|
from pyplumio.devices.ecomax import EcoMAX
|
|
18
20
|
from pyplumio.exceptions import ConnectionFailedError
|
|
19
21
|
from pyplumio.protocol import AsyncProtocol, DummyProtocol, Protocol
|
|
20
22
|
|
|
21
23
|
|
|
22
|
-
@pytest.fixture(name="use_fast", params=(True, False))
|
|
23
|
-
def fixture_use_fast(request, monkeypatch, caplog) -> Any:
|
|
24
|
-
"""Try with and without serial-asyncio-fast package."""
|
|
25
|
-
if not request.param:
|
|
26
|
-
monkeypatch.setitem(sys.modules, "serial_asyncio_fast", None)
|
|
27
|
-
|
|
28
|
-
with caplog.at_level(logging.INFO):
|
|
29
|
-
reload(pyplumio.connection)
|
|
30
|
-
|
|
31
|
-
message = "Using pyserial-asyncio-fast in place of pyserial-asyncio"
|
|
32
|
-
if request.param:
|
|
33
|
-
assert message in caplog.text
|
|
34
|
-
else:
|
|
35
|
-
assert message not in caplog.text
|
|
36
|
-
|
|
37
|
-
return request.param
|
|
38
|
-
|
|
39
|
-
|
|
40
24
|
@pytest.fixture(name="stream_writer")
|
|
41
25
|
def fixture_stream_writer():
|
|
42
26
|
"""Return a mock of asyncio stream writer."""
|
|
@@ -64,12 +48,11 @@ def fixture_asyncio_open_connection(
|
|
|
64
48
|
|
|
65
49
|
@pytest.fixture(name="serial_asyncio_open_serial_connection")
|
|
66
50
|
def fixture_serial_asyncio_open_serial_connection(
|
|
67
|
-
|
|
51
|
+
stream_reader: StreamReader, stream_writer: StreamWriter
|
|
68
52
|
):
|
|
69
53
|
"""Bypass opening serial_asyncio connection."""
|
|
70
|
-
module = "serial_asyncio_fast" if use_fast else "serial_asyncio"
|
|
71
54
|
with patch(
|
|
72
|
-
|
|
55
|
+
"serial_asyncio_fast.open_serial_connection",
|
|
73
56
|
return_value=(stream_reader, stream_writer),
|
|
74
57
|
) as mock_connection:
|
|
75
58
|
yield mock_connection
|
|
@@ -115,33 +98,43 @@ class TestConnection:
|
|
|
115
98
|
await connection.close()
|
|
116
99
|
mock_protocol.shutdown.assert_called_once()
|
|
117
100
|
|
|
118
|
-
@pytest.mark.parametrize(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
],
|
|
101
|
+
@pytest.mark.parametrize("reconnect_on_failure", [True, False])
|
|
102
|
+
@patch.object(
|
|
103
|
+
DummyConnection,
|
|
104
|
+
"_open_connection",
|
|
105
|
+
side_effect=(OSError, (AsyncMock(), AsyncMock), None),
|
|
124
106
|
)
|
|
125
|
-
@patch
|
|
107
|
+
@patch("pyplumio.protocol.AsyncProtocol.connection_established")
|
|
126
108
|
async def test_reconnect(
|
|
127
109
|
self,
|
|
110
|
+
mock_connection_established,
|
|
128
111
|
mock_open_connection,
|
|
129
112
|
caplog,
|
|
130
113
|
reconnect_on_failure: bool,
|
|
131
|
-
expected_log: str | None,
|
|
132
114
|
) -> None:
|
|
133
115
|
"""Test reconnect logic."""
|
|
134
116
|
connection = DummyConnection(reconnect_on_failure=reconnect_on_failure)
|
|
135
117
|
if reconnect_on_failure:
|
|
136
118
|
with caplog.at_level(logging.ERROR):
|
|
137
119
|
await connection.connect()
|
|
120
|
+
assert "Unable to connect to the device." in caplog.text
|
|
121
|
+
assert (
|
|
122
|
+
f"automatically every {RECONNECT_AFTER_SECONDS} seconds"
|
|
123
|
+
in caplog.text
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
with caplog.at_level(logging.INFO):
|
|
127
|
+
await connection.connect()
|
|
128
|
+
assert "Connection to device restored after 1 retries" in caplog.text
|
|
129
|
+
mock_connection_established.assert_called_once()
|
|
130
|
+
|
|
131
|
+
assert mock_open_connection.await_count == 2
|
|
138
132
|
|
|
139
|
-
assert expected_log in caplog.text
|
|
140
133
|
else:
|
|
141
134
|
with pytest.raises(ConnectionFailedError):
|
|
142
135
|
await connection.connect()
|
|
143
136
|
|
|
144
|
-
|
|
137
|
+
mock_open_connection.assert_awaited_once()
|
|
145
138
|
|
|
146
139
|
@patch.object(DummyConnection, "close")
|
|
147
140
|
@patch.object(DummyConnection, "connect")
|
pyplumio-0.6.7/requirements.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pyserial-asyncio==0.6
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|