Refactor radar system
This commit is contained in:
@@ -20,6 +20,8 @@ from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
from python_app.file_io import atomic_write_json
|
||||
|
||||
_PathLike = Union[str, os.PathLike[str]]
|
||||
|
||||
# Default IPC locations. Both are overridable via CLI/API so several runs can use
|
||||
@@ -46,12 +48,7 @@ class LaserVariationSession:
|
||||
Writes to a temp file in the same directory then renames, so a concurrent
|
||||
checker never observes a half-written file.
|
||||
"""
|
||||
dest = Path(path)
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = dest.with_name(f"{dest.name}.{os.getpid()}.tmp")
|
||||
tmp.write_text(json.dumps(asdict(self), indent=2), encoding="utf-8")
|
||||
os.replace(tmp, dest)
|
||||
return dest
|
||||
return atomic_write_json(Path(path), asdict(self))
|
||||
|
||||
@classmethod
|
||||
def load(cls, path: _PathLike = DEFAULT_SESSION_PATH) -> "LaserVariationSession":
|
||||
|
||||
@@ -196,6 +196,8 @@ class Protocol:
|
||||
the bus. Note the lock is advisory (``flock``): every program that opens
|
||||
this port must also use ``exclusive=True`` for the guarantee to hold.
|
||||
"""
|
||||
if self.is_connected:
|
||||
return
|
||||
port = self._port_name or self._detect_port()
|
||||
try:
|
||||
self._serial = serial.Serial(
|
||||
@@ -219,9 +221,10 @@ class Protocol:
|
||||
|
||||
def disconnect(self) -> None:
|
||||
"""Close the serial port if open."""
|
||||
if self._serial and self._serial.is_open:
|
||||
connection, self._serial = self._serial, None
|
||||
if connection is not None and connection.is_open:
|
||||
logger.debug("Closing laser serial port")
|
||||
self._serial.close()
|
||||
connection.close()
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool:
|
||||
@@ -246,37 +249,6 @@ class Protocol:
|
||||
raise CommunicationError("Serial port is not connected")
|
||||
return self._serial.read(length)
|
||||
|
||||
# ---- Static encoding helpers (no connection required) ---------------
|
||||
|
||||
@staticmethod
|
||||
def flipfour(value: int) -> int:
|
||||
"""Byte-swap a 16-bit integer (little-endian word swap)."""
|
||||
return ((value & 0xFF) << 8) | ((value >> 8) & 0xFF)
|
||||
|
||||
@staticmethod
|
||||
def pack_float(value: float) -> bytes:
|
||||
return struct.pack('<f', value)
|
||||
|
||||
@staticmethod
|
||||
def pack_uint16(value: int) -> bytes:
|
||||
return struct.pack('<H', value)
|
||||
|
||||
@staticmethod
|
||||
def calculate_crc(data: bytes) -> int:
|
||||
"""Return the XOR CRC over all 16-bit words except word 0 and the CRC field.
|
||||
|
||||
The command-code word (word 0) is excluded, matching the firmware's CRC
|
||||
expectation.
|
||||
"""
|
||||
hex_str = data.hex()
|
||||
words = [hex_str[i:i+4] for i in range(0, len(hex_str), 4)]
|
||||
# Word 0 (command code) is excluded from the CRC.
|
||||
crc_words = words[1:]
|
||||
result = int(crc_words[0], 16)
|
||||
for w in crc_words[1:]:
|
||||
result ^= int(w, 16)
|
||||
return result
|
||||
|
||||
# ---- Command encoders -----------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
@@ -404,11 +376,6 @@ class Protocol:
|
||||
"""Build DEFAULT_ENABLE command (0x2222) — reset device."""
|
||||
return bytearray.fromhex(_flipfour(_int_to_hex4(CMD_DEFAULT_ENABLE)))
|
||||
|
||||
@staticmethod
|
||||
def encode_remove_file() -> bytes:
|
||||
"""Build REMOVE_FILE command (0x5555) — delete saved data."""
|
||||
return bytearray.fromhex(_flipfour(_int_to_hex4(CMD_REMOVE_FILE)))
|
||||
|
||||
# ---- Response decoders -----------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
@@ -477,4 +444,4 @@ class Protocol:
|
||||
@staticmethod
|
||||
def state_to_description(state_hex_str: str) -> str:
|
||||
"""Return human-readable description for a state hex string."""
|
||||
return STATE_DESCRIPTIONS.get(state_hex_str, "Unknown or reserved error.")
|
||||
return STATE_DESCRIPTIONS.get(state_hex_str, "Unknown or reserved error.")
|
||||
|
||||
Reference in New Issue
Block a user