-
Notifications
You must be signed in to change notification settings - Fork 9
0404: Zone Schedule
The controller will respond to a RQ
/ 0404
with the schedule for that zone:
095 RQ --- 18:013393 01:145038 --:------ 0404 007 00200008000100
045 RP --- 01:145038 18:013393 --:------ 0404 048 0020000829010568816DD1BD...
All RQ
packets consist of a 7-byte header (only), while RP
packets are variable-length, with a similar 7-byte header and the remaining bytes making up a fragment of the overall message.
This message is large, and will usually require a sequence of 3-5 RP
packets to obtain all the fragments needed to obtain a zone's schedule - the first RP
will indicate the number of these packets.
All RQ
packets consist only of a header in this form (edited for readability):
00-200008-00-01-00
field name | RQ | |
---|---|---|
[0:2] |
zone_idx |
00 to 0B
|
[2:8] |
unknown_0 | always 200008
|
[8:10] |
fragment_length |
00 for all RQ s, up to 29 for RP s |
[10:12] |
fragment_ordinal | from 01 to total_fragments |
[12:14] |
total_fragments | but is 00 for first RQ
|
Note: Although payload lengths are in decimal:
048
= 48, fragment lengths are in hexadecimal:29
= 0x29 = 41.
RP
packets have the same header format, which will provide the total fragments for that zone's schedule (above, the fragment is 0x29 bytes long, and begins 68816DD1BD0...
):
00-200008-29-01-05 68816DD1BD0...
Subsequent RQ
packets must have the total fragments set correctly, as well as the fragment number, otherwise they will be ignored. So the complete exchange of RQ
/ RP
packets for zone 9 would be (payloads edited for readability):
095 RQ --- 18:013393 01:145038 --:------ 0404 007 09 200008 00 01-00
045 RP --- 01:145038 18:013393 --:------ 0404 048 09 200008 29 01-05 68816DD1BD...
095 RQ --- 18:013393 01:145038 --:------ 0404 007 09 200008 00 02-05
045 RP --- 01:145038 18:013393 --:------ 0404 048 09 200008 29 02-05 A42BEEC9F1...
095 RQ --- 18:013393 01:145038 --:------ 0404 007 09 200008 00 03-05
045 RP --- 01:145038 18:013393 --:------ 0404 048 09 200008 29 03-05 1BB833CBA4...
095 RQ --- 18:013393 01:145038 --:------ 0404 007 09 200008 00 04-05
045 RP --- 01:145038 18:013393 --:------ 0404 048 09 200008 29 04-05 3BB13AE93A...
095 RQ --- 18:013393 01:145038 --:------ 0404 007 09 200008 00 05-05
045 RP --- 01:145038 18:013393 --:------ 0404 010 09 200008 03 05-05 C9E63E
The last RP
is the end of the sequence of fragments because it is fragment 5 of 5 (05-05
). Note also, in this specific instance, the final fragment_length
is 03
rather than 29
and so the payload length is 010
rather than 048
.
The fragments, once concatenated into a complete block, can be inflated using zlib to obtain a sequence of 20-byte setpoints that can be decoded thus:
fragments = ["68816D...", "A42BEE...", "1BB833...", "3BB13A...", "C9E63E"]
message = zlib.decompress(bytearray.fromhex("".join(fragments)))
for i in range(0, len(message), 20):
(zone, day, time, temp, _) = struct.unpack("<xxxxBxxxBxxxHxxHH", message[i : i + 20])
print(
"ZONE={0:d} DAY={1:d} TIME={2:02d}:{3:02d} TEMP={4:.2f}".format(
zone, day, *divmod(time, 60), temp / 100
)
)
0001
RF Check0004
Zone name0008
Relay demand0009
Relay failsafe000A
Zone config000C
Zone actuators0016
RF signal test0100
Localisation0404
Zone schedule0418
System fault1030
Mix zone config1060
Battery state10A0
DHW setpoint10E0
Device info1100
Boiler relay info1260
DHW temperature12B0
Window sensor1F09
System Sync1F41
DHW mode1FC9
RF bind1FD4
Opentherm ticker22C9
UFH setpoint22D9
Boiler setpoint2309
Zone setpoint2349
Setpoint override2E04
Controller mode30C9
Zone temperature313F
System datetime3150
Heat demand3220
Opentherm message3B00
Actuator sync3EF0
Actuator info3EF1
Actuator unknown
0002
External sensor0005
Zone management0006
Schedule sync000E
Unknown01D0
Unknown01E9
Unknown042F
Unknown1280
Outdoor humidity1290
Outdoor temp12A0
Indoor humidity2249
Now/next setpoint22D0
UFH unknown22F1
Ventilation unit command22F3
Ventilation unit temp. high2389
Unknown2D49
Unknown3120
Unknown31D9
HVAC Unknown31DA
HVAC Unknown31E0
HVAC Unknown