Обработка sms на куче одинаковых gsm модемов без насилия над udev
Дано:
Есть бухгалтерия, которая работает с множеством коммерческих организаций. Банковские web-клиенты шлют коды подтверждения для той или иной банковской операции в виде sms. Одинаковые GSM модемы воткнуты в USB хаб Linux сервера. На сервере установлен пакет smstools3 для приёма и обработки sms и пакет usb_modeswitch для правильного определения модемов через udev.
Задача:
Организовать приём sms и их подачу бухгалтерам. Помечать приходящие смс наименованием организации.
Проблемы:
Модемы китайские, без индивидуальных серийных номеров и нет возможности их различить с помощью правил udev. При перезагрузке сервера или перестановке того или иного модема происходит переименование этих устройств.
Решение.
1. Создаём генератор (/usr/local/bin/smsdconfgen) кофигурационного файла (/etc/smsd.conf) для демона smsd:
#!/bin/sh
# Считаем кол-во доступных системе USB терминалов и создаём строку с их названиями.
num=`ls /dev/ttyUSB* | awk -F tty '{print $2}' | awk -F USB '{print $2}' | awk 'BEGIN { ORS = " " } { print }' | sed 's/.$//'`
devlist=`ls /dev/ttyUSB* | awk -F tty '{print $2}' | awk 'BEGIN { ORS = "," } { print }' | sed 's/.$//'`
# Подпрограмма с настройками для каждого устройства
selection () {
echo "["USB$i"]" >>/etc/smsd.conf
echo 'init = AT+CPMS="ME","ME","ME"' >>/etc/smsd.conf
echo "device = /dev/ttyUSB"$i >>/etc/smsd.conf
echo "baudrate = 115200" >>/etc/smsd.conf
echo "incoming = yes" >>/etc/smsd.conf
echo "memory_start = 1" >>/etc/smsd.conf
echo "eventhandler = /usr/local/bin/sms2mail" >>/etc/smsd.conf
echo >>/etc/smsd.conf
}
# Обнуляем конфигурационный файл /etc/smsd.conf
echo >/etc/smsd.conf
# Заносим в конфигурационный файл основные параметры sms демона
echo "devices = "$devlist >/etc/smsd.conf
echo "outgoing = /var/spool/sms/outgoing" >>/etc/smsd.conf
echo "checked = /var/spool/sms/checked" >>/etc/smsd.conf
echo "incoming = /var/spool/sms/incoming" >>/etc/smsd.conf
echo "receive_before_send = no" >>/etc/smsd.conf
echo "incoming_utf8 = yes" >>/etc/smsd.conf
echo >>/etc/smsd.conf
# Заносим настройки устройств в конфигурационный файл
for i in $num;
do selection;
done
Этот скрипт пропишет все имеющиеся в системе USB терминалы в конфиг smsd. Для своего удобства вы можете внести изменения в init скрипт smsd (обычно он находится в /etc/init.d) и прописать запуск генератора конфига перед стартом самого smsd. Это избавит вас от ручного запуска перед рестартом демона.
2. Создаём скрипт обработчик входящих смс. Он будет сканировать каждую входящую смс и определять принадлежность смс конкретной симке через код IMSI.
#!/bin/bash
#IMSI наших симок.
#Иванов - 250014712255725
#Петров - 250014712342902
#Сидоров - 250014712553982
#Яшин - 250014710661053
#$1 и $2 - это переменные самого smsd для каждой смс
status="$1"
file="$2"
#Вычленяем код IMSI из файла с смс
imsi=`head -12 $file | grep -e "IMSI: " | awk -F" " '{print $2}'`
#Проверяем чья смс
case "$1" in
RECEIVED)
if [ $imsi = 250014712255725 ]; then
name="Иванов"
fi
if [ $imsi = 250014712342902 ]; then
name="Петров"
fi
if [ $imsi = 250014712553982 ]; then
name="Сидоров"
fi
if [ $imsi = 250014710661053 ]; then
name="Яшин"
fi
head -12 $file | grep -e "^From: " -e "^Sent: " -e "^Received: " >> /tmp/sms.log
#Если смс приходят в кодировке UCS, перекодируем в UTF-8
if grep "Alphabet: UCS2" $file >/dev/null; then
echo "$name" >> /tmp/sms.log
tail -n +13 $file | iconv -f UCS-2BE -t UTF-8 >> /tmp/sms.log
tail -n +13 $file | iconv -f UCS-2BE -t UTF-8 | mutt -x -s "$name" x@mail.com
else
echo "$name" >> /tmp/sms.log
tail -n +13 $file >> /tmp/sms.log
tail -n +13 $file | mutt -x -s "$name" x@mail.com
fi
echo >> /tmp/sms.log
echo >> /tmp/sms.log
;;
esac
Из скрипта видно, что каждая смс подписывается и отсылается на определённый почтовый ящик. Кроме этого она попадает и в лог файл /tmp/sms.log. Что делать с смсками решать вам, моим бухгалтерам, кроме отправки на почту, я транслирую лог файл на пять последних смс через веб страницу. Для этого достаточно поднять веб сервер и закинуть в корень сайта файл index.php вроде этого:
SMS-ки
$output
»;
?>