Проблема с несколькими идентичными USB-устройствами
У меня есть Rasperry Pi с четырьмя камерами. Я принимаю пикс с fswebcam
которой идентифицирует камеры , как /dev/video0
.. video3
. Иногда камера video0
, vide02
, video4
и , video6
но мы можем забыть о том, что на данный момент.
Мне нужен постоянный идентификатор для идентификации номера камеры, чтобы, например video0
, всегда была одна и та же камера, потому что я подписываю снимки. К сожалению, это не происходит надежно - при загрузке камеры перечисляются как video0
... video3
но не всегда одинаково.
Все камеры имеют одинаковый идентификатор и серийный номер.
Решение этой проблемы включает в себя правила udev, но там также есть много рыболовных крючков.
Если вы выполните команду
udevadm info –attribute-walk –path=/dev/video0
вы получаете разметку выходных данных, но выдающиеся биты
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
Бит KERNELS - это порт USB-концентратора. С четырьмя камерами их четыре - они не меняются при перезагрузке, но video{x}
связанные с портом могут измениться.
Поэтому нам нужно правило udev для привязки номера видео к порту USB-концентратора - что-то вроде:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Выглядит просто - доступ к камере с
fswebcam –d $realpath /dev/camera0
За исключением того, что это не работает - если вы поместите это в правило udev, и система выделит video0 (при загрузке) для другого порта, правило udev игнорируется. Символьная ссылка в /dev/camera0
основном говорит no such device
. Квадратная.
Мы хотим связать символическую ссылку с адресом USB-концентратора, а не с video{x}
номером. Потребовалась программа на Python.
Первый шаг должен был бежать
fswebcam –d /dev/video${x} tst.jpg
для x
между 1 и 8. Существование tst.jpg
после каждого вызова идентифицирует есть ли камера на этом видео числом. Из этого сделайте список активных видео номеров. Мой опыт показывает, что это либо 0,1,2,3
или 0,2,4,6
для камер я использовал.
Другие могут, конечно, построить этот список, используя другой процесс.
Затем для каждого номера видео в списке запустить
udevadm info –attribute-walk –path=/dev/videox > dd
и извлечь KERNELS= line
из dd
. В результате вы получите список адресов портов USB для камер. Сортируйте этот список так, чтобы на следующем шаге вы всегда обрабатывали его в одном и том же порядке. Назовите это «список адресов».
Запустите udevadm … > dd
вещь снова и создайте список, который выглядит как
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Теперь пройдитесь по списку адресов - для каждой записи найдите соответствующую запись из списка видео. Создайте новый список, который выглядит как набор строк, таких как
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
Символ x (номер символической ссылки) заменяется порядковым номером в списке адресов.
Теперь у вас есть правило udev, которое работает. Символическая ссылка, привязанная к адресу концентратора USB, независимо от того, какой номер видео выделен этому порту при загрузке.
Запишите окончательный список в файл /etc/udev/rules.d/cam.rules
. Запустите, udevadm trigger
чтобы активировать его, и работа сделана. /dev/camera2
будет одна и та же камера (порт USB) независимо от ее номера видео.