ramses-rf 0.52.5__py3-none-any.whl → 0.53.0__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_rf/gateway.py CHANGED
@@ -11,6 +11,7 @@ from __future__ import annotations
11
11
 
12
12
  import asyncio
13
13
  import logging
14
+ from collections.abc import Awaitable, Callable
14
15
  from types import SimpleNamespace
15
16
  from typing import TYPE_CHECKING, Any
16
17
 
@@ -83,7 +84,12 @@ _LOGGER = logging.getLogger(__name__)
83
84
 
84
85
 
85
86
  class Gateway(Engine):
86
- """The gateway class."""
87
+ """The gateway class.
88
+
89
+ This class serves as the primary interface for the RAMSES RF network. It manages
90
+ the serial connection (via ``Engine``), device discovery, schema maintenance,
91
+ and message dispatching.
92
+ """
87
93
 
88
94
  def __init__(
89
95
  self,
@@ -94,8 +100,30 @@ class Gateway(Engine):
94
100
  block_list: DeviceListT | None = None,
95
101
  known_list: DeviceListT | None = None,
96
102
  loop: asyncio.AbstractEventLoop | None = None,
103
+ transport_constructor: Callable[..., Awaitable[RamsesTransportT]] | None = None,
97
104
  **kwargs: Any,
98
105
  ) -> None:
106
+ """Initialize the Gateway instance.
107
+
108
+ :param port_name: The serial port name (e.g., '/dev/ttyUSB0') or None if using a file.
109
+ :type port_name: str | None
110
+ :param input_file: Path to a packet log file for playback, defaults to None.
111
+ :type input_file: str | None, optional
112
+ :param port_config: Configuration dictionary for the serial port, defaults to None.
113
+ :type port_config: PortConfigT | None, optional
114
+ :param packet_log: Configuration for packet logging, defaults to None.
115
+ :type packet_log: PktLogConfigT | None, optional
116
+ :param block_list: A list of device IDs to block/ignore, defaults to None.
117
+ :type block_list: DeviceListT | None, optional
118
+ :param known_list: A list of known device IDs and their traits, defaults to None.
119
+ :type known_list: DeviceListT | None, optional
120
+ :param loop: The asyncio event loop to use, defaults to None.
121
+ :type loop: asyncio.AbstractEventLoop | None, optional
122
+ :param transport_constructor: A factory for creating the transport layer, defaults to None.
123
+ :type transport_constructor: Callable[..., Awaitable[RamsesTransportT]] | None, optional
124
+ :param kwargs: Additional configuration parameters passed to the engine and schema.
125
+ :type kwargs: Any
126
+ """
99
127
  if kwargs.pop("debug_mode", None):
100
128
  _LOGGER.setLevel(logging.DEBUG)
101
129
 
@@ -110,6 +138,7 @@ class Gateway(Engine):
110
138
  block_list=block_list,
111
139
  known_list=known_list,
112
140
  loop=loop,
141
+ transport_constructor=transport_constructor,
113
142
  **SCH_ENGINE_CONFIG(config),
114
143
  )
115
144
 
@@ -132,13 +161,23 @@ class Gateway(Engine):
132
161
  self.msg_db: MessageIndex | None = None
133
162
 
134
163
  def __repr__(self) -> str:
164
+ """Return a string representation of the Gateway.
165
+
166
+ :returns: A string describing the gateway's input source (port or file).
167
+ :rtype: str
168
+ """
135
169
  if not self.ser_name:
136
170
  return f"Gateway(input_file={self._input_file})"
137
171
  return f"Gateway(port_name={self.ser_name}, port_config={self._port_config})"
138
172
 
139
173
  @property
140
174
  def hgi(self) -> HgiGateway | None:
141
- """Return the active HGI80-compatible gateway device, if known."""
175
+ """Return the active HGI80-compatible gateway device, if known.
176
+
177
+ :returns: The gateway device instance or None if the transport is not set up
178
+ or the HGI ID is not found.
179
+ :rtype: HgiGateway | None
180
+ """
142
181
  if not self._transport:
143
182
  return None
144
183
  if device_id := self._transport.get_extra_info(SZ_ACTIVE_HGI):
