O problema de vários dispositivos USB idênticos
Eu tenho um Rasperry Pi com quatro câmeras. Eu tomo pix com fswebcam
que identifica as câmeras como /dev/video0
.. video3
. Às vezes, a câmera é video0
, vide02
, video4
e video6
mas podemos esquecer que, por enquanto.
Eu preciso de um ID persistente para identificar um número de câmera, de modo que, por exemplo, video0
seja sempre a mesma câmera, porque eu legendo as fotos. Infelizmente, isso não acontece de maneira confiável - na inicialização, as câmeras são enumeradas como video0
... video3
mas nem sempre da mesma maneira.
As câmeras têm o mesmo ID e número de série.
A solução para esse problema envolve regras do udev, mas também existem muitos anzóis.
Se você emitir o comando
udevadm info –attribute-walk –path=/dev/video0
você obtém uma mesa de saída, mas os bits salientes são
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
O bit KERNELS é uma porta de hub USB. Com quatro câmeras, há quatro delas - elas não mudam na reinicialização, mas a video{x}
associada a uma porta pode mudar.
Portanto, precisamos de uma regra do udev para vincular um número de vídeo a uma porta de hub USB - algo como:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Parece simples - acesse a câmera com
fswebcam –d $realpath /dev/camera0
Exceto que não funciona - se você colocar isso em uma regra do udev e o sistema tiver alocado video0 (na inicialização) para uma porta diferente, a regra do udev será ignorada. O link simbólico para /dev/camera0
basicamente diz no such device
. Quadrado um.
O que queremos é vincular um link simbólico a um endereço de hub USB, não a um video{x}
número. Foi necessário um programa Python.
O primeiro passo foi correr
fswebcam –d /dev/video${x} tst.jpg
para x
entre 1 e 8. A existência de tst.jpg
após cada chamada identifica a existência de uma câmara nesta número de vídeo. A partir disso, faça uma lista dos números de vídeo ativos. Minha experiência tem sido que é tanto 0,1,2,3
ou 0,2,4,6
para câmeras que tenho usado.
Outros podem, é claro, criar essa lista usando um processo diferente.
Em seguida, para cada número de vídeo na lista, execute
udevadm info –attribute-walk –path=/dev/videox > dd
e extraia o KERNELS= line
de dd
. Nesse processo, você acaba com uma lista dos endereços de porta USB das câmeras. Classifique esta lista para que, na próxima etapa, você sempre a processe na mesma ordem. Chame isso de "lista de endereços".
Execute a udevadm … > dd
coisa novamente e faça uma lista que se parece com
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Agora, percorra a lista de endereços - para cada entrada, encontre a entrada correspondente na lista de vídeos. Crie uma nova lista que se pareça com uma coleção de linhas como
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
O x (número do link simbólico) é substituído pelo número de sequência na lista de endereços.
Agora você tem uma regra do udev que funciona. Um link simbólico vinculado a um endereço de hub USB, independentemente do número de vídeo atribuído a essa porta na inicialização.
Escreva a lista final em um arquivo /etc/udev/rules.d/cam.rules
. Execute udevadm trigger
para ativá-lo e o trabalho está concluído. /dev/camera2
será a mesma câmera (porta USB), independentemente do número de vídeo.