PyPlumIO 0.5.17__py3-none-any.whl → 0.5.18__py3-none-any.whl
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.17.dist-info → PyPlumIO-0.5.18.dist-info}/METADATA +4 -4
- {PyPlumIO-0.5.17.dist-info → PyPlumIO-0.5.18.dist-info}/RECORD +10 -10
- pyplumio/_version.py +2 -2
- pyplumio/helpers/factory.py +10 -5
- pyplumio/helpers/schedule.py +7 -7
- pyplumio/protocol.py +4 -3
- pyplumio/structures/ecomax_parameters.py +20 -30
- {PyPlumIO-0.5.17.dist-info → PyPlumIO-0.5.18.dist-info}/LICENSE +0 -0
- {PyPlumIO-0.5.17.dist-info → PyPlumIO-0.5.18.dist-info}/WHEEL +0 -0
- {PyPlumIO-0.5.17.dist-info → PyPlumIO-0.5.18.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: PyPlumIO
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.18
|
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
|
@@ -33,12 +33,12 @@ Requires-Dist: sphinx-rtd-theme ==2.0.0 ; extra == 'docs'
|
|
33
33
|
Requires-Dist: readthedocs-sphinx-search ==0.3.2 ; extra == 'docs'
|
34
34
|
Provides-Extra: test
|
35
35
|
Requires-Dist: codespell ==2.2.6 ; extra == 'test'
|
36
|
-
Requires-Dist: coverage ==7.5.
|
37
|
-
Requires-Dist: mypy ==1.
|
36
|
+
Requires-Dist: coverage ==7.5.1 ; extra == 'test'
|
37
|
+
Requires-Dist: mypy ==1.10.0 ; extra == 'test'
|
38
38
|
Requires-Dist: pyserial-asyncio-fast ==0.11 ; extra == 'test'
|
39
39
|
Requires-Dist: pytest ==8.2.0 ; extra == 'test'
|
40
40
|
Requires-Dist: pytest-asyncio ==0.23.6 ; extra == 'test'
|
41
|
-
Requires-Dist: ruff ==0.4.
|
41
|
+
Requires-Dist: ruff ==0.4.3 ; extra == 'test'
|
42
42
|
Requires-Dist: tox ==4.15.0 ; extra == 'test'
|
43
43
|
Requires-Dist: types-pyserial ==3.5.0.20240311 ; extra == 'test'
|
44
44
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
pyplumio/__init__.py,sha256=4v9BaIkJ440qu2ITrcwVLOg9KO8k2W1gnGHe86sDLM8,3292
|
2
2
|
pyplumio/__main__.py,sha256=oop76iR-XDHhMFhW4LO8-xTnBHsqzUQ5VVh__94OaqY,499
|
3
|
-
pyplumio/_version.py,sha256=
|
3
|
+
pyplumio/_version.py,sha256=TJSWAybqN12Cw_kxmDDEn4jE4KWfkCe6C38YXdi-hN8,413
|
4
4
|
pyplumio/connection.py,sha256=0PmpNOcV7RgSfEeM7Wnhtbw0TpdtMTyqpJPQ2h7IX9M,6199
|
5
5
|
pyplumio/const.py,sha256=4_VRx5mY7qf5fwaUluVlhuK_NIb7bClzhnhRLA-3GkY,3914
|
6
6
|
pyplumio/exceptions.py,sha256=3tgfe0GD-T-DV2TUybsv7dwsk9P9f2g-4Gd8jnXw6DI,698
|
7
7
|
pyplumio/filters.py,sha256=kXR4SUS7YXGaljW35NpEB9prHgxDKpsf_U1ACMTnh5I,11174
|
8
|
-
pyplumio/protocol.py,sha256=
|
8
|
+
pyplumio/protocol.py,sha256=btBJiCyB2ys-tiQOm8kj97_Y7yesO4cIOKrEGbrCrsk,8787
|
9
9
|
pyplumio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
pyplumio/stream.py,sha256=UPqlUmNBobSS4SvS5BI19g_FeSTLpLj1k3l7OeE32bI,4374
|
11
11
|
pyplumio/utils.py,sha256=h46IS7hOHFbAFGGmnyAUVwlfk0m_eSwa3U8oZq6-bJY,687
|
@@ -21,9 +21,9 @@ pyplumio/frames/responses.py,sha256=7MHwXkNVTcwYpWRAXBMiPxmaJw3vgX9kgoaBTXeRy60,
|
|
21
21
|
pyplumio/helpers/__init__.py,sha256=H2xxdkF-9uADLwEbfBUoxNTdwru3L5Z2cfJjgsuRsn0,31
|
22
22
|
pyplumio/helpers/data_types.py,sha256=UIbJu0JfXaNCiHlg8EnYOfeyKq9Mxiu6j_D8GyRudZk,8211
|
23
23
|
pyplumio/helpers/event_manager.py,sha256=E9gMGCxOOBNZgnHCwpb8rtFgKsNIkjHvIN73XBgwQDk,6004
|
24
|
-
pyplumio/helpers/factory.py,sha256=
|
24
|
+
pyplumio/helpers/factory.py,sha256=Ld_PbKnkj0HFnuYcoDwcitiMRa-88UQKXcsE5vdgLqs,824
|
25
25
|
pyplumio/helpers/parameter.py,sha256=ihdom_tON2urYXmS7x_2-zk2I-PcogdjILE7tOiGR8M,8698
|
26
|
-
pyplumio/helpers/schedule.py,sha256=
|
26
|
+
pyplumio/helpers/schedule.py,sha256=395yTDAKV43so5vEG-q0mgqXGoFVWKpIyhdmqzKT-X4,4958
|
27
27
|
pyplumio/helpers/task_manager.py,sha256=P17Nw9HDbA9NMSdkJo2WQRbEsykzzFSwQyyRzI3uFPk,1089
|
28
28
|
pyplumio/helpers/timeout.py,sha256=bWBWvLPpgjCvdG5hlrSTXok_CsLme-jGnY9rHwupRc0,1286
|
29
29
|
pyplumio/helpers/typing.py,sha256=V3uYCMyC4oePM7YzL0S-xEsyTgjgDbkOM0VNe-1LBPo,684
|
@@ -32,7 +32,7 @@ pyplumio/structures/__init__.py,sha256=-nbLcQvbWcs2EmnChqJmMVo1CUfj8lqMHb8yK1mV4
|
|
32
32
|
pyplumio/structures/alerts.py,sha256=v--wbEKoB07r9KHMuZgMRT1dk4r8dPwxxB5cPv4lzZY,3259
|
33
33
|
pyplumio/structures/boiler_load.py,sha256=HVPKt53VWvp2KDuSK1B9kcpX1h3Bz3GPBqBI4Oscm2Q,837
|
34
34
|
pyplumio/structures/boiler_power.py,sha256=tP00IMz5qVQaePr70uTz_jCLoXHnmj_g3pvKxdNvenc,900
|
35
|
-
pyplumio/structures/ecomax_parameters.py,sha256=
|
35
|
+
pyplumio/structures/ecomax_parameters.py,sha256=Ywiabk0panLHSScv8SZC_cBmkdSXuXPEfDFyEsjR0ts,25895
|
36
36
|
pyplumio/structures/fan_power.py,sha256=fGU_BTPTtAplnjmTQQHhMXdoiHVYOdLlZ_PDA9F5u9c,870
|
37
37
|
pyplumio/structures/frame_versions.py,sha256=9lFnrlxkok_3CTbXz38cntacnubWYGcaubDnYq9NOAM,1559
|
38
38
|
pyplumio/structures/fuel_consumption.py,sha256=H23GVw9s0fbURvJHAfReTEvGp5q-oPOidh1mToOO3ec,975
|
@@ -54,8 +54,8 @@ pyplumio/structures/statuses.py,sha256=zjDQTU5fdORRzRkvlkzplgVS8A3AdyHG2qihfkdOH
|
|
54
54
|
pyplumio/structures/temperatures.py,sha256=O8rANFN-wz5NvTWqh_25oUfFajjVyI9hoOMmz8vkKHg,2336
|
55
55
|
pyplumio/structures/thermostat_parameters.py,sha256=1SJzHguN12JE-e2utwA448VgUkFddQxBQy3m66qCobk,7934
|
56
56
|
pyplumio/structures/thermostat_sensors.py,sha256=N9nm3Rp1Rhb8wUPUkJIX56olZztixoxyFxIxP4R5P2g,3176
|
57
|
-
PyPlumIO-0.5.
|
58
|
-
PyPlumIO-0.5.
|
59
|
-
PyPlumIO-0.5.
|
60
|
-
PyPlumIO-0.5.
|
61
|
-
PyPlumIO-0.5.
|
57
|
+
PyPlumIO-0.5.18.dist-info/LICENSE,sha256=m-UuZFjXJ22uPTGm9kSHS8bqjsf5T8k2wL9bJn1Y04o,1088
|
58
|
+
PyPlumIO-0.5.18.dist-info/METADATA,sha256=fHzLAiOHlj3nYHmvnm4OZsFBUMyJcSnSgmRg7zbbr0s,5415
|
59
|
+
PyPlumIO-0.5.18.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
60
|
+
PyPlumIO-0.5.18.dist-info/top_level.txt,sha256=kNBz9UPPkPD9teDn3U_sEy5LjzwLm9KfADCXtBlbw8A,9
|
61
|
+
PyPlumIO-0.5.18.dist-info/RECORD,,
|
pyplumio/_version.py
CHANGED
pyplumio/helpers/factory.py
CHANGED
@@ -2,21 +2,26 @@
|
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
4
|
import asyncio
|
5
|
-
|
5
|
+
import importlib
|
6
6
|
import logging
|
7
|
+
from types import ModuleType
|
7
8
|
from typing import Any
|
8
9
|
|
9
10
|
_LOGGER = logging.getLogger(__name__)
|
10
11
|
|
11
12
|
|
13
|
+
async def _load_module(module_name: str) -> ModuleType:
|
14
|
+
"""Load a module by name."""
|
15
|
+
return await asyncio.get_running_loop().run_in_executor(
|
16
|
+
None, importlib.import_module, f".{module_name}", "pyplumio"
|
17
|
+
)
|
18
|
+
|
19
|
+
|
12
20
|
async def create_instance(class_path: str, **kwargs: Any) -> Any:
|
13
21
|
"""Return a class instance from the class path."""
|
14
|
-
loop = asyncio.get_running_loop()
|
15
22
|
module_name, class_name = class_path.rsplit(".", 1)
|
16
23
|
try:
|
17
|
-
module = await
|
18
|
-
None, import_module, "." + module_name, "pyplumio"
|
19
|
-
)
|
24
|
+
module = await _load_module(module_name)
|
20
25
|
return getattr(module, class_name)(**kwargs)
|
21
26
|
except Exception:
|
22
27
|
_LOGGER.error("Failed to load module (%s)", class_path)
|
pyplumio/helpers/schedule.py
CHANGED
@@ -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.helpers.factory import create_instance
|
13
13
|
from pyplumio.structures.schedules import collect_schedule_data
|
14
14
|
|
15
15
|
TIME_FORMAT: Final = "%H:%M"
|
@@ -158,11 +158,11 @@ class Schedule(Iterable):
|
|
158
158
|
self.saturday,
|
159
159
|
).__iter__()
|
160
160
|
|
161
|
-
def commit(self) -> None:
|
161
|
+
async def commit(self) -> None:
|
162
162
|
"""Commit a weekly schedule to the device."""
|
163
|
-
|
164
|
-
SetScheduleRequest
|
165
|
-
|
166
|
-
|
167
|
-
)
|
163
|
+
request = await create_instance(
|
164
|
+
"frames.requests.SetScheduleRequest",
|
165
|
+
recipient=self.device.address,
|
166
|
+
data=collect_schedule_data(self.name, self.device),
|
168
167
|
)
|
168
|
+
await self.device.queue.put(request)
|
pyplumio/protocol.py
CHANGED
@@ -233,9 +233,10 @@ class AsyncProtocol(Protocol, EventManager):
|
|
233
233
|
async def get_device_entry(self, device_type: DeviceType) -> AddressableDevice:
|
234
234
|
"""Set up device entry."""
|
235
235
|
handler, name = get_device_handler_and_name(device_type)
|
236
|
-
|
237
|
-
name
|
238
|
-
|
236
|
+
if name not in self.data:
|
237
|
+
self.data[name] = await self._create_device_entry(name, handler)
|
238
|
+
|
239
|
+
return self.data[name]
|
239
240
|
|
240
241
|
async def _create_device_entry(self, name: str, handler: str) -> AddressableDevice:
|
241
242
|
"""Create device entry."""
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
from collections.abc import Generator
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import Any, Final
|
6
|
+
from typing import Any, Final, cast
|
7
7
|
|
8
8
|
from pyplumio.const import (
|
9
9
|
ATTR_INDEX,
|
@@ -47,37 +47,27 @@ class EcomaxParameter(Parameter):
|
|
47
47
|
async def create_request(self) -> Request:
|
48
48
|
"""Create a request to change the parameter."""
|
49
49
|
if self.description.name == ATTR_ECOMAX_CONTROL:
|
50
|
-
|
51
|
-
|
52
|
-
recipient=self.device.address,
|
53
|
-
data={
|
54
|
-
ATTR_VALUE: self.values.value,
|
55
|
-
},
|
56
|
-
)
|
57
|
-
|
50
|
+
cls = "frames.requests.EcomaxControlRequest"
|
51
|
+
data = {ATTR_VALUE: self.values.value}
|
58
52
|
elif self.description.name == ATTR_THERMOSTAT_PROFILE:
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
ATTR_SIZE: 1,
|
67
|
-
},
|
68
|
-
)
|
69
|
-
|
53
|
+
cls = "frames.requests.SetThermostatParameterRequest"
|
54
|
+
data = {
|
55
|
+
ATTR_INDEX: self._index,
|
56
|
+
ATTR_VALUE: self.values.value,
|
57
|
+
ATTR_OFFSET: 0,
|
58
|
+
ATTR_SIZE: 1,
|
59
|
+
}
|
70
60
|
else:
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
61
|
+
cls = "frames.requests.SetEcomaxParameterRequest"
|
62
|
+
data = {
|
63
|
+
ATTR_INDEX: self._index,
|
64
|
+
ATTR_VALUE: self.values.value,
|
65
|
+
}
|
66
|
+
|
67
|
+
return cast(
|
68
|
+
Request,
|
69
|
+
await create_instance(cls, recipient=self.device.address, data=data),
|
70
|
+
)
|
81
71
|
|
82
72
|
async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
|
83
73
|
"""Set a parameter value."""
|
File without changes
|
File without changes
|
File without changes
|