@@ -152,10 +191,21 @@ class Gateway(Engine):
152
191
  start_discovery: bool = True,
153
192
  cached_packets: dict[str, str] | None = None,
154
193
  ) -> None:
155
- """Start the Gateway and Initiate discovery as required."""
194
+ """Start the Gateway and Initiate discovery as required.
195
+
196
+ This method initializes packet logging, the SQLite index, loads the schema,
197
+ and optionally restores state from cached packets before starting the transport.
198
+
199
+ :param start_discovery: Whether to initiate the discovery process after start, defaults to True.
200
+ :type start_discovery: bool, optional
201
+ :param cached_packets: A dictionary of packet strings used to restore state, defaults to None.
202
+ :type cached_packets: dict[str, str] | None, optional
203
+ :returns: None
204
+ :rtype: None
205
+ """
156
206
 
157
207
  def initiate_discovery(dev_list: list[Device], sys_list: list[Evohome]) -> None:
158
- _LOGGER.debug("ENGINE: Initiating/enabling discovery...")
208
+ _LOGGER.debug("Engine: Initiating/enabling discovery...")
159
209
 
160
210
  # [d._start_discovery_poller() for d in devs]
161
211
  for device in dev_list:
@@ -201,10 +251,21 @@ class Gateway(Engine):
201
251
  initiate_discovery(self.devices, self.systems)
202
252
 
203
253
  def create_sqlite_message_index(self) -> None:
254
+ """Initialize the SQLite MessageIndex.
255
+
256
+ :returns: None
257
+ :rtype: None
258
+ """
204
259
  self.msg_db = MessageIndex() # start the index
205
260
 
206
261
  async def stop(self) -> None:
207
- """Stop the Gateway and tidy up."""
262
+ """Stop the Gateway and tidy up.
263
+
264
+ Stops the message database and the underlying engine/transport.
265
+
266
+ :returns: None
267
+ :rtype: None
268
+ """
208
269
 
209
270
  if self.msg_db:
210
271
  self.msg_db.stop()
@@ -214,6 +275,12 @@ class Gateway(Engine):
214
275
  """Pause the (unpaused) gateway (disables sending/discovery).
215
276
 
216
277
  There is the option to save other objects, as `args`.
278
+
279
+ :param args: Additional objects/state to save during the pause.
280
+ :type args: Any
281
+ :returns: None
282
+ :rtype: None
283
+ :raises RuntimeError: If the engine fails to pause.
217
284
  """
218
285
  _LOGGER.debug("Gateway: Pausing engine...")
219
286
 
@@ -229,6 +296,9 @@ class Gateway(Engine):
229
296
  """Resume the (paused) gateway (enables sending/discovery, if applicable).
230
297
 
231
298
  Will restore other objects, as `args`.
299
+
300
+ :returns: A tuple of arguments saved during the pause.
301
+ :rtype: tuple[Any]
232
302
  """
233
303
  args: tuple[Any]
234
304
 
@@ -241,7 +311,13 @@ class Gateway(Engine):
241
311
  def get_state(
242
312
  self, include_expired: bool = False
243
313
  ) -> tuple[dict[str, Any], dict[str, str]]:
244
- """Return the current schema & state (may include expired packets)."""
314
+ """Return the current schema & state (may include expired packets).
315
+
316
+ :param include_expired: If True, include expired packets in the state, defaults to False.
317
+ :type include_expired: bool, optional
318
+ :returns: A tuple containing the schema dictionary and the packet log dictionary.
319
+ :rtype: tuple[dict[str, Any], dict[str, str]]
320
+ """
245
321
 
246
322
  self._pause()
247
323
 
@@ -287,10 +363,21 @@ class Gateway(Engine):
287
363
  async def _restore_cached_packets(
288
364
  self, packets: dict[str, str], _clear_state: bool = False
289
365
  ) -> None:
