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.
Files changed (72) hide show
  1. ramses_cli/__init__.py +18 -0
  2. ramses_cli/client.py +597 -0
  3. ramses_cli/debug.py +20 -0
  4. ramses_cli/discovery.py +405 -0
  5. ramses_cli/utils/cat_slow.py +17 -0
  6. ramses_cli/utils/convert.py +60 -0
  7. ramses_rf/__init__.py +31 -10
  8. ramses_rf/binding_fsm.py +787 -0
  9. ramses_rf/const.py +124 -105
  10. ramses_rf/database.py +297 -0
  11. ramses_rf/device/__init__.py +69 -39
  12. ramses_rf/device/base.py +187 -376
  13. ramses_rf/device/heat.py +540 -552
  14. ramses_rf/device/hvac.py +286 -171
  15. ramses_rf/dispatcher.py +153 -177
  16. ramses_rf/entity_base.py +478 -361
  17. ramses_rf/exceptions.py +82 -0
  18. ramses_rf/gateway.py +378 -514
  19. ramses_rf/helpers.py +57 -19
  20. ramses_rf/py.typed +0 -0
  21. ramses_rf/schemas.py +148 -194
  22. ramses_rf/system/__init__.py +16 -23
  23. ramses_rf/system/faultlog.py +363 -0
  24. ramses_rf/system/heat.py +295 -302
  25. ramses_rf/system/schedule.py +312 -198
  26. ramses_rf/system/zones.py +318 -238
  27. ramses_rf/version.py +2 -8
  28. ramses_rf-0.51.1.dist-info/METADATA +72 -0
  29. ramses_rf-0.51.1.dist-info/RECORD +55 -0
  30. {ramses_rf-0.22.2.dist-info → ramses_rf-0.51.1.dist-info}/WHEEL +1 -2
  31. ramses_rf-0.51.1.dist-info/entry_points.txt +2 -0
  32. {ramses_rf-0.22.2.dist-info → ramses_rf-0.51.1.dist-info/licenses}/LICENSE +1 -1
  33. ramses_tx/__init__.py +160 -0
  34. {ramses_rf/protocol → ramses_tx}/address.py +65 -59
  35. ramses_tx/command.py +1454 -0
  36. ramses_tx/const.py +903 -0
  37. ramses_tx/exceptions.py +92 -0
  38. {ramses_rf/protocol → ramses_tx}/fingerprints.py +56 -15
  39. {ramses_rf/protocol → ramses_tx}/frame.py +132 -131
  40. ramses_tx/gateway.py +338 -0
  41. ramses_tx/helpers.py +883 -0
  42. {ramses_rf/protocol → ramses_tx}/logger.py +67 -53
  43. {ramses_rf/protocol → ramses_tx}/message.py +155 -191
  44. ramses_tx/opentherm.py +1260 -0
  45. ramses_tx/packet.py +210 -0
  46. ramses_tx/parsers.py +2957 -0
  47. ramses_tx/protocol.py +801 -0
  48. ramses_tx/protocol_fsm.py +672 -0
  49. ramses_tx/py.typed +0 -0
  50. {ramses_rf/protocol → ramses_tx}/ramses.py +262 -185
  51. {ramses_rf/protocol → ramses_tx}/schemas.py +150 -133
  52. ramses_tx/transport.py +1471 -0
  53. ramses_tx/typed_dicts.py +492 -0
  54. ramses_tx/typing.py +181 -0
  55. ramses_tx/version.py +4 -0
  56. ramses_rf/discovery.py +0 -398
  57. ramses_rf/protocol/__init__.py +0 -59
  58. ramses_rf/protocol/backports.py +0 -42
  59. ramses_rf/protocol/command.py +0 -1561
  60. ramses_rf/protocol/const.py +0 -697
  61. ramses_rf/protocol/exceptions.py +0 -111
  62. ramses_rf/protocol/helpers.py +0 -390
  63. ramses_rf/protocol/opentherm.py +0 -1170
  64. ramses_rf/protocol/packet.py +0 -235
  65. ramses_rf/protocol/parsers.py +0 -2673
  66. ramses_rf/protocol/protocol.py +0 -613
  67. ramses_rf/protocol/transport.py +0 -1011
  68. ramses_rf/protocol/version.py +0 -10
  69. ramses_rf/system/hvac.py +0 -82
  70. ramses_rf-0.22.2.dist-info/METADATA +0 -64
  71. ramses_rf-0.22.2.dist-info/RECORD +0 -42
  72. ramses_rf-0.22.2.dist-info/top_level.txt +0 -1
@@ -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
@@ -0,0 +1,4 @@
1
+ """RAMSES RF - a RAMSES-II protocol decoder & analyser (transport layer)."""
2
+
3
+ __version__ = "0.51.1"
4
+ VERSION = __version__