diff options
Diffstat (limited to 'api_layers/arduino_layer.py')
| -rw-r--r-- | api_layers/arduino_layer.py | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/api_layers/arduino_layer.py b/api_layers/arduino_layer.py index a3c3584..07520d6 100644 --- a/api_layers/arduino_layer.py +++ b/api_layers/arduino_layer.py @@ -575,6 +575,46 @@ class ArduinoLayer: return desc return "" + @staticmethod + def port_serial_number(port: str) -> str: + """USB serial number for a currently-connected port, if the OS/driver + exposes one — empty string if unavailable or the port isn't enumerable.""" + if not _SERIAL_AVAILABLE: + return "" + try: + for p in serial.tools.list_ports.comports(): + if p.device == port: + return getattr(p, "serial_number", None) or "" + except Exception as e: + print(f"[ArduinoLayer] port_serial_number() error: {e}") + return "" + + @staticmethod + def find_port_by_identity(description: str = "", serial_number: str = "") -> Optional[str]: + """Re-map a device saved in a profile to whatever port it enumerates + as on *this* machine — COM/tty numbers aren't stable across machines + (or even across replugs on Linux). Prefers USB serial number (unique + even between two identical board models); falls back to an exact + description-string match. Returns None if nothing matches — caller + should fall back to the saved port as-is (device will show ERROR + until the operator fixes it manually).""" + if not _SERIAL_AVAILABLE: + return None + try: + ports = list(serial.tools.list_ports.comports()) + except Exception as e: + print(f"[ArduinoLayer] find_port_by_identity() error: {e}") + return None + if serial_number: + for p in ports: + if (getattr(p, "serial_number", None) or "") == serial_number: + return p.device + if description: + for p in ports: + if (p.description or "") == description: + return p.device + return None + def __repr__(self): mode = "SIM" if self.simulate else f"HW:{self.port}@{self.baud}" return f"<ArduinoLayer {mode} pins={self.analog_pins}>" |
