client: wire trigger_level_geo, alarm_level_geo, max_range_geo from channel block
The channel block is only present in the full ~2126-byte cfg (when frame D delivers correctly rather than duplicating frame B's page). Layout per §7.6: [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 (label-24/label-18/label-10) are validated by checking the unit strings "in.\0" at label-14 and "/s\0\0" at label-6 before reading the floats. Guard against "Tran2" false-match. When frame D duplicates, cfg is ~1071 bytes and tran_pos search returns a hit without the unit string sentinels — we log the miss and leave fields None. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -682,6 +682,42 @@ def _decode_compliance_config_into(data: bytes, info: DeviceInfo) -> None:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
log.warning("compliance_config: project string extraction failed: %s", 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
|
info.compliance_config = config
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user