Простой SMS-шлюз на Raspberry Pi

МЕНЮ


Главная страница
Поиск
Регистрация на сайте
Помощь проекту
Архив новостей

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


Иногда случается так, что надо отправлять откуда-нибудь SMS-сообщения. При этом неважно — откуда именно. Речь может идти о домашней системе, объединяющей кучу устройств (эти системы называют «homelab»), из которой надо отправлять уведомления. Это может быть система сигнализации, информирующая своего владельца о разных событиях, требующих его внимания. Возможно это — программный комплекс, которому нужно подтверждать правильность телефонных номеров, вводимых его пользователями. Во всех этих случаях, да и во многих других, SMS-сообщения были и остаются наилучшим способом передачи неких уведомлений по инициативе отправителя. Но в большинстве вышеописанных сценариев использования SMS нельзя положиться на внешние SMS-шлюзы или API, так как система отправки уведомлений должна работать даже тогда, когда пропадает доступ в интернет. Особенно это важно для охранных систем, которые должны функционировать независимо от внешних источников питания.
Очевидное решение всех этих проблем заключается в поддержке собственного SMS-шлюза.

Результат этого проекта: устройство, поддерживающее полнофункциональный REST API, способное отправлять и получать сообщения

Как, с минимальными затратами, самостоятельно сделать такой шлюз?
Если в двух словах описать решение этой задачи, то оно заключается в использовании пакета gammu-smsd и кода API с GitHub. А подробный ответ на этот вопрос приведён ниже.

Компоненты

?Raspberry Pi

Одноплатные компьютеры Raspberry Pi

На самом деле — неважно, какой именно одноплатник Raspberry Pi выбрать. Можно даже использовать самый первый — тот, что появился в 2007 году.

Если говорить об операционной системе, то тут подойдёт и Raspbian, и Alpine Linux (да и, в общем-то, любая ОС, в которой, без особых сложностей, можно установить необходимые нам пакеты). Я выбрал Alpine из-за того, что она работает с RAM-диска, то есть, внезапное отключение питания не повредит данные на SD-карте. Но я тут приведу и инструкции по настройке Raspbian.

?3G/4G USB-модем

USB-модем Huawei E303

В моём проекте используется USB-модем Huawei E303. Не все USB-модемы подойдут для подобных проектов, но практически все модемы Huawei этой серии недороги и их легко достать. Если у вас уже есть USB-модем, можно заранее поискать в интернете сведения о том, работает ли он с Raspberry Pi, чтобы не оказалось так, что он вам не подойдёт. Понятно, что понадобится ещё и SIM-карта с тарифным планом, поддерживающим работу с SMS-сообщениями.

Шаг 1: подготовка Raspberry Pi

Я исхожу из предположения о том, что у вас уже имеется работающий одноплатный компьютер Raspberry Pi, на котором вы можете выполнять команды — либо по ssh, либо подключив к нему мышь, клавиатуру и монитор.

Нам понадобятся некоторые пакеты.

Вот команда для их установки в Apline Linux:

apk add gammu gammu-smsd php php-json usb-modeswitch usbutils git 

Вот — команда для Raspbian:

apt install gammu gammu-smsd php php-json usb-modeswitch git 

Большинство USB-модемов при подключении к компьютеру, по умолчанию, работают в режиме устройства хранения данных (storage mode), а нам нужен режим модема (modem mode). Для того чтобы понять, в каком именно режиме работает ваш модем — подключите его к настольному компьютеру. Если система монтирует его в виде USB-диска (обычно содержащего установщики разных программ и драйверов) — вам надо переключить его в режим модема.

Переключение режима устройства в различных модемах выполняется немного по-разному (тут, опять же — Google вам в помощь). В моём случае всё чудесным образом переключилось с помощью такой команды:

usb_modeswitch -W -v 12d1 -p 14fe -K -P 14ac -M "55534243000000000000000000000011060000000000000000000000000000" 

Команда lsusb возвращает Bus 001 Device 005: ID 12d1:1c05 HUAWEI HUAWEI Mobile. 12d1 — это код поставщика для Huawei, а строка, идущая за этим кодом (в моём случае — 1c05) — это ID продукта. Мы используем данные, полученные с помощью lsusb, при вызове usb_modeswitch.

Вы, чтобы изменить режим работы своего модема, можете обратиться к Arch Wiki или к Ubuntuusers Wiki. Там должно быть всё необходимое. Если система, после подключения модема, создаст /dev/ttyUSB0, это значит, что всё сделано правильно.

pi:~# ls -al /dev/ttyUSB0 crw-rw----    1 root     dialout   188,   0 Dec  3 12:10 /dev/ttyUSB0 

После этого аппаратная часть нашего проекта — Raspberry Pi и модем — готова к дальнейшей работе.

Шаг 2: установка Gammu

Что такое Gammu? Процитирую разработчиков проекта:

Утилита командной строки Gammu — это средство, дающее доступ к широкому набору телефонных возможностей.

В этой утилите уже реализованы сложные механизмы, ответственные за разбор сообщений и за их отправку по мобильным сетям. А нам нужно лишь сообщить утилите о том, как ей общаться с модемом, который мы настроили на предыдущем шаге.