290
- """Restore cached packets (may include expired packets)."""
366
+ """Restore cached packets (may include expired packets).
367
+
368
+ This process uses a temporary transport to replay the packet history
369
+ into the message handler.
370
+
371
+ :param packets: A dictionary of packet strings.
372
+ :type packets: dict[str, str]
373
+ :param _clear_state: If True, reset internal state before restoration (for testing), defaults to False.
374
+ :type _clear_state: bool, optional
375
+ :returns: None
376
+ :rtype: None
377
+ """
291
378
 
292
379
  def clear_state() -> None:
293
- _LOGGER.info("GATEWAY: Clearing existing schema/state...")
380
+ _LOGGER.info("Gateway: Clearing existing schema/state...")
294
381
 
295
382
  # self._schema = {}
296
383
 
@@ -303,7 +390,7 @@ class Gateway(Engine):
303
390
 
304
391
  tmp_transport: RamsesTransportT # mypy hint
305
392
 
306
- _LOGGER.debug("GATEWAY: Restoring a cached packet log...")
393
+ _LOGGER.debug("Gateway: Restoring a cached packet log...")
307
394
  self._pause()
308
395
 
309
396
  if _clear_state: # only intended for test suite use
@@ -339,11 +426,18 @@ class Gateway(Engine):
339
426
 
340
427
  await tmp_transport.get_extra_info(SZ_READER_TASK)
341
428
 
342
- _LOGGER.debug("GATEWAY: Restored, resuming")
429
+ _LOGGER.debug("Gateway: Restored, resuming")
343
430
  self._resume()
344
431
 
345
432
  def _add_device(self, dev: Device) -> None: # TODO: also: _add_system()
346
- """Add a device to the gateway (called by devices during instantiation)."""
433
+ """Add a device to the gateway (called by devices during instantiation).
434
+
435
+ :param dev: The device instance to add.
436
+ :type dev: Device
437
+ :returns: None
438
+ :rtype: None
439
+ :raises LookupError: If the device already exists in the gateway.
440
+ """
347
441
 
348
442
  if dev.id in self.device_by_id:
349
443
  raise LookupError(f"Device already exists: {dev.id}")
@@ -366,17 +460,17 @@ class Gateway(Engine):
366
460
  passes a message for it to handle. All devices have traits, but only
367
461
  controllers (CTL, UFC) have a schema.
368
462
 
369
- :param device_id: The unique identifier for the device (e.g., '01:123456')
463
+ :param device_id: The unique identifier for the device (e.g., '01:123456').
370
464
  :type device_id: DeviceIdT
371
- :param msg: An optional initial message for the device to process, defaults to None
372
- :type msg: Message | None
373
- :param parent: The parent entity of this device, if any, defaults to None
374
- :type parent: Parent | None
375
- :param child_id: The specific ID of the child component if applicable, defaults to None
376
- :type child_id: str | None
377
- :param is_sensor: Indicates if this device should be treated as a sensor, defaults to None
378
- :type is_sensor: bool | None
379
- :return: The existing or newly created device instance
465
+ :param msg: An optional initial message for the device to process, defaults to None.
466
+ :type msg: Message | None, optional
467
+ :param parent: The parent entity of this device, if any, defaults to None.
468
+ :type parent: Parent | None, optional
469
+ :param child_id: The specific ID of the child component if applicable, defaults to None.
470
+ :type child_id: str | None, optional
471
+ :param is_sensor: Indicates if this device should be treated as a sensor, defaults to None.
472
+ :type is_sensor: bool | None, optional
473
+ :returns: The existing or newly created device instance.
380
474
  :rtype: Device
381
475
  :raises LookupError: If the device ID is blocked or not in the allowed known_list.
