feat: mapped record_mode protocol
This commit is contained in:
+46
-3
@@ -847,6 +847,7 @@ class MiniMateClient:
|
||||
self,
|
||||
*,
|
||||
# Recording parameters
|
||||
recording_mode: Optional[int] = None,
|
||||
sample_rate: Optional[int] = None,
|
||||
record_time: Optional[float] = None,
|
||||
# Threshold parameters (geo channels, in/s)
|
||||
@@ -869,6 +870,7 @@ class MiniMateClient:
|
||||
Configurable fields
|
||||
-------------------
|
||||
Recording parameters:
|
||||
recording_mode : int — 0x00=Single Shot, 0x01=Continuous, 0x03=Histogram, 0x04=Histogram+Continuous
|
||||
sample_rate : int — samples/sec; valid values: 1024, 2048, 4096
|
||||
record_time : float — record duration in seconds (e.g. 2.0, 3.0)
|
||||
|
||||
@@ -914,6 +916,7 @@ class MiniMateClient:
|
||||
# 2. Patch the compliance buffer and build the 2128-byte write payload
|
||||
compliance_data = _encode_compliance_config(
|
||||
compliance_raw,
|
||||
recording_mode=recording_mode,
|
||||
sample_rate=sample_rate,
|
||||
record_time=record_time,
|
||||
trigger_level_geo=trigger_level_geo,
|
||||
@@ -1650,6 +1653,7 @@ def _extract_project_strings(data: bytes) -> Optional[ProjectInfo]:
|
||||
def _encode_compliance_config(
|
||||
raw: bytes,
|
||||
*,
|
||||
recording_mode: Optional[int] = None,
|
||||
sample_rate: Optional[int] = None,
|
||||
record_time: Optional[float] = None,
|
||||
trigger_level_geo: Optional[float] = None,
|
||||
@@ -1670,6 +1674,11 @@ def _encode_compliance_config(
|
||||
DLE-jitter shifts):
|
||||
|
||||
Anchor: b'\\xbe\\x80\\x00\\x00\\x00\\x00' (confirmed stable, both BE11529 and BE18189)
|
||||
recording_mode → uint8 at anchor_pos - 7 (write payload; one byte earlier than read format)
|
||||
Values: 0x00=Single Shot, 0x01=Continuous, 0x03=Histogram, 0x04=Histogram+Continuous
|
||||
NOTE: In the E5 read response the field is at anchor_pos - 8 due to an extra
|
||||
0x10 byte at anchor_pos - 7 present only in the read format. The write
|
||||
payload does NOT have this extra byte — use anchor_pos - 7 here.
|
||||
sample_rate → uint16 BE at anchor_pos - 6
|
||||
record_time → float32 BE at anchor_pos + 6
|
||||
|
||||
@@ -1702,10 +1711,18 @@ def _encode_compliance_config(
|
||||
|
||||
buf = bytearray(raw)
|
||||
|
||||
# ── Numeric: sample_rate + record_time (anchor-relative) ─────────────────
|
||||
# ── Numeric: recording_mode + sample_rate + record_time (anchor-relative) ──
|
||||
_ANC = b'\xbe\x80\x00\x00\x00\x00'
|
||||
_anc = buf.find(_ANC, 0, 150)
|
||||
|
||||
if recording_mode is not None:
|
||||
if _anc < 7:
|
||||
log.warning("_encode_compliance_config: anchor not found — cannot write recording_mode")
|
||||
else:
|
||||
buf[_anc - 7] = recording_mode & 0xFF
|
||||
log.debug("_encode_compliance_config: recording_mode=0x%02X -> offset %d",
|
||||
recording_mode, _anc - 7)
|
||||
|
||||
if sample_rate is not None:
|
||||
if _anc < 6:
|
||||
log.warning("_encode_compliance_config: anchor not found — cannot write sample_rate")
|
||||
@@ -1838,7 +1855,22 @@ def _decode_compliance_config_into(data: bytes, info: DeviceInfo) -> None:
|
||||
# record_time : float32 BE at anchor_pos + 6
|
||||
_ANCHOR = b'\xbe\x80\x00\x00\x00\x00'
|
||||
_anchor = data.find(_ANCHOR, 0, 150)
|
||||
if _anchor >= 6 and _anchor + 10 <= len(data):
|
||||
if _anchor >= 8 and _anchor + 10 <= len(data):
|
||||
# Layout (E5 read format, relative to 6-byte anchor suffix):
|
||||
# _anchor - 8 : recording_mode (uint8)
|
||||
# _anchor - 7 : 0x10 (extra byte present in E5 read only; absent in SUB 71 write)
|
||||
# _anchor - 6 : sample_rate_hi (uint8, MSB of uint16 BE)
|
||||
# _anchor - 5 : sample_rate_lo (uint8, LSB of uint16 BE)
|
||||
# _anchor - 4 : \x01\x2c\x00\x00 (10-byte anchor prefix)
|
||||
# _anchor : \xbe\x80\x00\x00\x00\x00 (6-byte anchor suffix)
|
||||
# _anchor + 6 : record_time (float32 BE)
|
||||
try:
|
||||
config.recording_mode = data[_anchor - 8]
|
||||
log.debug(
|
||||
"compliance_config: recording_mode = 0x%02X (anchor@%d)", config.recording_mode, _anchor
|
||||
)
|
||||
except Exception as exc:
|
||||
log.warning("compliance_config: recording_mode extraction failed: %s", exc)
|
||||
try:
|
||||
config.sample_rate = struct.unpack_from(">H", data, _anchor - 6)[0]
|
||||
log.debug(
|
||||
@@ -1853,10 +1885,21 @@ def _decode_compliance_config_into(data: bytes, info: DeviceInfo) -> None:
|
||||
)
|
||||
except Exception as exc:
|
||||
log.warning("compliance_config: record_time extraction failed: %s", exc)
|
||||
elif _anchor >= 6 and _anchor + 10 <= len(data):
|
||||
# Fallback: anchor found but not enough bytes before it for recording_mode
|
||||
log.warning("compliance_config: anchor too close to start (anchor@%d) — skipping recording_mode", _anchor)
|
||||
try:
|
||||
config.sample_rate = struct.unpack_from(">H", data, _anchor - 6)[0]
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
config.record_time = struct.unpack_from(">f", data, _anchor + 6)[0]
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
log.warning(
|
||||
"compliance_config: anchor %s not found in cfg[0:150] (len=%d) "
|
||||
"— sample_rate and record_time will be None",
|
||||
"— sample_rate, record_time and recording_mode will be None",
|
||||
_ANCHOR.hex(), len(data),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user