O problema do dispositivo USB com vários dispositivos idênticos
Eu tenho um Rasperry Pi com quatro câmeras. Eu tiro 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 isso por enquanto.
Eu preciso de um ID persistente para identificar um número de câmera, por exemplo, video0
é sempre a mesma câmera porque eu lego as imagens. Infelizmente isso não acontece de forma confiável - na inicialização, as câmeras são enumeradas como video0
.. video3
, mas nem sempre da mesma maneira.
Todas as câmeras têm o mesmo ID e número de série.
A solução para este problema envolve regras do udev, mas também há 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 o video{x}
associado 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 o vídeo0 (durante a inicialização) para uma porta diferente, a regra do udev será ignorada. O link simbólico para /dev/camera0
diz basicamente no such device
. Quadrado um.
O que queremos é vincular um link simbólico a um endereço de hub USB, não um video{x}
number. Demorou um programa em 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 se há uma câmera neste número de vídeo. A partir disso, faça uma lista de números de vídeo ativos. Minha experiência tem sido que é 0,1,2,3
ou 0,2,4,6
para câmeras que usei.
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
. Deste processo você acaba com uma lista de endereços de porta USB para as câmeras. Classifique essa lista para que, na próxima etapa, você sempre a processe na mesma ordem. Chame isso de "lista de endereços".
Execute novamente a coisa udevadm … > dd
e faça uma lista parecida 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, localize a entrada correspondente na lista de vídeos. Crie uma nova lista que se parece 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 alocado 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 seu número de vídeo.