382
476
  """
@@ -446,7 +540,21 @@ class Gateway(Engine):
446
540
  device_id: DeviceIdT,
447
541
  create_device: bool = False,
448
542
  ) -> Device | Fakeable:
449
- """Create a faked device."""
543
+ """Create a faked device.
544
+
545
+ Converts an existing device to a fake device, or creates a new fake device
546
+ if it satisfies strict criteria (valid ID, presence in known_list).
547
+
548
+ :param device_id: The ID of the device to fake.
549
+ :type device_id: DeviceIdT
550
+ :param create_device: If True, allow creation of a new device if it doesn't exist, defaults to False.
551
+ :type create_device: bool, optional
552
+ :returns: The faked device instance.
553
+ :rtype: Device | Fakeable
554
+ :raises TypeError: If the device ID is invalid or the device is not fakeable.
555
+ :raises LookupError: If the device does not exist and create_device is False,
556
+ or if create_device is True but the ID is not in known_list.
557
+ """
450
558
 
451
559
  if not is_valid_dev_id(device_id):
452
560
  raise TypeError(f"The device id is not valid: {device_id}")
@@ -464,7 +572,11 @@ class Gateway(Engine):
464
572
 
465
573
  @property
466
574
  def tcs(self) -> Evohome | None:
467
- """Return the primary TCS, if any."""
575
+ """Return the primary Temperature Control System (TCS), if any.
576
+
577
+ :returns: The primary Evohome system or None.
578
+ :rtype: Evohome | None
579
+ """
468
580
 
469
581
  if self._tcs is None and self.systems:
470
582
  self._tcs = self.systems[0]
@@ -477,6 +589,9 @@ class Gateway(Engine):
477
589
  Unlike orphans, which are always instantiated when a schema is loaded, these
478
590
  devices may/may not exist. However, if they are ever instantiated, they should
479
591
  be given these traits.
592
+
593
+ :returns: A dictionary where keys are device IDs and values are their traits.
594
+ :rtype: DeviceListT
480
595
  """
481
596
 
482
597
  result = self._include # could be devices here, not (yet) in gwy.devices
@@ -491,6 +606,11 @@ class Gateway(Engine):
491
606
 
492
607
  @property
493
608
  def system_by_id(self) -> dict[DeviceIdT, Evohome]:
609
+ """Return a mapping of device IDs to their associated Evohome systems.
610
+
611
+ :returns: A dictionary mapping DeviceId to Evohome instances.
612
+ :rtype: dict[DeviceIdT, Evohome]
613
+ """
494
614
  return {
495
615
  d.id: d.tcs
496
616
  for d in self.devices
@@ -499,6 +619,11 @@ class Gateway(Engine):
499
619
 
500
620
  @property
501
621
  def systems(self) -> list[Evohome]:
622
+ """Return a list of all identified Evohome systems.
623
+
624
+ :returns: A list of Evohome system instances.
625
+ :rtype: list[Evohome]
626
+ """
502
627
  return list(self.system_by_id.values())
503
628
 
504
629
  @property
@@ -510,6 +635,9 @@ class Gateway(Engine):
510
635
  - schema (everything else)
511
636
  - known_list
512
637
  - block_list
638
+
639
+ :returns: A dictionary representing the current internal configuration state.
640
+ :rtype: dict[str, Any]
513
641
  """
514
642
 
515
643
  return {
@@ -531,6 +659,9 @@ class Gateway(Engine):
531
659
  Orphans are devices that 'exist' but don't yet have a place in the schema
532
660
  hierarchy (if ever): therefore, they are instantiated when the schema is loaded,
533
661
  just like the other devices in the schema.
662
+
663
+ :returns: A dictionary representing the entire system schema structure.
664
+ :rtype: dict[str, Any]
534
665
  """
535
666
 
536
667
  schema: dict[str, Any] = {SZ_MAIN_TCS: self.tcs.ctl.id if self.tcs else None}
@@ -558,10 +689,20 @@ class Gateway(Engine):
558
689
 
559
690
  @property
560
691
  def params(self) -> dict[str, Any]:
692
+ """Return the parameters for all devices.
693
+
694
+ :returns: A dictionary containing parameters for every device in the gateway.
695
+ :rtype: dict[str, Any]
696
+ """
561
697
  return {SZ_DEVICES: {d.id: d.params for d in sorted(self.devices)}}
562
698
 
563
699
  @property
564
700
  def status(self) -> dict[str, Any]:
701
+ """Return the status for all devices and the transport rate.
702
+
703
+ :returns: A dictionary containing device statuses and transmission rate.
704
+ :rtype: dict[str, Any]
705
+ """
565
706
  tx_rate = self._transport.get_extra_info("tx_rate") if self._transport else None
566
707
  return {
567
708
  SZ_DEVICES: {d.id: d.status for d in sorted(self.devices)},
@@ -569,7 +710,15 @@ class Gateway(Engine):
569
710
  }
570
711
 
571
712
  def _msg_handler(self, msg: Message) -> None:
572
- """A callback to handle messages from the protocol stack."""
713
+ """A callback to handle messages from the protocol stack.
714
+
715
+ Handles message reassembly (fragmentation) and dispatches the message for processing.
716
+
717
+ :param msg: The incoming message to handle.
718
+ :type msg: Message
719
+ :returns: None
720
+ :rtype: None
721
+ """
573
722
 
574
723
  super()._msg_handler(msg)
575
724
 
@@ -597,9 +746,20 @@ class Gateway(Engine):
597
746
  ) -> asyncio.Task[Packet]:
