- 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)
6.5 KiB
ambilight-plasmoid
Ambilight per KDE Plasma 6: cattura il bordo superiore dello schermo su Wayland (portal ScreenCast + PipeWire), calcola il colore medio di 47 zone e pilota una striscia WS2812B collegata a un ESP8266 (Wemos D1 mini) con firmware Adalight via seriale. Il controllo sta in un plasmoide nel vassoio di sistema, con popup per luminosità, contrasto, saturazione e banda campionata.
schermo ──portal──▶ ambilightd ──Adalight/seriale──▶ ESP8266 ──▶ striscia
▲
│ D-Bus org.enne2.Ambilight
│
ambilight-ctl ◀── plasmoide (Plasma 6, QML)
Componenti
| File | Ruolo |
|---|---|
backend/ambicapture.py |
negoziazione ScreenCast portal + pipeline GStreamer (pipewiresrc) |
backend/ambilightd.py |
demone: cattura, calcolo zone, luminosità/contrasto/saturazione, invio Adalight, servizio D-Bus |
backend/ambilight-ctl |
CLI che parla col demone e stampa JSON (usata dal plasmoide) |
backend/ambilight.service |
unit systemd --user (avvio automatico al login) |
package/org.enne2.ambilight/ |
plasmoide Plasma 6 (icona nel vassoio + popup con slider) |
install.sh / uninstall.sh |
installazione e rimozione, senza root |
Hardware
- ESP8266 Wemos D1 mini (clone), firmware Adalight-FastLED con
PIN_DATA 5(= D1/GPIO5),Num_Leds= dimensione buffer (256): il numero reale di LED lo decide il software che invia i frame. - Striscia WS2812B 47 LED sul solo bordo superiore.
- Cablaggio:
D1 → 470 Ω → DIN, alimentatore 5 V separato (~60 mA/LED), massa comune, 1000 µF sull'alimentazione; level shifter 74AHCT125 se il filo dati è lungo.
Installazione
./install.sh # backend + servizio utente + plasmoide
Al primo avvio il desktop chiede il permesso di condividere lo schermo: va concesso
una volta (viene memorizzato in ~/.cache/ambilight/restore_token).
Il plasmoide appare nel vassoio come Ambilight (icona TV); clic per il popup.
Uso da terminale
ambilight-ctl state # JSON con tutto lo stato
ambilight-ctl start | stop | toggle
ambilight-ctl set brightness 0.8 # brightness|contrast|saturation|band|reverse|leds
ambilight-ctl get fps
systemctl --user status ambilight.service
Configurazione
~/.config/ambilight/config.json (scritto dal demone a ogni modifica):
| chiave | range | default | note |
|---|---|---|---|
brightness |
0.05 – 2.0 | 1.0 | moltiplicatore |
contrast |
0.5 – 2.0 | 1.0 | pivot sul grigio 128 |
saturation |
0.0 – 2.0 | 1.0 | 0 = bianco e nero |
band |
0.02 – 0.5 | 0.12 | frazione di altezza campionata |
reverse |
bool | true | LED 0 sul lato destro (verificato a schermo) |
leds |
1 – 256 | 47 | LED della striscia |
port, baud |
– | /dev/ttyUSB0, 115200 |
seriale |
side |
top/bottom | top | bordo campionato |
auto_start |
bool | true | streaming attivo all'avvio del demone |
Prestazioni misurate
- 47 LED, Adalight a 115200: ~78 fps (limite teorico della seriale per 147 byte/frame).
- Cattura: portal + PipeWire, pipeline ridotta a
47×4 × 72px RGB → costo CPU trascurabile.
Nome stabile del dispositivo seriale
La scheda (CH340, 1a86:7523) non espone un iSerial: verificato con
cat /sys/bus/usb/devices/1-2/serial → vuoto. Di conseguenza:
| percorso | valore su questa macchina | unico? |
|---|---|---|
/dev/ttyUSB0 |
assegnato in ordine di enumerazione | no |
/dev/serial/by-id/usb-1a86_USB_Serial-if00-port0 |
derivato da ID_SERIAL=1a86_USB_Serial |
no (due cloni identici collidono) |
/dev/serial/by-path/pci-0000:65:00.3-usb-0:2:1.0-port0 |
legato alla porta USB fisica | sì |
/dev/ambilight (regola udev) |
symlink creato da noi | sì |
Installa la regola (richiede sudo, una volta):
sudo ./setup-udev.sh /dev/ttyUSB0 # rileva la porta fisica e scrive /etc/udev/rules.d/99-ambilight.rules
ambilight-ctl set port /dev/ambilight
systemctl --user restart ambilight.service
La regola aggancia KERNELS=="<porta>" + VID/PID (non il numero ttyUSB), crea
/dev/ambilight, aggiunge ID_MM_DEVICE_IGNORE (ModemManager smette di sondare la
porta) e TAG+="uaccess" (accesso ACL all'utente attivo). Se sposti la scheda su
un'altra porta USB il nome non segue: rilancia setup-udev.sh.
Il demone comunque ripiega su /dev/ambilight e poi /dev/ttyUSB0 se il percorso
configurato non esiste, e riporta il dispositivo realmente aperto nel campo dev
di ambilight-ctl state.
L'indicatore di condivisione schermo nel vassoio
Con la cattura via portal ScreenCast, KDE mostra nel vassoio un pallino rosso finché la sessione di condivisione è attiva. Verificato su questa macchina:
- compare/scompare insieme allo streaming (diff di due screenshot: cambia solo quella regione del vassoio, ~1.500 px in 172x22);
- non è un plasmoide di sistema (
/usr/share/plasma/plasmoidsnon contiene nulla di simile) e non compare inknownItems/extraItemsdel vassoio, quindi non esiste la voce "Configure System Tray → Entries" per nasconderlo: è un indicatore di stato del shell, per scelta di KDE.
Le alternative per non averlo:
- KWin ScreenShot2 (nessun portal, nessun indicatore): KWin autorizza solo i
processi con un
.desktopche dichiaraX-KDE-DBUS-Restricted-Interfaces=org.kde.KWin.ScreenShot2. Provato con un.desktoputente (Exec=/usr/bin/python3epython3.14) +kbuildsycoca6: risponde ancoraorg.kde.KWin.ScreenShot2.Error.NoAuthorized. Non provato l'entry in/usr/local/share/applications(richiede sudo). Se funziona, la cattura è unCaptureAreadella sola fascia (nessun indicatore, ma costo CPU per frame). - kmsgrab (
ffmpeg -f kmsgrab) da un servizio privilegiato conCAP_SYS_ADMIN: nessun portal e nessun indicatore, ma cattura DRM grezza (piano/format legati alla GPU) e un servizio di sistema: più fragile. - Tenere il portal: costo GPU minimo, ~78 fps, indicatore visibile.
Note
- Il firmware Adalight manda
Ada\nuna volta al secondo quando non riceve frame: è l'heartbeat del protocollo, non un errore. - Il demone tiene la seriale in esclusiva: Prismatik (o altri programmi Adalight) vanno chiusi.
ModemManagersu Fedora può contendere/dev/ttyUSB0: se la porta risulta occupata serve una regola udev conID_MM_DEVICE_IGNORE.
Licenza
GPL-3.0-or-later (come i componenti KDE con cui interagisce).