projector version
This commit is contained in:
@@ -33,6 +33,7 @@ from .models import Measurements, VariationType
|
||||
from .exceptions import (
|
||||
CommunicationError,
|
||||
PortNotFoundError,
|
||||
PortBusyError,
|
||||
CRCError,
|
||||
ProtocolError,
|
||||
)
|
||||
@@ -184,20 +185,36 @@ class Protocol:
|
||||
# ---- Connection management
|
||||
|
||||
def connect(self) -> None:
|
||||
"""Open the serial port. Auto-detects the device path when port is None."""
|
||||
"""Open the serial port. Auto-detects the device path when port is None.
|
||||
|
||||
The port is opened with ``exclusive=True`` so only one program can own the
|
||||
laser controller at a time. This is required because the board is a single
|
||||
half-duplex request/response bus: if two processes opened it, their
|
||||
commands and responses would interleave and corrupt each other. A second
|
||||
opener fails fast with :class:`PortBusyError` instead of silently sharing
|
||||
the bus. Note the lock is advisory (``flock``): every program that opens
|
||||
this port must also use ``exclusive=True`` for the guarantee to hold.
|
||||
"""
|
||||
port = self._port_name or self._detect_port()
|
||||
try:
|
||||
self._serial = serial.Serial(
|
||||
port=port,
|
||||
baudrate=BAUDRATE,
|
||||
timeout=SERIAL_TIMEOUT_SEC,
|
||||
exclusive=True,
|
||||
)
|
||||
except serial.SerialException as exc:
|
||||
# pyserial raises SerialException with errno EAGAIN/EWOULDBLOCK (11)
|
||||
# when another process already holds the exclusive flock.
|
||||
if getattr(exc, "errno", None) in (11,) or "exclusively lock" in str(exc).lower():
|
||||
logger.error("Laser serial port '%s' is busy (held by another program)", port)
|
||||
raise PortBusyError(port) from exc
|
||||
logger.error("Cannot open laser serial port '%s': %s", port, exc)
|
||||
raise CommunicationError(f"Cannot connect to port '{port}': {exc}") from exc
|
||||
except Exception as exc:
|
||||
logger.error("Cannot open laser serial port '%s': %s", port, exc)
|
||||
raise CommunicationError(
|
||||
f"Cannot connect to port '{port}': {exc}"
|
||||
) from exc
|
||||
logger.debug("Laser serial port opened: %s @ %d baud", port, BAUDRATE)
|
||||
raise CommunicationError(f"Cannot connect to port '{port}': {exc}") from exc
|
||||
logger.debug("Laser serial port opened (exclusive): %s @ %d baud", port, BAUDRATE)
|
||||
|
||||
def disconnect(self) -> None:
|
||||
"""Close the serial port if open."""
|
||||
|
||||
Reference in New Issue
Block a user