598
747
  """Wrapper to schedule an async_send_cmd() and return the Task.
599
748
 
600
- num_repeats: 0 = send once, 1 = send twice, etc.
601
- gap_duration: the gap between repeats (in seconds)
602
- priority: the priority of the command
749
+ :param cmd: The command object to send.
750
+ :type cmd: Command
751
+ :param gap_duration: The gap between repeats (in seconds), defaults to DEFAULT_GAP_DURATION.
752
+ :type gap_duration: float, optional
753
+ :param num_repeats: Number of times to repeat the command (0 = once, 1 = twice, etc.), defaults to DEFAULT_NUM_REPEATS.
754
+ :type num_repeats: int, optional
755
+ :param priority: The priority of the command, defaults to Priority.DEFAULT.
756
+ :type priority: Priority, optional
757
+ :param timeout: Time to wait for a send to complete, defaults to DEFAULT_SEND_TIMEOUT.
758
+ :type timeout: float, optional
759
+ :param wait_for_reply: Whether to wait for a reply packet, defaults to DEFAULT_WAIT_FOR_REPLY.
760
+ :type wait_for_reply: bool | None, optional
761
+ :returns: The asyncio Task wrapping the send operation.
762
+ :rtype: asyncio.Task[Packet]
603
763
  """
604
764
 
