SMS Server Tools 3
This site is hosted by Kekekasvi.com
 Menu
Basic information:
Additional information:
Support:
Get SMS Server Tools 3:
Additional Options

 Sponsored links

 Search
Custom Search

 Visitor locations
 
 SMS Server Tools 3 Community
Welcome, Guest. Please login or register. Mon May 25, 2020 14:10
SMSTools3 Community » Sample scripts / setups Bottom

How-to: Linking modem name to IMEI

Login and Post Reply

Page:  1

Author Post
Member
Registered:
Mar 2016
Location: Voronezh, Russian Federation
Hello.

Practical daily usage of smsd+set of USB-modems (19 items) shows, that /dev/ttyUSB1 can point to different modem after this modem has been reinserted or inserted into another USB hole at motherboard (usb-hub). Also, 2-port USB-device MODEM_A can occupy /devttyUSB3 and /dev/ttyUSB5 instead of /dev/ttyUSB0+/dev/ttyUSB1.
As a result, we have strong ravel in smsd.conf. Also, keep in mind, that Huawei 3G USB modems have 1 hardware port but 2 software (/dev/ttyUSB) ports.

The only reliable way to uniquely define modem in OS - is its IMEI. Other ways (e.g. udev+ATTRS{serial}) are not reliable and depend on capability of modem to show its serial number. We will create another virtual device with its personal number, a /dev/modemx (which actually is a symlink to /dev/ttyUSBy , interested for us) and set this /dev/modemx as a "device" parameter in section [GSMx] in smsd.conf . List of "IMEI-to-logical name" relations is stored in /etc/udev/rules.d/IDS.lst in following format:


Here is sample of how to link modem to its IMEI and define obtained device in smsd.conf permanently.

We use udev mechanism to catch event of device's insertion/removal:
/etc/udev/rules.d/50.modems.rules:

KERNEL=="ttyUSB*" ACTION=="remove" , RUN+="/etc/udev/rules.d/eventer.sh remove"
KERNEL=="ttyUSB*" ACTION=="add" , RUN+="/etc/udev/rules.d/eventer.sh add"
 
'smsdconf' Syntax Highlight powered by GeSHi


As we see, during insertion|removal event, OS calls /etc/udev/rules.d/eventer.sh with parameters "add" or "remove". Of couse, this parameter can be replaced with $ACTION environment variable, but let it stay like this. Except $ACTION, udev sets many env vars during insertion|removal, which provide many info about connected device, and eventer.sh user some of them.

Here is eventer.sh , who logs into /etc/udev/rules.d/eventer.log for better debugging. Keep in mind, that udev launches 2 eventer.sh according to number of /dev/ttyUSB's appeared in OS during insertion (for Huawei modem):

#!/bin/bash
dt=`date`

echo $dt Device $DEVNAME, Maker is $ID_VENDOR_FROM_DATABASE was $1 >> /etc/udev/rules.d/eventer.log   #simple example of using env vars, pointed to device, provided by udev

if [ "$1" == "add" -a "$SUBSYSTEM" == "tty" ]  # if exactly modem has been inserted , not usb-drive etc. To find it out , we take 2 env vars, which have been set just by udev engine. You can take "$ACTION" var  instead of $1
then
    iam=`whoami`
    echo "We do it all under user $iam"  >> /etc/udev/rules.d/eventer.log
    echo Modem insertion detected  >> /etc/udev/rules.d/eventer.log
    echo Finding out IMEI for $DEVNAME >> /etc/udev/rules.d/eventer.log
#debug     chmod 777 $DEVNAME  #you may want to do it or not, it's optional
    echo ---Calling  "/etc/udev/rules.d/poll_modem.py $DEVNAME | grep IMEI | cut -d " " -f 2 | tr -d \\r\\n"  >> /etc/udev/rules.d/eventer.log  #here we call special Python script who communicates to modem and asks for IMEI via AT-coomands (listed below)
    imei=`/etc/udev/rules.d/poll_modem.py $DEVNAME | grep IMEI | cut -d " " -f 2 | tr -d "\r"`
