Рассылать смс сегодня нетрудно — регистрируемся в одном из многочисленных сервисах рассылок, вносим сумму и вперед. А как принимать смс от граждан в автоматическом режиме?

Короткие номера не подходит, ибо они навек закрепили за собой репутацию лохотрона. К тому же нужно вводить префикс, а минимальная стоимость 4 рубля. Принимать только на короткие номера — верх свинства по отношению к абонентам.

А ведь все можно сделать своими руками! Берем простой 3Г-модем, втыкаем в него местную симку (я взял Мегафон), подключаем к компьютеру, ставим драйвера. Проверяем, появился ли в системе модем.

Качаем замечательную утилиту Гамму, а конкретно — виндовые бинарники (не Minimal, а обычные). Распаковываем.

Утилита gammu может рулить модемом программно, например, читать и отправлять смс, совершать звонки, делать бекапы содержимого телефона и массу других полезных штук. В комплекте идет gammu-smsd — демон для чтения смс в фоновом режиме. Он постоянно проверяет наличие смс, складывает их в базу данных и вызывает заданную команду в момент прихода новой смски.

Теперь о том, как все настроить. В папке bin создаем файл smsdrc следующего содержания:

[gammu]
device = COM6:
connection = at

[smsd]
Service = sql
Driver = native_mysql
User = user
Password = password
PC = xxx.xxx.xxx.xxx
Database = smsd
PIN = 8730
LogFile = smsd.log
RunOnReceive = smsd_callback.bat

Стартуем демона:

gammu-smsd --config smsdrc

Секция [gammu] в конфигурации отвечает за параметры соединения с устройством. device — номер КОМ-порта, узнать его можно в свойствах модема, connection — тип соединения, для 3Г-модема обычно at.

Раздел [smsd] содержит параметры демона. Как видно, в качестве базы я использую Мускуль. Опция PIN задает пин-код симки (если защита ПИН не отключена). LogFile — текстовый файл логов.

Самое интересное — RunOnReceive, это имя команды, скрипта или батника, который будет вызываться при получении смс. Параметры сообщения передаются в переменных окружения SMS_1_NUMBER, SMS_1_TEXT и др.

В батнике у меня прописан вызов питоньего скрипта:

start pythonw path\to\smsd_callback.py

Почему бы сразу не вызвать скрипт? Потому, что вызов осуществляется в том же потоке, что и чтение смс, поэтому пока не завершится процесс команды, чтение будет приостановлено. А в данном случае батник вызывает скрипт и сразу закрывается.

Фрагмент кода на питоне:

number = os.environ["SMS_1_NUMBER"]
message = os.environ["SMS_1_TEXT"]

msg_pattern = r"\d+"
account, value = re.findall(msg_pattern, message)[:2]

statement = Statement(account=account, value=value)
statement.save()

answer = u"Принято. Абонент %s, показание %s" % (account, value)

send_sms(answer, number)

Получаем номер и сообщение, находим в нем пару чисел — лицевой счет и показание прибора. Сохраняем в базу и отвечаем абоненту, что все в порядке.

Комментарии из старого блога

11/04/13 Сергей: Статья интерсная, много нового узнал, пытаясь запустить. Но нет ничего про структуру базы. Мануалов гаммы на русском нет. Вот и как бы статья по прямому предназначению “Прием смс” (профи и без статьи организует) пока не очень полезна.

11/05/13 Иван Гришаев: Структуру базы можно посмотреть в .sql-файле, который лежит где-то в папке с программой.

11/07/13 Сергей: Спасибо. Теперь вот такая картина в логфайле (тут я баран)) поможете??? подключаю 3g модем - железка от алкател.

Thu 2013/11/07 15:09:29 gammu-smsd[2452]: Connected to Database: smsd on localhost
Thu 2013/11/07 15:09:29 gammu-smsd[2452]: Connected to Database native_mysql: smsd on localhost
Thu 2013/11/07 15:09:29 gammu-smsd[2452]: Created Windows RW shared memory at 003A0000
Thu 2013/11/07 15:09:29 gammu-smsd[2452]: Starting phone communication...
Thu 2013/11/07 15:09:40 gammu-smsd[2452]: Error at init connection: No response in specified timeout. Probably phone not connected. (TIMEOUT[14])
Thu 2013/11/07 15:09:40 gammu-smsd[2452]: Already hit 250 errors
Thu 2013/11/07 15:09:40 gammu-smsd[2452]: Terminating communication: No response in specified timeout. Probably phone not connected. (TIMEOUT[14])
Thu 2013/11/07 15:09:40 gammu-smsd[2452]: Starting phone communication...
Thu 2013/11/07 15:09:50 gammu-smsd[2452]: Error at init connection: No response in specified timeout. Probably phone not connected. (TIMEOUT[14])
Thu 2013/11/07 15:09:50 gammu-smsd[2452]: Already hit 250 errors
Thu 2013/11/07 15:09:50 gammu-smsd[2452]: Terminating communication: No response in specified timeout. Probably phone not connected. (TIMEOUT[14])
Thu 2013/11/07 15:09:50 gammu-smsd[2452]: Starting phone communication...

