Nome stabile della seriale via udev e note sull'indicatore di cattura

- udev/99-ambilight.rules: symlink /dev/ambilight ancorato alla porta USB fisica
  (il CH340 clone non ha iSerial, quindi by-id non e' univoco), ID_MM_DEVICE_IGNORE,
  TAG+=uaccess
- setup-udev.sh: rileva VID/PID/porta, installa la regola, verifica il symlink
- backend: fallback di porta (config -> /dev/ambilight -> /dev/ttyUSB0) e campo 'dev'
  nello stato D-Bus
- README: tabella dei percorsi, prove sull'indicatore di condivisione schermo e le
  tre alternative (portal, KWin ScreenShot2, kmsgrab)
This commit is contained in:
enne2
2026-11-01 13:16:08 +01:00
parent a3b6bc66c9
commit db47640846
5 changed files with 154 additions and 2 deletions
+22 -2
View File
@@ -87,16 +87,32 @@ def adalight_frame(pixels):
class Strip:
"""Porta seriale con apertura pigra e riconnessione."""
"""Porta seriale con apertura pigra, nome stabile e riconnessione.
Il percorso configurato ha la precedenza; se non esiste si prova il symlink
udev /dev/ambilight e infine /dev/ttyUSB0 (primo disponibile).
"""
def __init__(self, port, baud):
self.port, self.baud = port, baud
self.ser = None
self.resolved = port
self.error = ""
def _candidates(self):
seen = []
for p in (self.port, "/dev/ambilight", "/dev/ttyUSB0"):
if p and p not in seen:
seen.append(p)
return [p for p in seen if os.path.exists(p)]
def _open(self):
import serial
self.ser = serial.Serial(self.port, self.baud, timeout=0.2, write_timeout=0.2)
cands = self._candidates()
if not cands:
raise RuntimeError(f"nessun dispositivo seriale fra {self.port}, /dev/ambilight, /dev/ttyUSB0")
self.resolved = cands[0]
self.ser = serial.Serial(self.resolved, self.baud, timeout=0.2, write_timeout=0.2)
try:
self.ser.setDTR(False)
self.ser.setRTS(False)
@@ -134,6 +150,7 @@ class State:
def __init__(self, cfg):
self.lock = threading.Lock()
self.cfg = cfg
self.strip_dev = cfg.get("port", "")
self.running = bool(cfg.get("auto_start", True))
self.fps = 0.0
self.stream_error = ""
@@ -146,6 +163,7 @@ class State:
d["fps"] = round(self.fps, 1)
d["stream_error"] = self.stream_error
d["last_error"] = self.last_error
d["dev"] = getattr(self, "strip_dev", "")
return d
def update(self, **kw):
@@ -229,6 +247,7 @@ def capture_loop(state, strip):
if cfg["reverse"]:
px.reverse()
state.strip_dev = strip.resolved
if strip.write(adalight_frame(px)):
sent += 1
now = time.time()
@@ -400,6 +419,7 @@ def main():
cfg = load_config()
state = State(cfg)
strip = Strip(cfg["port"], cfg["baud"])
state.strip_dev = strip.resolved
svc = DBusService(state, strip)
th = threading.Thread(target=capture_loop, args=(state, strip), daemon=True)
th.start()