SMS (сокр. от англ. Short Messaging Service — «служба коротких сообщений») — один из лучших способов доставки краткой информации в текстовой форме.
Использование SMS позволяет решать следующие задачи:
- рекламная рассылка;
- рассылка от организации (информация о событиях внутри фирмы, рассылка от ЖКХ и т. д.);
- информация о событиях для быстрого реагирования.
Для рекламных рассылок существует множество интернет шлюзов, но для отправки сообщений о пропаже связи с внешним миром у сервера, этот способ не подходит ввиду отсутствия связи с шлюзом. В решении этой задачи инструментом послужит отправка сообщения с компьютера через GSM модем. Готовых кроссплатформенных решений в настоящий момент нет, поэтому приходится писать приложение для своих целей самостоятельно. Разрабатывая такое приложение, я столкнулся с недостатком информации на русском языке, поэтому информацию пришлось собирать по частям. Результаты моей работы представлены ниже.
Для реализации требуется связка компьютер — модем. В качестве модема выступает специальное устройство для работы в сети GSM (GPRS-модем с функцией отправки SMS). Также подойдет мобильный телефон, подключенный к компьютеру через USB или Bluetooth.
Для взаимодействия с модемом используются АТ-команды. Данный формат поддерживается большинством современных модемов. Модем подключается к компьютеру через COM порт, физический или виртуальный. При подключении через виртуальный порт, в качестве канала связи могут использоваться, например, USB или Bluetooth.
АТ-команды могут быть обработаны модемом только когда он находится в командном режиме. Большинство модемов переходит в командный режим сразу при включении. Ввод команд в режиме непосредственной работы модема распознается самим модемом как ввод данных. Принятые команды подтверждаются выводом сообщения [Ok] на терминал.
Большинство АТ команд (кроме двух) начинаются с префикса at. Исключением являются escape последовательность +++ и команда повтора /. Команды нечувствительны к регистру. Максимальный размер (не считая пробелы и символы возврата каретки) команды составляет 39 символов.
АТ команды для работы с SMS
+++ — escape последовательность. Используется для перевода модема из режима соединения связи в командный режим;
o — перевод в online-режим, используется для восстановления связи после ввода escape последовательности;
/ — повтор последней введенной команды;
AT+CMGF=* — установка режима работы, * — 0 для цифрового режима, или 1 для текстового. Отправка сообщений в кириллице возможна через цифровой режим с предварительной перекодировкой текста в UCS.
AT+CMGS=* — отправка SMS сообщений, * — текст сообщения в формате установленном командой AT+CMGF, в текстовом режиме используется данный формат:
AT+CMGS= [номер_получателя] [Enter]
[Текст_сообщения] [Ctrl + Z]
Для передачи сообщения в цифровом режиме используется формат PDU:
AT+CMGS= [длина сообщения] [Enter]
[номер SMS центра] [состояние сообщения] [количество успешно переданных] [длина и номер отправителя] [длина номера получателя] [формат номера] [номер получателя] [идентификатор протокола] [save sms] [кодировка] [срок доставки сообщения] [длина текста] [текст] [Ctrl + Z]
Пояснения к полям:
[длина сообщения] — длина всего полученного сообщения в байтах;
[Enter] — перевод каретки, в шестнадцетиричном виде равно 0x0D;
[номер SMS центра] — длина номера и номер SMS центра. 00 — использовать номер из настроек вшитых в SIM карту;
[состояние сообщения] — 11 для отправляемого сообщения, 00 для принимаемого;
[количество успешно переданных] — устанавливается устройством, изначально должно быть 00;
[длина и номер отправителя] — длина номера и номер отправителя. 00 — использовать значение по умолчанию;
[длина номера получателя] — длина номера получателя;
[формат номера] — 91 для международного формата, 81 для местного;
[номер получателя] — номер получателя в формате PDU;
[идентификатор протокола] — для SMS равен 00;
[save sms] — 0 — для сохранения сообщения, 1 — сообщение выводится на экран (flash sms);
[кодировка] — 0 — латиница, 1 — кириллица;
[срок доставки сообщения] — срок доставки сообщения, по истечению времени если сообщение не будет доставлено, то оно будет уничтожено, указывается SMSC время;
[длина текста] — длина текста сообщения;
[текст] — текст сообщения переведенный в формат USC2;
[Ctrl + Z] — конец команды, в шестнадцатеричном виде равно 26.
Все численные значения (длины строк) передаются в шестнадцатеричной системе счисления.
Команда отправки сообщения «Hello world!" на номер 79876543210 в текстовом режиме, имеет вид:
AT+CMGF=1 [Enter]
AT+CMGS=79876543210 [Enter]
Hello world! [Ctrl + Z]
Для отправки такого сообщения на тот же номер, но используя цифровой режим, нужно передать в модем:
AT+CMGF=0 [Enter]
AT+CMGS=37 [Enter]
0011000B919778563412F00008A71600480065006C006C006F00200057006F0072006C0064 [Ctrl + Z]
AT+CMGL=* — чтение сообщений из памяти модема, * — одно из пяти значений, в зависимости от режима (CMGF) используется текстовый или цифровой параметр, значения параметров в Таблице 1;
AT+CMGD=* — удаление сообщения из памяти модема, * — номер сообщения.
Таблица 1
Параметры команды AT+CMGL
Значение параметра |
Текстовый вид |
Цифровой вид |
Входящие не прочитанные |
«REC UNREAD» |
0 |
Входящие прочитанные |
«REC READ» |
1 |
Исходящие не отправленные |
«STO UNSENT» |
2 |
Исходящие отправленные |
«STO SENT» |
3 |
Все сообщения |
«ALL» |
4 |
При получении сообщения в цифровом режиме оно имеет вид:
[номер SMS центра] [состояние сообщения] [длина и номер отправителя] [идентификатор протокола] [кодировка] [длина текста] [текст]
От исходного сообщения отличается: состояние сообщения равно 00, отсутствуют такие поля, как номер получателя и поля связанные с ним, поле save sms, и поле времени доставки сообщения.
Рассмотрим основные моменты практической реализации. В качестве примера я буду использовать код на Java.
Для подключения к устройству используется класс jssc.SerialPort.SerialPort, при инициализации объекта в конструктор передается строка с названием порта. При подключении через порт COM4:
SerialPort serialPort = new SerialPort("COM4");
Потом открывается порт и настраивается подключение:
// Открываем порт
serialPort.openPort();
// Выставляем параметры
serialPort.setParams(SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
Для передачи команд в устройство используем метод writeString объекта SerialPort, например установка режима отправки сообщения:
char Enter = 0x0D;// Символ перевода каретки serialPort.writeString("AT+CMGF=0" + Enter);
Метод перевода номера телефона в PDU-формат, формат требует чтобы номер телефона имеет четное число знаков, поэтому для нечетных добавляем F:
private static String reversePhone(String phone)
{
if (phone.length() % 2 == 1)
phone += "F";
String phoneRev = "";
phoneRev += phone.charAt(1);
phoneRev += phone.charAt(0);
phoneRev += phone.charAt(3);
phoneRev += phone.charAt(2);
phoneRev += phone.charAt(5);
phoneRev += phone.charAt(4);
phoneRev += phone.charAt(7);
phoneRev += phone.charAt(6);
phoneRev += phone.charAt(9);
phoneRev += phone.charAt(8);
phoneRev += phone.charAt(11);
phoneRev += phone.charAt(10);
return phoneRev;
}
Функция конвертации текста в USC2 формат с добавлением длины сообщения:
private static String StringToUSC2(String text) throws IOException
{
byte[] textOnBytes = text.getBytes("UTF-16");
String textInUSC = "";
for (int i = 2; i < textOnBytes.length; i++)
{
String buff = Integer.toHexString((int) textOnBytes[i]);
if (buff.length() % 2 == 1)
textInUSC += "0";
textInUSC += buff;
}
String msgTextLength = Integer.toHexString(textInUSC.length() / 2);
// Если длина нечётная - добавляем в начале 0
if (msgTextLength.length() % 2 == 1)
msgTextLength = "0" + msgTextLength;
return (msgTextLength + textInUSC).toUpperCase();
}
Исходя из приведенных рассуждений, реализовать отправку и получение сообщения с компьютера через модем не представляет особых трудностей.
Литература:
1. AT-команды. Руководство по использованию АТ-команд для GSM/GPRS модемов.: Пер. с англ. — М.: Серия «Библиотека Компэла». ЗАО «Компэл», 2005. — 432 с.