Для того чтобы узнать о том, видит ли утилита модем, можно выполнить команду gammu identify. Если всё нормально — в ответ вы получите примерно следующее:

vpnpi:~# gammu identify Device               : /dev/ttyUSB0 Manufacturer         : Huawei Model                : E303 (E303) Firmware             : 21.157.01.00.199 IMEI                 : 860000000000619 SIM IMSI             : 230000000000006 

Пока всё нормально. Создадим теперь конфигурационный файл со следующим содержимым и сохраним его в папке /etc/gammurc:

[gammu] device = /dev/ttyUSB0 name = Bob connection = at logfile = /var/log/gammu.log  [smsd] service = files logfile = syslog #PIN = 1234 # Увеличьте значение для получения отладочной информации debuglevel = 0 # Пути, по которым хранятся сообщения inboxpath = /var/spool/gammu/inbox/ outboxpath = /var/spool/gammu/outbox/ sentsmspath = /var/spool/gammu/sent/ errorsmspath = /var/spool/gammu/error/ 

Имя (поле Name) может быть любым. Я выбрал Bob — так зовут «абонента», от имени которого отправляются сообщения.

Если для работы с вашей SIM-картой нужен PIN-код — его можно задать в соответствующем поле раздела [smsd].

?Быстрая проверка возможности отправки SMS

Для того чтобы проверить, что всё, что мы до сих пор настраивали, правильно работает, и то, что мы можем отправлять SMS-сообщения — достаточно выполнить такую команду:

echo "some message" | gammu --sendsms TEXT 0664xxxxxxx 

Ясно, что вам надо будет, как минимум, подставить сюда свой номер телефона.

Попробуем:

vpnpi:~# echo "Hello from your Pi" | gammu --sendsms TEXT 0664xxxxxxx If you want break, press Ctrl+C… Sending SMS 1/1…waiting for network answer..OK, message reference=22 

Заглянем в телефон.

SMS успешно получено

Работает! На телефон пришло сообщение.

На этом можно и остановиться, автоматизировав отправку сообщений средствами командной строки. Но мне хотелось бы отправлять и получать сообщения с помощью API, к которому можно обращаться с любого устройства, находящегося в моей домашней сети, поэтому в описании этого проекта присутствует ещё два шага.

Шаг 3: подготовка к созданию API для отправки и получения SMS-сообщений

Мы, для отправки сообщений, использовали команду gammu. Но получение сообщений — операция более сложная, её непросто автоматизировать. Правда — её можно было бы назвать сложной в том случае, если бы создатели Gammu не написали бы ещё и утилиту gammu-smsd.

?Утилита gammu-smsd

На вопрос о том, что такое gammu-smsd, как и прежде, лучше всего способны ответить разработчики проекта:

Gammu SMS Daemon — это программа, которая периодически сканирует SMS-модем на предмет полученных сообщений, сохраняет их в заданном месте и, кроме того, отправляет сообщения, которые находятся в хранилище и ждут отправки. Это — программа, которая отлично подходит для автоматизации управления большими объёмами принятых или отправленных сообщений.

Получается, что gammu-smsd — это демон, который ожидает появления новых входящих или исходящих SMS-сообщений.

Так как в вышеприведённом конфигурационном файле для Gammu уже содержится всё, что нужно для gammu-smsd, нам осталось лишь создать папки, где gammu будет хранить данные:

mkdir -p /var/spool/gammu/inbox/ mkdir -p /var/spool/gammu/outbox/ mkdir -p /var/spool/gammu/sent/ mkdir -p /var/spool/gammu/error/ 

?Отправка сообщений

Запустим gammu-smsd в режиме демона (то есть — позволим программе выполняться в фоновом режиме) и скажем ей о том, где находится созданный нами ранее конфигурационный файл:

gammu-smsd -d -c /etc/gammurc 

Так как теперь у нас имеется демон, который общается с модемом, пользоваться ранее рассмотренным способом отправки сообщений с помощью gammu мы уже не сможем. Правда, мы, всё же, можем их отправлять самостоятельно, но для этого нам понадобится команда gammu-smsd-inject, созданная для использования совместно с gammu-smsd. Теперь отправка сообщений выглядит как постановка их в локальную очередь, а демон будет брать сообщения из этой очереди и отправлять их.

Пример команды для отправки сообщения будет выглядеть так:

gammu-smsd-inject TEXT 0664xxxxxxx -unicode -text "hello world from the daemon!" 

Заглянем в телефон.

Привет от демона получен

Мы, как и прежде, получили сообщение. В этот раз его доставка может занять на несколько секунд дольше, чем прежде. Такое ощущение, что демон проверяет очередь исходящих сообщений с некоторой периодичностью.

pi:~# gammu-smsd-inject TEXT 0664xxxxxxx -unicode -text "hello world from the daemon!" gammu-smsd-inject[2964]: Warning: No PIN code in /etc/gammu-smsdrc file gammu-smsd-inject[2964]: Created outbox message OUTC20211203_193330_00_0664xxxxxxx_sms0.smsbackup Written message with ID /var/spool/gammu/outbox/OUTC20211203_193330_00_0664xxxxxxx_sms0.smsbackup 

