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_rf/__init__.py +1 -0
- ramses_rf/binding_fsm.py +18 -4
- ramses_rf/database.py +57 -39
- ramses_rf/device/heat.py +4 -6
- ramses_rf/device/hvac.py +116 -56
- ramses_rf/dispatcher.py +9 -4
- ramses_rf/entity_base.py +133 -66
- ramses_rf/gateway.py +2 -2
- ramses_rf/schemas.py +1 -1
- ramses_rf/system/zones.py +1 -1
- ramses_rf/version.py +1 -1
- {ramses_rf-0.52.1.dist-info → ramses_rf-0.52.3.dist-info}/METADATA +1 -1
- {ramses_rf-0.52.1.dist-info → ramses_rf-0.52.3.dist-info}/RECORD +24 -24
- ramses_tx/__init__.py +3 -1
- ramses_tx/command.py +6 -5
- ramses_tx/gateway.py +3 -0
- ramses_tx/logger.py +8 -0
- ramses_tx/parsers.py +41 -37
- ramses_tx/schemas.py +28 -15
- ramses_tx/transport.py +45 -25
- ramses_tx/version.py +1 -1
- {ramses_rf-0.52.1.dist-info → ramses_rf-0.52.3.dist-info}/WHEEL +0 -0
- {ramses_rf-0.52.1.dist-info → ramses_rf-0.52.3.dist-info}/entry_points.txt +0 -0
- {ramses_rf-0.52.1.dist-info → ramses_rf-0.52.3.dist-info}/licenses/LICENSE +0 -0
ramses_rf/__init__.py
CHANGED
ramses_rf/binding_fsm.py
CHANGED
|
@@ -178,6 +178,8 @@ class BindContextBase:
|
|
|
178
178
|
self, state: type[BindStateBase], result: asyncio.Future[Message] | None = None
|
|
179
179
|
) -> None:
|
|
180
180
|
"""Transition the State of the Context, and process the result, if any."""
|
|
181
|
+
# Ensure prev_state is always available, not only during debugging
|
|
182
|
+
prev_state = self._state
|
|
181
183
|
|
|
182
184
|
# if False and result:
|
|
183
185
|
# try:
|
|
@@ -185,10 +187,6 @@ class BindContextBase:
|
|
|
185
187
|
# except exc.BindingError as err:
|
|
186
188
|
# self._fut.set_result(err)
|
|
187
189
|
|
|
188
|
-
if _DBG_MAINTAIN_STATE_CHAIN: # HACK for debugging
|
|
189
|
-
# if prev_state in (None, )
|
|
190
|
-
prev_state = self._state
|
|
191
|
-
|
|
192
190
|
self._state = state(self)
|
|
193
191
|
if not self.is_binding:
|
|
194
192
|
self._is_respondent = None
|
|
@@ -197,6 +195,14 @@ class BindContextBase:
|
|
|
197
195
|
elif state is SuppSendOfferWaitForAccept:
|
|
198
196
|
self._is_respondent = False
|
|
199
197
|
|
|
198
|
+
# Log binding completion transitions
|
|
199
|
+
if isinstance(
|
|
200
|
+
self._state, (RespHasBoundAsRespondent, SuppHasBoundAsSupplicant)
|
|
201
|
+
):
|
|
202
|
+
_LOGGER.info(
|
|
203
|
+
f"{self._dev.id}: Binding process completed: {type(prev_state).__name__} -> {state.__name__} (role: {self.role})"
|
|
204
|
+
)
|
|
205
|
+
|
|
200
206
|
if _DBG_MAINTAIN_STATE_CHAIN: # HACK for debugging
|
|
201
207
|
setattr(self._state, "_prev_state", prev_state) # noqa: B010
|
|
202
208
|
|
|
@@ -663,6 +669,10 @@ class RespHasBoundAsRespondent(BindStateBase):
|
|
|
663
669
|
|
|
664
670
|
_attr_role = BindRole.IS_DORMANT
|
|
665
671
|
|
|
672
|
+
def __init__(self, context: BindContextBase) -> None:
|
|
673
|
+
super().__init__(context)
|
|
674
|
+
_LOGGER.info(f"{context._dev.id}: Binding completed as respondent")
|
|
675
|
+
|
|
666
676
|
|
|
667
677
|
class RespIsWaitingForAddenda(_DevIsWaitingForMsg, BindStateBase):
|
|
668
678
|
"""Respondent has received a Confirm & is waiting for an Addenda."""
|
|
@@ -715,6 +725,10 @@ class SuppHasBoundAsSupplicant(BindStateBase):
|
|
|
715
725
|
|
|
716
726
|
_attr_role = BindRole.IS_DORMANT
|
|
717
727
|
|
|
728
|
+
def __init__(self, context: BindContextBase) -> None:
|
|
729
|
+
super().__init__(context)
|
|
730
|
+
_LOGGER.info(f"{context._dev.id}: Binding completed as supplicant")
|
|
731
|
+
|
|
718
732
|
|
|
719
733
|
class SuppIsReadyToSendAddenda(
|
|
720
734
|
_DevIsReadyToSendCmd, BindStateBase
|
ramses_rf/database.py
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""
|
|
3
|
+
RAMSES RF - Message database and index.
|
|
4
|
+
|
|
5
|
+
.. table:: Database Query Methods[^1][#fn1]
|
|
6
|
+
:widths: auto
|
|
7
|
+
|
|
8
|
+
===== ============ =========== ========== ==== ========================
|
|
9
|
+
ix method name args returns uses used by
|
|
10
|
+
===== ============ =========== ========== ==== ========================
|
|
11
|
+
i1 get Msg, kwargs tuple(Msg) i3
|
|
12
|
+
i2 contains kwargs bool i4
|
|
13
|
+
i3 _select_from kwargs tuple(Msg) i4
|
|
14
|
+
i4 qry_dtms kwargs list(dtm)
|
|
15
|
+
i5 qry sql, kwargs tuple(Msg) _msgs()
|
|
16
|
+
i6 qry_field sql, kwargs tuple(fld) e4, e5
|
|
17
|
+
i7 get_rp_codes src, dst list(Code) Discovery-supported_cmds
|
|
18
|
+
===== ============ =========== ========== ==== ========================
|
|
19
|
+
|
|
20
|
+
[#fn1] A word of explanation.
|
|
21
|
+
[^1]: ex = entity_base.py query methods
|
|
22
|
+
"""
|
|
3
23
|
|
|
4
24
|
from __future__ import annotations
|
|
5
25
|
|
|
@@ -62,9 +82,10 @@ def payload_keys(parsed_payload: list[dict] | dict) -> str: # type: ignore[type
|
|
|
62
82
|
|
|
63
83
|
|
|
64
84
|
class MessageIndex:
|
|
65
|
-
"""A
|
|
66
|
-
Index holds the latest
|
|
67
|
-
(
|
|
85
|
+
"""A central in-memory SQLite3 database for indexing RF messages.
|
|
86
|
+
Index holds all the latest messages to & from all devices by `dtm`
|
|
87
|
+
(timestamp) and `hdr` header
|
|
88
|
+
(example of a hdr: ``000C|RP|01:223036|0208``)."""
|
|
68
89
|
|
|
69
90
|
_housekeeping_task: asyncio.Task[None]
|
|
70
91
|
|
|
@@ -72,7 +93,8 @@ class MessageIndex:
|
|
|
72
93
|
"""Instantiate a message database/index."""
|
|
73
94
|
|
|
74
95
|
self.maintain = maintain
|
|
75
|
-
self._msgs: MsgDdT = OrderedDict() # stores all messages for retrieval.
|
|
96
|
+
self._msgs: MsgDdT = OrderedDict() # stores all messages for retrieval.
|
|
97
|
+
# Filled & cleaned up in housekeeping_loop.
|
|
76
98
|
|
|
77
99
|
# Connect to a SQLite DB in memory
|
|
78
100
|
self._cx = sqlite3.connect(
|
|
@@ -122,16 +144,17 @@ class MessageIndex:
|
|
|
122
144
|
def _setup_db_schema(self) -> None:
|
|
123
145
|
"""Set up the message database schema.
|
|
124
146
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
147
|
+
.. note::
|
|
148
|
+
messages TABLE Fields:
|
|
149
|
+
|
|
150
|
+
- dtm message timestamp
|
|
151
|
+
- verb " I", "RQ" etc.
|
|
152
|
+
- src message origin address
|
|
153
|
+
- dst message destination address
|
|
154
|
+
- code packet code aka command class e.g. _0005, _31DA
|
|
155
|
+
- ctx message context, created from payload as index + extra markers (Heat)
|
|
156
|
+
- hdr packet header e.g. 000C|RP|01:223036|0208 (see: src/ramses_tx/frame.py)
|
|
157
|
+
- plk the keys stored in the parsed payload, separated by the | char
|
|
135
158
|
"""
|
|
136
159
|
|
|
137
160
|
self._cu.execute(
|
|
@@ -160,7 +183,7 @@ class MessageIndex:
|
|
|
160
183
|
|
|
161
184
|
async def _housekeeping_loop(self) -> None:
|
|
162
185
|
"""Periodically remove stale messages from the index,
|
|
163
|
-
unless self.maintain is False."""
|
|
186
|
+
unless `self.maintain` is False."""
|
|
164
187
|
|
|
165
188
|
async def housekeeping(dt_now: dt, _cutoff: td = td(days=1)) -> None:
|
|
166
189
|
"""
|
|
@@ -196,6 +219,7 @@ class MessageIndex:
|
|
|
196
219
|
"""
|
|
197
220
|
Add a single message to the MessageIndex.
|
|
198
221
|
Logs a warning if there is a duplicate dtm.
|
|
222
|
+
|
|
199
223
|
:returns: any message that was removed because it had the same header
|
|
200
224
|
"""
|
|
201
225
|
# TODO: eventually, may be better to use SqlAlchemy
|
|
@@ -239,7 +263,11 @@ class MessageIndex:
|
|
|
239
263
|
|
|
240
264
|
def add_record(self, src: str, code: str = "", verb: str = "") -> None:
|
|
241
265
|
"""
|
|
242
|
-
Add a single record to the MessageIndex with timestamp now() and no Message contents.
|
|
266
|
+
Add a single record to the MessageIndex with timestamp `now()` and no Message contents.
|
|
267
|
+
|
|
268
|
+
:param src: device id to use as source address
|
|
269
|
+
:param code: device id to use as destination address (can be identical)
|
|
270
|
+
:param verb: two letter verb str to use
|
|
243
271
|
"""
|
|
244
272
|
# Used by OtbGateway init, via entity_base.py
|
|
245
273
|
dtm: DtmStrT = dt.strftime(dt.now(), "%Y-%m-%dT%H:%M:%S") # type: ignore[assignment]
|
|
@@ -274,6 +302,7 @@ class MessageIndex:
|
|
|
274
302
|
def _insert_into(self, msg: Message) -> Message | None:
|
|
275
303
|
"""
|
|
276
304
|
Insert a message into the index.
|
|
305
|
+
|
|
277
306
|
:returns: any message replaced (by same hdr)
|
|
278
307
|
"""
|
|
279
308
|
assert msg._pkt._hdr is not None, "Skipping: Packet has no hdr: {msg._pkt}"
|
|
@@ -305,7 +334,7 @@ class MessageIndex:
|
|
|
305
334
|
payload_keys(msg.payload),
|
|
306
335
|
),
|
|
307
336
|
)
|
|
308
|
-
_LOGGER.debug(f"Added {msg} to gwy.msg_db")
|
|
337
|
+
# _LOGGER.debug(f"Added {msg} to gwy.msg_db")
|
|
309
338
|
|
|
310
339
|
return _old_msgs[0] if _old_msgs else None
|
|
311
340
|
|
|
@@ -348,6 +377,7 @@ class MessageIndex:
|
|
|
348
377
|
|
|
349
378
|
def _delete_from(self, **kwargs: bool | dt | str) -> tuple[Message, ...]:
|
|
350
379
|
"""Remove message(s) from the index.
|
|
380
|
+
|
|
351
381
|
:returns: any messages that were removed"""
|
|
352
382
|
|
|
353
383
|
msgs = self._select_from(**kwargs)
|
|
@@ -359,32 +389,14 @@ class MessageIndex:
|
|
|
359
389
|
|
|
360
390
|
return msgs
|
|
361
391
|
|
|
362
|
-
# MessageIndex msg_db query methods
|
|
363
|
-
# (ex = entity_base.py query methods
|
|
364
|
-
#
|
|
365
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
366
|
-
# | ix |method name | args | returns | uses | used by |
|
|
367
|
-
# +====+==============+=============+============+======+==========================+
|
|
368
|
-
# | i1 | get | Msg/kwargs | tuple[Msg] | i3 | |
|
|
369
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
370
|
-
# | i2 | contains | kwargs | bool | i4 | |
|
|
371
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
372
|
-
# | i3 | _select_from | kwargs | tuple[Msg] | i4 | |
|
|
373
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
374
|
-
# | i4 | qry_dtms | kwargs | list(dtm) | | |
|
|
375
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
376
|
-
# | i5 | qry | sql, kwargs | tuple[Msg] | | _msgs() |
|
|
377
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
378
|
-
# | i6 | qry_field | sql, kwargs | tuple[fld] | | e4, e5 |
|
|
379
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
380
|
-
# | i7 | get_rp_codes | src, dst | list[Code] | | Discovery#supported_cmds |
|
|
381
|
-
# +----+--------------+-------------+------------+------+--------------------------+
|
|
392
|
+
# MessageIndex msg_db query methods
|
|
382
393
|
|
|
383
394
|
def get(
|
|
384
395
|
self, msg: Message | None = None, **kwargs: bool | dt | str
|
|
385
396
|
) -> tuple[Message, ...]:
|
|
386
397
|
"""
|
|
387
398
|
Public method to get a set of message(s) from the index.
|
|
399
|
+
|
|
388
400
|
:param msg: Message to return, by dtm (expect a single result as dtm is unique key)
|
|
389
401
|
:param kwargs: data table field names and criteria, e.g. (hdr=...)
|
|
390
402
|
:return: tuple of matching Messages
|
|
@@ -401,6 +413,7 @@ class MessageIndex:
|
|
|
401
413
|
def contains(self, **kwargs: bool | dt | str) -> bool:
|
|
402
414
|
"""
|
|
403
415
|
Check if the MessageIndex contains at least 1 record that matches the provided fields.
|
|
416
|
+
|
|
404
417
|
:param kwargs: (exact) SQLite table field_name: required_value pairs
|
|
405
418
|
:return: True if at least one message fitting the given conditions is present, False when qry returned empty
|
|
406
419
|
"""
|
|
@@ -410,6 +423,7 @@ class MessageIndex:
|
|
|
410
423
|
def _select_from(self, **kwargs: bool | dt | str) -> tuple[Message, ...]:
|
|
411
424
|
"""
|
|
412
425
|
Select message(s) using the MessageIndex.
|
|
426
|
+
|
|
413
427
|
:param kwargs: (exact) SQLite table field_name: required_value pairs
|
|
414
428
|
:returns: a tuple of qualifying messages
|
|
415
429
|
"""
|
|
@@ -421,7 +435,8 @@ class MessageIndex:
|
|
|
421
435
|
|
|
422
436
|
def qry_dtms(self, **kwargs: bool | dt | str) -> list[Any]:
|
|
423
437
|
"""
|
|
424
|
-
Select from the
|
|
438
|
+
Select from the MessageIndex a list of dtms that match the provided arguments.
|
|
439
|
+
|
|
425
440
|
:param kwargs: data table field names and criteria
|
|
426
441
|
:return: list of unformatted dtms that match, useful for msg lookup, or an empty list if 0 matches
|
|
427
442
|
"""
|
|
@@ -444,6 +459,7 @@ class MessageIndex:
|
|
|
444
459
|
def qry(self, sql: str, parameters: tuple[str, ...]) -> tuple[Message, ...]:
|
|
445
460
|
"""
|
|
446
461
|
Get a tuple of messages from _msgs using the index, given sql and parameters.
|
|
462
|
+
|
|
447
463
|
:param sql: a bespoke SQL query SELECT string that should return dtm as first field
|
|
448
464
|
:param parameters: tuple of kwargs with the selection filter
|
|
449
465
|
:return: a tuple of qualifying messages
|
|
@@ -474,6 +490,7 @@ class MessageIndex:
|
|
|
474
490
|
def get_rp_codes(self, parameters: tuple[str, ...]) -> list[Code]:
|
|
475
491
|
"""
|
|
476
492
|
Get a list of Codes from the index, given parameters.
|
|
493
|
+
|
|
477
494
|
:param parameters: tuple of additional kwargs
|
|
478
495
|
:return: list of Code: value pairs
|
|
479
496
|
"""
|
|
@@ -499,6 +516,7 @@ class MessageIndex:
|
|
|
499
516
|
) -> list[tuple[dt | str, str]]:
|
|
500
517
|
"""
|
|
501
518
|
Get a list of fields from the index, given select sql and parameters.
|
|
519
|
+
|
|
502
520
|
:param sql: a bespoke SQL query SELECT string
|
|
503
521
|
:param parameters: tuple of additional kwargs
|
|
504
522
|
:return: list of key: value pairs as defined in sql
|
ramses_rf/device/heat.py
CHANGED
|
@@ -120,7 +120,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
120
120
|
|
|
121
121
|
class Actuator(DeviceHeat): # 3EF0, 3EF1 (for 10:/13:)
|
|
122
122
|
# .I --- 13:109598 --:------ 13:109598 3EF0 003 00C8FF # event-driven, 00/C8
|
|
123
|
-
# RP --- 13:109598 18:002563 --:------ 0008 002 00C8 # 00/C8, as
|
|
123
|
+
# RP --- 13:109598 18:002563 --:------ 0008 002 00C8 # 00/C8, as above
|
|
124
124
|
# RP --- 13:109598 18:002563 --:------ 3EF1 007 0000BF-00BFC8FF # 00/C8, as above
|
|
125
125
|
|
|
126
126
|
# RP --- 10:048122 18:140805 --:------ 3EF1 007 007FFF-003C2A10 # 10:s only RP, always 7FFF
|
|
@@ -668,11 +668,8 @@ class OtbGateway(Actuator, HeatDemand): # OTB (10): 3220 (22D9, others)
|
|
|
668
668
|
self._child_id = FC # NOTE: domain_id
|
|
669
669
|
|
|
670
670
|
# TODO(eb): cleanup
|
|
671
|
-
# should fix src/ramses_rf/database.py _add_record try/except when activating next line
|
|
672
671
|
if self._gwy.msg_db:
|
|
673
|
-
self._add_record(
|
|
674
|
-
address=self.addr, code=Code._3220, verb="RP"
|
|
675
|
-
) # << essential?
|
|
672
|
+
self._add_record(address=self.addr, code=Code._3220, verb="RP")
|
|
676
673
|
# adds a "sim" RP opentherm_msg to the SQLite MessageIndex with code _3220
|
|
677
674
|
# causes exc when fetching ALL, when no "real" msg was added to _msgs_. We skip those.
|
|
678
675
|
else:
|
|
@@ -1263,6 +1260,7 @@ class BdrSwitch(Actuator, RelayDemand): # BDR (13):
|
|
|
1263
1260
|
"""The BDR class, such as a BDR91.
|
|
1264
1261
|
|
|
1265
1262
|
BDR91s can be used in six distinct modes, including:
|
|
1263
|
+
|
|
1266
1264
|
- x2 boiler controller (FC/TPI): either traditional, or newer heat pump-aware
|
|
1267
1265
|
- x1 electric heat zones (0x/ELE)
|
|
1268
1266
|
- x1 zone valve zones (0x/VAL)
|
|
@@ -1410,7 +1408,7 @@ class UfhCircuit(Child, Entity): # FIXME
|
|
|
1410
1408
|
def __init__(self, ufc: UfhController, ufh_idx: str) -> None:
|
|
1411
1409
|
super().__init__(ufc._gwy)
|
|
1412
1410
|
|
|
1413
|
-
# FIXME:
|
|
1411
|
+
# FIXME: gwy.msg_db entities must know their parent device ID and their own idx
|
|
1414
1412
|
self._z_id = ufc.id
|
|
1415
1413
|
self._z_idx = ufh_idx
|
|
1416
1414
|
|
ramses_rf/device/hvac.py
CHANGED
|
@@ -728,12 +728,15 @@ class HvacVentilator(FilterChange): # FAN: RP/31DA, I/31D[9A], 2411
|
|
|
728
728
|
In HomeAssistant, ramses_cc, you can set a bound device in the device configuration.
|
|
729
729
|
|
|
730
730
|
System schema and known devices example:
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
731
|
+
|
|
732
|
+
.. code-block::
|
|
733
|
+
|
|
734
|
+
"32:153289":
|
|
735
|
+
bound: "37:168270"
|
|
736
|
+
class: FAN
|
|
737
|
+
"37:168270":
|
|
738
|
+
class: REM
|
|
739
|
+
faked: true
|
|
737
740
|
|
|
738
741
|
:param device_id: The unique identifier of the device to bind
|
|
739
742
|
:type device_id: str
|
|
@@ -1142,7 +1145,7 @@ def class_dev_hvac(
|
|
|
1142
1145
|
) -> type[DeviceHvac]:
|
|
1143
1146
|
"""Return a device class, but only if the device must be from the HVAC group.
|
|
1144
1147
|
|
|
1145
|
-
May return a base
|
|
1148
|
+
May return a base class, `DeviceHvac`, which will need promotion.
|
|
1146
1149
|
"""
|
|
1147
1150
|
|
|
1148
1151
|
if not eavesdrop:
|
|
@@ -1206,54 +1209,111 @@ _REMOTES = {
|
|
|
1206
1209
|
# see: https://github.com/arjenhiemstra/ithowifi/blob/master/software/NRG_itho_wifi/src/IthoPacket.h
|
|
1207
1210
|
|
|
1208
1211
|
"""
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
"
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
"
|
|
1224
|
-
"
|
|
1225
|
-
"
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
"
|
|
1246
|
-
"
|
|
1247
|
-
"
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
"
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1212
|
+
Itho Remote (model) enums.
|
|
1213
|
+
|
|
1214
|
+
CVE/HRU remote (536-0124) RFT W: 3 modes, timer
|
|
1215
|
+
-------------------------------------------------
|
|
1216
|
+
|
|
1217
|
+
.. table:: 536-0124
|
|
1218
|
+
:widths: auto
|
|
1219
|
+
|
|
1220
|
+
=========== ========================= ================================================
|
|
1221
|
+
"away": (Code._22F1, 00, 01|04"), how to invoke?
|
|
1222
|
+
"low": (Code._22F1, 00, 02|04"), aka eco
|
|
1223
|
+
"medium": (Code._22F1, 00, 03|04"), aka auto (with sensors) - is that only for 63?
|
|
1224
|
+
"high": (Code._22F1, 00, 04|04"), aka full
|
|
1225
|
+
|
|
1226
|
+
"timer_1": (Code._22F3, 00, 00|0A"), 10 minutes full speed
|
|
1227
|
+
"timer_2": (Code._22F3, 00, 00|14"), 20 minutes full speed
|
|
1228
|
+
"timer_3": (Code._22F3, 00, 00|1E"), 30 minutes full speed
|
|
1229
|
+
=========== ========================= ================================================
|
|
1230
|
+
|
|
1231
|
+
RFT-AUTO (536-0150) RFT CAR: 2 modes, auto, timer: idx = 63, essentially same as above, but also...
|
|
1232
|
+
-----------------------------------------------------------------------------------------------------
|
|
1233
|
+
|
|
1234
|
+
.. table:: 536-0150
|
|
1235
|
+
:widths: auto
|
|
1236
|
+
|
|
1237
|
+
============= ========================= ================================================
|
|
1238
|
+
"auto_night": (Code._22F8, 63, 02|03"), additional - press auto x2
|
|
1239
|
+
============= ========================= ================================================
|
|
1240
|
+
|
|
1241
|
+
RFT-RV (04-00046), RFT-CO2 (04-00045) - sensors with control
|
|
1242
|
+
------------------------------------------------------------
|
|
1243
|
+
|
|
1244
|
+
.. table:: 04-00046
|
|
1245
|
+
:widths: auto
|
|
1246
|
+
|
|
1247
|
+
============== ======================================== =============
|
|
1248
|
+
"medium": (Code._22F1, 00, 03|07"), 1=away, 2=low?
|
|
1249
|
+
"auto": (Code._22F1, 00, 05|07"), 4=high
|
|
1250
|
+
"auto_night": (Code._22F1, 00, 0B|0B"),
|
|
1251
|
+
|
|
1252
|
+
"timer_1": (Code._22F3, 00, 00|0A, 00|00, 0000"), 10 minutes
|
|
1253
|
+
"timer_2": (Code._22F3, 00, 00|14, 00|00, 0000"), 20 minutes
|
|
1254
|
+
"timer_3": (Code._22F3, 00, 00|1E, 00|00, 0000"), 30 minutes
|
|
1255
|
+
============== ======================================== =============
|
|
1256
|
+
|
|
1257
|
+
RFT-PIR (545-7550) - presence sensor
|
|
1258
|
+
------------------------------------
|
|
1259
|
+
|
|
1260
|
+
RFT_DF: DemandFlow remote (536-0146)
|
|
1261
|
+
------------------------------------
|
|
1262
|
+
|
|
1263
|
+
.. table:: 536-0146
|
|
1264
|
+
:widths: auto
|
|
1265
|
+
|
|
1266
|
+
=========== ================================ =========================================
|
|
1267
|
+
"timer_1": (Code._22F3, 00, 42|03, 03|03"), 0b01-000-010 = 3 hrs, back to last mode
|
|
1268
|
+
"timer_2": (Code._22F3, 00, 42|06, 03|03"), 0b01-000-010 = 6 hrs, back to last mode
|
|
1269
|
+
"timer_3": (Code._22F3, 00, 42|09, 03|03"), 0b01-000-010 = 9 hrs, back to last mode
|
|
1270
|
+
"cook_30": (Code._22F3, 00, 02|1E, 02|03"), 30 mins (press 1x)
|
|
1271
|
+
"cook_60": (Code._22F3, 00, 02|3C, 02|03"), 60 mins (press 2x)
|
|
1272
|
+
|
|
1273
|
+
"low": (Code._22F8, 00, 01|02"), ?eco co2 <= 1200 ppm?
|
|
1274
|
+
"high": (Code._22F8, 00, 02|02"), ?comfort co2 <= 1000 ppm?
|
|
1275
|
+
=========== ================================ =========================================
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
Join commands:
|
|
1279
|
+
--------------
|
|
1280
|
+
|
|
1281
|
+
.. table:: join per accessory type
|
|
1282
|
+
:widths: auto
|
|
1283
|
+
|
|
1284
|
+
========== ================= ===================== ========================= ========================== ========================= ========================== ================= ==========
|
|
1285
|
+
type set 1 set 2 set 3 set 4 set 5 set 6 description art #
|
|
1286
|
+
========== ================= ===================== ========================= ========================== ========================= ========================== ================= ==========
|
|
1287
|
+
"CVERFT": (Code._1FC9, 00, Code._22F1, 0x000000, 01, Code._10E0, 0x000000") CVE/HRU remote (536-0124)
|
|
1288
|
+
"AUTORFT": (Code._1FC9, 63, Code._22F8, 0x000000, 01, Code._10E0, 0x000000") AUTO RFT (536-0150)
|
|
1289
|
+
"DF": (Code._1FC9, 00, Code._22F8, 0x000000, 00, Code._10E0, 0x000000") DemandFlow remote (536-0146)
|
|
1290
|
+
"RV": (Code._1FC9, 00, Code._12A0, 0x000000, 01, Code._10E0, 0x000000, 00, Code._31E0, 0x000000, 00, Code._1FC9, 0x000000") RFT-RV (04-00046)
|
|
1291
|
+
"CO2": (Code._1FC9, 00, Code._1298, 0x000000, 00, Code._2E10, 0x000000, 01, Code._10E0, 0x000000, 00, Code._31E0, 0x000000, 00, Code._1FC9, 0x000000") RFT-CO2 (04-00045)
|
|
1292
|
+
========== ================= ===================== ========================= ========================== ========================= ========================== ================= ==========
|
|
1293
|
+
|
|
1294
|
+
Leave commands:
|
|
1295
|
+
---------------
|
|
1296
|
+
|
|
1297
|
+
.. table:: leave per accessory type
|
|
1298
|
+
:widths: auto
|
|
1299
|
+
|
|
1300
|
+
========== ================= ====================== ========================= ==========
|
|
1301
|
+
type set 1 set 2 description art #
|
|
1302
|
+
========== ================= ====================== ========================= ==========
|
|
1303
|
+
"Others": (Code._1FC9, 00, Code._1FC9, 0x000000") standard leave command
|
|
1304
|
+
"AUTORFT": (Code._1FC9, 63, Code._1FC9, 0x000000") leave command of AUTO RFT (536-0150)
|
|
1305
|
+
========== ================= ====================== ========================= ==========
|
|
1306
|
+
|
|
1307
|
+
.. table:: verbs
|
|
1308
|
+
:widths: 2, 4
|
|
1309
|
+
|
|
1310
|
+
====== ========
|
|
1311
|
+
verb byte
|
|
1312
|
+
====== ========
|
|
1313
|
+
``RQ`` ``0x00``
|
|
1314
|
+
``I_`` ``0x01``
|
|
1315
|
+
``W_`` ``0x02``
|
|
1316
|
+
``RP`` ``0x03``
|
|
1317
|
+
====== ========
|
|
1258
1318
|
|
|
1259
1319
|
"""
|
ramses_rf/dispatcher.py
CHANGED
|
@@ -186,6 +186,12 @@ def process_msg(gwy: Gateway, msg: Message) -> None:
|
|
|
186
186
|
# which requires a valid payload only for 000C.
|
|
187
187
|
|
|
188
188
|
def logger_xxxx(msg: Message) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Log msg according to src, code, log.debug setting.
|
|
191
|
+
|
|
192
|
+
:param msg: the Message being processed
|
|
193
|
+
:return: None
|
|
194
|
+
"""
|
|
189
195
|
if _DBG_FORCE_LOG_MESSAGES:
|
|
190
196
|
_LOGGER.warning(msg)
|
|
191
197
|
elif msg.src != gwy.hgi or (msg.code != Code._PUZZ and msg.verb != RQ):
|
|
@@ -268,10 +274,9 @@ def process_msg(gwy: Gateway, msg: Message) -> None:
|
|
|
268
274
|
|
|
269
275
|
else:
|
|
270
276
|
logger_xxxx(msg)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
# ) # why add it? passes all tests without
|
|
277
|
+
if gwy.msg_db:
|
|
278
|
+
gwy.msg_db.add(msg)
|
|
279
|
+
# why add it? enable for evohome
|
|
275
280
|
|
|
276
281
|
|
|
277
282
|
# TODO: this needs cleaning up (e.g. handle intervening packet)
|