@Scorpiored88

Как привязать usb модем через udev symlink?

Всем доброго! Никак не могу решить решить проблему с которой столкнулся.
Есть у меня несколько модемов (2шт) при подключении система видит один модем как
ttyUSB0,ttyUSB1,ttyUSB2

голос,данные и что-то ище...
При подключении 2-х модемов, в системе получается от USB0 .... до ttyUSB5.
Все как бы ок, но после еперезагрузки, модемы определяются уже по другому. Тоесть если MTS_01 раньше был равен ttyUSB0,ttyUSB1,ttyUSB2 то тепер он определяется как ttyUSB3,ttyUSB4,ttyUSB5 , а модем MTS_02 тепер виден как ttyUSB0,ttyUSB1,ttyUSB2.
Решил я привязать их через udev symlink, создал вот такое правило :


KERNEL=="ttyUSB*", DEVPATH=="/devices/pci0000:00/0000:00:1a.7/usb1/1-3/1-3:1.0/*", SYMLINK+="mts-01-audio"
KERNEL=="ttyUSB*", DEVPATH=="/devices/pci0000:00/0000:00:1a.7/usb1/1-3/1-3:1.1/*", SYMLINK+="mts-01-data"
KERNEL=="ttyUSB*", DEVPATH=="/devices/pci0000:00/0000:00:1a.7/usb1/1-3/1-3:1.2/*", SYMLINK+="mts-01-other"