?Получение сообщений

Пришло время отправить SMS нашей системе и выяснить, дойдёт ли оно до получателя. Для этого достаточно ответить на одно из полученных от системы сообщений и посмотреть, появится ли оно в виде файла в папке /var/spool/gammu/inbox/.

Отправляем сообщение, ждём несколько секунд и заглядываем в папку.

pi:~# ls /var/spool/gammu/inbox/ IN20211203_194458_00_+43664xxxxxxx_00.txt  pi:~# cat /var/spool/gammu/inbox/IN20211203_194458_00_+43664xxxxxxx_00.txt Hello also from the outside world! 

Каждое из полученных сообщений сохраняется в отдельном файле. Можно догадаться, что в имени файла вида IN20211203_194458_00_+43664xxxxxxx_00.txt закодированы дата, время, телефон отправителя и номер части сообщения (для SMS, длина которых превышает 140 символов, так как они разбиваются на части).

Шаг 4: API для работы с сообщениями

Нам нужен простой механизм для отправки и получения сообщений с использованием API, такой, для применения которого не нужно устанавливать множество плагинов и пакетов. Я написал пару весьма компактных PHP-скриптов, которые заточены именно под эту задачу. Найти их можно здесь. Для того чтобы они функционировали, нужен работающий демон gammu-smsd.

В директории, где лежат соответствующие .php-файлы (send.php и get.php) нужно выполнить команду php -S 0.0.0.0:8080. Благодаря этому обратиться к ним из сети сможет любая нуждающаяся в них сущность.

?Отправка SMS с помощью API

Теперь всё делается до крайности просто и понятно. Для отправки сообщения достаточно обратиться по адресу такого вида:

http://ip.of.your.pi/send.php?phone=0664xxxxxxx&text=Testmessage 

В ответ придёт JSON-объект, в котором будут сведения о том, удалась ли отправка сообщения (status:ok) или нет (status:error).

{   "status": "ok",   "log": "2021-12-04 15:43:39 gammu-smsd-inject TEXT 0664xxxxxxx -unicode -text 'Testmessage' gammu-smsd-inject[2669]: Warning: No PIN code in /etc/gammu-smsdrc file gammu-smsd-inject[2669]: Created outbox message OUTC20211204_164340_00_0664xxxxxxx_sms0.smsbackup Written message with ID /var/spool/gammu/outbox/OUTC20211204_164340_00_0664xxxxxxx_sms0.smsbackup   " } 

?Получение SMS с помощью API

Получить сообщение с помощью нашего API тоже очень просто. Достаточно обратиться по адресу такого вида:

http://ip.of.your.pi/get.php 

В ответ, в виде JSON-объекта, придут все полученные сообщения:

curl -s http://ip.of.your.pi/get.php | jq . [   {     "id": "f0a7789a657bb34eddd17c8e64609c48",     "timestamp": 1638636342,     "year": "2021",     "month": "12",     "day": "04",     "time": "16:45",     "test": "04.12.2021 16:45:42",     "sender": "+43664xxxxxxx",     "message": "Hello bob!"   },   {     "id": "c358d0a4ca868c1d7d2eedab181eddd6",     "timestamp": 1638636414,     "year": "2021",     "month": "12",     "day": "04",     "time": "16:46",     "test": "04.12.2021 16:46:54",     "sender": "+43664xxxxxxx",     "message": "Hello "   } ] 

Теперь можно интегрировать систему отправки и получения SMS-сообщений в любые проекты. Если вы это сделаете — сообщите мне. Если захотите — я могу об этом рассказать в своём блоге.

Вопросы и ответы

?Почему тут используются PHP-скрипты собственной разработки, а не gammu-python?

Мне хотелось, чтобы код, обеспечивающий работу API, занимал бы как можно меньше места и потреблял бы как можно меньше ресурсов. Я попробовал несколько Python-реализаций подобного механизма, и ни один из них не выглядел достаточно компактным и простым. Для их использования нужно было компилировать код с множеством подпакетов. Кроме того, моему Raspberry Pi не хватало памяти на компиляцию некоторых из этих пакетов. Да и оказалось, что быстрее написать небольшой PHP-скрипт, чем заниматься оптимизацией Python-пакетов.

?Что если пользователь отправит длинное SMS-сообщение?

API может обрабатывать сообщения, разбиваемые при отправке на части, даже в том случае, если между частями одного сообщения, находящегося в очереди, находятся другие сообщения. Поэтому данная возможность должна работать без дополнительных настроек, так как API самостоятельно собирает сообщения, разбитые на части.

?Можно ли работать с MMS?

Gammu поддерживает MMS (Multimedia Messaging Service, служба мультимедийных сообщений). Но такие сообщения хранятся в бинарном формате, и я пока не нашёл документацию, посвящённую тому, как с ними работать. Буду весьма благодарен за любые сведения об этом.

Пригодится ли SMS-шлюз в каком-нибудь из ваших проектов?


Источник: habr.com

Комментарии: