-
Notifications
You must be signed in to change notification settings - Fork 9
0418: System Fault Log
David Bonnes edited this page Jan 23, 2020
·
18 revisions
When a fault occurs, the controller will send an I
packet:
071 I --- 01:145038 --:------ 01:145038 0418 022 000000B00606040000001714359AFFFFFF700012E296
071 I --- 01:145038 --:------ 01:145038 0418 022 000000B00AFA05000000BB1375FCFFFFFF7000000002
The controller will respond to an RQ
with an RQ
of the corresponding log entry - this is for entry #7 (entry numbers start from 0):
095 RQ --- 18:013393 01:145038 --:------ 0418 003 000006
045 RP --- 01:145038 18:056026 --:------ 0418 022 000006B006FA05000000C413A587FFFFFF70001CB388
The controller does not send a packet when the log is cleared.
Payload decode: | ||
---|---|---|
Unknown | [0:2] | fixed value 0x00 |
Entry Type | [2:4] | 00=Fault, 0x40=Restore |
Entry Number | [4:6] | Fault log entry number |
Unknown | [6:8] | fixed value 0xB0 |
Error Type | [8:10] | 0x04=Battery Low, 0x06=Comms Fault, ... |
zone_idx/domain_id | [10:12] | (0-0xA, 0xFC etc) |
device class | [12:14] | 0x04=Actuator, 0x01=Sensor |
unknown | [14:18] | fixed value 0x0000 |
datetime | [18:30] | |
unknown | [30:38] | fixed value 0xFFFF7000 |
device_id | [38:44] |
STATE_MAP = {
"00": "Fault ",
"40": "Restore",
"C0": "Unknown (C0)"
}
DEVICE_CLASS_MAP = {
"00": "Controller?",
"01": "Sensor",
"04": "Actuator",
"05": "DhwController?"
}
FAULT_TYPE_MAP = {
"04": "BatteryLow",
"06": "CommsFault",
"0A": "SensorError"
}
@parser_decorator
def parser_0418(payload) -> dict:
def _timestamp(seqx):
"""In the controller UI: YYYY-MM-DD HH:MM"""
_seqx = int(seqx, 16)
return dt(
year=(_seqx & 0b1111111 << 24) >> 24,
month=(_seqx & 0b1111 << 36) >> 36,
day=(_seqx & 0b11111 << 31) >> 31,
hour=(_seqx & 0b11111 << 19) >> 19,
minute=(_seqx & 0b111111 << 13) >> 13,
second=(_seqx & 0b111111 << 7) >> 7,
).strftime("%Y-%m-%d %H:%M:%S")
if payload == "000000B0000000000000000000007FFFFF7000000000":
return {"log_idx": None} # a null log entry, (or: payload[38:] == "000000")
assert len(payload) / 2 == 22
assert payload[:2] == "00" # unknown_0
assert payload[2:4] in list(STATE_MAP)
assert int(payload[4:6], 16) <= 63
assert payload[6:8] == "B0" # unknown_1
assert payload[8:10] in list(FAULT_TYPE_MAP)
assert int(payload[10:12], 16) <= 11 or payload[10:12] in ["FA"]
assert payload[12:14] in list(DEVICE_CLASS_MAP)
assert payload[14:18] == "0000" # unknown_2
assert payload[28:30] in ["7F", "FF"] # last bit in dt field
assert payload[30:38] == "FFFF7000" # unknown_3
return {
"state": STATE_MAP.get(payload[2:4], payload[2:4]),
"timestamp": _timestamp(payload[18:30]),
"fault_type": FAULT_TYPE_MAP.get(payload[8:10], payload[8:10]),
"zone_idx" if int(payload[10:12], 16) <= 11 else "domain_id": payload[10:12],
"device_class": DEVICE_CLASS_MAP.get(payload[12:14], payload[12:14]),
"device_id": dev_hex_to_id(payload[38:]), # is "00:000001/2 for CTL?
"log_idx": int(payload[4:6], 16),
}
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