KERNEL=="ttyUSB*", DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb7/7-1/7-1:1.0/*", SYMLINK+="mts-02-audio"
KERNEL=="ttyUSB*", DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb7/7-1/7-1:1.1/*", SYMLINK+="mts-02-data"
KERNEL=="ttyUSB*", DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb7/7-1/7-1:1.2/*", SYMLINK+="mts-02-other"


в сети видел примеры где в место DEVPATH (как у меня) берут другие параметры, но у меня работает только с DEVPATH параметры которого я беру с udevadm info --query=property --name=ttyUSB0.

С таким правилом , если передергивать модемы - все работает отлично, но если перегрузить систему, то вот номер usb "usb7/7-1/7-1:1" по которому собственно и делается привязка, почему-то меняется,и соответственно правила не срабатывают :(
Как мне привязать устройство по symlink?
Каких то других уникальных данных,к которым я мог бы привязатся не вижу :( модели модемов одинаковы.
Пытался я привязать по параметру ATTRS{device} который можно найти введя команду
udevadm info -a -n /dev/ttyUSB , но он идентичен для всех ttyUSB данного модема (тоесть для MTS-01 ttyUSB0,ttyUSB1 и ttyUSB2 он тот же) но другой нежели y MTS-02 ttyUSB3... .
поэтому пробывал добавить туда ище и параметры DEVLINKS c команды udevadm info --query=property --name=ttyUSB там у каждого ttyUSB разний HUAWEI_Mobile-if00 ,HUAWEI_Mobile-if01, HUAWEI_Mobile-if02


KERNEL=="ttyUSB*", DEVLINKS==“/dev/serial/by-id/usb-HUAWEI_Technology_HUAWEI_Mobile-if00-port0*” , ATTRS{device}=="0x2835", SYMLINK+=“mts—audio”

и так тоже не работает

SUBSYSTEMS=="tty", ENV{DEVLINKS}==“/dev/serial/by-id/usb-HUAWEI_Technology_HUAWEI_Mobile-if00-port0*” , ATTRS{device}=="0x2835", SYMLINK+=“mts—audio”


Может я не оттуда параметры для привязки беру (
udevadm info -a -n /dev/ttyUSB , udevadm info --query=property --name=ttyUSB , udevadm monitor --environment --udev
) или причина в чем то другом...
  • Вопрос задан
  • 2280 просмотров
Пригласить эксперта
Ответы на вопрос 2
tomat17
@tomat17
Ну, раз внятного ответа до сих пор нет, поделюсь я)

И так, аналогичная ситуация, имеем 15 модемов, все определяются как близнецы братья, в udevadm info никаких различий нет, значит биндить будем по номеру ttyUSB с привязкой к IMEI.

Нам понадобится:
PHP
ATCom
SMS демон, в моем случае SMS Server Tools 3

И так логика следующая: отваливается модем, демон после ошибки запускает "alarmhandler" (в моём случае он просто килит свой же процесс), cron проверяет запущен ли демон, если нет то запускает скрипт для бинда модемов и перезапуска смс демона.

Конфиг демона:
devices = #список девайсов
logfile = /var/log/sms/smsd.log 
loglevel = 5
alarmlevel = 3
alarmhandler = /usr/local/bin/smserror.sh
failed = /var/spool/sms/failed
blacklist = /var/spool/sms/blacklist
report = /var/spool/sms/report
incoming = /var/spool/sms/incoming
stats = /var/log/sms/smsd_stats

[B0818760]
device = /dev/ttyModem1
incoming = yes
queues = B0818760
logfile = /var/log/sms/B0818760.log
loglevel = 5

#и т.д. все устройства


smserror.sh
#!/bin/sh
killall -9 smsd


checkSmsDaemon.sh - скрипт для проверки работы демона и бинда модемов, запускается кроном
#!/bin/sh

COUNT=`ps aux | grep smsd | grep -v grep | wc -l`
if [ $COUNT -lt 2 ];
then
#запускаем скрипт через flock, чтобы не создать "петлю" параллельным выполнением
flock -w0 /tmp/tp.lock /usr/local/bin/testPorts.sh

fi


testPorts.sh - вся магия происходит тут)
#!/bin/bash
dev=($(ls /dev | grep ttyUSB)) #массив имен устройств
obj="" #сюда будем складывать связки IMEI => порт

for i in ${dev[@]}; do
#запрос IMEI у модема, для моих Huawei e171 это ATI (пример ответа на скрине ниже)
RESP=$(/usr/local/bin/atcom --port /dev/$i ATI)
#парсим ответ с помощью php скрипта
imei=$(curl --connect-timeout 3 -s -d "data=$RESP" -X POST http://localhost/ajax/parseIMEI.php) 
#проверяем ответ по длине строки
if [[ $(expr length $imei) -gt 5 ]]; 
then
#вывод в консоль, хоть для какой то визуализации)
echo $imei $i
#добавляем "связку" в массив
obj+=$imei:$i, 
fi
done
#отправляем "объект" imei и портов в php скрипт для создания правил
rules=$(curl -s -d "data=$obj" -X POST http://localhost/ajax/createRule.php)
#записываем ответ в файл правила udevatm 
echo -e $rules > /etc/udev/rules.d/02-modems_conformity.rules
#обновляем правила
sudo udevadm control --reload-rules
#биндим устройства
udevadm trigger
#запускаем смс демона
/etc/init.d/sms3 restart


RESP=$(/usr/local/bin/atcom --port /dev/$i ATI)
63241178a7185875682521.jpeg

*PHP для парсинга я выбрал, т.к. у меня для смс сервиса написан собственный веб интерфейс и php уже установлен. Парсить можно чем угодно, хоть прямо в этом скрипте, но я не фанат работы со строками в bash.


parseIMEI.php
<?php
$data = $_POST['data'];

if (strpos($data, 'IMEI') !== false) {
    echo substr($data, strpos($data, 'IMEI: ') + 6, 15);
} else {
    echo 0;
}


createRule.php
<?php
$data = $_POST['data'];

$arr = array_slice(explode(',', $data), 0, -1);

$ports = [ //здесь IMEI привязывается к имени устройства
    '3548070428.....' => 'ttyModem1',
    '3548070428.....' => 'ttyModem2',
    '3548070413.....' => 'ttyModem3',
    '3548070428.....' => 'ttyModem4',
    '3548070428.....' => 'ttyModem5',
    '3548070455.....' => 'ttyModem6',
    '3548070455.....' => 'ttyModem7',
    '3548070455.....' => 'ttyModem8',
    '3548070428.....' => 'ttyModem9',
    '3548070428.....' => 'ttyModem10',
    '8631150121.....' => 'ttyModem11',
    '8631150125.....' => 'ttyModem12',
    '8631150124.....' => 'ttyModem13',
    '8614960137.....' => 'ttyModem14',
    '8631150124.....' => 'ttyModem15',
];

$rule = '';
foreach ($arr as $v) {
    $a = explode(':', $v);
    $rule .= getRule($a[1], $ports[$a[0]]);
}

echo $rule;

function getRule($kerlen, $link) //создаю 2 строки, т.к. у меня модемы одной модели, но разных ревизий, и имеют разный idProduct
{
    $str = 'SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="' . $kerlen . '", SYMLINK+="' . $link . '"\n';
    $str .= 'SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="' . $kerlen . '", SYMLINK+="' . $link . '"\n';
    return $str;
}


В результате работы php скрипта возвращается строка правила, для дальнейшей записи:
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB0", SYMLINK+="ttyModem2"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB0", SYMLINK+="ttyModem2"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB12", SYMLINK+="ttyModem11"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB12", SYMLINK+="ttyModem11"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB15", SYMLINK+="ttyModem3"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB15", SYMLINK+="ttyModem3"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB18", SYMLINK+="ttyModem4"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB18", SYMLINK+="ttyModem4"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB19", SYMLINK+="ttyModem8"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB19", SYMLINK+="ttyModem8"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB21", SYMLINK+="ttyModem10"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB21", SYMLINK+="ttyModem10"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB24", SYMLINK+="ttyModem9"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB24", SYMLINK+="ttyModem9"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB28", SYMLINK+="ttyModem5"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB28", SYMLINK+="ttyModem5"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB3", SYMLINK+="ttyModem7"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB3", SYMLINK+="ttyModem7"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB33", SYMLINK+="ttyModem6"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB33", SYMLINK+="ttyModem6"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB36", SYMLINK+="ttyModem14"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB36", SYMLINK+="ttyModem14"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB39", SYMLINK+="ttyModem13"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB39", SYMLINK+="ttyModem13"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB42", SYMLINK+="ttyModem15"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB42", SYMLINK+="ttyModem15"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB6", SYMLINK+="ttyModem12"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB6", SYMLINK+="ttyModem12"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", KERNEL=="ttyUSB9", SYMLINK+="ttyModem1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1506", KERNEL=="ttyUSB9", SYMLINK+="ttyModem1"


Результат запуска testPorts.sh
63241404c8417218133339.jpeg
Проверяем "бинды"
[root@localhost ~]# ls /dev/ | grep ttyModem
ttyModem1
ttyModem10
ttyModem11
ttyModem12
ttyModem13
ttyModem14
ttyModem15
ttyModem2
ttyModem3
ttyModem4
ttyModem5
ttyModem6
ttyModem7
ttyModem8
ttyModem9


PROFIT!

Благодарю за внимание, надеюсь кому-то поможет =)
Ответ написан
TerAnYu
@TerAnYu
Системный администратор
Я монтировал через imei и задавал нужные порты, примерно так:
ACTION=="add", iSerial=="AS11302000", SYMLINK+="apc-1" > /etc/udev/rules.d/z99-ups.rules


P.S.
Найти конфиг как я монтировал модемы не получается, но я использовал их imei, что бы задать порт.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы