diff --git a/minimateplus/client.py b/minimateplus/client.py index 8033697..9941bee 100644 --- a/minimateplus/client.py +++ b/minimateplus/client.py @@ -682,6 +682,42 @@ def _decode_compliance_config_into(data: bytes, info: DeviceInfo) -> None: except Exception as exc: log.warning("compliance_config: project string extraction failed: %s", exc) + # ── Channel block: trigger_level_geo, alarm_level_geo, max_range_geo ───── + # The channel block is only present in the full cfg (frame D delivered, + # ~2126 bytes). Per §7.6, each channel record ends with the label string: + # [00 00][max_range f32][00 00][trigger f32]["in.\0"][alarm f32]["/s\0\0"][00 01][label] + # Relative offsets from the "Tran" label position: + # trigger = float32_BE at label - 18 + # alarm = float32_BE at label - 10 + # max_range = float32_BE at label - 24 + # Validated by checking unit strings "in.\0" at label-14 and "/s\0\0" at label-6. + # "Tran2" at a later position won't match because its surrounding bytes differ. + try: + tran_pos = data.find(b"Tran", 1000) + if ( + tran_pos >= 24 + and data[tran_pos + 4 : tran_pos + 5] != b"2" # not "Tran2" + and data[tran_pos - 14 : tran_pos - 10] == b"in.\x00" + and data[tran_pos - 6 : tran_pos - 2 ] == b"/s\x00\x00" + ): + config.trigger_level_geo = struct.unpack_from(">f", data, tran_pos - 18)[0] + config.alarm_level_geo = struct.unpack_from(">f", data, tran_pos - 10)[0] + config.max_range_geo = struct.unpack_from(">f", data, tran_pos - 24)[0] + log.debug( + "compliance_config: trigger=%.4f alarm=%.4f max_range=%.4f in/s", + config.trigger_level_geo, config.alarm_level_geo, config.max_range_geo, + ) + elif tran_pos >= 0: + log.debug( + "compliance_config: 'Tran' at %d but unit strings absent " + "— channel block not yet in cfg (frame D duplicate?)", + tran_pos, + ) + else: + log.debug("compliance_config: channel block not present in cfg (len=%d)", len(data)) + except Exception as exc: + log.warning("compliance_config: channel block extraction failed: %s", exc) + info.compliance_config = config