import csv, re, serial from typing import Callable, Optional CTRL_SPLIT_RE = re.compile(rb'[\x1d\x1e\x04]+') # GS, RS, EOT def _strip_header_bytes(b: bytes) -> bytes: b = b.strip() if b.startswith(b'\x02'): b = b[1:] # STX if b.startswith(b'[)>'): b = b[3:] if b.startswith(b'06'): b = b[2:] # format code return b def _normalize_from_bytes(raw: bytes) -> str: raw = _strip_header_bytes(raw) chunks = [c for c in CTRL_SPLIT_RE.split(raw) if c] flat = b''.join(chunks) if chunks else raw s = flat.decode('ascii', errors='ignore').strip() if s.startswith('06'): s = s[2:] return s def scan_loop(port: str, baud: int, on_scan: Callable[[str], None]): ser = serial.Serial(port, baud, timeout=2) print(f"Opened {port}. Ready — scan a label.") while True: data = ser.read_until(b'\r') # adjust to b'\n' if needed if not data: continue flat = _normalize_from_bytes(data) if flat: on_scan(flat) def maybe_append_csv(path: Optional[str], fields: dict): if not path: return newfile = not os.path.exists(path) import os with open(path, "a", newline="", encoding="utf-8") as f: w = csv.DictWriter(f, fieldnames=list(fields.keys())) if newfile: w.writeheader() w.writerow(fields) def read_one_scan(port: str, baud: int, read_terminator: bytes = b'\r') -> str: with serial.Serial(port, baud, timeout=10) as ser: data = ser.read_until(read_terminator) return _normalize_from_bytes(data)