Il problema con più dispositivi USB identici
Ho un Rasperry Pi con quattro telecamere. Prendo pix con fswebcam
che individua le telecamere come /dev/video0
.. video3
. A volte la fotocamera è video0
, vide02
, video4
e video6
ma possiamo dimenticare che per ora.
Ho bisogno di un ID persistente per identificare un numero di telecamera in modo che, ad esempio, video0
sia sempre la stessa telecamera perché inserisco le didascalie delle immagini. Sfortunatamente questo non accade in modo affidabile: all'avvio, le telecamere vengono elencate come video0
.. video3
ma non sempre allo stesso modo.
Tutte le telecamere hanno lo stesso ID e numero di serie.
La soluzione a questo problema riguarda le regole di udev, ma ci sono anche molti ami.
Se si emette il comando
udevadm info –attribute-walk –path=/dev/video0
ottieni un massetto di output ma i bit salienti lo sono
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
Il bit KERNELS è una porta hub USB. Con quattro telecamere ce ne sono quattro: non cambiano al riavvio, ma le video{x}
porte associate possono cambiare.
Quindi abbiamo bisogno di una regola udev per legare un numero video a una porta hub USB - qualcosa del tipo:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Sembra semplice: accedi alla videocamera con
fswebcam –d $realpath /dev/camera0
Tranne che non funziona: se lo inserisci in una regola udev e il sistema ha allocato video0 (all'avvio) su una porta diversa, la regola udev viene ignorata. Il link simbolico /dev/camera0
dice sostanzialmente no such device
. Square one.
Ciò che vogliamo è associare un collegamento simbolico a un indirizzo hub USB, non a un video{x}
numero. Ci è voluto un programma Python.
Il primo passo è stato correre
fswebcam –d /dev/video${x} tst.jpg
per x
tra 1 e 8. L'esistenza di tst.jpg
dopo ogni chiamata identifica se v'è una fotocamera a questo numero video. Da questo crea un elenco di numeri di video attivi. La mia esperienza è stata che è 0,1,2,3
o 0,2,4,6
per le fotocamere che ho usato.
Altri possono ovviamente compilare questo elenco usando un processo diverso.
Quindi, per ogni numero di video nell'elenco eseguire
udevadm info –attribute-walk –path=/dev/videox > dd
ed estrarre il KERNELS= line
da dd
. Da questo processo si finisce con un elenco degli indirizzi delle porte USB per le telecamere. Ordina questo elenco in modo che al passaggio successivo, lo elabori sempre nello stesso ordine. Chiamalo "elenco indirizzi".
Esegui di udevadm … > dd
nuovo la cosa e crea un elenco simile
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Ora passa attraverso l'elenco degli indirizzi - per ogni voce trova la voce corrispondente dall'elenco dei video. Crea un nuovo elenco che assomigli a una raccolta di linee simili
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
La x (numero del collegamento simbolico) è sostituita dal numero di sequenza nell'elenco indirizzi.
Ora hai una regola udev che funziona. Un collegamento simbolico collegato a un indirizzo hub USB, indipendentemente dal numero di video assegnato a quella porta all'avvio.
Scrivi l'elenco finale in un file /etc/udev/rules.d/cam.rules
. Esegui udevadm trigger
per attivarlo e il lavoro è fatto. /dev/camera2
sarà la stessa fotocamera (porta USB) indipendentemente dal suo numero video.