# is  modem didn't answer instantly  - we keep trying to poll it
    if [ -z $imei ]
    then
        echo "---IMEI was not found, retry 1..." >> /etc/udev/rules.d/eventer.log
        imei=`/etc/udev/rules.d/poll_modem.py $DEVNAME | grep IMEI | cut -d " " -f 2 | tr -d "\r"`
    fi

    if [ -z $imei ]
    then
        echo "---IMEI was not found, retry 2..." >> /etc/udev/rules.d/eventer.log
        imei=`/etc/udev/rules.d/poll_modem.py $DEVNAME | grep IMEI | cut -d " " -f 2 | tr -d  "\r"`
    fi

    if [ -z $imei ]
    then
        echo "---IMEI was not found, retry 3..." >> /etc/udev/rules.d/eventer.log
        imei=`/etc/udev/rules.d/poll_modem.py $DEVNAME | grep IMEI | cut -d " " -f 2 | tr -d  "\r"`
    fi

    if [ -z $imei ]
    then
        dt=`date`
        echo "$dt +++ERROR+++ IMEI was not found, i give up. Please reinsert modem $ID_VENDOR_FROM_DATABASE. Exit." >> /etc/udev/rules.d/eventer.log
        exit
    fi

    echo "Found IMEI $imei for $DEVNAME">> /etc/udev/rules.d/eventer.log

# as said before, 1 Huawei USB-modem has 2 virtual modems. I use first to send sms via smsd,  and second is to get helpful info about modem's life. First one has ID_USB_INTERFACE_NUM=00, second one - ID_USB_INTERFACE_NUM=01. Here I call 00 and 01 "a role".
    echo "Finding out role of $DEVNAME (main/help)..."  >> /etc/udev/rules.d/eventer.log
    echo "---ID_USB_INTERFACE_NUM for $DEVNAME is $ID_USB_INTERFACE_NUM"  >> /etc/udev/rules.d/eventer.log

#now we try to make symlink for device
    echo "Trying to find device alias for $imei (subdevice $ID_USB_INTERFACE_NUM) in /etc/udev/rules.d/IDS.lst"  >> /etc/udev/rules.d/eventer.log
#grepping IDS.lst for IMEI and "role":
    alias=`grep $imei /etc/udev/rules.d/IDS.lst | grep $ID_USB_INTERFACE_NUM | cut -d " " -f 3`
    if [ -z $alias ]
    then
        dt=`date`
        echo "$dt +++ERROR+++ No record for $imei and $ID_USB_INTERFACE_NUM was found in /etc/udev/rules.d/IDS.lst, check it. Exit." >> /etc/udev/rules.d/eventer.log
        exit  
    fi
    echo "Found alias - $alias"  >> /etc/udev/rules.d/eventer.log
    #set symlink in OS
    echo "Setting alias in OS..." >> /etc/udev/rules.d/eventer.log
    echo "---Executing ln -s $DEVNAME /dev/$alias"  >> /etc/udev/rules.d/eventer.log
    ln -s $DEVNAME /dev/$alias
     echo "Done. All finished. Exit."  >> /etc/udev/rules.d/eventer.log
fi


###action if  modem is removed. We need to remove earlier created symlinks
if [ "$1" == "remove" -a "$SUBSYSTEM" == "tty" ]
then
    dt=`date`
    echo "$dt $DEVNAME Device  has been removed"  >> /etc/udev/rules.d/eventer.log
    dt=`date`    
    echo "$dt $DEVNAME Finding symlink for this device and removing it (them)..."  >> /etc/udev/rules.d/eventer.log
    ls -l /dev/modem* | tr "\n"  ";" | sed -e s/";"/";\n"/g | grep "$DEVNAME;" | ls -l /dev/modem* | tr "\n"  ";" | sed -e s/";"/";\n"/g | grep "$DEVNAME;" | cut -d "/" -f 2,3 | cut -d  " " -f 1 | sed -e s/"dev"/"\/dev"/g | xargs rm
    dt=`date`    
    echo "$dt $DEVNAME Removing done."  >> /etc/udev/rules.d/eventer.log