11/07/13 Иван Гришаев: Пишет, что нет соединения с телефоном. Сначала нужно указать проге, какой порт слушать. Создайте файл Gammu\bin\gammurc (без расширения), в нем пишете:

[gammu]
device = COM6:
connection = at

только вместо COM6 - ваш порт. Двоеточие на конце нужно.

11/07/13 Сергей: Я так и делал, модем откликается (в терминале) на сом3,4,5 в диспетчере оборудования модем=сом5.

[gammu]
device = COM

пробовал все результат почти один, 3 и 5 сукунд через 10 закрывается гамми, ком4 каждые 10-20 сек перепроверяет соединение с телефоном, пока сам не закрою.

11/07/13 Иван Гришаев: Вспомнил - для смс-демона нужен отдельный конфиг! Gammu\bin\smsdrc

У меня он такой:

[gammu]
device = COM5:
connection = at

[smsd]
Service = sql
Driver = native_mysql
User = username
Password = passowrd
PC = 172.27.86.8
Database = smsd

LogFile = smsd.log
RunOnReceive = some_bat_file.bat
CheckSecurity = 0
CheckBattery = 0

11/07/13 Сергей: Не помогло добавление Check ов. Нарыл гдето другой терминал, вот он АТ командами смски вытягивает. А можно както на питоне опросить АТ командами com порт? Думаю так проще будет.

11/07/13 Иван Гришаев: Конечно можно, есть либа для ком-порта: http://pyserial.sourceforge.net/

Кстати, вы пробовали http://www.simplesms.ru/ ? Прога очень хорошая, разработчик - русский, есть документация и форум.

11/07/13 Сергей: Хороший вы (я не против и на ты) человек. С библиотекой буду разбираться (инглиша не знаю), а платные вещи отпадают я имено хочу разобраться и сделать - типа хобби). Можно вообще не париться - 800р/мес и прикрутить их API к своему сервису, я так и делал, но как то не уютно))).

11/07/13 Сергей: надо же скрипт php заработал, раньше порты были 14,15,16 и не работало. Попробую на php получалку сделать!

$telnumb='904*****37';
$sms_text='poluchilos';
$format = "AT+CMGF=1\r\n";
        $tel = "at+cmgs=\"+7".$telnumb."\"\r\n ";
        $text = $sms_text.chr(26)."\r\n ";
        $fp = fopen ("COM3:", "w");
        flock($fp,LOCK_EX);
        if(!$fp){
                echo "COM-Port not opened";
        }
        else{
                fwrite($fp, $format);
                                sleep(1);
                fwrite($fp, $tel);
                                sleep(1);
                fwrite($fp, $text);
                                sleep(1);
                flock($fp,LOCK_UN);
                echo $format.$tel.$text;
        }
        $fp = fclose ($fp);

11/07/13 Иван Гришаев: Сообщения с кириллицей нормально приходят? А сообщения из нескольких частей?

11/07/13 Сергей: Нет под w1251 все усложняется, там меняется алгоритм сборки, но это решаемо. Мне прием нужен, его и ковыряю. На php отправить оказывается просто, а вот принять “одна темнота” пока, т.что гамми, питон не закрываю.

11/07/13 Сергей: Так то все дожно быть просто. Всего то нужно в порт заслать "AT+CMGL=4\r\n" и получить все что он отдаст. А потом раскодить, распарсить. Ну нннникак.

11/08/13 Иван Гришаев: Да, кириллица хранится в последовательностях UFT-16, кажется. Придется декодировать.

11/07/13 Сергей: Еще об отправке, там без подтверждения получения смс абонентом и по той же причине - читать порт не получается.

11/07/13 Сергей: simplesms пробовал скачать - антивирус заблокировал(((

11/08/13 Иван Гришаев: А вы разблокируйте.