ramses-rf 0.52.1__py3-none-any.whl → 0.52.3__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_tx/parsers.py CHANGED
@@ -3,9 +3,11 @@
3
3
 
4
4
  NOTES: aspirations on a consistent Schema, going forward:
5
5
 
6
- :mode/state: | :bool: | :mutex (infinitive. vs -ing): | :flags:
7
- mode (config.) | enabled | disabled, heat, cool, heat_cool... | ch_enabled, dhw_enabled
8
- state (action) | active | idle, heating, cooling... | is_heating, is_cooling
6
+ ============== ======== =================================== ========================
7
+ :mode/state: :bool: :mutex (infinitive. vs -ing): :flags:
8
+ mode (config.) enabled disabled, heat, cool, heat_cool... ch_enabled, dhw_enabled
9
+ state (action) active idle, heating, cooling... is_heating, is_cooling
10
+ ============== ======== =================================== ========================
9
11
 
10
12
  - prefer: enabled: True over xx_enabled: True (if only ever 1 flag)
11
13
  - prefer: active: True over is_heating: True (if only ever 1 flag)
@@ -362,8 +364,9 @@ def parser_0009(payload: str, msg: Message) -> dict | list[dict]: # TODO: only
362
364
 
363
365
  The failsafe mode defines the relay behaviour if the RF communication is lost (e.g.
364
366
  when a room thermostat stops communicating due to discharged batteries):
365
- False (disabled) - if RF comms are lost, relay will be held in OFF position
366
- True (enabled) - if RF comms are lost, relay will cycle at 20% ON, 80% OFF
367
+
368
+ - False (disabled) - if RF comms are lost, relay will be held in OFF position
369
+ - True (enabled) - if RF comms are lost, relay will cycle at 20% ON, 80% OFF
367
370
 
368
371
  This setting may need to be enabled to ensure frost protect mode.
369
372
  """
@@ -2289,45 +2292,46 @@ def parser_31da(payload: str, msg: Message) -> PayDictT._31DA:
2289
2292
  def parser_31e0(payload: str, msg: Message) -> dict | list[dict]: # TODO: only dict
2290
2293
  """Notes are.
2291
2294
 
2292
- van means of”.
2295
+ "van" means "of".
2293
2296
  - 0 = min. van min. potm would be:
2294
2297
  - 0 = minimum of minimum potentiometer
2295
2298
 
2296
2299
  See: https://www.industrialcontrolsonline.com/honeywell-t991a
2297
2300
  - modulates air temperatures in ducts
2298
-
2299
- case 0x31E0: ' 12768:
2300
- {
2301
- string str4;
2302
- unchecked
2303
- {
2304
- result.Fan = Conversions.ToString((double)(int)data[checked(start + 1)] / 2.0);
2305
- str4 = "";
2306
- }
2307
- str4 = (data[start + 2] & 0xF) switch
2308
- {
2309
- 0 => str4 + "0 = min. potm. ",
2310
- 1 => str4 + "0 = min. van min. potm ",
2311
- 2 => str4 + "0 = min. fan ",
2312
- _ => "",
2313
- };
2314
- switch (data[start + 2] & 0xF0)
2315
- {
2316
- case 16:
2317
- str4 += "100 = max. potm";
2318
- break;
2319
- case 32:
2320
- str4 += "100 = max. van max. potm ";
2321
- break;
2322
- case 48:
2323
- str4 += "100 = max. fan ";
2324
- break;
2325
- }
2326
- result.Data = str4;
2327
- break;
2328
- }
2329
2301
  """
2330
2302
 
2303
+ # coding note:
2304
+ # case 0x31E0: ' 12768:
2305
+ # {
2306
+ # string str4;
2307
+ # unchecked
2308
+ # {
2309
+ # result.Fan = Conversions.ToString((double)(int)data[checked(start + 1)] / 2.0);
2310
+ # str4 = "";
2311
+ # }
2312
+ # str4 = (data[start + 2] & 0xF) switch
2313
+ # {
2314
+ # 0 => str4 + "0 = min. potm. ",
2315
+ # 1 => str4 + "0 = min. van min. potm ",
2316
+ # 2 => str4 + "0 = min. fan ",
2317
+ # _ => "",
2318
+ # };
2319
+ # switch (data[start + 2] & 0xF0)
2320
+ # {
2321
+ # case 16:
2322
+ # str4 += "100 = max. potm";
2323
+ # break;
2324
+ # case 32:
2325
+ # str4 += "100 = max. van max. potm ";
2326
+ # break;
2327
+ # case 48:
2328
+ # str4 += "100 = max. fan ";
2329
+ # break;
2330
+ # }
2331
+ # result.Data = str4;
2332
+ # break;
2333
+ # }
2334
+
2331
2335
  # .I --- 37:005302 32:132403 --:------ 31E0 008 00-0000-00 01-0064-00 # RF15 CO2 to Orcon HRC400 series SmartComfort Valve
2332
2336
 
2333
2337
  # .I --- 29:146052 32:023459 --:------ 31E0 003 00-0000
ramses_tx/schemas.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """RAMSES RF - a RAMSES-II protocol decoder & analyser.
3
3
 