fi
 
'bash' Syntax Highlight powered by GeSHi



Important part of this process is a Python script which polls modem, sending there ATI command and reading output with IMEI. Python has been selected after trying:
* bash+minicom - failed. (minicom -D /dev/ttyUSB0 -S poll.min -C /tmp/result.txt writes empty
/tmp/result.txt)
* bash+socat - failed. unpredictable output.
* php - failed. (php_dio.so extension unstable works in my PHP 5.4-5.6)

don't forget to install pyserial module.

poll_modem.py:
#!/usr/bin/python
import serial
import sys
#print 'Num of parameters passed '+str(len(sys.argv))
if len(sys.argv) < 2:
    print('No modem path specified. Use '+sys.argv[0]+' /dev/ttyUSBx')
    print('Exit')
    sys.exit()
#print 'Polling '+sys.argv[1]
try:
    ser = serial.Serial(sys.argv[1],9600,dsrdtr=True,rtscts=True) #Mandatorily set dsrdtr=True,rtscts=True. In case of unsetting them, You can get successfull polling /dev/ttyUSB0, but failed /dev/ttyUSB1
except:
    sys.exit("ERROR. Unable to open "+sys.argv[1]+' at speed 115200')
#print ser.isOpen()
ser.write("ATI1\r")
response =  ser.read(100)
print response
ser.close()
 
'smsdconf' Syntax Highlight powered by GeSHi


Now, as a result, we can 1 000 times reinsert modem with IMEI 1111111 into different holes in M/B or USB-hub, reboot server 10000 times - device with IMEI 1111111 will always be /dev/modem1


« Last edit by kontrolsson on Mon Jul 04, 2016 12:19, 47 months ago. »
Member
Registered:
May 2020
Location: Cape Town, South Africa
I know this was posted in 2016 but this script and python program has really saved me a lot of time and frustration. :D I don't think there is another mechanism for identifying the correct ttyUSBy device to use when inserting USB GSM modems in random order that works quite as well. If something else works better than this please let us know.

A big thank you for this.

I made one change to the eventer.sh script to locate the IMEI and USB_INTERFACE_NUM and decided to post this in case someone else comes across this really helpful script.

In eventer.sh changed this:

alias=`grep $imei /etc/udev/rules.d/IDS.lst | grep $ID_USB_INTERFACE_NUM | cut -d " " -f 3`

to

alias=`grep "$imei $ID_USB_INTERFACE_NUM" /etc/udev/rules.d/IDS.lst | cut -d " " -f 3`

Reason:

If the IMEI contains a sequence appearing in the $ID_USB_INTERFACE_NUM variable, an unwanted result can occur

EG entries in IDS.lst as in this example will always return modem8 for all rows with this IMEI as the grep for 00 $ID_USBINTERFACE_NUM will find 00 in the IMEI reference on all rows

EG.

IDS.lst
860016016276797 00 modem6
860016016276797 01 modem7
860016016276797 02 modem8

#grep 860016016276797 IDS.lst|grep 00 IDS.lst

860016016276797 00 modem6
860016016276797 01 modem7
860016016276797 02 modem8


#grep "860016016276797 00" IDS.lst

860016016276797 00 modem6

Thanks again for this clever mechanism

Member
Registered:
Mar 2016
Location: Voronezh, Russian Federation
Topic owner
Hi, yes, thank You for attention and reply! :)

Login and Post Reply

Page:  1

SMSTools3 Community » Sample scripts / setups Top

 
Time in this board is UTC.  

Privacy Policy   SMS Server Tools 3 Copyright © Keijo Kasvi.