PyPlumIO 0.5.5__py3-none-any.whl → 0.5.7__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.5.dist-info → PyPlumIO-0.5.7.dist-info}/METADATA +7 -12
- PyPlumIO-0.5.7.dist-info/RECORD +60 -0
- pyplumio/__init__.py +83 -16
- pyplumio/_version.py +2 -2
- pyplumio/connection.py +46 -14
- pyplumio/const.py +2 -2
- pyplumio/devices/__init__.py +38 -12
- pyplumio/devices/ecomax.py +4 -6
- pyplumio/devices/ecoster.py +2 -2
- pyplumio/devices/mixer.py +2 -2
- pyplumio/devices/thermostat.py +2 -2
- pyplumio/filters.py +56 -2
- pyplumio/frames/__init__.py +12 -7
- pyplumio/frames/messages.py +6 -2
- pyplumio/frames/requests.py +53 -19
- pyplumio/frames/responses.py +46 -18
- pyplumio/helpers/data_types.py +32 -1
- pyplumio/helpers/event_manager.py +57 -8
- pyplumio/helpers/parameter.py +18 -8
- pyplumio/helpers/schedule.py +2 -2
- pyplumio/helpers/task_manager.py +0 -2
- pyplumio/helpers/typing.py +0 -1
- pyplumio/protocol.py +142 -71
- pyplumio/stream.py +0 -4
- pyplumio/structures/alerts.py +9 -15
- pyplumio/structures/ecomax_parameters.py +4 -2
- pyplumio/structures/network_info.py +13 -1
- pyplumio/structures/regulator_data.py +4 -4
- pyplumio/structures/{data_schema.py → regulator_data_schema.py} +4 -6
- pyplumio/structures/schedules.py +2 -2
- pyplumio/structures/temperatures.py +0 -2
- pyplumio/structures/thermostat_parameters.py +2 -2
- PyPlumIO-0.5.5.dist-info/RECORD +0 -60
- {PyPlumIO-0.5.5.dist-info → PyPlumIO-0.5.7.dist-info}/LICENSE +0 -0
- {PyPlumIO-0.5.5.dist-info → PyPlumIO-0.5.7.dist-info}/WHEEL +0 -0
- {PyPlumIO-0.5.5.dist-info → PyPlumIO-0.5.7.dist-info}/top_level.txt +0 -0
pyplumio/frames/__init__.py
CHANGED
@@ -25,7 +25,7 @@ ECONET_VERSION: Final = 5
|
|
25
25
|
struct_header = struct.Struct("<BH4B")
|
26
26
|
|
27
27
|
if TYPE_CHECKING:
|
28
|
-
from pyplumio.devices import
|
28
|
+
from pyplumio.devices import AddressableDevice
|
29
29
|
|
30
30
|
|
31
31
|
def bcc(data: bytes) -> int:
|
@@ -82,23 +82,22 @@ class Frame(ABC):
|
|
82
82
|
"sender",
|
83
83
|
"sender_type",
|
84
84
|
"econet_version",
|
85
|
-
"frame_type",
|
86
85
|
"_message",
|
87
86
|
"_data",
|
88
87
|
)
|
89
88
|
|
90
|
-
recipient: DeviceType |
|
91
|
-
sender: DeviceType |
|
89
|
+
recipient: DeviceType | AddressableDevice | int
|
90
|
+
sender: DeviceType | AddressableDevice | int
|
92
91
|
sender_type: int
|
93
92
|
econet_version: int
|
94
|
-
frame_type: ClassVar[int]
|
93
|
+
frame_type: ClassVar[FrameType | int]
|
95
94
|
_message: bytearray | None
|
96
95
|
_data: EventDataType | None
|
97
96
|
|
98
97
|
def __init__(
|
99
98
|
self,
|
100
|
-
recipient: DeviceType |
|
101
|
-
sender: DeviceType |
|
99
|
+
recipient: DeviceType | AddressableDevice | int = DeviceType.ALL,
|
100
|
+
sender: DeviceType | AddressableDevice | int = DeviceType.ECONET,
|
102
101
|
sender_type: int = ECONET_TYPE,
|
103
102
|
econet_version: int = ECONET_VERSION,
|
104
103
|
message: bytearray | None = None,
|
@@ -244,6 +243,8 @@ class Frame(ABC):
|
|
244
243
|
class Request(Frame):
|
245
244
|
"""Represents a request."""
|
246
245
|
|
246
|
+
__slots__ = ()
|
247
|
+
|
247
248
|
def create_message(self, data: EventDataType) -> bytearray:
|
248
249
|
"""Create a frame message."""
|
249
250
|
return bytearray()
|
@@ -260,6 +261,8 @@ class Request(Frame):
|
|
260
261
|
class Response(Frame):
|
261
262
|
"""Represents a response."""
|
262
263
|
|
264
|
+
__slots__ = ()
|
265
|
+
|
263
266
|
def create_message(self, data: EventDataType) -> bytearray:
|
264
267
|
"""Create a frame message."""
|
265
268
|
return bytearray()
|
@@ -271,3 +274,5 @@ class Response(Frame):
|
|
271
274
|
|
272
275
|
class Message(Response):
|
273
276
|
"""Represents a message."""
|
277
|
+
|
278
|
+
__slots__ = ()
|
pyplumio/frames/messages.py
CHANGED
@@ -34,7 +34,9 @@ from pyplumio.structures.thermostat_sensors import ThermostatSensorsStructure
|
|
34
34
|
class RegulatorDataMessage(Message):
|
35
35
|
"""Represents a regulator data message."""
|
36
36
|
|
37
|
-
|
37
|
+
__slots__ = ()
|
38
|
+
|
39
|
+
frame_type: ClassVar[FrameType | int] = FrameType.MESSAGE_REGULATOR_DATA
|
38
40
|
|
39
41
|
def decode_message(self, message: bytearray) -> EventDataType:
|
40
42
|
"""Decode a frame message."""
|
@@ -45,7 +47,9 @@ class RegulatorDataMessage(Message):
|
|
45
47
|
class SensorDataMessage(Message):
|
46
48
|
"""Represents a sensor data message."""
|
47
49
|
|
48
|
-
|
50
|
+
__slots__ = ()
|
51
|
+
|
52
|
+
frame_type: ClassVar[FrameType | int] = FrameType.MESSAGE_SENSOR_DATA
|
49
53
|
|
50
54
|
def decode_message(self, message: bytearray) -> EventDataType:
|
51
55
|
"""Decode a frame message."""
|
pyplumio/frames/requests.py
CHANGED
@@ -22,7 +22,9 @@ from pyplumio.structures.schedules import SchedulesStructure
|
|
22
22
|
class ProgramVersionRequest(Request):
|
23
23
|
"""Represents a program version request."""
|
24
24
|
|
25
|
-
|
25
|
+
__slots__ = ()
|
26
|
+
|
27
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_PROGRAM_VERSION
|
26
28
|
|
27
29
|
def response(self, **kwargs) -> Response | None:
|
28
30
|
"""Return a response frame."""
|
@@ -32,7 +34,9 @@ class ProgramVersionRequest(Request):
|
|
32
34
|
class CheckDeviceRequest(Request):
|
33
35
|
"""Represents a check device request."""
|
34
36
|
|
35
|
-
|
37
|
+
__slots__ = ()
|
38
|
+
|
39
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_CHECK_DEVICE
|
36
40
|
|
37
41
|
def response(self, **kwargs) -> Response | None:
|
38
42
|
"""Return a response frame."""
|
@@ -42,13 +46,17 @@ class CheckDeviceRequest(Request):
|
|
42
46
|
class UIDRequest(Request):
|
43
47
|
"""Represents an UID request."""
|
44
48
|
|
45
|
-
|
49
|
+
__slots__ = ()
|
50
|
+
|
51
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_UID
|
46
52
|
|
47
53
|
|
48
54
|
class PasswordRequest(Request):
|
49
55
|
"""Represents a password request."""
|
50
56
|
|
51
|
-
|
57
|
+
__slots__ = ()
|
58
|
+
|
59
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_PASSWORD
|
52
60
|
|
53
61
|
|
54
62
|
class EcomaxParametersRequest(Request):
|
@@ -57,7 +65,9 @@ class EcomaxParametersRequest(Request):
|
|
57
65
|
Contains number of parameters and index of the first parameter.
|
58
66
|
"""
|
59
67
|
|
60
|
-
|
68
|
+
__slots__ = ()
|
69
|
+
|
70
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_ECOMAX_PARAMETERS
|
61
71
|
|
62
72
|
def create_message(self, data: EventDataType) -> bytearray:
|
63
73
|
"""Create a frame message."""
|
@@ -71,7 +81,9 @@ class MixerParametersRequest(Request):
|
|
71
81
|
parameter.
|
72
82
|
"""
|
73
83
|
|
74
|
-
|
84
|
+
__slots__ = ()
|
85
|
+
|
86
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_MIXER_PARAMETERS
|
75
87
|
|
76
88
|
def create_message(self, data: EventDataType) -> bytearray:
|
77
89
|
"""Create a frame message."""
|
@@ -85,17 +97,21 @@ class ThermostatParametersRequest(Request):
|
|
85
97
|
parameter.
|
86
98
|
"""
|
87
99
|
|
88
|
-
|
100
|
+
__slots__ = ()
|
101
|
+
|
102
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_THERMOSTAT_PARAMETERS
|
89
103
|
|
90
104
|
def create_message(self, data: EventDataType) -> bytearray:
|
91
105
|
"""Create a frame message."""
|
92
106
|
return bytearray([data.get(ATTR_COUNT, 255), data.get(ATTR_INDEX, 0)])
|
93
107
|
|
94
108
|
|
95
|
-
class
|
96
|
-
"""Represents data schema request."""
|
109
|
+
class RegulatorDataSchemaRequest(Request):
|
110
|
+
"""Represents regulator data schema request."""
|
97
111
|
|
98
|
-
|
112
|
+
__slots__ = ()
|
113
|
+
|
114
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_REGULATOR_DATA_SCHEMA
|
99
115
|
|
100
116
|
|
101
117
|
class SetEcomaxParameterRequest(Request):
|
@@ -104,7 +120,9 @@ class SetEcomaxParameterRequest(Request):
|
|
104
120
|
Contains parameter index and new value.
|
105
121
|
"""
|
106
122
|
|
107
|
-
|
123
|
+
__slots__ = ()
|
124
|
+
|
125
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_SET_ECOMAX_PARAMETER
|
108
126
|
|
109
127
|
def create_message(self, data: EventDataType) -> bytearray:
|
110
128
|
"""Create a frame message."""
|
@@ -120,7 +138,9 @@ class SetMixerParameterRequest(Request):
|
|
120
138
|
Contains parameter index, new value and mixer index.
|
121
139
|
"""
|
122
140
|
|
123
|
-
|
141
|
+
__slots__ = ()
|
142
|
+
|
143
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_SET_MIXER_PARAMETER
|
124
144
|
|
125
145
|
def create_message(self, data: EventDataType) -> bytearray:
|
126
146
|
"""Create a frame message."""
|
@@ -146,7 +166,9 @@ class SetThermostatParameterRequest(Request):
|
|
146
166
|
and for the third thermostat is 24 (2 * 12).
|
147
167
|
"""
|
148
168
|
|
149
|
-
|
169
|
+
__slots__ = ()
|
170
|
+
|
171
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_SET_THERMOSTAT_PARAMETER
|
150
172
|
|
151
173
|
def create_message(self, data: EventDataType) -> bytearray:
|
152
174
|
"""Create a frame message."""
|
@@ -167,7 +189,9 @@ class EcomaxControlRequest(Request):
|
|
167
189
|
be turned off, 1 - means that it should be turned on.
|
168
190
|
"""
|
169
191
|
|
170
|
-
|
192
|
+
__slots__ = ()
|
193
|
+
|
194
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_ECOMAX_CONTROL
|
171
195
|
|
172
196
|
def create_message(self, data: EventDataType) -> bytearray:
|
173
197
|
"""Create a frame message."""
|
@@ -184,7 +208,9 @@ class StartMasterRequest(Request):
|
|
184
208
|
periodic messages.
|
185
209
|
"""
|
186
210
|
|
187
|
-
|
211
|
+
__slots__ = ()
|
212
|
+
|
213
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_START_MASTER
|
188
214
|
|
189
215
|
|
190
216
|
class StopMasterRequest(Request):
|
@@ -194,7 +220,9 @@ class StopMasterRequest(Request):
|
|
194
220
|
periodic messages.
|
195
221
|
"""
|
196
222
|
|
197
|
-
|
223
|
+
__slots__ = ()
|
224
|
+
|
225
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_STOP_MASTER
|
198
226
|
|
199
227
|
|
200
228
|
class AlertsRequest(Request):
|
@@ -204,7 +232,9 @@ class AlertsRequest(Request):
|
|
204
232
|
alert.
|
205
233
|
"""
|
206
234
|
|
207
|
-
|
235
|
+
__slots__ = ()
|
236
|
+
|
237
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_ALERTS
|
208
238
|
|
209
239
|
def create_message(self, data: EventDataType) -> bytearray:
|
210
240
|
"""Create a frame message."""
|
@@ -215,13 +245,17 @@ class AlertsRequest(Request):
|
|
215
245
|
class SchedulesRequest(Request):
|
216
246
|
"""Represents a schedules request."""
|
217
247
|
|
218
|
-
|
248
|
+
__slots__ = ()
|
249
|
+
|
250
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_SCHEDULES
|
219
251
|
|
220
252
|
|
221
253
|
class SetScheduleRequest(Request):
|
222
254
|
"""Represents a request to set a schedule."""
|
223
255
|
|
224
|
-
|
256
|
+
__slots__ = ()
|
257
|
+
|
258
|
+
frame_type: ClassVar[FrameType | int] = FrameType.REQUEST_SET_SCHEDULE
|
225
259
|
|
226
260
|
def create_message(self, data: EventDataType) -> bytearray:
|
227
261
|
"""Create a frame message."""
|
pyplumio/frames/responses.py
CHANGED
@@ -7,12 +7,12 @@ from pyplumio.const import ATTR_PASSWORD, FrameType
|
|
7
7
|
from pyplumio.frames import Response
|
8
8
|
from pyplumio.helpers.typing import EventDataType
|
9
9
|
from pyplumio.structures.alerts import AlertsStructure
|
10
|
-
from pyplumio.structures.data_schema import DataSchemaStructure
|
11
10
|
from pyplumio.structures.ecomax_parameters import EcomaxParametersStructure
|
12
11
|
from pyplumio.structures.mixer_parameters import MixerParametersStructure
|
13
12
|
from pyplumio.structures.network_info import NetworkInfoStructure
|
14
13
|
from pyplumio.structures.product_info import ProductInfoStructure
|
15
14
|
from pyplumio.structures.program_version import ProgramVersionStructure
|
15
|
+
from pyplumio.structures.regulator_data_schema import RegulatorDataSchemaStructure
|
16
16
|
from pyplumio.structures.schedules import SchedulesStructure
|
17
17
|
from pyplumio.structures.thermostat_parameters import ThermostatParametersStructure
|
18
18
|
|
@@ -23,7 +23,9 @@ class ProgramVersionResponse(Response):
|
|
23
23
|
Contains software version info.
|
24
24
|
"""
|
25
25
|
|
26
|
-
|
26
|
+
__slots__ = ()
|
27
|
+
|
28
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_PROGRAM_VERSION
|
27
29
|
|
28
30
|
def create_message(self, data: EventDataType) -> bytearray:
|
29
31
|
"""Create a frame message."""
|
@@ -40,7 +42,9 @@ class DeviceAvailableResponse(Response):
|
|
40
42
|
Contains network information and status.
|
41
43
|
"""
|
42
44
|
|
43
|
-
|
45
|
+
__slots__ = ()
|
46
|
+
|
47
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_DEVICE_AVAILABLE
|
44
48
|
|
45
49
|
def create_message(self, data: EventDataType) -> bytearray:
|
46
50
|
"""Create a frame message."""
|
@@ -57,7 +61,9 @@ class UIDResponse(Response):
|
|
57
61
|
Contains product info and product UID.
|
58
62
|
"""
|
59
63
|
|
60
|
-
|
64
|
+
__slots__ = ()
|
65
|
+
|
66
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_UID
|
61
67
|
|
62
68
|
def create_message(self, data: EventDataType) -> bytearray:
|
63
69
|
"""Create a frame message."""
|
@@ -74,7 +80,9 @@ class PasswordResponse(Response):
|
|
74
80
|
Contains device service password as plaintext.
|
75
81
|
"""
|
76
82
|
|
77
|
-
|
83
|
+
__slots__ = ()
|
84
|
+
|
85
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_PASSWORD
|
78
86
|
|
79
87
|
def decode_message(self, message: bytearray) -> EventDataType:
|
80
88
|
"""Decode a frame message."""
|
@@ -88,7 +96,9 @@ class EcomaxParametersResponse(Response):
|
|
88
96
|
Contains editable ecoMAX parameters.
|
89
97
|
"""
|
90
98
|
|
91
|
-
|
99
|
+
__slots__ = ()
|
100
|
+
|
101
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_ECOMAX_PARAMETERS
|
92
102
|
|
93
103
|
def decode_message(self, message: bytearray) -> EventDataType:
|
94
104
|
"""Decode a frame message."""
|
@@ -101,7 +111,9 @@ class MixerParametersResponse(Response):
|
|
101
111
|
Contains editable mixer parameters.
|
102
112
|
"""
|
103
113
|
|
104
|
-
|
114
|
+
__slots__ = ()
|
115
|
+
|
116
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_MIXER_PARAMETERS
|
105
117
|
|
106
118
|
def decode_message(self, message: bytearray) -> EventDataType:
|
107
119
|
"""Decode a frame message."""
|
@@ -114,25 +126,29 @@ class ThermostatParametersResponse(Response):
|
|
114
126
|
Contains editable thermostat parameters.
|
115
127
|
"""
|
116
128
|
|
117
|
-
|
129
|
+
__slots__ = ()
|
130
|
+
|
131
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_THERMOSTAT_PARAMETERS
|
118
132
|
|
119
133
|
def decode_message(self, message: bytearray) -> EventDataType:
|
120
134
|
"""Decode a frame message."""
|
121
135
|
return ThermostatParametersStructure(self).decode(message)[0]
|
122
136
|
|
123
137
|
|
124
|
-
class
|
125
|
-
"""Represents a data schema response.
|
138
|
+
class RegulatorDataSchemaResponse(Response):
|
139
|
+
"""Represents a regulator data schema response.
|
126
140
|
|
127
141
|
Contains schema, that describes structure of ecoMAX regulator data
|
128
142
|
message.
|
129
143
|
"""
|
130
144
|
|
131
|
-
|
145
|
+
__slots__ = ()
|
146
|
+
|
147
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_REGULATOR_DATA_SCHEMA
|
132
148
|
|
133
149
|
def decode_message(self, message: bytearray) -> EventDataType:
|
134
150
|
"""Decode a frame message."""
|
135
|
-
return
|
151
|
+
return RegulatorDataSchemaStructure(self).decode(message)[0]
|
136
152
|
|
137
153
|
|
138
154
|
class SetEcomaxParameterResponse(Response):
|
@@ -142,7 +158,9 @@ class SetEcomaxParameterResponse(Response):
|
|
142
158
|
successfully set.
|
143
159
|
"""
|
144
160
|
|
145
|
-
|
161
|
+
__slots__ = ()
|
162
|
+
|
163
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_SET_ECOMAX_PARAMETER
|
146
164
|
|
147
165
|
|
148
166
|
class SetMixerParameterResponse(Response):
|
@@ -152,7 +170,9 @@ class SetMixerParameterResponse(Response):
|
|
152
170
|
successfully set.
|
153
171
|
"""
|
154
172
|
|
155
|
-
|
173
|
+
__slots__ = ()
|
174
|
+
|
175
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_SET_MIXER_PARAMETER
|
156
176
|
|
157
177
|
|
158
178
|
class SetThermostatParameterResponse(Response):
|
@@ -162,7 +182,9 @@ class SetThermostatParameterResponse(Response):
|
|
162
182
|
successfully set.
|
163
183
|
"""
|
164
184
|
|
165
|
-
|
185
|
+
__slots__ = ()
|
186
|
+
|
187
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_SET_THERMOSTAT_PARAMETER
|
166
188
|
|
167
189
|
|
168
190
|
class EcomaxControlResponse(Response):
|
@@ -172,13 +194,17 @@ class EcomaxControlResponse(Response):
|
|
172
194
|
successfully processed.
|
173
195
|
"""
|
174
196
|
|
175
|
-
|
197
|
+
__slots__ = ()
|
198
|
+
|
199
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_ECOMAX_CONTROL
|
176
200
|
|
177
201
|
|
178
202
|
class AlertsResponse(Response):
|
179
203
|
"""Represents response to a device alerts request."""
|
180
204
|
|
181
|
-
|
205
|
+
__slots__ = ()
|
206
|
+
|
207
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_ALERTS
|
182
208
|
|
183
209
|
def decode_message(self, message: bytearray) -> EventDataType:
|
184
210
|
"""Decode a frame message."""
|
@@ -188,7 +214,9 @@ class AlertsResponse(Response):
|
|
188
214
|
class SchedulesResponse(Response):
|
189
215
|
"""Represents response to a device schedules request."""
|
190
216
|
|
191
|
-
|
217
|
+
__slots__ = ()
|
218
|
+
|
219
|
+
frame_type: ClassVar[FrameType | int] = FrameType.RESPONSE_SCHEDULES
|
192
220
|
|
193
221
|
def decode_message(self, message: bytearray) -> EventDataType:
|
194
222
|
"""Decode a frame message."""
|
pyplumio/helpers/data_types.py
CHANGED
@@ -68,6 +68,8 @@ class DataType(ABC):
|
|
68
68
|
class Undefined(DataType):
|
69
69
|
"""Represents an undefined."""
|
70
70
|
|
71
|
+
__slots__ = ()
|
72
|
+
|
71
73
|
def pack(self) -> bytes:
|
72
74
|
"""Pack the data."""
|
73
75
|
return bytes()
|
@@ -122,6 +124,8 @@ class BitArray(DataType):
|
|
122
124
|
class IPv4(DataType):
|
123
125
|
"""Represents an IPv4 address."""
|
124
126
|
|
127
|
+
__slots__ = ()
|
128
|
+
|
125
129
|
@property
|
126
130
|
def size(self) -> int:
|
127
131
|
"""A data size."""
|
@@ -139,6 +143,8 @@ class IPv4(DataType):
|
|
139
143
|
class IPv6(DataType):
|
140
144
|
"""Represents an IPv6 address."""
|
141
145
|
|
146
|
+
__slots__ = ()
|
147
|
+
|
142
148
|
@property
|
143
149
|
def size(self) -> int:
|
144
150
|
"""A data size."""
|
@@ -156,6 +162,8 @@ class IPv6(DataType):
|
|
156
162
|
class String(DataType):
|
157
163
|
"""Represents a null terminated string."""
|
158
164
|
|
165
|
+
__slots__ = ()
|
166
|
+
|
159
167
|
def __init__(self, value: Any = ""):
|
160
168
|
"""Initialize a new null terminated string data type."""
|
161
169
|
super().__init__(value)
|
@@ -174,6 +182,8 @@ class String(DataType):
|
|
174
182
|
class VarBytes(DataType):
|
175
183
|
"""Represents a variable length bytes."""
|
176
184
|
|
185
|
+
__slots__ = ()
|
186
|
+
|
177
187
|
def __init__(self, value: Any = b""):
|
178
188
|
"""Initialize a new variable length bytes data type."""
|
179
189
|
super().__init__(value)
|
@@ -192,6 +202,8 @@ class VarBytes(DataType):
|
|
192
202
|
class VarString(VarBytes):
|
193
203
|
"""Represents a variable length string."""
|
194
204
|
|
205
|
+
__slots__ = ()
|
206
|
+
|
195
207
|
def pack(self) -> bytes:
|
196
208
|
"""Pack the data."""
|
197
209
|
return UnsignedChar(self.size - 1).to_bytes() + self.value.encode()
|
@@ -207,7 +219,7 @@ class BuiltInDataType(DataType, ABC):
|
|
207
219
|
struct module.
|
208
220
|
"""
|
209
221
|
|
210
|
-
__slots__ = (
|
222
|
+
__slots__ = ()
|
211
223
|
|
212
224
|
_struct: ClassVar[struct.Struct]
|
213
225
|
|
@@ -228,60 +240,79 @@ class BuiltInDataType(DataType, ABC):
|
|
228
240
|
class SignedChar(BuiltInDataType):
|
229
241
|
"""Represents a signed char."""
|
230
242
|
|
243
|
+
__slots__ = ()
|
244
|
+
|
231
245
|
_struct: ClassVar[struct.Struct] = struct.Struct("<b")
|
232
246
|
|
233
247
|
|
234
248
|
class UnsignedChar(BuiltInDataType):
|
235
249
|
"""Represents an unsigned char."""
|
236
250
|
|
251
|
+
__slots__ = ()
|
252
|
+
|
237
253
|
_struct: ClassVar[struct.Struct] = struct.Struct("<B")
|
238
254
|
|
239
255
|
|
240
256
|
class Short(BuiltInDataType):
|
241
257
|
"""Represents a 16 bit integer."""
|
242
258
|
|
259
|
+
__slots__ = ()
|
260
|
+
|
243
261
|
_struct: ClassVar[struct.Struct] = struct.Struct("<h")
|
244
262
|
|
245
263
|
|
246
264
|
class UnsignedShort(BuiltInDataType):
|
247
265
|
"""Represents an unsigned 16 bit integer."""
|
248
266
|
|
267
|
+
__slots__ = ()
|
268
|
+
|
249
269
|
_struct: ClassVar[struct.Struct] = struct.Struct("<H")
|
250
270
|
|
251
271
|
|
252
272
|
class Int(BuiltInDataType):
|
253
273
|
"""Represents a 32 bit integer."""
|
254
274
|
|
275
|
+
__slots__ = ()
|
276
|
+
|
255
277
|
_struct: ClassVar[struct.Struct] = struct.Struct("<i")
|
256
278
|
|
257
279
|
|
258
280
|
class UnsignedInt(BuiltInDataType):
|
259
281
|
"""Represents a unsigned 32 bit integer."""
|
260
282
|
|
283
|
+
__slots__ = ()
|
284
|
+
|
261
285
|
_struct: ClassVar[struct.Struct] = struct.Struct("<I")
|
262
286
|
|
263
287
|
|
264
288
|
class Float(BuiltInDataType):
|
265
289
|
"""Represents a float."""
|
266
290
|
|
291
|
+
__slots__ = ()
|
292
|
+
|
267
293
|
_struct: ClassVar[struct.Struct] = struct.Struct("<f")
|
268
294
|
|
269
295
|
|
270
296
|
class Double(BuiltInDataType):
|
271
297
|
"""Represents a double."""
|
272
298
|
|
299
|
+
__slots__ = ()
|
300
|
+
|
273
301
|
_struct: ClassVar[struct.Struct] = struct.Struct("<d")
|
274
302
|
|
275
303
|
|
276
304
|
class Int64(BuiltInDataType):
|
277
305
|
"""Represents a 64 bit signed integer."""
|
278
306
|
|
307
|
+
__slots__ = ()
|
308
|
+
|
279
309
|
_struct: ClassVar[struct.Struct] = struct.Struct("<q")
|
280
310
|
|
281
311
|
|
282
312
|
class UInt64(BuiltInDataType):
|
283
313
|
"""Represents a 64 bit unsigned integer."""
|
284
314
|
|
315
|
+
__slots__ = ()
|
285
316
|
_struct: ClassVar[struct.Struct] = struct.Struct("<Q")
|
286
317
|
|
287
318
|
|
@@ -10,8 +10,6 @@ from pyplumio.helpers.typing import EventCallbackType, EventDataType
|
|
10
10
|
class EventManager(TaskManager):
|
11
11
|
"""Represents an event manager."""
|
12
12
|
|
13
|
-
__slots__ = ("data", "_events", "_callbacks")
|
14
|
-
|
15
13
|
data: EventDataType
|
16
14
|
_events: dict[str | int, asyncio.Event]
|
17
15
|
_callbacks: dict[str | int, list[EventCallbackType]]
|
@@ -31,31 +29,74 @@ class EventManager(TaskManager):
|
|
31
29
|
raise AttributeError from e
|
32
30
|
|
33
31
|
async def wait_for(self, name: str | int, timeout: float | None = None) -> None:
|
34
|
-
"""Wait for the value to become available.
|
32
|
+
"""Wait for the value to become available.
|
33
|
+
|
34
|
+
:param name: Event name or ID
|
35
|
+
:type name: str | int
|
36
|
+
:param timeout: Wait this amount of seconds for a data to
|
37
|
+
become available, defaults to `None`
|
38
|
+
:type timeout: float, optional
|
39
|
+
:raise asyncio.TimeoutError: when waiting past specified timeout
|
40
|
+
"""
|
35
41
|
if name not in self.data:
|
36
42
|
await asyncio.wait_for(self.create_event(name).wait(), timeout=timeout)
|
37
43
|
|
38
44
|
async def get(self, name: str | int, timeout: float | None = None):
|
39
|
-
"""Get the value.
|
45
|
+
"""Get the value by name.
|
46
|
+
|
47
|
+
:param name: Event name or ID
|
48
|
+
:type name: str | int
|
49
|
+
:param timeout: Wait this amount of seconds for a data to
|
50
|
+
become available, defaults to `None`
|
51
|
+
:type timeout: float, optional
|
52
|
+
:return: An event data
|
53
|
+
:raise asyncio.TimeoutError: when waiting past specified timeout
|
54
|
+
"""
|
40
55
|
await self.wait_for(name, timeout=timeout)
|
41
56
|
return self.data[name]
|
42
57
|
|
43
58
|
def get_nowait(self, name: str | int, default=None):
|
44
|
-
"""Get the value without waiting.
|
59
|
+
"""Get the value by name without waiting.
|
60
|
+
|
61
|
+
If value is not available, default value will be
|
62
|
+
returned instead.
|
63
|
+
|
64
|
+
:param name: Event name or ID
|
65
|
+
:type name: str | int
|
66
|
+
:param default: default value to return if data is unavailable,
|
67
|
+
defaults to `None`
|
68
|
+
:type default: Any, optional
|
69
|
+
:return: An event data
|
70
|
+
"""
|
45
71
|
try:
|
46
72
|
return self.data[name]
|
47
73
|
except KeyError:
|
48
74
|
return default
|
49
75
|
|
50
76
|
def subscribe(self, name: str | int, callback: EventCallbackType) -> None:
|
51
|
-
"""Subscribe a callback to the event.
|
77
|
+
"""Subscribe a callback to the event.
|
78
|
+
|
79
|
+
:param name: Event name or ID
|
80
|
+
:type name: str
|
81
|
+
:param callback: A coroutine callback function, that will be
|
82
|
+
awaited on the with the event data as an argument.
|
83
|
+
:type callback: Callable[[Any], Awaitable[Any]]
|
84
|
+
"""
|
52
85
|
if name not in self._callbacks:
|
53
86
|
self._callbacks[name] = []
|
54
87
|
|
55
88
|
self._callbacks[name].append(callback)
|
56
89
|
|
57
90
|
def subscribe_once(self, name: str | int, callback: EventCallbackType) -> None:
|
58
|
-
"""Subscribe a callback to the
|
91
|
+
"""Subscribe a callback to the event once. Callback will be
|
92
|
+
unsubscribed after single event.
|
93
|
+
|
94
|
+
:param name: Event name or ID
|
95
|
+
:type name: str
|
96
|
+
:param callback: A coroutine callback function, that will be
|
97
|
+
awaited on the with the event data as an argument.
|
98
|
+
:type callback: Callable[[Any], Awaitable[Any]]
|
99
|
+
"""
|
59
100
|
|
60
101
|
async def _callback(value):
|
61
102
|
"""Unsubscribe callback from the event and calls it."""
|
@@ -65,7 +106,15 @@ class EventManager(TaskManager):
|
|
65
106
|
self.subscribe(name, _callback)
|
66
107
|
|
67
108
|
def unsubscribe(self, name: str | int, callback: EventCallbackType) -> None:
|
68
|
-
"""Usubscribe a callback from the event.
|
109
|
+
"""Usubscribe a callback from the event.
|
110
|
+
|
111
|
+
:param name: Event name or ID
|
112
|
+
:type name: str
|
113
|
+
:param callback: A coroutine callback function, previously
|
114
|
+
subscribed to an event using ``subscribe()`` or
|
115
|
+
``subscribe_once()`` methods.
|
116
|
+
:type callback: Callable[[Any], Awaitable[Any]]
|
117
|
+
"""
|
69
118
|
if name in self._callbacks and callback in self._callbacks[name]:
|
70
119
|
self._callbacks[name].remove(callback)
|
71
120
|
|