ramses-rf 0.22.2__py3-none-any.whl → 0.51.1__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.
- ramses_cli/__init__.py +18 -0
- ramses_cli/client.py +597 -0
- ramses_cli/debug.py +20 -0
- ramses_cli/discovery.py +405 -0
- ramses_cli/utils/cat_slow.py +17 -0
- ramses_cli/utils/convert.py +60 -0
- ramses_rf/__init__.py +31 -10
- ramses_rf/binding_fsm.py +787 -0
- ramses_rf/const.py +124 -105
- ramses_rf/database.py +297 -0
- ramses_rf/device/__init__.py +69 -39
- ramses_rf/device/base.py +187 -376
- ramses_rf/device/heat.py +540 -552
- ramses_rf/device/hvac.py +286 -171
- ramses_rf/dispatcher.py +153 -177
- ramses_rf/entity_base.py +478 -361
- ramses_rf/exceptions.py +82 -0
- ramses_rf/gateway.py +378 -514
- ramses_rf/helpers.py +57 -19
- ramses_rf/py.typed +0 -0
- ramses_rf/schemas.py +148 -194
- ramses_rf/system/__init__.py +16 -23
- ramses_rf/system/faultlog.py +363 -0
- ramses_rf/system/heat.py +295 -302
- ramses_rf/system/schedule.py +312 -198
- ramses_rf/system/zones.py +318 -238
- ramses_rf/version.py +2 -8
- ramses_rf-0.51.1.dist-info/METADATA +72 -0
- ramses_rf-0.51.1.dist-info/RECORD +55 -0
- {ramses_rf-0.22.2.dist-info → ramses_rf-0.51.1.dist-info}/WHEEL +1 -2
- ramses_rf-0.51.1.dist-info/entry_points.txt +2 -0
- {ramses_rf-0.22.2.dist-info → ramses_rf-0.51.1.dist-info/licenses}/LICENSE +1 -1
- ramses_tx/__init__.py +160 -0
- {ramses_rf/protocol → ramses_tx}/address.py +65 -59
- ramses_tx/command.py +1454 -0
- ramses_tx/const.py +903 -0
- ramses_tx/exceptions.py +92 -0
- {ramses_rf/protocol → ramses_tx}/fingerprints.py +56 -15
- {ramses_rf/protocol → ramses_tx}/frame.py +132 -131
- ramses_tx/gateway.py +338 -0
- ramses_tx/helpers.py +883 -0
- {ramses_rf/protocol → ramses_tx}/logger.py +67 -53
- {ramses_rf/protocol → ramses_tx}/message.py +155 -191
- ramses_tx/opentherm.py +1260 -0
- ramses_tx/packet.py +210 -0
- ramses_tx/parsers.py +2957 -0
- ramses_tx/protocol.py +801 -0
- ramses_tx/protocol_fsm.py +672 -0
- ramses_tx/py.typed +0 -0
- {ramses_rf/protocol → ramses_tx}/ramses.py +262 -185
- {ramses_rf/protocol → ramses_tx}/schemas.py +150 -133
- ramses_tx/transport.py +1471 -0
- ramses_tx/typed_dicts.py +492 -0
- ramses_tx/typing.py +181 -0
- ramses_tx/version.py +4 -0
- ramses_rf/discovery.py +0 -398
- ramses_rf/protocol/__init__.py +0 -59
- ramses_rf/protocol/backports.py +0 -42
- ramses_rf/protocol/command.py +0 -1561
- ramses_rf/protocol/const.py +0 -697
- ramses_rf/protocol/exceptions.py +0 -111
- ramses_rf/protocol/helpers.py +0 -390
- ramses_rf/protocol/opentherm.py +0 -1170
- ramses_rf/protocol/packet.py +0 -235
- ramses_rf/protocol/parsers.py +0 -2673
- ramses_rf/protocol/protocol.py +0 -613
- ramses_rf/protocol/transport.py +0 -1011
- ramses_rf/protocol/version.py +0 -10
- ramses_rf/system/hvac.py +0 -82
- ramses_rf-0.22.2.dist-info/METADATA +0 -64
- ramses_rf-0.22.2.dist-info/RECORD +0 -42
- ramses_rf-0.22.2.dist-info/top_level.txt +0 -1
ramses_tx/typed_dicts.py
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
# We use typed dicts rather than data classes because we migrated from dicts
|
|
2
|
+
|
|
3
|
+
from enum import EnumCheck, StrEnum, verify
|
|
4
|
+
from typing import Literal, NotRequired, TypeAlias, TypedDict
|
|
5
|
+
|
|
6
|
+
from ramses_tx.const import FaultDeviceClass, FaultState, FaultType
|
|
7
|
+
from ramses_tx.schemas import DeviceIdT
|
|
8
|
+
|
|
9
|
+
_HexToTempT: TypeAlias = float | None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = ["PayDictT"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# fmt: off
|
|
16
|
+
LogIdxT = Literal[
|
|
17
|
+
'00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0A', '0B', '0C', '0D', '0E', '0F',
|
|
18
|
+
'10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1A', '1B', '1C', '1D', '1E', '1F',
|
|
19
|
+
'20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2A', '2B', '2C', '2D', '2E', '2F',
|
|
20
|
+
'30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3A', '3B', '3C', '3D', '3E', '3F',
|
|
21
|
+
]
|
|
22
|
+
# fmt: on
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _FlowRate(TypedDict):
|
|
26
|
+
dhw_flow_rate: _HexToTempT
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class _Pressure(TypedDict):
|
|
30
|
+
pressure: _HexToTempT
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _Setpoint(TypedDict):
|
|
34
|
+
setpoint: _HexToTempT
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class _Temperature(TypedDict):
|
|
38
|
+
temperature: _HexToTempT
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class FaultLogEntryNull(TypedDict): # NOTE: not identical to _0418
|
|
42
|
+
_log_idx: LogIdxT # "00" to ?"3F"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class FaultLogEntry(TypedDict): # NOTE: not identical to _0418
|
|
46
|
+
_log_idx: LogIdxT # "00" to ?"3F"
|
|
47
|
+
|
|
48
|
+
timestamp: str
|
|
49
|
+
fault_state: FaultState
|
|
50
|
+
fault_type: FaultType
|
|
51
|
+
domain_idx: str
|
|
52
|
+
device_class: FaultDeviceClass
|
|
53
|
+
device_id: DeviceIdT | None
|
|
54
|
+
|
|
55
|
+
_unknown_3: str
|
|
56
|
+
_unknown_7: str
|
|
57
|
+
_unknown_15: str
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# These are from 31DA...
|
|
61
|
+
class AirQuality(TypedDict):
|
|
62
|
+
air_quality: float | None
|
|
63
|
+
air_quality_basis: NotRequired[str]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class Co2Level(TypedDict):
|
|
67
|
+
co2_level: float | None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class RelativeHumidity(TypedDict):
|
|
71
|
+
relative_humidity: _HexToTempT
|
|
72
|
+
temperature: NotRequired[float | None]
|
|
73
|
+
dewpoint_temp: NotRequired[float | None]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class IndoorHumidity(TypedDict):
|
|
77
|
+
indoor_humidity: _HexToTempT
|
|
78
|
+
temperature: NotRequired[float | None]
|
|
79
|
+
dewpoint_temp: NotRequired[float | None]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class OutdoorHumidity(TypedDict):
|
|
83
|
+
outdoor_humidity: _HexToTempT
|
|
84
|
+
temperature: NotRequired[float | None]
|
|
85
|
+
dewpoint_temp: NotRequired[float | None]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class ExhaustTemp(TypedDict):
|
|
89
|
+
exhaust_temp: _HexToTempT
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class SupplyTemp(TypedDict):
|
|
93
|
+
supply_temp: _HexToTempT
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class IndoorTemp(TypedDict):
|
|
97
|
+
indoor_temp: _HexToTempT
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class OutdoorTemp(TypedDict):
|
|
101
|
+
outdoor_temp: _HexToTempT
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class Capabilities(TypedDict):
|
|
105
|
+
speed_capabilities: list[str] | None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class BypassPosition(TypedDict):
|
|
109
|
+
bypass_position: float | None
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class FanInfo(TypedDict):
|
|
113
|
+
fan_info: str
|
|
114
|
+
_unknown_fan_info_flags: list[int]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class ExhaustFanSpeed(TypedDict):
|
|
118
|
+
exhaust_fan: float | None
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class SupplyFanSpeed(TypedDict):
|
|
122
|
+
supply_fan: float | None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class RemainingMins(TypedDict):
|
|
126
|
+
remaining_mins: int | None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class PostHeater(TypedDict):
|
|
130
|
+
post_heater: float | None
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class PreHeater(TypedDict):
|
|
134
|
+
pre_heater: float | None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class SupplyFlow(TypedDict):
|
|
138
|
+
supply_flow: float | None
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class ExhaustFlow(TypedDict):
|
|
142
|
+
exhaust_flow: float | None
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class _VentilationState(
|
|
146
|
+
AirQuality,
|
|
147
|
+
Co2Level,
|
|
148
|
+
ExhaustTemp,
|
|
149
|
+
SupplyTemp,
|
|
150
|
+
IndoorTemp,
|
|
151
|
+
OutdoorTemp,
|
|
152
|
+
Capabilities,
|
|
153
|
+
BypassPosition,
|
|
154
|
+
FanInfo,
|
|
155
|
+
ExhaustFanSpeed,
|
|
156
|
+
SupplyFanSpeed,
|
|
157
|
+
RemainingMins,
|
|
158
|
+
PostHeater,
|
|
159
|
+
PreHeater,
|
|
160
|
+
SupplyFlow,
|
|
161
|
+
ExhaustFlow,
|
|
162
|
+
):
|
|
163
|
+
indoor_humidity: _HexToTempT
|
|
164
|
+
outdoor_humidity: _HexToTempT
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# These are payload-specific...
|
|
168
|
+
class _empty(TypedDict):
|
|
169
|
+
pass
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class _0004(TypedDict):
|
|
173
|
+
name: NotRequired[str | None]
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class _0006(TypedDict):
|
|
177
|
+
change_counter: NotRequired[int | None]
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class _0008(TypedDict):
|
|
181
|
+
relay_demand: float | None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class _000a(TypedDict):
|
|
185
|
+
zone_idx: NotRequired[str]
|
|
186
|
+
min_temp: float | None
|
|
187
|
+
max_temp: float | None
|
|
188
|
+
local_override: bool
|
|
189
|
+
openwindow_function: bool
|
|
190
|
+
multiroom_mode: bool
|
|
191
|
+
_unknown_bitmap: str
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class _0100(TypedDict):
|
|
195
|
+
language: str
|
|
196
|
+
_unknown_0: str
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class _0404(TypedDict):
|
|
200
|
+
frag_number: int
|
|
201
|
+
total_frags: int | None
|
|
202
|
+
frag_length: NotRequired[int | None]
|
|
203
|
+
fragment: NotRequired[str]
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class _0418_NULL(TypedDict): # only I_/RP with null payload
|
|
207
|
+
log_idx: NotRequired[LogIdxT] # only when I_|0418|00 with null payload
|
|
208
|
+
log_entry: None
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class _0418(TypedDict):
|
|
212
|
+
log_idx: LogIdxT
|
|
213
|
+
log_entry: tuple[str, ...] # TODO: = namedtuple("Fault", "timestamp fault_state...
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class _1060(TypedDict):
|
|
217
|
+
battery_low: bool
|
|
218
|
+
battery_level: float | None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class _1030(TypedDict):
|
|
222
|
+
max_flow_setpoint: float
|
|
223
|
+
min_flow_setpoint: float
|
|
224
|
+
valve_run_time: int
|
|
225
|
+
pump_run_time: int
|
|
226
|
+
boolean_cc: bool
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class _1090(TypedDict):
|
|
230
|
+
temperature_0: float | None
|
|
231
|
+
temperature_1: float | None
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class _10a0(TypedDict):
|
|
235
|
+
setpoint: _HexToTempT | None
|
|
236
|
+
overrun: NotRequired[int]
|
|
237
|
+
differential: NotRequired[_HexToTempT]
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class _10d0(TypedDict):
|
|
241
|
+
days_remaining: int | None
|
|
242
|
+
days_lifetime: NotRequired[int | None]
|
|
243
|
+
percent_remaining: NotRequired[float | None]
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class _10e1(TypedDict):
|
|
247
|
+
device_id: DeviceIdT
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class _1100(TypedDict):
|
|
251
|
+
domain_id: NotRequired[str]
|
|
252
|
+
cycle_rate: int
|
|
253
|
+
min_on_time: float
|
|
254
|
+
min_off_time: float
|
|
255
|
+
_unknown_0: str
|
|
256
|
+
proportional_band_width: NotRequired[float | None]
|
|
257
|
+
_unknown_1: NotRequired[str | None]
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class _1100_IDX(TypedDict):
|
|
261
|
+
domain_id: str
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class _12a0(TypedDict):
|
|
265
|
+
hvac_idx: str
|
|
266
|
+
indoor_humidity: NotRequired[_HexToTempT | None]
|
|
267
|
+
outdoor_humidity: NotRequired[_HexToTempT | None]
|
|
268
|
+
relative_humidity: NotRequired[_HexToTempT | None]
|
|
269
|
+
temperature: NotRequired[float | None]
|
|
270
|
+
dewpoint_temp: NotRequired[float | None]
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class _12b0(TypedDict):
|
|
274
|
+
window_open: bool | None
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class _12c0(TypedDict):
|
|
278
|
+
temperature: float | None
|
|
279
|
+
units: Literal["Fahrenheit", "Celsius"]
|
|
280
|
+
_unknown_6: NotRequired[str]
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class _1f09(TypedDict):
|
|
284
|
+
remaining_seconds: float
|
|
285
|
+
_next_sync: str
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class _1f41(TypedDict):
|
|
289
|
+
mode: str
|
|
290
|
+
active: NotRequired[bool | None]
|
|
291
|
+
until: NotRequired[str | None]
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class _1fd4(TypedDict):
|
|
295
|
+
ticker: int
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@verify(EnumCheck.UNIQUE)
|
|
299
|
+
class _BindPhase(StrEnum):
|
|
300
|
+
OFFER = "offer"
|
|
301
|
+
ACCEPT = "accept"
|
|
302
|
+
CONFIRM = "confirm"
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class _1fc9(TypedDict):
|
|
306
|
+
phase: str | None
|
|
307
|
+
bindings: list[list[str]]
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class _22b0(TypedDict):
|
|
311
|
+
enabled: bool
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class _22f4(TypedDict): # WIP
|
|
315
|
+
fan_mode: str | None
|
|
316
|
+
fan_rate: str | None
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
class _2309(TypedDict):
|
|
320
|
+
zone_idx: NotRequired[str]
|
|
321
|
+
setpoint: float | None
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
@verify(EnumCheck.UNIQUE)
|
|
325
|
+
class _ZoneMode(StrEnum):
|
|
326
|
+
FOLLOW = "follow_schedule"
|
|
327
|
+
ADVANCED = "advanced_override" # until the next scheduled setpoint
|
|
328
|
+
PERMANENT = "permanent_override" # indefinitely, until auto_reset
|
|
329
|
+
COUNTDOWN = "countdown_override" # for x mins (duration, max 1,215?)
|
|
330
|
+
TEMPORARY = "temporary_override" # until a given date/time (until)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class _2349(TypedDict):
|
|
334
|
+
mode: _ZoneMode
|
|
335
|
+
setpoint: float | None
|
|
336
|
+
duration: NotRequired[int | None]
|
|
337
|
+
until: NotRequired[str | None]
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class _2d49(TypedDict):
|
|
341
|
+
state: bool | None
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class _2e04(TypedDict):
|
|
345
|
+
system_mode: str
|
|
346
|
+
until: NotRequired[str | None]
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class _3110(TypedDict):
|
|
350
|
+
mode: str
|
|
351
|
+
demand: NotRequired[float | None]
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
class _313f(TypedDict):
|
|
355
|
+
datetime: str | None
|
|
356
|
+
is_dst: bool | None
|
|
357
|
+
_unknown_0: str
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class _3220(TypedDict):
|
|
361
|
+
msg_id: int # OtDataId
|
|
362
|
+
msg_type: str # OtMsgType
|
|
363
|
+
msg_name: str
|
|
364
|
+
description: str
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
class _3222(TypedDict):
|
|
368
|
+
start: int | None
|
|
369
|
+
length: int
|
|
370
|
+
data: NotRequired[str]
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
class _3b00(TypedDict):
|
|
374
|
+
domain_id: NotRequired[Literal["FC"]]
|
|
375
|
+
actuator_sync: bool | None
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class _3ef0_3(TypedDict): # payload of 3 bytes
|
|
379
|
+
modulation_level: float | None
|
|
380
|
+
_flags_2: str
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
class _3ef0_6(_3ef0_3): # payload of 6 bytes
|
|
384
|
+
_flags_3: list[int]
|
|
385
|
+
ch_active: bool
|
|
386
|
+
dhw_active: bool
|
|
387
|
+
cool_active: bool
|
|
388
|
+
flame_on: bool
|
|
389
|
+
_unknown_4: str
|
|
390
|
+
_unknown_5: str
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class _3ef0_9(_3ef0_6): # payload of 9 bytes
|
|
394
|
+
_flags_6: list[int]
|
|
395
|
+
ch_enabled: bool
|
|
396
|
+
ch_setpoint: int
|
|
397
|
+
max_rel_modulation: float
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class _3ef1(TypedDict):
|
|
401
|
+
modulation_level: float | None
|
|
402
|
+
actuator_countdown: int | None
|
|
403
|
+
cycle_countdown: int | None
|
|
404
|
+
_unknown_0: str
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class _JASPER(TypedDict):
|
|
408
|
+
ordinal: str
|
|
409
|
+
blob: str
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
class PayDictT:
|
|
413
|
+
"""Payload dict types."""
|
|
414
|
+
|
|
415
|
+
EMPTY: TypeAlias = _empty
|
|
416
|
+
|
|
417
|
+
# command codes
|
|
418
|
+
_0004: TypeAlias = _0004
|
|
419
|
+
_0006: TypeAlias = _0006
|
|
420
|
+
_0008: TypeAlias = _0008
|
|
421
|
+
_000A: TypeAlias = _000a
|
|
422
|
+
_0100: TypeAlias = _0100
|
|
423
|
+
_0404: TypeAlias = _0404
|
|
424
|
+
_0418: TypeAlias = _0418
|
|
425
|
+
_0418_NULL: TypeAlias = _0418_NULL
|
|
426
|
+
_1030: TypeAlias = _1030
|
|
427
|
+
_1060: TypeAlias = _1060
|
|
428
|
+
_1081: TypeAlias = _Setpoint
|
|
429
|
+
_1090: TypeAlias = _1090
|
|
430
|
+
_10A0: TypeAlias = _10a0
|
|
431
|
+
_10D0: TypeAlias = _10d0
|
|
432
|
+
_10E1: TypeAlias = _10e1
|
|
433
|
+
_1100: TypeAlias = _1100
|
|
434
|
+
_1100_IDX: TypeAlias = _1100_IDX
|
|
435
|
+
_1260: TypeAlias = _Temperature
|
|
436
|
+
_1280: TypeAlias = OutdoorHumidity
|
|
437
|
+
_1290: TypeAlias = OutdoorTemp
|
|
438
|
+
_1298: TypeAlias = Co2Level
|
|
439
|
+
_12A0: TypeAlias = _12a0
|
|
440
|
+
_12B0: TypeAlias = _12b0
|
|
441
|
+
_12C0: TypeAlias = _12c0
|
|
442
|
+
_12C8: TypeAlias = AirQuality
|
|
443
|
+
_12F0: TypeAlias = _FlowRate
|
|
444
|
+
_1300: TypeAlias = _Pressure
|
|
445
|
+
_1F09: TypeAlias = _1f09
|
|
446
|
+
_1F41: TypeAlias = _1f41
|
|
447
|
+
_1FC9: TypeAlias = _1fc9
|
|
448
|
+
_1FD4: TypeAlias = _1fd4
|
|
449
|
+
_22B0: TypeAlias = _22b0
|
|
450
|
+
_22F4: TypeAlias = _22f4
|
|
451
|
+
_2309: TypeAlias = _2309
|
|
452
|
+
_2349: TypeAlias = _2349
|
|
453
|
+
_22D9: TypeAlias = _Setpoint
|
|
454
|
+
_2D49: TypeAlias = _2d49
|
|
455
|
+
_2E04: TypeAlias = _2e04
|
|
456
|
+
_3110: TypeAlias = _3110
|
|
457
|
+
_313F: TypeAlias = _313f
|
|
458
|
+
_31DA: TypeAlias = _VentilationState
|
|
459
|
+
_3200: TypeAlias = _Temperature
|
|
460
|
+
_3210: TypeAlias = _Temperature
|
|
461
|
+
_3B00: TypeAlias = _3b00
|
|
462
|
+
_3EF0: TypeAlias = _3ef0_3 | _3ef0_6 | _3ef0_9
|
|
463
|
+
_3EF1: TypeAlias = _3ef1
|
|
464
|
+
|
|
465
|
+
_JASPER: TypeAlias = _JASPER
|
|
466
|
+
|
|
467
|
+
FAULT_LOG_ENTRY: TypeAlias = FaultLogEntry
|
|
468
|
+
FAULT_LOG_ENTRY_NULL: TypeAlias = FaultLogEntryNull
|
|
469
|
+
TEMPERATURE: TypeAlias = _Temperature
|
|
470
|
+
|
|
471
|
+
# 12A0 primitive
|
|
472
|
+
RELATIVE_HUMIDITY: TypeAlias = RelativeHumidity
|
|
473
|
+
|
|
474
|
+
# 31DA primitives
|
|
475
|
+
AIR_QUALITY: TypeAlias = AirQuality
|
|
476
|
+
CO2_LEVEL: TypeAlias = Co2Level
|
|
477
|
+
EXHAUST_TEMP: TypeAlias = ExhaustTemp
|
|
478
|
+
SUPPLY_TEMP: TypeAlias = SupplyTemp
|
|
479
|
+
INDOOR_HUMIDITY: TypeAlias = IndoorHumidity
|
|
480
|
+
OUTDOOR_HUMIDITY: TypeAlias = OutdoorHumidity
|
|
481
|
+
INDOOR_TEMP: TypeAlias = IndoorTemp
|
|
482
|
+
OUTDOOR_TEMP: TypeAlias = OutdoorTemp
|
|
483
|
+
CAPABILITIES: TypeAlias = Capabilities
|
|
484
|
+
BYPASS_POSITION: TypeAlias = BypassPosition
|
|
485
|
+
FAN_INFO: TypeAlias = FanInfo
|
|
486
|
+
EXHAUST_FAN_SPEED: TypeAlias = ExhaustFanSpeed
|
|
487
|
+
SUPPLY_FAN_SPEED: TypeAlias = SupplyFanSpeed
|
|
488
|
+
REMAINING_MINUTES: TypeAlias = RemainingMins
|
|
489
|
+
POST_HEATER: TypeAlias = PostHeater
|
|
490
|
+
PRE_HEATER: TypeAlias = PreHeater
|
|
491
|
+
SUPPLY_FLOW: TypeAlias = SupplyFlow
|
|
492
|
+
EXHAUST_FLOW: TypeAlias = ExhaustFlow
|
ramses_tx/typing.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""RAMSES RF - Typing for RamsesProtocol & RamsesTransport."""
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from datetime import datetime as dt
|
|
7
|
+
from typing import Any, Protocol, TypeVar
|
|
8
|
+
|
|
9
|
+
from serial import Serial # type: ignore[import-untyped]
|
|
10
|
+
|
|
11
|
+
from .command import Command
|
|
12
|
+
from .const import (
|
|
13
|
+
DEFAULT_GAP_DURATION,
|
|
14
|
+
DEFAULT_MAX_RETRIES,
|
|
15
|
+
DEFAULT_NUM_REPEATS,
|
|
16
|
+
DEFAULT_SEND_TIMEOUT,
|
|
17
|
+
DEFAULT_WAIT_FOR_REPLY,
|
|
18
|
+
Priority,
|
|
19
|
+
)
|
|
20
|
+
from .message import Message
|
|
21
|
+
from .packet import Packet
|
|
22
|
+
|
|
23
|
+
ExceptionT = TypeVar("ExceptionT", bound=type[Exception])
|
|
24
|
+
MsgFilterT = Callable[[Message], bool]
|
|
25
|
+
MsgHandlerT = Callable[[Message], None]
|
|
26
|
+
SerPortNameT = str
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class QosParams:
|
|
30
|
+
"""A container for QoS attributes and state."""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
*,
|
|
35
|
+
max_retries: int | None = DEFAULT_MAX_RETRIES,
|
|
36
|
+
timeout: float | None = DEFAULT_SEND_TIMEOUT,
|
|
37
|
+
wait_for_reply: bool | None = DEFAULT_WAIT_FOR_REPLY,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Create a QosParams instance."""
|
|
40
|
+
|
|
41
|
+
self._max_retries = DEFAULT_MAX_RETRIES if max_retries is None else max_retries
|
|
42
|
+
self._timeout = timeout or DEFAULT_SEND_TIMEOUT
|
|
43
|
+
self._wait_for_reply = wait_for_reply
|
|
44
|
+
|
|
45
|
+
self._echo_pkt: Packet | None = None
|
|
46
|
+
self._rply_pkt: Packet | None = None
|
|
47
|
+
|
|
48
|
+
self._dt_cmd_sent: dt | None = None
|
|
49
|
+
self._dt_echo_rcvd: dt | None = None
|
|
50
|
+
self._dt_rply_rcvd: dt | None = None
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def max_retries(self) -> int:
|
|
54
|
+
return self._max_retries
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def timeout(self) -> float:
|
|
58
|
+
return self._timeout
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def wait_for_reply(self) -> bool | None:
|
|
62
|
+
return self._wait_for_reply
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class SendParams:
|
|
66
|
+
"""A container for Send attributes and state."""
|
|
67
|
+
|
|
68
|
+
def __init__(
|
|
69
|
+
self,
|
|
70
|
+
*,
|
|
71
|
+
gap_duration: float | None = DEFAULT_GAP_DURATION,
|
|
72
|
+
num_repeats: int | None = DEFAULT_NUM_REPEATS,
|
|
73
|
+
priority: Priority | None = Priority.DEFAULT,
|
|
74
|
+
) -> None:
|
|
75
|
+
"""Create a SendParams instance."""
|
|
76
|
+
|
|
77
|
+
self._gap_duration = gap_duration or DEFAULT_GAP_DURATION
|
|
78
|
+
self._num_repeats = num_repeats or DEFAULT_NUM_REPEATS
|
|
79
|
+
self._priority = priority or Priority.DEFAULT
|
|
80
|
+
|
|
81
|
+
self._dt_cmd_arrived: dt | None = None
|
|
82
|
+
self._dt_cmd_queued: dt | None = None
|
|
83
|
+
self._dt_cmd_sent: dt | None = None
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def gap_duration(self) -> float:
|
|
87
|
+
return self._gap_duration
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def num_repeats(self) -> int:
|
|
91
|
+
return self._num_repeats
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def priority(self) -> Priority:
|
|
95
|
+
return self._priority
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class xRamsesTransportT(Protocol):
|
|
99
|
+
"""A typing.Protocol (i.e. a structural type) of asyncio.Transport."""
|
|
100
|
+
|
|
101
|
+
_is_closing: bool
|
|
102
|
+
# _is_reading: bool
|
|
103
|
+
|
|
104
|
+
def __init__( # type: ignore[no-any-unimported]
|
|
105
|
+
self,
|
|
106
|
+
protocol: asyncio.Protocol,
|
|
107
|
+
pkt_source: Serial | dict[str, str] | str,
|
|
108
|
+
loop: asyncio.AbstractEventLoop | None = None,
|
|
109
|
+
extra: dict[str, Any] | None = None,
|
|
110
|
+
**kwargs: Any,
|
|
111
|
+
) -> None: ...
|
|
112
|
+
|
|
113
|
+
def _dt_now(self) -> dt: ...
|
|
114
|
+
|
|
115
|
+
def _abort(self, exc: ExceptionT) -> None: # only in serial transport
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def _close(self, exc: ExceptionT | None = None) -> None: ...
|
|
119
|
+
|
|
120
|
+
def close(self) -> None:
|
|
121
|
+
"""Close the transport gracefully.
|
|
122
|
+
|
|
123
|
+
Schedules a call to `transport._protocol.connection_lost(None)`."""
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
def get_extra_info(self, name: str, default: Any | None = None) -> Any: ...
|
|
127
|
+
|
|
128
|
+
def is_closing(self) -> bool: ...
|
|
129
|
+
|
|
130
|
+
# NOTE this should not be included - maybe is a subclasses
|
|
131
|
+
# @staticmethod
|
|
132
|
+
# def is_hgi80(serial_port: SerPortName) -> None | bool: ...
|
|
133
|
+
|
|
134
|
+
def is_reading(self) -> bool: ...
|
|
135
|
+
|
|
136
|
+
def pause_reading(self) -> None: ...
|
|
137
|
+
|
|
138
|
+
def resume_reading(self) -> None: ...
|
|
139
|
+
|
|
140
|
+
def send_frame(self, frame: str) -> None: ...
|
|
141
|
+
|
|
142
|
+
# NOTE RamsesProtocol will not invoke write() directly
|
|
143
|
+
def write(self, data: bytes) -> None: ...
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class xRamsesProtocolT(Protocol):
|
|
147
|
+
"""A typing.Protocol (i.e. a structural type) of asyncio.Protocol."""
|
|
148
|
+
|
|
149
|
+
_msg_handler: MsgHandlerT
|
|
150
|
+
_pause_writing: bool
|
|
151
|
+
_transport: xRamsesTransportT
|
|
152
|
+
|
|
153
|
+
def __init__(self, msg_handler: MsgHandlerT) -> None: ...
|
|
154
|
+
|
|
155
|
+
def add_handler(
|
|
156
|
+
self, msg_handler: MsgHandlerT, /, *, msg_filter: MsgFilterT | None = None
|
|
157
|
+
) -> Callable[[], None]: ...
|
|
158
|
+
|
|
159
|
+
def connection_lost(self, err: ExceptionT | None) -> None: ...
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def wait_connection_lost(self) -> asyncio.Future[ExceptionT | None]: ...
|
|
163
|
+
|
|
164
|
+
def connection_made(self, transport: xRamsesTransportT) -> None: ...
|
|
165
|
+
|
|
166
|
+
def pause_writing(self) -> None: ...
|
|
167
|
+
|
|
168
|
+
def pkt_received(self, pkt: Packet) -> None: ...
|
|
169
|
+
|
|
170
|
+
def resume_writing(self) -> None: ...
|
|
171
|
+
|
|
172
|
+
async def send_cmd(
|
|
173
|
+
self,
|
|
174
|
+
cmd: Command,
|
|
175
|
+
/,
|
|
176
|
+
*,
|
|
177
|
+
gap_duration: float = DEFAULT_GAP_DURATION,
|
|
178
|
+
num_repeats: int = DEFAULT_NUM_REPEATS,
|
|
179
|
+
priority: Priority = Priority.DEFAULT,
|
|
180
|
+
qos: QosParams | None = None,
|
|
181
|
+
) -> Packet | None: ...
|
ramses_tx/version.py
ADDED