605
765
  coro = self.async_send_cmd(
@@ -632,6 +792,22 @@ class Gateway(Engine):
632
792
  If wait_for_reply is True (*and* the Command has a rx_header), return the
633
793
  reply Packet. Otherwise, simply return the echo Packet.
634
794
 
795
+ :param cmd: The command object to send.
796
+ :type cmd: Command
797
+ :param gap_duration: The gap between repeats (in seconds), defaults to DEFAULT_GAP_DURATION.
798
+ :type gap_duration: float, optional
799
+ :param num_repeats: Number of times to repeat the command, defaults to DEFAULT_NUM_REPEATS.
800
+ :type num_repeats: int, optional
801
+ :param priority: The priority of the command, defaults to Priority.DEFAULT.
802
+ :type priority: Priority, optional
803
+ :param max_retries: Maximum number of retries if sending fails, defaults to DEFAULT_MAX_RETRIES.
804
+ :type max_retries: int, optional
805
+ :param timeout: Time to wait for the command to send, defaults to DEFAULT_SEND_TIMEOUT.
806
+ :type timeout: float, optional
807
+ :param wait_for_reply: Whether to wait for a reply packet, defaults to DEFAULT_WAIT_FOR_REPLY.
808
+ :type wait_for_reply: bool | None, optional
809
+ :returns: The echo packet or reply packet depending on wait_for_reply.
810
+ :rtype: Packet
635
811
  :raises ProtocolSendFailed: If the command was sent but no reply/echo was received.
636
812
  :raises ProtocolError: If the system failed to attempt the transmission.
637
813
  """
ramses_rf/schemas.py CHANGED
@@ -237,6 +237,7 @@ SCH_GLOBAL_SCHEMAS_DICT = { # System schemas - can be 0-many Heat/HVAC schemas
237
237
  vol.Optional(SCH_DEVICE_ID_ANY): SCH_VCS, # must be after SCH_DEVICE_ID_CTL
238
238
  vol.Optional(SZ_ORPHANS_HEAT): vol.All([SCH_DEVICE_ID_ANY], vol.Unique()),
239
239
  vol.Optional(SZ_ORPHANS_HVAC): vol.All([SCH_DEVICE_ID_ANY], vol.Unique()),
240
+ vol.Optional("transport_constructor"): vol.Any(callable, None),
240
241
  }
241
242
  SCH_GLOBAL_SCHEMAS = vol.Schema(SCH_GLOBAL_SCHEMAS_DICT, extra=vol.PREVENT_EXTRA)
242
243
 
ramses_rf/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """RAMSES RF - a RAMSES-II protocol decoder & analyser (application layer)."""
2
2
 
3
- __version__ = "0.52.5"
3
+ __version__ = "0.53.0"
4
4
  VERSION = __version__
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ramses_rf
3
- Version: 0.52.5
3
+ Version: 0.53.0
4
4
  Summary: A stateful RAMSES-II protocol decoder & analyser.
5
5
  Project-URL: Homepage, https://github.com/ramses-rf/ramses_rf
6
6
  Project-URL: Bug Tracker, https://github.com/ramses-rf/ramses_rf/issues
@@ -1,21 +1,22 @@
1
1
  ramses_cli/__init__.py,sha256=uvGzWqOf4avvgzxJNSLFWEelIWqSZ-AeLAZzg5x58bc,397
2
- ramses_cli/client.py,sha256=h6liNKFXGsR2q9Unn81ushK53zqKgmkT0oAWNB5Jn0I,20369
2
+ ramses_cli/client.py,sha256=OpsVfrdwChrBKia_yfAlI60ERMg7KAk3BWRpQyY3AWA,24762
3
3
  ramses_cli/debug.py,sha256=PLcz-3PjUiMVqtD_p6VqTA92eHUM58lOBFXh_qgQ_wA,576
4
4
  ramses_cli/discovery.py,sha256=MWoahBnAAVzfK2S7EDLsY2WYqN_ZK9L-lktrj8_4cb0,12978
5
+ ramses_cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
6
  ramses_cli/utils/cat_slow.py,sha256=AhUpM5gnegCitNKU-JGHn-DrRzSi-49ZR1Qw6lxe_t8,607
6
7
  ramses_cli/utils/convert.py,sha256=N3LxGe3_0pclijtmYW-ChqCuPTzbkoJA4XNAnoSnBk0,1806
7
- ramses_rf/__init__.py,sha256=vp2TyFGqc1fGQHsevhmaw0QEmSSCnZx7fqizKiEwHtw,1245
8
+ ramses_rf/__init__.py,sha256=AXsCK1Eh9FWeAI9D_zY_2KB0dqrTb9a5TNY1NvyQaDM,1271
8
9
  ramses_rf/binding_fsm.py,sha256=fuqvcc9YW-wr8SPH8zadpPqrHAvzl_eeWF-IBtlLppY,26632
9
10
  ramses_rf/const.py,sha256=L3z31CZ-xqno6oZp_h-67CB_5tDDqTwSWXsqRtsjMcs,5460
10
11
  ramses_rf/database.py,sha256=9nY1Wt2hjkBoDvDqopzPP3mPSH5-Q5XHPQuJnM2GHOw,21362
11
12
  ramses_rf/dispatcher.py,sha256=YjEU-QrBLo9IfoEhJo2ikg_FxOaMYoWvzelr9Vi-JZ8,11398
12
- ramses_rf/entity_base.py,sha256=Psa75zsZf6GOvXIv4c37vJDbg5iVQ1gQCADkBNOz1m8,58912
13
+ ramses_rf/entity_base.py,sha256=6jsHQD_5buaV56rF6nTgzPKOLsXFGVly9EHAeigqeRg,59039
13
14
  ramses_rf/exceptions.py,sha256=mt_T7irqHSDKir6KLaf6oDglUIdrw0S40JbOrWJk5jc,3657
14
- ramses_rf/gateway.py,sha256=B7BlrNHx26lIHzjgy6-4NMtohb_GATaBuucgsUUxRj4,22005
15
+ ramses_rf/gateway.py,sha256=KWE7ZkHGPcZFp9eaKN9zXchkykMJLEx_k5Le99or5lQ,30064
15
16
  ramses_rf/helpers.py,sha256=TNk_QkpIOB3alOp1sqnA9LOzi4fuDCeapNlW3zTzNas,4250
16
17
  ramses_rf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- ramses_rf/schemas.py,sha256=0_qQZSGj2ixq4UCtMxoAeWklOJiM4bbBUzMsPw8gUPw,13475
18
- ramses_rf/version.py,sha256=wV7QvKiXDL06V_DHo0XYcc-6CIYMlhztVGzCh1m45D8,125
18
+ ramses_rf/schemas.py,sha256=X1GAK3kttuLMiSCUDY2s-85fgBxPeU8xiDa6gJ1I5mY,13543
19
+ ramses_rf/version.py,sha256=FlL_C6hC_miMOJxgK12zDE2CvaAfRA3KoLOL1_U-7QE,125
19
20
  ramses_rf/device/__init__.py,sha256=sUbH5dhbYFXSoM_TPFRutpRutBRpup7_cQ9smPtDTy8,4858
20
21
  ramses_rf/device/base.py,sha256=Tu5I8Lj7KplfRsIBQAYjilS6YPgTyjpU8qgKugMR2Jk,18281
21
22
  ramses_rf/device/heat.py,sha256=T-ENFzH1AEOd0m4-TgV-Qk0TnLNir_pYmyKlJtxy6NI,54538
@@ -27,8 +28,8 @@ ramses_rf/system/schedule.py,sha256=Ts6tdZPTQLV5NkgwA73tPa5QUsnZNIIuYoKC-8VsXDk,
27
28
  ramses_rf/system/zones.py,sha256=qMv7CuvZUKBNLpPRXgFA70NFRStgVJcw062h5mc3Y8Q,37034
28
29
  ramses_tx/__init__.py,sha256=sqnjM7pUGJDmec6igTtKViSB8FLX49B5gwhAmcY9ERY,3596
29
30
  ramses_tx/address.py,sha256=IuwUwZxykn3fP1UCRcv4D-zbTICBe2FJjDAFX5X6VoI,9108
30
- ramses_tx/command.py,sha256=NeqWbdaWrXjP5KEZgXFicy_1UYOoUznRHN2ZfhVyDH0,125652
31
- ramses_tx/const.py,sha256=AMwHitDq115rB24f3fzclNGC4ArMW16DbqiFWQc0U5o,30306
31
+ ramses_tx/command.py,sha256=drxmpdM4YgyPg4h0QIr1ouxK9QjfeLVgnFpDRox0CCY,125652
32
+ ramses_tx/const.py,sha256=gmRQ59V5AJx2TlACL3tDSBy5VpvEOVbQfG0z7WjFCKE,32941
32
33
  ramses_tx/exceptions.py,sha256=FJSU9YkvpKjs3yeTqUJX1o3TPFSe_B01gRGIh9b3PNc,2632
33
34
  ramses_tx/fingerprints.py,sha256=nfftA1E62HQnb-eLt2EqjEi_la0DAoT0wt-PtTMie0s,11974
34
35
  ramses_tx/frame.py,sha256=GzNsXr15YLeidJYGtk_xPqsZQh4ehDDlUCtT6rTDhT8,22046
@@ -39,17 +40,17 @@ ramses_tx/message.py,sha256=HUSNiBgGlnWEBeBqb4K28GcU5oB7RbS9a0JC2p9SGe4,13676
39
40
  ramses_tx/opentherm.py,sha256=58PXz9l5x8Ou6Fm3y-R_UnGHCYahoi2RKIDdYStUMzk,42378
40
41
  ramses_tx/packet.py,sha256=_nzuInS_WhdOI26SYvgsdDqIaDvVNguc2YDwdPOVCbU,7661
41
42
  ramses_tx/parsers.py,sha256=qQz8VOKaH26MUvo9AfUwhrnbH7VwXLxFc2gKJYvjXvY,148571
42
- ramses_tx/protocol.py,sha256=ApA__ubfxM63c1OAxRcH6fhjMQTdC07SnSH9cGfWO2U,32427
43
- ramses_tx/protocol_fsm.py,sha256=ZKtehCr_4TaDdfdlfidFLJaOVTYtaEq5h4tLqNIhb9s,26827
43
+ ramses_tx/protocol.py,sha256=nBPKCD1tcGp_FiX0qhsY0XoGO_h87w5cYywBjSpum4w,33048
44
+ ramses_tx/protocol_fsm.py,sha256=o9vLvlXor3LkPgsY1zii5P1R01GzYLf_PECDdoxtC24,27520
44
45
  ramses_tx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
46
  ramses_tx/ramses.py,sha256=vp748Tf_a-56OMM8CWDA2ZktRfTuj0QVyPRcnsOstSM,53983
46
- ramses_tx/schemas.py,sha256=bqKW_V0bR6VbBD8ZQiBExNtVdXs0fryVKe3GEhupgIo,13424
47
- ramses_tx/transport.py,sha256=-Ikwj_Hy6JEnQPS9gBalV3H5AKQd3ATxKskR7Dy7_sE,59774
47
+ ramses_tx/schemas.py,sha256=Hrmf_q9bAZtkKJzGu6GtUO0QV_-K9i4L99EzGWR13eE,13408
48
+ ramses_tx/transport.py,sha256=Tk2CPAu9W0T4HCe6Q2VUYex2bFNZlyYsluP7iLf0rdQ,76277
48
49
  ramses_tx/typed_dicts.py,sha256=w-0V5t2Q3GiNUOrRAWiW9GtSwbta_7luME6GfIb1zhI,10869
49
50
  ramses_tx/typing.py,sha256=eF2SlPWhNhEFQj6WX2AhTXiyRQVXYnFutiepllYl2rI,5042
50
- ramses_tx/version.py,sha256=j7HXmU97PXKJClRv1saySQ_JZYHAxBznxUTdWH64uHE,123
51
- ramses_rf-0.52.5.dist-info/METADATA,sha256=gGSPoi37fljrfFxDIVHXFUU5RuzGu6wwwD0JbvdwiVQ,4179
52
- ramses_rf-0.52.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
53
- ramses_rf-0.52.5.dist-info/entry_points.txt,sha256=NnyK29baOCNg8DinPYiZ368h7MTH7bgTW26z2A1NeIE,50
54
- ramses_rf-0.52.5.dist-info/licenses/LICENSE,sha256=-Kc35W7l1UkdiQ4314_yVWv7vDDrg7IrJfMLUiq6Nfs,1074
55
- ramses_rf-0.52.5.dist-info/RECORD,,
51
+ ramses_tx/version.py,sha256=DToXw6Td-r5_4JxS4fbBBGkajaXoEj8xCJOh7vaNcQI,123
52
+ ramses_rf-0.53.0.dist-info/METADATA,sha256=YkSNqr4RWgOsSi-z8SO5H4LEbzOI87IVYurjHWpUgRc,4179
53
+ ramses_rf-0.53.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
54
+ ramses_rf-0.53.0.dist-info/entry_points.txt,sha256=NnyK29baOCNg8DinPYiZ368h7MTH7bgTW26z2A1NeIE,50
55
+ ramses_rf-0.53.0.dist-info/licenses/LICENSE,sha256=ptVutrtSMr7X-ek6LduiD8Cce4JsNn_8sR8MYlm-fvo,1086
56
+ ramses_rf-0.53.0.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021-2025 David Bonnes
3
+ Copyright (c) 2021-2026 D. Bonnes and E. Broerse
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
ramses_tx/command.py CHANGED
@@ -1866,7 +1866,7 @@ class Command(Frame):
1866
1866
  The actual number of available zones depends on the controller configuration.
1867
1867
  Requesting a non-existent zone will typically result in no response.
1868
1868
  """
1869
- return cls.from_attrs(W_, ctl_id, Code._2309, _check_idx(zone_idx))
1869
+ return cls.from_attrs(RQ, ctl_id, Code._2309, _check_idx(zone_idx))
1870
1870
 
1871
1871
  @classmethod # constructor for W|2309
1872
1872
  def set_zone_setpoint(