4
- Schema processor for protocol (lower) layer.
4
+ :term:`Schema` processor for protocol (lower) layer.
5
5
  """
6
6
 
7
7
  from __future__ import annotations
@@ -73,13 +73,17 @@ class PktLogConfigT(TypedDict):
73
73
  def sch_packet_log_dict_factory(
74
74
  default_backups: int = 0,
75
75
  ) -> dict[vol.Required, vol.Any]:
76
- """Return a packet log dict with a configurable default rotation policy.
76
+ """
77
+ :return: a packet log dict with a configurable default rotation policy.
77
78
 
78
- usage:
79
+ Usage:
80
+
81
+ .. code-block::
82
+
83
+ SCH_PACKET_LOG_7 = vol.Schema(
84
+ packet_log_dict_factory(default_backups=7), extra=vol.PREVENT_EXTRA
85
+ )
79
86
 
80
- SCH_PACKET_LOG_7 = vol.Schema(
81
- packet_log_dict_factory(default_backups=7), extra=vol.PREVENT_EXTRA
82
- )
83
87
  """
84
88
 
85
89
  SCH_PACKET_LOG_CONFIG = vol.Schema(
@@ -162,11 +166,13 @@ class PortConfigT(TypedDict):
162
166
  def sch_serial_port_dict_factory() -> dict[vol.Required, vol.Any]:
163
167
  """Return a serial port dict.
164
168
 
165
- usage:
169
+ Usage:
166
170
 
167
- SCH_SERIAL_PORT = vol.Schema(
168
- sch_serial_port_dict_factory(), extra=vol.PREVENT_EXTRA
169
- )
171
+ .. code-block::
172
+
173
+ SCH_SERIAL_PORT = vol.Schema(
174
+ sch_serial_port_dict_factory(), extra=vol.PREVENT_EXTRA
175
+ )
170
176
  """
171
177
 
172
178
  SCH_SERIAL_PORT_NAME = str
@@ -252,11 +258,13 @@ def sch_global_traits_dict_factory(
252
258
  ) -> tuple[dict[vol.Optional, vol.Any], vol.Any]:
253
259
  """Return a global traits dict with a configurable extra traits.
254
260
 
255
- usage:
261
+ Usage:
256
262
 
257
- SCH_GLOBAL_TRAITS = vol.Schema(
258
- sch_global_traits_dict(heat=traits), extra=vol.PREVENT_EXTRA
259
- )
263
+ .. code-block::
264
+
265
+ SCH_GLOBAL_TRAITS = vol.Schema(
266
+ sch_global_traits_dict(heat=traits), extra=vol.PREVENT_EXTRA
267
+ )
260
268
  """
261
269
 
262
270
  heat_traits = heat_traits or {}
@@ -348,7 +356,8 @@ def select_device_filter_mode(
348
356
  known_list: DeviceListT,
349
357
  block_list: DeviceListT,
350
358
  ) -> bool:
351
- """Determine which device filter to use, if any.
359
+ """
360
+ Determine which device filter to use, if any.
352
361
 
353
362
  Either:
354
363
  - block if device_id in block_list (could be empty), otherwise
@@ -404,6 +413,7 @@ SZ_EVOFW_FLAG: Final = "evofw_flag"
404
413
  SZ_SQLITE_INDEX: Final = (
405
414
  "sqlite_index" # temporary 0.52.x SQLite dev config option in ramses_cc
406
415
  )
416
+ SZ_LOG_ALL_MQTT: Final = "log_all_mqtt"
407
417
  SZ_USE_REGEX: Final = "use_regex"
408
418
 
409
419
  SCH_ENGINE_DICT = {
@@ -418,6 +428,9 @@ SCH_ENGINE_DICT = {
418
428
  vol.Optional(
419
429
  SZ_SQLITE_INDEX, default=False
420
430
  ): bool, # temporary 0.52.x dev config option
431
+ vol.Optional(
432
+ SZ_LOG_ALL_MQTT, default=False
433
+ ): bool, # log all incoming MQTT traffic config option
421
434
  vol.Optional(SZ_USE_REGEX): dict, # vol.All(ConvertNullToDict(), dict),
422
435
  vol.Optional(SZ_COMMS_PARAMS): SCH_COMMS_PARAMS,
423
436
  }
ramses_tx/transport.py CHANGED
@@ -3,30 +3,38 @@
3
3
 
4
4
  Operates at the pkt layer of: app - msg - pkt - h/w
5
5
 
6
- For ser2net, use the following YAML with: ser2net -c misc/ser2net.yaml
7
- connection: &con00
8
- accepter: telnet(rfc2217),tcp,5001
9
- timeout: 0
10
- connector: serialdev,/dev/ttyUSB0,115200n81,local
11
- options:
12
- max-connections: 3
13
-
14
- For socat, see:
15
- socat -dd pty,raw,echo=0 pty,raw,echo=0
16
- python client.py monitor /dev/pts/0
17
- cat packet.log | cut -d ' ' -f 2- | unix2dos > /dev/pts/1
6
+ For ser2net, use the following YAML with: ``ser2net -c misc/ser2net.yaml``
7
+
8
+ .. code-block::
9
+
10
+ connection: &con00
11
+ accepter: telnet(rfc2217),tcp,5001
12
+ timeout: 0
13
+ connector: serialdev,/dev/ttyUSB0,115200n81,local
14
+ options:
15
+ max-connections: 3
16
+
17
+ For ``socat``, see:
18
+
19
+ .. code-block::
20
+
21
+ socat -dd pty,raw,echo=0 pty,raw,echo=0
22
+ python client.py monitor /dev/pts/0
23
+ cat packet.log | cut -d ' ' -f 2- | unix2dos > /dev/pts/1
18
24
 
19
25
  For re-flashing evofw3 via Arduino IDE on *my* atmega328p (YMMV):
20
- - Board: atmega328p (SW UART)
21
- - Bootloader: Old Bootloader
22
- - Processor: atmega328p (5V, 16 MHz)
23
- - Host: 57600 (or 115200, YMMV)
24
- - Pinout: Nano
26
+
27
+ - Board: atmega328p (SW UART)
28
+ - Bootloader: Old Bootloader
29
+ - Processor: atmega328p (5V, 16 MHz)
30
+ - Host: 57600 (or 115200, YMMV)
31
+ - Pinout: Nano
25
32
 
26
33
  For re-flashing evofw3 via Arduino IDE on *my* atmega32u4 (YMMV):
27
- - Board: atmega32u4 (HW UART)
28
- - Processor: atmega32u4 (5V, 16 MHz)
29
- - Pinout: Pro Micro
34
+
35
+ - Board: atmega32u4 (HW UART)
36
+ - Processor: atmega32u4 (5V, 16 MHz)
37
+ - Pinout: Pro Micro
30
38
  """
31
39
 
32
40
  from __future__ import annotations
@@ -250,11 +258,12 @@ async def is_hgi80(serial_port: SerPortNameT) -> bool | None:
250
258
 
251
259
 
252
260
  def _normalise(pkt_line: str) -> str:
253
- """Perform any (transparent) frame-level hacks, as required at (near-)RF layer.
261
+ """
262
+ Perform any (transparent) frame-level hacks, as required at (near-)RF layer.
254
263
 
255
264
  Goals:
256
265
  - ensure an evofw3 provides the same output as a HGI80 (none, presently)
257
- - handle 'strange' packets (e.g. I|08:|0008)
266
+ - handle 'strange' packets (e.g. ``I|08:|0008``)
258
267
  """
259
268
 
260
269
  # TODO: deprecate as only for ramses_esp <0.4.0
@@ -1015,6 +1024,7 @@ class PortTransport(_RegHackMixin, _FullTransport, _PortTransportAbstractor): #
1015
1024
 
1016
1025
  class MqttTransport(_FullTransport, _MqttTransportAbstractor):
1017
1026
  """Send/receive packets to/from ramses_esp via MQTT.
1027
+ For full RX logging, turn on debug logging.
1018
1028
 
1019
1029
  See: https://github.com/IndaloTech/ramses_esp
1020
1030
  """
@@ -1057,6 +1067,9 @@ class MqttTransport(_FullTransport, _MqttTransportAbstractor):
1057
1067
  self._max_tokens: float = self._MAX_TOKENS * 2 # allow for the initial burst
1058
1068
  self._num_tokens: float = self._MAX_TOKENS * 2
1059
1069
 
1070
+ # set log MQTT flag
1071
+ self._log_all = kwargs.pop("log_all", False)
1072
+
1060
1073
  # instantiate a paho mqtt client
1061
1074
  self.client = mqtt.Client(
1062
1075
  protocol=mqtt.MQTTv5, callback_api_version=CallbackAPIVersion.VERSION2
@@ -1274,8 +1287,9 @@ class MqttTransport(_FullTransport, _MqttTransportAbstractor):
1274
1287
 
1275
1288
  if _DBG_FORCE_FRAME_LOGGING:
1276
1289
  _LOGGER.warning("Rx: %s", msg.payload)
1277
- elif _LOGGER.getEffectiveLevel() == logging.INFO: # log for INFO not DEBUG
1278
- _LOGGER.info("Rx: %s", msg.payload)
1290
+ elif self._log_all and _LOGGER.getEffectiveLevel() == logging.INFO:
1291
+ # log for INFO not DEBUG
1292
+ _LOGGER.info("mq Rx: %s", msg.payload) # TODO remove mq marker?
1279
1293
 
1280
1294
  if msg.topic[-3:] != "/rx": # then, e.g. 'RAMSES/GATEWAY/18:017804'
1281
1295
  if msg.payload == b"offline":
@@ -1498,6 +1512,7 @@ async def transport_factory(
1498
1512
  disable_sending: bool | None = False,
1499
1513
  extra: dict[str, Any] | None = None,
1500
1514
  loop: asyncio.AbstractEventLoop | None = None,
1515
+ log_all: bool = False,
1501
1516
  **kwargs: Any, # HACK: odd/misc params
1502
1517
  ) -> RamsesTransportT:
1503
1518
  """Create and return a Ramses-specific async packet Transport."""
@@ -1549,19 +1564,24 @@ async def transport_factory(
1549
1564
  "Packet source must be exactly one of: packet_dict, packet_log, port_name"
1550
1565
  )
1551
1566
 
1567
+ # File
1552
1568
  if (pkt_source := packet_log or packet_dict) is not None:
1553
1569
  return FileTransport(pkt_source, protocol, extra=extra, loop=loop, **kwargs)
1554
1570
 
1555
1571
  assert port_name is not None # mypy check
1556
1572
  assert port_config is not None # mypy check
1557
1573
 
1574
+ # MQTT
1558
1575
  if port_name[:4] == "mqtt": # TODO: handle disable_sending
1559
- transport = MqttTransport(port_name, protocol, extra=extra, loop=loop, **kwargs)
1576
+ transport = MqttTransport(
1577
+ port_name, protocol, extra=extra, loop=loop, log_all=log_all, **kwargs
1578
+ )
1560
1579
 
1561
1580
  # TODO: remove this? better to invoke timeout after factory returns?
1562
1581
  await protocol.wait_for_connection_made(timeout=_DEFAULT_TIMEOUT_MQTT)
1563
1582
  return transport
1564
1583
 
1584
+ # Serial
1565
1585
  ser_instance = get_serial_instance(port_name, port_config)
1566
1586
 
1567
1587
  if os.name == "nt" or ser_instance.portstr[:7] in ("rfc2217", "socket:"):
ramses_tx/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """RAMSES RF - a RAMSES-II protocol decoder & analyser (transport layer)."""
2
2
 
3
- __version__ = "0.52.1"
3
+ __version__ = "0.52.3"
4
4
  VERSION = __version__