Le problème de plusieurs périphériques USB identiques
J'ai un Rasperry Pi avec quatre caméras. Je prends pix avec fswebcam
qui identifie les caméras comme /dev/video0
.. video3
. Parfois , la caméra est video0
, vide02
, video4
et video6
mais nous pouvons oublier que pour l' instant.
J'ai besoin d'un identifiant persistant pour identifier un numéro de caméra, par exemple, video0
c'est toujours la même caméra car je sous-titrai les images. Malheureusement, cela n’arrive pas de façon fiable: au démarrage, les caméras sont énumérées de la manière suivante video0
… video3
mais pas toujours de la même manière.
Les caméras ont toutes le même ID et le même numéro de série.
La solution à ce problème implique des règles udev, mais il y a aussi beaucoup d'hameçons.
Si vous lancez la commande
udevadm info –attribute-walk –path=/dev/video0
vous obtenez une table de sortie, mais les éléments saillants sont
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
Le bit KERNELS est un port hub USB. Avec quatre caméras, il y en a quatre - elles ne changent pas au redémarrage, mais le video{x}
port associé à un port peut changer.
Nous avons donc besoin d’une règle udev pour lier un numéro de vidéo à un port de hub USB - quelque chose comme:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Ça a l'air simple - accéder à la caméra avec
fswebcam –d $realpath /dev/camera0
Sauf que cela ne fonctionne pas - si vous mettez cela dans une règle udev et que le système a alloué video0 (au démarrage) à un autre port, la règle udev est ignorée. Le lien symbolique /dev/camera0
dit en gros no such device
. Carré un.
Ce que nous voulons, c'est lier un lien symbolique à une adresse de concentrateur USB, pas à un video{x}
numéro. Il a fallu un programme Python.
La première étape a été de courir
fswebcam –d /dev/video${x} tst.jpg
pour x
entre 1 et 8. L'existence de tst.jpg
après chaque appel identifie s'il y a une caméra sur ce numéro de vidéo. À partir de cela, faites une liste des numéros de vidéo actifs. Mon expérience a été que c'est soit 0,1,2,3
ou 0,2,4,6
pour les appareils photo que j'ai utilisés.
D'autres peuvent bien sûr construire cette liste en utilisant un processus différent.
Puis pour chaque numéro de vidéo dans la liste
udevadm info –attribute-walk –path=/dev/videox > dd
et extraire le KERNELS= line
de dd
. A partir de ce processus, vous obtenez une liste d'adresses de ports USB pour les caméras. Triez cette liste de manière à la traiter toujours dans le même ordre à l'étape suivante. Appelez cela la "liste d'adresses".
Exécutez la udevadm … > dd
chose à nouveau et faites une liste qui ressemble à
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Parcourez maintenant la liste d'adresses - pour chaque entrée, recherchez l'entrée correspondante dans la liste de vidéos. Créez une nouvelle liste qui ressemble à une collection de lignes comme
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
Le x (numéro de lien symbolique) est remplacé par le numéro de séquence dans la liste d'adresses.
Maintenant, vous avez une règle udev qui fonctionne. Un lien symbolique lié à une adresse de concentrateur USB, quel que soit le numéro de vidéo attribué à ce port au démarrage.
Écrivez la liste finale dans un fichier /etc/udev/rules.d/cam.rules
. Exécuter udevadm trigger
pour l'activer et le travail est terminé. /dev/camera2
sera la même caméra (port USB) quel que soit son numéro de vidéo.