From 9d9c14af7987ce729d27ed064cc2215605dc3e21 Mon Sep 17 00:00:00 2001 From: Brian Harrison Date: Fri, 10 Apr 2026 01:06:27 -0400 Subject: [PATCH] fix: replace Unicode chars in log messages, fix DeviceInfo.serial, UTF-8 file log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace all Unicode arrows/checkmarks (-> [OK] [FAIL]) in ach_server.py and client.py log calls — Windows cp1252 console can't encode them - Fix DeviceInfo attribute: serial_number -> serial - Fix _device_info_to_dict key: serial_number -> serial - Demote count_events 1E/1F per-key log lines from WARNING to DEBUG (they were flooding the console on devices with many stored events) - FileHandler now opens with encoding='utf-8' so session log files can hold any characters without codec errors Co-Authored-By: Claude Sonnet 4.6 --- bridges/ach_server.py | 2 +- minimateplus/client.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bridges/ach_server.py b/bridges/ach_server.py index 69050b7..19b7f43 100644 --- a/bridges/ach_server.py +++ b/bridges/ach_server.py @@ -136,7 +136,7 @@ class AchSession: raw_path = session_dir / f"raw_rx_{ts}.bin" # Wire up a file handler so every protocol log line goes to the session log - fh = logging.FileHandler(log_path) + fh = logging.FileHandler(log_path, encoding="utf-8") fh.setFormatter(logging.Formatter("%(asctime)s %(levelname)-7s %(name)s %(message)s")) root_logger = logging.getLogger() root_logger.addHandler(fh) diff --git a/minimateplus/client.py b/minimateplus/client.py index 984cbcf..2538f48 100644 --- a/minimateplus/client.py +++ b/minimateplus/client.py @@ -216,8 +216,8 @@ class MiniMateClient: log.warning("count_events: 1E failed: %s — returning 0", exc) return 0 - log.warning( - "count_events: 1E → key=%s data8=%s trailing=%s", + log.debug( + "count_events: 1E -> key=%s data8=%s trailing=%s", key4.hex(), data8.hex(), data8[4:8].hex(), ) @@ -241,8 +241,8 @@ class MiniMateClient: break try: key4, data8 = proto.advance_event(browse=True) - log.warning( - "count_events: 1F [iter %d] → key=%s data8=%s trailing=%s", + log.debug( + "count_events: 1F [iter %d] -> key=%s data8=%s trailing=%s", count, key4.hex(), data8.hex(), data8[4:8].hex(), ) except ProtocolError as exc: @@ -426,7 +426,7 @@ class MiniMateClient: try: key4, data8 = proto.advance_event(browse=True) log.info( - "get_events: 1F(browse) → key=%s trailing=%s", + "get_events: 1F(browse) -> key=%s trailing=%s", key4.hex(), data8[4:8].hex(), ) except ProtocolError as exc: @@ -481,7 +481,7 @@ class MiniMateClient: try: key4, data8 = proto.advance_event(browse=True) log.info( - "get_events: 1F → key=%s trailing=%s", + "get_events: 1F -> key=%s trailing=%s", key4.hex(), data8[4:8].hex(), ) except ProtocolError as exc: @@ -1499,14 +1499,14 @@ def _encode_compliance_config( log.warning("_encode_compliance_config: anchor not found — cannot write sample_rate") else: struct.pack_into(">H", buf, _anc - 6, sample_rate) - log.debug("_encode_compliance_config: sample_rate=%d → offset %d", sample_rate, _anc - 6) + log.debug("_encode_compliance_config: sample_rate=%d -> offset %d", sample_rate, _anc - 6) if record_time is not None: if _anc < 0 or _anc + 10 > len(buf): log.warning("_encode_compliance_config: anchor not found — cannot write record_time") else: struct.pack_into(">f", buf, _anc + 6, record_time) - log.debug("_encode_compliance_config: record_time=%.3f → offset %d", record_time, _anc + 6) + log.debug("_encode_compliance_config: record_time=%.3f -> offset %d", record_time, _anc + 6) # ── Numeric: channel block (Tran label + unit-string guard) ─────────────── _needs_channel = any( @@ -1529,13 +1529,13 @@ def _encode_compliance_config( else: if max_range_geo is not None: struct.pack_into(">f", buf, _tran + 28, max_range_geo) - log.debug("_encode_compliance_config: max_range_geo=%.4f → offset %d", max_range_geo, _tran + 28) + log.debug("_encode_compliance_config: max_range_geo=%.4f -> offset %d", max_range_geo, _tran + 28) if trigger_level_geo is not None: struct.pack_into(">f", buf, _tran + 34, trigger_level_geo) - log.debug("_encode_compliance_config: trigger_level_geo=%.4f → offset %d", trigger_level_geo, _tran + 34) + log.debug("_encode_compliance_config: trigger_level_geo=%.4f -> offset %d", trigger_level_geo, _tran + 34) if alarm_level_geo is not None: struct.pack_into(">f", buf, _tran + 42, alarm_level_geo) - log.debug("_encode_compliance_config: alarm_level_geo=%.4f → offset %d", alarm_level_geo, _tran + 42) + log.debug("_encode_compliance_config: alarm_level_geo=%.4f -> offset %d", alarm_level_geo, _tran + 42) # ── ASCII strings (64-byte slot, value at label_pos+22) ─────────────────── def _set_string(label: bytes, value: Optional[str]) -> None: @@ -1548,7 +1548,7 @@ def _encode_compliance_config( val_bytes = value.encode("ascii", errors="replace")[:_COMPLIANCE_VALUE_MAX - 1] padded = val_bytes + b"\x00" * (_COMPLIANCE_VALUE_MAX - len(val_bytes)) buf[idx + _COMPLIANCE_VALUE_OFFSET : idx + _COMPLIANCE_SLOT_SIZE] = padded - log.debug("_encode_compliance_config: %r → %r", label, value) + log.debug("_encode_compliance_config: %r -> %r", label, value) _set_string(b"Project:", project) _set_string(b"Client:", client_name)