PyPlumIO 0.5.18__py3-none-any.whl → 0.5.19__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.18.dist-info → PyPlumIO-0.5.19.dist-info}/METADATA +8 -8
- PyPlumIO-0.5.19.dist-info/RECORD +61 -0
- pyplumio/__init__.py +1 -0
- pyplumio/__main__.py +1 -0
- pyplumio/_version.py +2 -2
- pyplumio/connection.py +1 -0
- pyplumio/const.py +1 -0
- pyplumio/devices/__init__.py +25 -19
- pyplumio/devices/ecomax.py +3 -11
- pyplumio/devices/ecoster.py +1 -0
- pyplumio/devices/mixer.py +1 -0
- pyplumio/devices/thermostat.py +1 -0
- pyplumio/exceptions.py +1 -0
- pyplumio/filters.py +8 -10
- pyplumio/frames/__init__.py +35 -28
- pyplumio/frames/messages.py +1 -0
- pyplumio/frames/requests.py +1 -0
- pyplumio/frames/responses.py +1 -0
- pyplumio/helpers/data_types.py +1 -0
- pyplumio/helpers/event_manager.py +1 -0
- pyplumio/helpers/factory.py +10 -3
- pyplumio/helpers/parameter.py +1 -0
- pyplumio/helpers/schedule.py +11 -7
- pyplumio/helpers/task_manager.py +1 -0
- pyplumio/helpers/timeout.py +1 -0
- pyplumio/helpers/typing.py +1 -0
- pyplumio/helpers/uid.py +1 -0
- pyplumio/protocol.py +44 -54
- pyplumio/stream.py +16 -12
- pyplumio/structures/__init__.py +1 -0
- pyplumio/structures/alerts.py +1 -0
- pyplumio/structures/boiler_load.py +1 -0
- pyplumio/structures/boiler_power.py +1 -0
- pyplumio/structures/ecomax_parameters.py +8 -8
- pyplumio/structures/fan_power.py +1 -0
- pyplumio/structures/frame_versions.py +1 -0
- pyplumio/structures/fuel_consumption.py +1 -0
- pyplumio/structures/fuel_level.py +1 -0
- pyplumio/structures/lambda_sensor.py +1 -0
- pyplumio/structures/mixer_parameters.py +11 -13
- pyplumio/structures/mixer_sensors.py +1 -0
- pyplumio/structures/modules.py +1 -0
- pyplumio/structures/network_info.py +1 -0
- pyplumio/structures/output_flags.py +1 -0
- pyplumio/structures/outputs.py +1 -0
- pyplumio/structures/pending_alerts.py +1 -0
- pyplumio/structures/product_info.py +1 -0
- pyplumio/structures/program_version.py +3 -2
- pyplumio/structures/regulator_data.py +3 -4
- pyplumio/structures/regulator_data_schema.py +1 -0
- pyplumio/structures/schedules.py +14 -11
- pyplumio/structures/statuses.py +1 -0
- pyplumio/structures/temperatures.py +1 -0
- pyplumio/structures/thermostat_parameters.py +17 -22
- pyplumio/structures/thermostat_sensors.py +1 -0
- pyplumio/utils.py +1 -0
- PyPlumIO-0.5.18.dist-info/RECORD +0 -61
- {PyPlumIO-0.5.18.dist-info → PyPlumIO-0.5.19.dist-info}/LICENSE +0 -0
- {PyPlumIO-0.5.18.dist-info → PyPlumIO-0.5.19.dist-info}/WHEEL +0 -0
- {PyPlumIO-0.5.18.dist-info → PyPlumIO-0.5.19.dist-info}/top_level.txt +0 -0
pyplumio/protocol.py
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
"""Contains protocol representation."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
from abc import ABC, abstractmethod
|
5
6
|
import asyncio
|
6
7
|
from collections.abc import Awaitable, Callable
|
7
8
|
import logging
|
8
|
-
from typing import cast
|
9
|
+
from typing import NamedTuple, cast
|
9
10
|
|
10
11
|
from pyplumio.const import ATTR_CONNECTED, DeviceType
|
11
|
-
from pyplumio.devices import AddressableDevice
|
12
|
+
from pyplumio.devices import AddressableDevice
|
12
13
|
from pyplumio.exceptions import (
|
13
14
|
FrameDataError,
|
14
15
|
FrameError,
|
@@ -18,7 +19,6 @@ from pyplumio.exceptions import (
|
|
18
19
|
from pyplumio.frames import Frame
|
19
20
|
from pyplumio.frames.requests import StartMasterRequest
|
20
21
|
from pyplumio.helpers.event_manager import EventManager
|
21
|
-
from pyplumio.helpers.factory import create_instance
|
22
22
|
from pyplumio.stream import FrameReader, FrameWriter
|
23
23
|
from pyplumio.structures.network_info import (
|
24
24
|
EthernetParameters,
|
@@ -101,36 +101,43 @@ class DummyProtocol(Protocol):
|
|
101
101
|
await self.close_writer()
|
102
102
|
|
103
103
|
|
104
|
+
class Queues(NamedTuple):
|
105
|
+
"""Represents asyncio queues."""
|
106
|
+
|
107
|
+
read: asyncio.Queue
|
108
|
+
write: asyncio.Queue
|
109
|
+
|
110
|
+
|
104
111
|
class AsyncProtocol(Protocol, EventManager):
|
105
112
|
"""Represents an async protocol.
|
106
113
|
|
107
114
|
This protocol implements producer-consumers pattern using
|
108
115
|
asyncio queues.
|
109
116
|
|
110
|
-
The frame producer tries to read frames from write queue
|
111
|
-
available,
|
117
|
+
The frame producer tries to read frames from the write queue.
|
118
|
+
If any is available, it sends them to the device via frame writer.
|
112
119
|
|
113
|
-
It reads stream via frame reader, creates device
|
114
|
-
|
120
|
+
It then reads stream via frame reader, creates device entry and puts
|
121
|
+
received frame into the read queue.
|
115
122
|
|
116
|
-
Frame consumers
|
117
|
-
|
123
|
+
Frame consumers read frames from the read queue and send frame to
|
124
|
+
their respective device class for further processing.
|
118
125
|
"""
|
119
126
|
|
127
|
+
consumers_count: int
|
120
128
|
data: dict[str, AddressableDevice]
|
121
|
-
consumers_number: int
|
122
129
|
_network: NetworkInfo
|
123
|
-
_queues:
|
130
|
+
_queues: Queues
|
124
131
|
|
125
132
|
def __init__(
|
126
133
|
self,
|
127
134
|
ethernet_parameters: EthernetParameters | None = None,
|
128
135
|
wireless_parameters: WirelessParameters | None = None,
|
129
|
-
|
136
|
+
consumers_count: int = 3,
|
130
137
|
) -> None:
|
131
138
|
"""Initialize a new async protocol."""
|
132
139
|
super().__init__()
|
133
|
-
self.
|
140
|
+
self.consumers_count = consumers_count
|
134
141
|
self._network = NetworkInfo(
|
135
142
|
eth=(
|
136
143
|
EthernetParameters(status=False)
|
@@ -143,7 +150,7 @@ class AsyncProtocol(Protocol, EventManager):
|
|
143
150
|
else wireless_parameters
|
144
151
|
),
|
145
152
|
)
|
146
|
-
self._queues = (asyncio.Queue(), asyncio.Queue())
|
153
|
+
self._queues = Queues(asyncio.Queue(), asyncio.Queue())
|
147
154
|
|
148
155
|
def connection_established(
|
149
156
|
self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter
|
@@ -151,11 +158,10 @@ class AsyncProtocol(Protocol, EventManager):
|
|
151
158
|
"""Start frame producer and consumers."""
|
152
159
|
self.reader = FrameReader(reader)
|
153
160
|
self.writer = FrameWriter(writer)
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
self.create_task(self.frame_consumer(read_queue))
|
161
|
+
self._queues.write.put_nowait(StartMasterRequest(recipient=DeviceType.ECOMAX))
|
162
|
+
self.create_task(self.frame_producer(self._queues))
|
163
|
+
for _ in range(self.consumers_count):
|
164
|
+
self.create_task(self.frame_consumer(self._queues.read))
|
159
165
|
|
160
166
|
for device in self.data.values():
|
161
167
|
device.dispatch_nowait(ATTR_CONNECTED, True)
|
@@ -178,7 +184,7 @@ class AsyncProtocol(Protocol, EventManager):
|
|
178
184
|
|
179
185
|
async def shutdown(self) -> None:
|
180
186
|
"""Shutdown protocol tasks."""
|
181
|
-
await asyncio.gather(*[queue.join() for queue in self.
|
187
|
+
await asyncio.gather(*[queue.join() for queue in self._queues])
|
182
188
|
await super(Protocol, self).shutdown()
|
183
189
|
for device in self.data.values():
|
184
190
|
await device.shutdown()
|
@@ -187,24 +193,19 @@ class AsyncProtocol(Protocol, EventManager):
|
|
187
193
|
self.connected.clear()
|
188
194
|
await self.close_writer()
|
189
195
|
|
190
|
-
async def frame_producer(
|
191
|
-
self, read_queue: asyncio.Queue, write_queue: asyncio.Queue
|
192
|
-
) -> None:
|
196
|
+
async def frame_producer(self, queues: Queues) -> None:
|
193
197
|
"""Handle frame reads and writes."""
|
194
198
|
await self.connected.wait()
|
195
199
|
reader = cast(FrameReader, self.reader)
|
196
200
|
writer = cast(FrameWriter, self.writer)
|
197
201
|
while self.connected.is_set():
|
198
202
|
try:
|
199
|
-
if
|
200
|
-
await writer.write(await
|
201
|
-
|
203
|
+
if queues.write.qsize() > 0:
|
204
|
+
await writer.write(await queues.write.get())
|
205
|
+
queues.write.task_done()
|
202
206
|
|
203
207
|
if (response := await reader.read()) is not None:
|
204
|
-
|
205
|
-
cast(DeviceType, response.sender)
|
206
|
-
)
|
207
|
-
read_queue.put_nowait((device, response))
|
208
|
+
queues.read.put_nowait(response)
|
208
209
|
|
209
210
|
except FrameDataError as e:
|
210
211
|
_LOGGER.warning("Incorrect payload: %s", e)
|
@@ -220,36 +221,25 @@ class AsyncProtocol(Protocol, EventManager):
|
|
220
221
|
except Exception as e: # pylint: disable=broad-except
|
221
222
|
_LOGGER.exception(e)
|
222
223
|
|
223
|
-
async def frame_consumer(self,
|
224
|
+
async def frame_consumer(self, queue: asyncio.Queue) -> None:
|
224
225
|
"""Handle frame processing."""
|
225
226
|
await self.connected.wait()
|
226
227
|
while self.connected.is_set():
|
227
|
-
|
228
|
-
|
229
|
-
)
|
228
|
+
frame: Frame = await queue.get()
|
229
|
+
device = await self.get_device_entry(frame.sender)
|
230
230
|
device.handle_frame(frame)
|
231
|
-
|
231
|
+
queue.task_done()
|
232
232
|
|
233
233
|
async def get_device_entry(self, device_type: DeviceType) -> AddressableDevice:
|
234
|
-
"""Set up device entry."""
|
235
|
-
|
234
|
+
"""Set up or return a device entry."""
|
235
|
+
name = device_type.name.lower()
|
236
236
|
if name not in self.data:
|
237
|
-
|
237
|
+
device = await AddressableDevice.create(
|
238
|
+
device_type, queue=self._queues.write, network=self._network
|
239
|
+
)
|
240
|
+
device.dispatch_nowait(ATTR_CONNECTED, True)
|
241
|
+
self.create_task(device.async_setup())
|
242
|
+
self.set_event(name)
|
243
|
+
self.data[name] = device
|
238
244
|
|
239
245
|
return self.data[name]
|
240
|
-
|
241
|
-
async def _create_device_entry(self, name: str, handler: str) -> AddressableDevice:
|
242
|
-
"""Create device entry."""
|
243
|
-
write_queue = self.queues[1]
|
244
|
-
device: AddressableDevice = await create_instance(
|
245
|
-
handler, queue=write_queue, network=self._network
|
246
|
-
)
|
247
|
-
device.dispatch_nowait(ATTR_CONNECTED, True)
|
248
|
-
self.create_task(device.async_setup())
|
249
|
-
self.set_event(name)
|
250
|
-
return device
|
251
|
-
|
252
|
-
@property
|
253
|
-
def queues(self) -> tuple[asyncio.Queue, asyncio.Queue]:
|
254
|
-
"""Return the protocol queues."""
|
255
|
-
return self._queues
|
pyplumio/stream.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Contains a frame reader and writer classes."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
import asyncio
|
@@ -7,9 +8,9 @@ import logging
|
|
7
8
|
from typing import Final
|
8
9
|
|
9
10
|
from pyplumio.const import DeviceType
|
10
|
-
from pyplumio.
|
11
|
-
from pyplumio.
|
12
|
-
from pyplumio.
|
11
|
+
from pyplumio.devices import is_known_device_type
|
12
|
+
from pyplumio.exceptions import ChecksumError, ReadError, UnknownDeviceError
|
13
|
+
from pyplumio.frames import FRAME_START, Frame, bcc, struct_header
|
13
14
|
from pyplumio.helpers.timeout import timeout
|
14
15
|
|
15
16
|
READER_TIMEOUT: Final = 10
|
@@ -83,7 +84,7 @@ class FrameReader:
|
|
83
84
|
length,
|
84
85
|
recipient,
|
85
86
|
sender,
|
86
|
-
|
87
|
+
econet_type,
|
87
88
|
econet_version,
|
88
89
|
] = struct_header.unpack_from(buffer)
|
89
90
|
|
@@ -92,7 +93,7 @@ class FrameReader:
|
|
92
93
|
length,
|
93
94
|
recipient,
|
94
95
|
sender,
|
95
|
-
|
96
|
+
econet_type,
|
96
97
|
econet_version,
|
97
98
|
)
|
98
99
|
|
@@ -111,13 +112,16 @@ class FrameReader:
|
|
111
112
|
length,
|
112
113
|
recipient,
|
113
114
|
sender,
|
114
|
-
|
115
|
+
econet_type,
|
115
116
|
econet_version,
|
116
117
|
) = await self._read_header()
|
117
118
|
|
118
119
|
if recipient not in (DeviceType.ECONET, DeviceType.ALL):
|
119
120
|
return None
|
120
121
|
|
122
|
+
if not is_known_device_type(sender):
|
123
|
+
raise UnknownDeviceError(f"Unknown sender type ({sender})")
|
124
|
+
|
121
125
|
if length > MAX_FRAME_LENGTH or length < MIN_FRAME_LENGTH:
|
122
126
|
raise ReadError(f"Unexpected frame length ({length})")
|
123
127
|
|
@@ -132,13 +136,13 @@ class FrameReader:
|
|
132
136
|
if payload[-2] != bcc(header + payload[:-2]):
|
133
137
|
raise ChecksumError(f"Incorrect frame checksum ({payload[-2]})")
|
134
138
|
|
135
|
-
frame
|
136
|
-
|
137
|
-
recipient=recipient,
|
138
|
-
|
139
|
-
|
140
|
-
sender_type=sender_type,
|
139
|
+
frame = await Frame.create(
|
140
|
+
frame_type=payload[0],
|
141
|
+
recipient=DeviceType(recipient),
|
142
|
+
sender=DeviceType(sender),
|
143
|
+
econet_type=econet_type,
|
141
144
|
econet_version=econet_version,
|
145
|
+
message=payload[1:-2],
|
142
146
|
)
|
143
147
|
_LOGGER.debug("Received frame: %s", frame)
|
144
148
|
|
pyplumio/structures/__init__.py
CHANGED
pyplumio/structures/alerts.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
"""Contains regulator parameter structure decoder."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
from collections.abc import Generator
|
5
6
|
from dataclasses import dataclass
|
6
|
-
from typing import Any, Final
|
7
|
+
from typing import Any, Final
|
7
8
|
|
8
9
|
from pyplumio.const import (
|
9
10
|
ATTR_INDEX,
|
@@ -11,12 +12,12 @@ from pyplumio.const import (
|
|
11
12
|
ATTR_SIZE,
|
12
13
|
ATTR_VALUE,
|
13
14
|
PERCENTAGE,
|
15
|
+
FrameType,
|
14
16
|
ProductType,
|
15
17
|
UnitOfMeasurement,
|
16
18
|
)
|
17
19
|
from pyplumio.devices import AddressableDevice
|
18
20
|
from pyplumio.frames import Request
|
19
|
-
from pyplumio.helpers.factory import create_instance
|
20
21
|
from pyplumio.helpers.parameter import (
|
21
22
|
BinaryParameter,
|
22
23
|
BinaryParameterDescription,
|
@@ -47,10 +48,10 @@ class EcomaxParameter(Parameter):
|
|
47
48
|
async def create_request(self) -> Request:
|
48
49
|
"""Create a request to change the parameter."""
|
49
50
|
if self.description.name == ATTR_ECOMAX_CONTROL:
|
50
|
-
|
51
|
+
frame_type = FrameType.REQUEST_ECOMAX_CONTROL
|
51
52
|
data = {ATTR_VALUE: self.values.value}
|
52
53
|
elif self.description.name == ATTR_THERMOSTAT_PROFILE:
|
53
|
-
|
54
|
+
frame_type = FrameType.REQUEST_SET_THERMOSTAT_PARAMETER
|
54
55
|
data = {
|
55
56
|
ATTR_INDEX: self._index,
|
56
57
|
ATTR_VALUE: self.values.value,
|
@@ -58,15 +59,14 @@ class EcomaxParameter(Parameter):
|
|
58
59
|
ATTR_SIZE: 1,
|
59
60
|
}
|
60
61
|
else:
|
61
|
-
|
62
|
+
frame_type = FrameType.REQUEST_SET_ECOMAX_PARAMETER
|
62
63
|
data = {
|
63
64
|
ATTR_INDEX: self._index,
|
64
65
|
ATTR_VALUE: self.values.value,
|
65
66
|
}
|
66
67
|
|
67
|
-
return
|
68
|
-
|
69
|
-
await create_instance(cls, recipient=self.device.address, data=data),
|
68
|
+
return await Request.create(
|
69
|
+
frame_type, recipient=self.device.address, data=data
|
70
70
|
)
|
71
71
|
|
72
72
|
async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
|
pyplumio/structures/fan_power.py
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
"""Contains a mixer parameter structure decoder."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
from collections.abc import Generator
|
5
6
|
from dataclasses import dataclass
|
6
|
-
from typing import TYPE_CHECKING, Any, Final
|
7
|
+
from typing import TYPE_CHECKING, Any, Final
|
7
8
|
|
8
9
|
from pyplumio.const import (
|
9
10
|
ATTR_DEVICE_INDEX,
|
10
11
|
ATTR_INDEX,
|
11
12
|
ATTR_VALUE,
|
13
|
+
FrameType,
|
12
14
|
ProductType,
|
13
15
|
UnitOfMeasurement,
|
14
16
|
)
|
15
17
|
from pyplumio.frames import Request
|
16
|
-
from pyplumio.helpers.factory import create_instance
|
17
18
|
from pyplumio.helpers.parameter import (
|
18
19
|
BinaryParameter,
|
19
20
|
BinaryParameterDescription,
|
@@ -44,17 +45,14 @@ class MixerParameter(Parameter):
|
|
44
45
|
|
45
46
|
async def create_request(self) -> Request:
|
46
47
|
"""Create a request to change the parameter."""
|
47
|
-
return
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
ATTR_DEVICE_INDEX: self.device.index,
|
56
|
-
},
|
57
|
-
),
|
48
|
+
return await Request.create(
|
49
|
+
FrameType.REQUEST_SET_MIXER_PARAMETER,
|
50
|
+
recipient=self.device.parent.address,
|
51
|
+
data={
|
52
|
+
ATTR_INDEX: self._index,
|
53
|
+
ATTR_VALUE: self.values.value,
|
54
|
+
ATTR_DEVICE_INDEX: self.device.index,
|
55
|
+
},
|
58
56
|
)
|
59
57
|
|
60
58
|
async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
|
pyplumio/structures/modules.py
CHANGED
pyplumio/structures/outputs.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Contains a program version decoder."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
from dataclasses import dataclass
|
@@ -23,9 +24,9 @@ class VersionInfo:
|
|
23
24
|
"""Represents a version info provided in program version response."""
|
24
25
|
|
25
26
|
software: str = SOFTWARE_VERSION
|
26
|
-
struct_tag: bytes = b"\
|
27
|
+
struct_tag: bytes = b"\xff\xff"
|
27
28
|
struct_version: int = 5
|
28
|
-
device_id: bytes = b"\
|
29
|
+
device_id: bytes = b"\x7a\x00"
|
29
30
|
processor_signature: bytes = b"\x00\x00\x00"
|
30
31
|
|
31
32
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
"""Contains a regulator data structure decoder."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
from typing import Any, Final
|
5
6
|
|
6
|
-
from pyplumio.devices import AddressableDevice
|
7
7
|
from pyplumio.helpers.data_types import BitArray, DataType
|
8
8
|
from pyplumio.structures import StructureDecoder
|
9
9
|
from pyplumio.structures.frame_versions import FrameVersionsStructure
|
@@ -55,9 +55,8 @@ class RegulatorDataStructure(StructureDecoder):
|
|
55
55
|
message, offset + 2, data
|
56
56
|
)
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
schema := sender.get_nowait(ATTR_REGDATA_SCHEMA, [])
|
58
|
+
if (device := self.frame.sender_device) is not None and (
|
59
|
+
schema := device.get_nowait(ATTR_REGDATA_SCHEMA, [])
|
61
60
|
):
|
62
61
|
self._bitarray_index = 0
|
63
62
|
data[ATTR_REGDATA] = {
|
pyplumio/structures/schedules.py
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
"""Contains schedule decoder."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
5
|
from collections.abc import Sequence
|
5
6
|
from dataclasses import dataclass
|
6
7
|
from functools import reduce
|
7
8
|
from itertools import chain
|
8
|
-
from typing import Any, Final
|
9
|
-
|
10
|
-
from pyplumio.const import
|
9
|
+
from typing import Any, Final
|
10
|
+
|
11
|
+
from pyplumio.const import (
|
12
|
+
ATTR_PARAMETER,
|
13
|
+
ATTR_SCHEDULE,
|
14
|
+
ATTR_SWITCH,
|
15
|
+
ATTR_TYPE,
|
16
|
+
FrameType,
|
17
|
+
)
|
11
18
|
from pyplumio.devices import AddressableDevice, Device
|
12
19
|
from pyplumio.exceptions import FrameDataError
|
13
20
|
from pyplumio.frames import Request
|
14
|
-
from pyplumio.helpers.factory import create_instance
|
15
21
|
from pyplumio.helpers.parameter import (
|
16
22
|
BinaryParameter,
|
17
23
|
BinaryParameterDescription,
|
@@ -84,13 +90,10 @@ class ScheduleParameter(Parameter):
|
|
84
90
|
async def create_request(self) -> Request:
|
85
91
|
"""Create a request to change the parameter."""
|
86
92
|
schedule_name, _ = self.description.name.split("_schedule_", 1)
|
87
|
-
return
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
recipient=self.device.address,
|
92
|
-
data=collect_schedule_data(schedule_name, self.device),
|
93
|
-
),
|
93
|
+
return await Request.create(
|
94
|
+
FrameType.REQUEST_SET_SCHEDULE,
|
95
|
+
recipient=self.device.address,
|
96
|
+
data=collect_schedule_data(schedule_name, self.device),
|
94
97
|
)
|
95
98
|
|
96
99
|
|
pyplumio/structures/statuses.py
CHANGED