El problema de múltiples dispositivos USB idénticos
Tengo un Rasperry Pi con cuatro cámaras. Tomo pix con las fswebcam
que se identifican las cámaras como /dev/video0
.. video3
. A veces, la cámara es video0
, vide02
, video4
y video6
pero puede olvidarse de eso por ahora.
Necesito una identificación persistente para identificar un número de cámara para que, por ejemplo, video0
sea siempre la misma cámara porque subtitulo las imágenes. Desafortunadamente, esto no sucede de manera confiable: en el arranque, las cámaras se enumeran como video0
... video3
pero no siempre de la misma manera.
Todas las cámaras tienen la misma identificación y número de serie.
La solución a este problema involucra las reglas de udev, pero también hay muchos anzuelos allí.
Si emite el comando
udevadm info –attribute-walk –path=/dev/video0
obtienes una regla de salida, pero los bits más destacados son
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
El bit KERNELS es un puerto concentrador USB. Con cuatro cámaras hay cuatro de estas: no cambian al reiniciar, pero las video{x}
asociadas con un puerto pueden cambiar.
Por lo tanto, necesitamos una regla udev para vincular un número de video a un puerto concentrador USB, algo como:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Parece simple: acceda a la cámara con
fswebcam –d $realpath /dev/camera0
Excepto que no funciona: si coloca esto en una regla udev y el sistema ha asignado video0 (en el arranque) a un puerto diferente, la regla udev se ignora. El enlace simbólico a /dev/camera0
básicamente dice no such device
. Un cuadrado.
Lo que queremos es vincular un enlace simbólico a una dirección de concentrador USB, no un video{x}
número. Tomó un programa de Python.
El primer paso fue correr
fswebcam –d /dev/video${x} tst.jpg
para x
entre 1 y 8. La existencia de tst.jpg
después de cada llamada identifica si hay una cámara en este número de video. A partir de esto, haga una lista de números de video activos. Mi experiencia ha sido que es 0,1,2,3
o 0,2,4,6
para las cámaras que he usado.
Otros, por supuesto, pueden construir esta lista utilizando un proceso diferente.
Luego, para cada número de video en la lista,
udevadm info –attribute-walk –path=/dev/videox > dd
y extraer el KERNELS= line
de dd
. De este proceso, termina con una lista de las direcciones de puerto USB para las cámaras. Ordene esta lista para que en el siguiente paso, siempre la procese en el mismo orden. Llame a esto la "lista de direcciones".
Ejecute la udevadm … > dd
cosa nuevamente y haga una lista que se vea como
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Ahora recorra la lista de direcciones: para cada entrada, busque la entrada correspondiente en la lista de videos. Cree una nueva lista que se parezca a una colección de líneas como
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
La x (número de enlace simbólico) se reemplaza por el número de secuencia en la lista de direcciones.
Ahora tienes una regla de udev que funciona. Un enlace simbólico vinculado a una dirección de concentrador USB, sin importar el número de video asignado a ese puerto en el arranque.
Escribe la lista final en un archivo /etc/udev/rules.d/cam.rules
. Ejecute udevadm trigger
para activarlo y el trabajo está hecho. /dev/camera2
será la misma cámara (puerto USB) independientemente de su número de video.