refactor: normalize data directory naming, and consolidate serial connection handling
This commit is contained in:
@@ -309,9 +309,11 @@ class SessionController(QObject):
|
||||
|
||||
# The new binary protocol sends payload of (sensorCount * 2) bytes
|
||||
# Each sensor is a big-endian 16-bit value (Sign-Magnitude).
|
||||
expected_sensors = 80 if (family_code or "") == "X" else 244
|
||||
|
||||
def parse_binary_frame(payload: bytes, seq: int) -> Frame:
|
||||
values = []
|
||||
num_sensors = min(80, len(payload) // 2)
|
||||
num_sensors = min(expected_sensors, len(payload) // 2)
|
||||
for i in range(num_sensors):
|
||||
high_byte = payload[i * 2]
|
||||
low_byte = payload[i * 2 + 1]
|
||||
@@ -333,13 +335,9 @@ class SessionController(QObject):
|
||||
self._last = None
|
||||
self._last_raw_frame = None
|
||||
|
||||
try:
|
||||
transport = pyserial.Serial(port, SerialPort.BAUDRATE, timeout=1)
|
||||
except Exception as exc:
|
||||
log.warning("Baud rate %d failed on %s, falling back to 115200: %s", SerialPort.BAUDRATE, port, exc)
|
||||
transport = pyserial.Serial(port, 115200, timeout=1)
|
||||
transport = SerialPort.open_port(port, timeout=1)
|
||||
# Send 'D2' command padded to 512 bytes to start the stream
|
||||
cmd = b"D2" + (b"F" * 510)
|
||||
cmd = b"D2" + SerialPort.COMMAND_PAD.encode()
|
||||
transport.write(cmd)
|
||||
|
||||
def on_error(exc: Exception):
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# ===== Backend Data Constants =====
|
||||
|
||||
DEFAULT_DATA_DIR_NAME = "isc_data"
|
||||
@@ -10,6 +10,7 @@ from PySide6.QtWidgets import QFileDialog, QMessageBox
|
||||
|
||||
from pygui.backend.data.csv_file_metadata import CSVFileMetadata
|
||||
from pygui.backend.wafer.zwafer_parser import ZWaferParser
|
||||
from pygui.backend.data.constants import DEFAULT_DATA_DIR_NAME
|
||||
|
||||
|
||||
# ===== File Browser Model =====
|
||||
@@ -232,7 +233,7 @@ class FileBrowser(QObject):
|
||||
QStandardPaths.DocumentsLocation
|
||||
)
|
||||
base_dir = Path(documents_dir) if documents_dir else (Path.home() / "Documents")
|
||||
return base_dir / "ISC_DATA"
|
||||
return base_dir / DEFAULT_DATA_DIR_NAME
|
||||
|
||||
def _set_current_directory(self, directory: Path) -> None:
|
||||
normalized = Path(directory)
|
||||
|
||||
@@ -7,6 +7,7 @@ from typing import Any
|
||||
from PySide6.QtCore import QObject, Property, QDateTime, QStandardPaths, Signal, Slot
|
||||
|
||||
from pygui.backend.data.local_settings import LocalSettings
|
||||
from pygui.backend.data.constants import DEFAULT_DATA_DIR_NAME
|
||||
|
||||
|
||||
MASTER_FAMILIES = ("A", "B", "C", "D", "E", "F", "P", "X", "Z")
|
||||
@@ -52,7 +53,7 @@ class LocalSettingsModel(QObject):
|
||||
QStandardPaths.DocumentsLocation
|
||||
)
|
||||
base_dir = Path(documents_dir) if documents_dir else (Path.home() / "Documents")
|
||||
return base_dir / "ISC_DATA"
|
||||
return base_dir / DEFAULT_DATA_DIR_NAME
|
||||
|
||||
def _new_defaults(self) -> dict[str, Any]:
|
||||
return {
|
||||
|
||||
@@ -46,28 +46,16 @@ class SerialPort:
|
||||
self._port_name = port_name
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Context manager for scoped port access
|
||||
# Port opening (shared between scoped and long-lived use)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@contextmanager
|
||||
def _open(self, timeout: float | None = None) -> Iterator[pyserial.Serial]:
|
||||
"""Open the serial port, yield it, then close on exit."""
|
||||
try:
|
||||
port = pyserial.Serial(
|
||||
self._port_name,
|
||||
self.BAUDRATE,
|
||||
parity=pyserial.PARITY_NONE,
|
||||
bytesize=8,
|
||||
stopbits=pyserial.STOPBITS_ONE,
|
||||
xonxoff=False,
|
||||
rtscts=False,
|
||||
dsrdtr=False,
|
||||
)
|
||||
except Exception as exc:
|
||||
log.warning("Baud rate %d failed on %s, falling back to 115200: %s", self.BAUDRATE, self._port_name, exc)
|
||||
port = pyserial.Serial(
|
||||
self._port_name,
|
||||
115200,
|
||||
@staticmethod
|
||||
def open_port(port_name: str, timeout: float | None = None) -> pyserial.Serial:
|
||||
"""Open a serial port with baud-rate fallback.
|
||||
|
||||
Tries SerialPort.BAUDRATE first, falls back to 115200 on failure.
|
||||
The caller owns the lifecycle of the returned Serial object."""
|
||||
kwargs = dict(
|
||||
parity=pyserial.PARITY_NONE,
|
||||
bytesize=8,
|
||||
stopbits=pyserial.STOPBITS_ONE,
|
||||
@@ -76,7 +64,22 @@ class SerialPort:
|
||||
dsrdtr=False,
|
||||
)
|
||||
if timeout is not None:
|
||||
port.timeout = timeout
|
||||
kwargs["timeout"] = timeout
|
||||
|
||||
try:
|
||||
return pyserial.Serial(port_name, SerialPort.BAUDRATE, **kwargs)
|
||||
except Exception as exc:
|
||||
log.warning("Baud rate %d failed on %s, falling back to 115200: %s", SerialPort.BAUDRATE, port_name, exc)
|
||||
return pyserial.Serial(port_name, 115200, **kwargs)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Context manager for scoped port access
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@contextmanager
|
||||
def _open(self, timeout: float | None = None) -> Iterator[pyserial.Serial]:
|
||||
"""Open the serial port, yield it, then close on exit."""
|
||||
port = self.open_port(self._port_name, timeout=timeout)
|
||||
try:
|
||||
yield port
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user