Skip to content

0418: System Fault Log

David Bonnes edited this page Jan 22, 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
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]

Python Code

def parser_0418(payload, msg) -> Optional[dict]:  # system_fault
    """10 * 6 log entries in the UI, but 63 via RQs"""
    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
    #
    # assert msg.verb in [" I", "RP"]
    assert len(payload) / 2 == 22
    #
    assert payload[2:4] in ["00", "40", "C0"]  # C0 dont appear in the UI
    assert int(payload[4:6], 16) <= 63  # TODO: upper limit is: 60? 63? more?
    assert payload[8:10] in ["04", "06", "0A"]
    assert int(payload[10:12], 16) <= 11 or payload[10:12] in ["FA"]
    assert payload[12:14] in ["00", "01", "04", "05"]
    assert payload[28:30] in ["7F", "FF"]  # last bit in dt field
    #
    assert payload[:2] == "00"  # unknown_0
    assert payload[6:8] == "B0"  # unknown_1
    assert payload[14:18] == "0000"  # unknown_2
    assert payload[30:38] == "FFFF7000"  # unknown_3
    #
    attrs = {
        "log_idx": int(payload[4:6], 16),  # is also "00" for null entry
        "state": {
            "00": "Fault  ", "40": "Restore"
        }.get(payload[2:4], f"{payload[2:4]:<7}"),
        "timestamp": _timestamp(payload[18:30]),
        "device_id": dev_hex_to_id(payload[38:]),  # is "00:000001/2 for CTL?
        "zone_idx" if int(payload[10:12], 16) <= 11 else "domain_id": payload[10:12],
        "device_type": {
            "00": "Cntrllr?",
            "01": "Sensor  ",
            "04": "Actuator",
            "05": "???05???"
        }.get(payload[12:14], f"{payload[12:14]:<8}"),
        "error_type": {
            "04": "BatteryLow", "06": "CommsFault"
        }.get(payload[8:10], f"{payload[8:10]:<10}"),
    }
    return attrs
Clone this wiki locally