ramses-rf 0.51.4__py3-none-any.whl → 0.51.5__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/const.py +2 -0
- ramses_rf/device/hvac.py +14 -0
- ramses_rf/dispatcher.py +6 -6
- ramses_rf/entity_base.py +1 -1
- ramses_rf/system/heat.py +3 -3
- ramses_rf/system/zones.py +3 -3
- ramses_rf/version.py +1 -1
- {ramses_rf-0.51.4.dist-info → ramses_rf-0.51.5.dist-info}/METADATA +1 -1
- {ramses_rf-0.51.4.dist-info → ramses_rf-0.51.5.dist-info}/RECORD +17 -17
- ramses_tx/const.py +2 -0
- ramses_tx/helpers.py +1 -1
- ramses_tx/parsers.py +19 -14
- ramses_tx/transport.py +15 -11
- ramses_tx/version.py +1 -1
- {ramses_rf-0.51.4.dist-info → ramses_rf-0.51.5.dist-info}/WHEEL +0 -0
- {ramses_rf-0.51.4.dist-info → ramses_rf-0.51.5.dist-info}/entry_points.txt +0 -0
- {ramses_rf-0.51.4.dist-info → ramses_rf-0.51.5.dist-info}/licenses/LICENSE +0 -0
ramses_rf/const.py
CHANGED
|
@@ -61,6 +61,8 @@ from ramses_tx.const import ( # noqa: F401
|
|
|
61
61
|
SZ_REMAINING_DAYS as SZ_REMAINING_DAYS,
|
|
62
62
|
SZ_REMAINING_MINS as SZ_REMAINING_MINS,
|
|
63
63
|
SZ_REMAINING_PERCENT as SZ_REMAINING_PERCENT,
|
|
64
|
+
SZ_REQ_REASON as SZ_REQ_REASON,
|
|
65
|
+
SZ_REQ_SPEED as SZ_REQ_SPEED,
|
|
64
66
|
SZ_SCHEDULE as SZ_SCHEDULE,
|
|
65
67
|
SZ_SENSOR as SZ_SENSOR,
|
|
66
68
|
SZ_SETPOINT as SZ_SETPOINT,
|
ramses_rf/device/hvac.py
CHANGED
|
@@ -31,6 +31,8 @@ from ramses_rf.const import (
|
|
|
31
31
|
SZ_REMAINING_DAYS,
|
|
32
32
|
SZ_REMAINING_MINS,
|
|
33
33
|
SZ_REMAINING_PERCENT,
|
|
34
|
+
SZ_REQ_REASON,
|
|
35
|
+
SZ_REQ_SPEED,
|
|
34
36
|
SZ_SPEED_CAPABILITIES,
|
|
35
37
|
SZ_SUPPLY_FAN_SPEED,
|
|
36
38
|
SZ_SUPPLY_FLOW,
|
|
@@ -506,6 +508,18 @@ class HvacVentilator(FilterChange): # FAN: RP/31DA, I/31D[9A]
|
|
|
506
508
|
def remaining_mins(self) -> int | None:
|
|
507
509
|
return self._msg_value(Code._31DA, key=SZ_REMAINING_MINS)
|
|
508
510
|
|
|
511
|
+
@property
|
|
512
|
+
def request_fan_speed(self) -> float | None:
|
|
513
|
+
return self._msg_value(Code._2210, key=SZ_REQ_SPEED)
|
|
514
|
+
|
|
515
|
+
@property
|
|
516
|
+
def request_src(self) -> str | None:
|
|
517
|
+
"""
|
|
518
|
+
Orcon, others?
|
|
519
|
+
:return: source sensor of auto speed request: IDL, CO2 or HUM
|
|
520
|
+
"""
|
|
521
|
+
return self._msg_value(Code._2210, key=SZ_REQ_REASON)
|
|
522
|
+
|
|
509
523
|
@property
|
|
510
524
|
def speed_cap(self) -> int | None:
|
|
511
525
|
return self._msg_value(Code._31DA, key=SZ_SPEED_CAPABILITIES)
|
ramses_rf/dispatcher.py
CHANGED
|
@@ -91,7 +91,7 @@ def _create_devices_from_addrs(gwy: Gateway, this: Message) -> None:
|
|
|
91
91
|
if not gwy.config.enable_eavesdrop:
|
|
92
92
|
return
|
|
93
93
|
|
|
94
|
-
if not isinstance(this.dst, Device) and this.src
|
|
94
|
+
if not isinstance(this.dst, Device) and this.src != gwy.hgi: # type: ignore[unreachable]
|
|
95
95
|
with contextlib.suppress(LookupError):
|
|
96
96
|
this.dst = gwy.get_device(this.dst.id) # type: ignore[assignment]
|
|
97
97
|
|
|
@@ -188,9 +188,9 @@ def process_msg(gwy: Gateway, msg: Message) -> None:
|
|
|
188
188
|
def logger_xxxx(msg: Message) -> None:
|
|
189
189
|
if _DBG_FORCE_LOG_MESSAGES:
|
|
190
190
|
_LOGGER.warning(msg)
|
|
191
|
-
elif msg.src
|
|
191
|
+
elif msg.src != gwy.hgi or (msg.code != Code._PUZZ and msg.verb != RQ):
|
|
192
192
|
_LOGGER.info(msg)
|
|
193
|
-
elif msg.src
|
|
193
|
+
elif msg.src != gwy.hgi or msg.verb != RQ:
|
|
194
194
|
_LOGGER.info(msg)
|
|
195
195
|
elif _LOGGER.getEffectiveLevel() == logging.DEBUG:
|
|
196
196
|
_LOGGER.info(msg)
|
|
@@ -215,7 +215,7 @@ def process_msg(gwy: Gateway, msg: Message) -> None:
|
|
|
215
215
|
if (
|
|
216
216
|
msg.src._SLUG != DevType.HGI # avoid: msg.src.id != gwy.hgi.id
|
|
217
217
|
and msg.verb != I_
|
|
218
|
-
and msg.dst
|
|
218
|
+
and msg.dst != msg.src
|
|
219
219
|
):
|
|
220
220
|
# HGI80 can do what it likes
|
|
221
221
|
# receiving an I isn't currently in the schema & so can't yet be tested
|
|
@@ -234,10 +234,10 @@ def process_msg(gwy: Gateway, msg: Message) -> None:
|
|
|
234
234
|
# TODO: only be for fully-faked (not Fakable) dst (it picks up via RF if not)
|
|
235
235
|
|
|
236
236
|
if msg.code == Code._1FC9 and msg.payload[SZ_PHASE] == SZ_OFFER:
|
|
237
|
-
devices = [d for d in gwy.devices if d
|
|
237
|
+
devices = [d for d in gwy.devices if d != msg.src and d._is_binding]
|
|
238
238
|
|
|
239
239
|
elif msg.dst == ALL_DEV_ADDR: # some offers use dst=63:, so after 1FC9 offer
|
|
240
|
-
devices = [d for d in gwy.devices if d
|
|
240
|
+
devices = [d for d in gwy.devices if d != msg.src and d.is_faked]
|
|
241
241
|
|
|
242
242
|
elif msg.dst is not msg.src and isinstance(msg.dst, Fakeable): # type: ignore[unreachable]
|
|
243
243
|
# to eavesdrop pkts from other devices, but relevant to this device
|
ramses_rf/entity_base.py
CHANGED
|
@@ -387,7 +387,7 @@ class _MessageDB(_Entity):
|
|
|
387
387
|
codes = {
|
|
388
388
|
k: (CODES_SCHEMA[k][SZ_NAME] if k in CODES_SCHEMA else None)
|
|
389
389
|
for k in sorted(self._msgs)
|
|
390
|
-
if self._msgs[k].src
|
|
390
|
+
if self._msgs[k].src == (self if hasattr(self, "addr") else self.ctl)
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
return {"_sent": list(codes.keys())}
|
ramses_rf/system/heat.py
CHANGED
|
@@ -193,19 +193,19 @@ class SystemBase(Parent, Entity): # 3B00 (multi-relay)
|
|
|
193
193
|
this.code in (Code._22D9, Code._3220) and this.verb == RQ
|
|
194
194
|
): # TODO: RPs too?
|
|
195
195
|
# dst could be an Address...
|
|
196
|
-
if this.src
|
|
196
|
+
if this.src == self.ctl and isinstance(this.dst, OtbGateway): # type: ignore[unreachable]
|
|
197
197
|
app_cntrl = this.dst # type: ignore[unreachable]
|
|
198
198
|
|
|
199
199
|
elif this.code == Code._3EF0 and this.verb == RQ:
|
|
200
200
|
# dst could be an Address...
|
|
201
|
-
if this.src
|
|
201
|
+
if this.src == self.ctl and isinstance(
|
|
202
202
|
this.dst, # type: ignore[unreachable]
|
|
203
203
|
BdrSwitch | OtbGateway,
|
|
204
204
|
):
|
|
205
205
|
app_cntrl = this.dst # type: ignore[unreachable]
|
|
206
206
|
|
|
207
207
|
elif this.code == Code._3B00 and this.verb == I_ and prev is not None:
|
|
208
|
-
if this.src
|
|
208
|
+
if this.src == self.ctl and isinstance(prev.src, BdrSwitch): # type: ignore[unreachable]
|
|
209
209
|
if prev.code == this.code and prev.verb == this.verb: # type: ignore[unreachable]
|
|
210
210
|
app_cntrl = prev.src
|
|
211
211
|
|
ramses_rf/system/zones.py
CHANGED
|
@@ -266,7 +266,7 @@ class DhwZone(ZoneSchedule): # CS92A
|
|
|
266
266
|
# self._get_dhw(sensor=this.dst)
|
|
267
267
|
|
|
268
268
|
assert (
|
|
269
|
-
msg.src
|
|
269
|
+
msg.src == self.ctl
|
|
270
270
|
and msg.code in (Code._0005, Code._000C, Code._10A0, Code._1260, Code._1F41)
|
|
271
271
|
or msg.payload.get(SZ_DOMAIN_ID) in (F9, FA)
|
|
272
272
|
or msg.payload.get(SZ_ZONE_IDX) == "HW"
|
|
@@ -633,13 +633,13 @@ class Zone(ZoneSchedule):
|
|
|
633
633
|
self._update_schema(**{SZ_CLASS: ZON_ROLE_MAP[ZoneRole.UFH]})
|
|
634
634
|
|
|
635
635
|
assert (
|
|
636
|
-
msg.src
|
|
636
|
+
msg.src == self.ctl or msg.src.type == DEV_TYPE_MAP.UFC
|
|
637
637
|
) and ( # DEX
|
|
638
638
|
isinstance(msg.payload, dict)
|
|
639
639
|
or [d for d in msg.payload if d.get(SZ_ZONE_IDX) == self.idx]
|
|
640
640
|
), f"msg inappropriately routed to {self}"
|
|
641
641
|
|
|
642
|
-
assert (msg.src
|
|
642
|
+
assert (msg.src == self.ctl or msg.src.type == DEV_TYPE_MAP.UFC) and ( # DEX
|
|
643
643
|
isinstance(msg.payload, list)
|
|
644
644
|
or msg.code == Code._0005
|
|
645
645
|
or msg.payload.get(SZ_ZONE_IDX) == self.idx
|
ramses_rf/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ramses_rf
|
|
3
|
-
Version: 0.51.
|
|
3
|
+
Version: 0.51.5
|
|
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
|
|
@@ -6,50 +6,50 @@ ramses_cli/utils/cat_slow.py,sha256=AhUpM5gnegCitNKU-JGHn-DrRzSi-49ZR1Qw6lxe_t8,
|
|
|
6
6
|
ramses_cli/utils/convert.py,sha256=D_YiCyX5na9pgC-_NhBlW9N1dgRKUK-uLtLBfofjzZM,1804
|
|
7
7
|
ramses_rf/__init__.py,sha256=zONFBiRdf07cPTSxzr2V3t-b3CGokZjT9SGit4JUKRA,1055
|
|
8
8
|
ramses_rf/binding_fsm.py,sha256=uZAOl3i19KCXqqlaLJWkEqMMP7NJBhVPW3xTikQD1fY,25996
|
|
9
|
-
ramses_rf/const.py,sha256=
|
|
9
|
+
ramses_rf/const.py,sha256=L3z31CZ-xqno6oZp_h-67CB_5tDDqTwSWXsqRtsjMcs,5460
|
|
10
10
|
ramses_rf/database.py,sha256=6k5MLtK5Lplz8THfluQoQU-eniUkqSwEUMvVW7VyGhI,9880
|
|
11
|
-
ramses_rf/dispatcher.py,sha256=
|
|
12
|
-
ramses_rf/entity_base.py,sha256=
|
|
11
|
+
ramses_rf/dispatcher.py,sha256=L-XQ-mbE3HyyxExkhe5kfD4elKlGZnV0kHT4OHTWzE8,11197
|
|
12
|
+
ramses_rf/entity_base.py,sha256=EaIyGIu3fU1Ks30jdqS69nYmcWRKXaWx81oBGDiaXGw,39602
|
|
13
13
|
ramses_rf/exceptions.py,sha256=rzVZDcYxFH7BjUAQ3U1fHWtgBpwk3BgjX1TO1L1iM8c,2538
|
|
14
14
|
ramses_rf/gateway.py,sha256=vqoTEb6QXnwaIMa66oed_3LEVvlyQ3flsAAMliEEvVA,20921
|
|
15
15
|
ramses_rf/helpers.py,sha256=LcrVLqnF2qJWqXrC7UXKOQE8khCT3OhoTpZ_ZVBjw3A,4249
|
|
16
16
|
ramses_rf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
ramses_rf/schemas.py,sha256=mYOUZOH5OIDNBxRM2vd8POzDWEEmLhxh5UtqjTpFNek,13287
|
|
18
|
-
ramses_rf/version.py,sha256=
|
|
18
|
+
ramses_rf/version.py,sha256=2CNEExhYqbwGxmDWyifsA3RubG0bCgN6a1NUTKnIfBM,125
|
|
19
19
|
ramses_rf/device/__init__.py,sha256=sUbH5dhbYFXSoM_TPFRutpRutBRpup7_cQ9smPtDTy8,4858
|
|
20
20
|
ramses_rf/device/base.py,sha256=V2YzRhdxrTqfHYrCBq6pJsYdTgAx8gGzfdo8pkbeEo8,17450
|
|
21
21
|
ramses_rf/device/heat.py,sha256=2sCsggySVcuTzyXDmgWy76QbhlU5MQWSejy3zgI5BDE,54242
|
|
22
|
-
ramses_rf/device/hvac.py,sha256=
|
|
22
|
+
ramses_rf/device/hvac.py,sha256=fRzFGQD6zrkii0Ns9EV1uqh8MTXHn2CO3LZ1WOXLjhs,23835
|
|
23
23
|
ramses_rf/system/__init__.py,sha256=uZLKio3gLlBzePa2aDQ1nxkcp1YXOGrn6iHTG8LiNIw,711
|
|
24
24
|
ramses_rf/system/faultlog.py,sha256=GdGmVGT3137KsTlV_nhccgIFEmYu6DFsLTn4S-8JSok,12799
|
|
25
|
-
ramses_rf/system/heat.py,sha256=
|
|
25
|
+
ramses_rf/system/heat.py,sha256=3jaFEChU-HlWCRMY1y7u09s7AH4hT0pC63hnqwdmZOc,39223
|
|
26
26
|
ramses_rf/system/schedule.py,sha256=Ts6tdZPTQLV5NkgwA73tPa5QUsnZNIIuYoKC-8VsXDk,18808
|
|
27
|
-
ramses_rf/system/zones.py,sha256=
|
|
27
|
+
ramses_rf/system/zones.py,sha256=2_c1YHrGbObUeEqjcqJDO08Fo2Mr1aYn4VorNmfFaKk,36041
|
|
28
28
|
ramses_tx/__init__.py,sha256=wJ7Ntx-0AyJwYwSG8OrFMpxDLXs6GbECbCcYhq98mSA,3162
|
|
29
29
|
ramses_tx/address.py,sha256=2640K3sXzogZtd4-tSxwVjYEEXcFE1DgmtvZlTMM5mE,8444
|
|
30
30
|
ramses_tx/command.py,sha256=g5PBf9JnuygveyaYrqIuV8wIn7grm0evuqKy9Cp1oaA,53844
|
|
31
|
-
ramses_tx/const.py,sha256=
|
|
31
|
+
ramses_tx/const.py,sha256=ILZvbIp9qI2ZTmGDDJ0YFoxOH3GtQ7g9MT3vAUtHWAE,30291
|
|
32
32
|
ramses_tx/exceptions.py,sha256=FJSU9YkvpKjs3yeTqUJX1o3TPFSe_B01gRGIh9b3PNc,2632
|
|
33
33
|
ramses_tx/fingerprints.py,sha256=nfftA1E62HQnb-eLt2EqjEi_la0DAoT0wt-PtTMie0s,11974
|
|
34
34
|
ramses_tx/frame.py,sha256=9lUVh8gAMXNRAolfFw2WuWANjn24AWkmscuM9Tm5imE,22036
|
|
35
35
|
ramses_tx/gateway.py,sha256=FE5MWA1eIE9JATA2vRoBSQ8fAzqp7TqAm3Ds3k1KnKE,11267
|
|
36
|
-
ramses_tx/helpers.py,sha256=
|
|
36
|
+
ramses_tx/helpers.py,sha256=qDJTsTU2tfSZrfJuFi1q29efkkHzqRtg85M6ItQH6qA,32247
|
|
37
37
|
ramses_tx/logger.py,sha256=7vUpcfOFMW95juMWDx5dhUOqV8DTsindZ-Qz2aCmEoA,11073
|
|
38
38
|
ramses_tx/message.py,sha256=J1wvVkLPJQr2ffKCUQYSWwLPzRTZBC0zUU5W9DkN3hU,13190
|
|
39
39
|
ramses_tx/opentherm.py,sha256=58PXz9l5x8Ou6Fm3y-R_UnGHCYahoi2RKIDdYStUMzk,42378
|
|
40
40
|
ramses_tx/packet.py,sha256=NGunaGCkEjhTp9t4mARK5e7kbqT-Z_JKCH7ibMYMJXU,7357
|
|
41
|
-
ramses_tx/parsers.py,sha256=
|
|
41
|
+
ramses_tx/parsers.py,sha256=uwu_HsMjpsSyMYzoBpVnAxu2pqBJiQDL5ls8_B60V7c,109708
|
|
42
42
|
ramses_tx/protocol.py,sha256=ifj3qwcQivjQDaQUwM94xp-U8Pmef6zwSH7mav8DLWA,28867
|
|
43
43
|
ramses_tx/protocol_fsm.py,sha256=YhHkTqbl8w-myimsOjV50uIFgg9HiApwPU7xA_jg5nU,26827
|
|
44
44
|
ramses_tx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
45
|
ramses_tx/ramses.py,sha256=GnZwvx-HSVFdjXfUen6aWClDtrAmYaKwbrWl-LsyKO4,52045
|
|
46
46
|
ramses_tx/schemas.py,sha256=h2AcArVROy1_C4n6F0Crj4e-2BxXxH74xogFlc6nKHI,12769
|
|
47
|
-
ramses_tx/transport.py,sha256
|
|
47
|
+
ramses_tx/transport.py,sha256=aLpULRSivoJqzH8GDPRDcbehETOhFflEqmHbaniGLvg,56210
|
|
48
48
|
ramses_tx/typed_dicts.py,sha256=4ZT50M-Cuwy2ljAIorwoxEJ9c737xUHrUxX9wTh79xE,10834
|
|
49
49
|
ramses_tx/typing.py,sha256=eF2SlPWhNhEFQj6WX2AhTXiyRQVXYnFutiepllYl2rI,5042
|
|
50
|
-
ramses_tx/version.py,sha256=
|
|
51
|
-
ramses_rf-0.51.
|
|
52
|
-
ramses_rf-0.51.
|
|
53
|
-
ramses_rf-0.51.
|
|
54
|
-
ramses_rf-0.51.
|
|
55
|
-
ramses_rf-0.51.
|
|
50
|
+
ramses_tx/version.py,sha256=uQWGeAYKPd3vO8uf3sjQlNE_kdbcsQl2FfC3y2J7NJg,123
|
|
51
|
+
ramses_rf-0.51.5.dist-info/METADATA,sha256=5qyM_GCuZGD5rzMMGOjQUfNR4NJAd5TOQwIrBnoSEmY,3906
|
|
52
|
+
ramses_rf-0.51.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
53
|
+
ramses_rf-0.51.5.dist-info/entry_points.txt,sha256=NnyK29baOCNg8DinPYiZ368h7MTH7bgTW26z2A1NeIE,50
|
|
54
|
+
ramses_rf-0.51.5.dist-info/licenses/LICENSE,sha256=-Kc35W7l1UkdiQ4314_yVWv7vDDrg7IrJfMLUiq6Nfs,1074
|
|
55
|
+
ramses_rf-0.51.5.dist-info/RECORD,,
|
ramses_tx/const.py
CHANGED
|
@@ -88,6 +88,8 @@ SZ_REL_HUMIDITY: Final = "rel_humidity"
|
|
|
88
88
|
SZ_REMAINING_DAYS: Final = "days_remaining"
|
|
89
89
|
SZ_REMAINING_MINS: Final = "remaining_mins"
|
|
90
90
|
SZ_REMAINING_PERCENT: Final = "percent_remaining"
|
|
91
|
+
SZ_REQ_REASON: Final = "req_reason"
|
|
92
|
+
SZ_REQ_SPEED: Final = "req_speed"
|
|
91
93
|
SZ_SUPPLY_FAN_SPEED: Final = "supply_fan_speed"
|
|
92
94
|
SZ_SUPPLY_FLOW: Final = "supply_flow"
|
|
93
95
|
SZ_SUPPLY_TEMP: Final = "supply_temp"
|
ramses_tx/helpers.py
CHANGED
|
@@ -757,7 +757,7 @@ def parse_fan_info(value: HexStr2) -> PayDictT.FAN_INFO:
|
|
|
757
757
|
}
|
|
758
758
|
|
|
759
759
|
|
|
760
|
-
# 31DA[38:40]
|
|
760
|
+
# 31DA[38:40], also 2210
|
|
761
761
|
def parse_exhaust_fan_speed(value: HexStr2) -> PayDictT.EXHAUST_FAN_SPEED:
|
|
762
762
|
"""Return the exhaust fan speed (% of max speed)."""
|
|
763
763
|
return _parse_fan_speed(SZ_EXHAUST_FAN_SPEED, value) # type: ignore[return-value]
|
ramses_tx/parsers.py
CHANGED
|
@@ -72,6 +72,7 @@ from .const import (
|
|
|
72
72
|
SZ_RELAY_DEMAND,
|
|
73
73
|
SZ_REMAINING_DAYS,
|
|
74
74
|
SZ_REMAINING_PERCENT,
|
|
75
|
+
SZ_REQ_REASON,
|
|
75
76
|
SZ_SETPOINT,
|
|
76
77
|
SZ_SETPOINT_BOUNDS,
|
|
77
78
|
SZ_SYSTEM_MODE,
|
|
@@ -1378,22 +1379,18 @@ def parser_1fd4(payload: str, msg: Message) -> PayDictT._1FD4:
|
|
|
1378
1379
|
return {"ticker": int(payload[2:], 16)}
|
|
1379
1380
|
|
|
1380
1381
|
|
|
1381
|
-
# WIP:
|
|
1382
|
+
# WIP: HVAC auto requests (confirmed for Orcon, others?)
|
|
1382
1383
|
def parser_2210(payload: str, msg: Message) -> dict[str, Any]:
|
|
1383
1384
|
try:
|
|
1384
1385
|
assert msg.verb in (RP, I_) or payload == "00"
|
|
1385
|
-
assert payload[10:12] == payload[38:40]
|
|
1386
|
-
10:12
|
|
1387
|
-
|
|
1388
|
-
"58",
|
|
1389
|
-
"64",
|
|
1390
|
-
"96",
|
|
1391
|
-
"FF",
|
|
1392
|
-
), f"expected req.speed? (58|64|96|FF), not {payload[10:12]}"
|
|
1386
|
+
assert payload[10:12] == payload[38:40], (
|
|
1387
|
+
f"expected byte 19 {payload[10:12]}, not {payload[38:40]}"
|
|
1388
|
+
) # auto requested fan speed %. Identical [38:40] is for supply?
|
|
1393
1389
|
assert payload[20:22] == payload[48:50] and payload[20:22] in (
|
|
1394
|
-
"00",
|
|
1395
|
-
"
|
|
1396
|
-
|
|
1390
|
+
"00", # idle
|
|
1391
|
+
"02", # requested by CO2 level/sensor
|
|
1392
|
+
"03", # requested by humidity level/sensor
|
|
1393
|
+
), f"expected req_reason (00|02|03), not {payload[20:22]}"
|
|
1397
1394
|
assert payload[78:80] in ("00", "02"), (
|
|
1398
1395
|
f"expected byte 39 (00|02), not {payload[78:80]}"
|
|
1399
1396
|
)
|
|
@@ -1407,9 +1404,17 @@ def parser_2210(payload: str, msg: Message) -> dict[str, Any]:
|
|
|
1407
1404
|
except AssertionError as err:
|
|
1408
1405
|
_LOGGER.warning(f"{msg!r} < {_INFORM_DEV_MSG} ({err})")
|
|
1409
1406
|
|
|
1407
|
+
_req = "IDL"
|
|
1408
|
+
if payload[20:22] == "02":
|
|
1409
|
+
_req = "CO2"
|
|
1410
|
+
elif payload[20:22] == "03":
|
|
1411
|
+
_req = "HUM"
|
|
1412
|
+
|
|
1410
1413
|
return {
|
|
1411
|
-
|
|
1412
|
-
|
|
1414
|
+
**parse_exhaust_fan_speed(
|
|
1415
|
+
payload[10:12]
|
|
1416
|
+
), # for Orcon: 29 hex == 41 decimal divided by 2 gives 20.5 (%)
|
|
1417
|
+
SZ_REQ_REASON: _req,
|
|
1413
1418
|
"unknown_78": payload[78:80],
|
|
1414
1419
|
"unknown_80": payload[80:82],
|
|
1415
1420
|
"unknown_82": payload[82:],
|
ramses_tx/transport.py
CHANGED
|
@@ -1073,7 +1073,7 @@ class MqttTransport(_FullTransport, _MqttTransportAbstractor):
|
|
|
1073
1073
|
self._connecting = True
|
|
1074
1074
|
try:
|
|
1075
1075
|
self.client.connect_async(
|
|
1076
|
-
self._broker_url.hostname
|
|
1076
|
+
str(self._broker_url.hostname or "localhost"),
|
|
1077
1077
|
self._broker_url.port or 1883,
|
|
1078
1078
|
60,
|
|
1079
1079
|
)
|
|
@@ -1172,10 +1172,18 @@ class MqttTransport(_FullTransport, _MqttTransportAbstractor):
|
|
|
1172
1172
|
self,
|
|
1173
1173
|
client: mqtt.Client,
|
|
1174
1174
|
userdata: Any,
|
|
1175
|
-
|
|
1176
|
-
|
|
1175
|
+
*args: Any,
|
|
1176
|
+
**kwargs: Any,
|
|
1177
1177
|
) -> None:
|
|
1178
|
-
|
|
1178
|
+
# Handle different paho-mqtt callback signatures
|
|
1179
|
+
reason_code = args[0] if len(args) >= 1 else None
|
|
1180
|
+
|
|
1181
|
+
reason_name = (
|
|
1182
|
+
reason_code.getName()
|
|
1183
|
+
if reason_code is not None and hasattr(reason_code, "getName")
|
|
1184
|
+
else str(reason_code)
|
|
1185
|
+
)
|
|
1186
|
+
_LOGGER.warning(f"MQTT disconnected: {reason_name}")
|
|
1179
1187
|
|
|
1180
1188
|
was_connected = self._connected
|
|
1181
1189
|
self._connected = False
|
|
@@ -1191,13 +1199,9 @@ class MqttTransport(_FullTransport, _MqttTransportAbstractor):
|
|
|
1191
1199
|
self._protocol.pause_writing()
|
|
1192
1200
|
|
|
1193
1201
|
# Only attempt reconnection if we didn't deliberately disconnect
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
self._schedule_reconnect()
|
|
1198
|
-
elif reason_code.is_failure and not self._closing:
|
|
1199
|
-
# Connection failed, also schedule reconnection
|
|
1200
|
-
_LOGGER.debug("MQTT connection failed - scheduling reconnection")
|
|
1202
|
+
|
|
1203
|
+
if not self._closing:
|
|
1204
|
+
# Schedule reconnection for any disconnect (unexpected or failure)
|
|
1201
1205
|
self._schedule_reconnect()
|
|
1202
1206
|
|
|
1203
1207
|
def _create_connection(self, msg: mqtt.MQTTMessage) -> None:
|
ramses_tx/version.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|