Flash-SMS – такая SMS, текст которой сразу выводится на экран телефона/смартфона пользователя вместо записи в память устройства. Пользователь её читает и решает, сохранять её в памяти или нет.
Для отправки flash-SMS потребуется использовать так называемый режим PDU — Packet Data Unit. Это режим, который позволяет контролировать все секретные параметры SMS, описанные в ETSI GSM Technical Specification GSM 03.40.
Для доступа к PDU рекомендуется использовать любой GSM-модем или модуль. Некоторые старые телефоны в режиме модема это тоже умели, а по поводу современных смартфонов ничего сказать не могу, ибо не знаю.
Я использовал GSM-модуль Neoway M660, но для модемов/модулей других производителей это должно быть также справедливо.
В режиме PDU SMS-сообщение представляет собой набор данных, передаваемых модему в виде символов ASCII.
Давайте рассмотрим формат передаваемого SMS-сообщения, последовательность команд, подаваемых на GSM-модем, а также сформируем пакет PDU и пошлем flash-SMS «Привет!» на гипотетический номер +70123456789.
Формат передаваемого SMS-сообщения в режиме PDU
изображен на картинке:
Название поля PDU | Длина, байт | Краткое описание |
---|---|---|
SCA, Service Center Address | 1-12 | Номер телефона Центра SMS (может не указываться) |
PDU Type | Тип PDU | |
MR, Message Reference | 1 | Порядковый номер сообщения, устанавливаемый самим модемом/модулем |
DA, Destination Address | 2-12 | Номер телефона получателя сообщения |
PID, Protocol Identifier | 1 | Идентификатор протокола |
DCS, Data Coding Scheme | 1 | Кодировка сообщения |
VP, Validity Period | 0,1 или 7 | Время жизни SMS |
UDL, User Data Length | 1 | Длина поля User Data в байтах |
UD, User Data | 0-140 | Сообщение |
Итак, рассмотрим назначение отдельных полей пакета PDU передаваемого сообщения.
1. SCA (Service Center Address) — номер телефона Центра SMS (SMSC).
Данное поле не является обязательным, так как номер SMSC хранится на SIM-карте и считывается GSM-модулями Neoway автоматически. Воспользуемся этой возможностью и не будем указывать номер Центра SMS в нашем примере, тем более, что в этом случае содержимое PDU не зависит от используемой SIM-карты. Если номер SMSC в PDU не указывается, поле SCA принимает значение 0x00.
Но если вам всё же захочется считать номер Центра SMS из GSM-модуля, вы всегда можете это сделать с помощью команды AT+CSCA?..
2. PDU Type – тип PDU
2.1 RP (Reply Path)
0 — путь для ответа не определен,
1 – путь для ответа определен, используется тот же Центр SMS (SMSC).
2.2 UDHI (User Data Header Included):
0 – поле UD содержит только само сообщение,
1- поле UD содержит сообщение и дополнительный заголовок.
2.3 SRR (Status Report Request):
0 – статус сообщения не запрашивается,
1- статус сообщения запрашивается.
2.4 VPF (Validity Period Format):
00 – поле VP отсутствует,
01 – зарезервировано,
10 – поле VP содержит времянные данные в относительном формате,
11 – поле VP содержит времянные данные в абсолютном формате.
2.5 RD (Reject Duplicates):
0 – SMSC следует переслать сообщение получателю в случае, если оно имеет те же значения полей MR и DA, что и предыдущее сообщение.
1 — SMSC следует отклонить сообщение в случае, если оно имеет те же значения полей MR и DA, что и предыдущее сообщение.
2.6 MTI (Message Type Indicator):
00 – принимаемое сообщение (от SMSC к модулю) или подтверждение приема (от модуля к SMSC)
01 – отправляемое сообщение (от модуля к SMSC) или подтверждение отправки (от SMSC к модулю),
10 – отчет о доставке (от SMSC к модулю) или SMS-команда (от модуля к SMSC)
11 – зарезервировано.
С целью упрощения поле VP (время жизни SMS, см. п. 7) использовать не будем и установим биты VPF в нулевое значение. Также в нулевое значение установим биты RP, UDHI, SRR, RD. Биты MTI отправляемого сообщения необходимо установить в значение 01. Таким образом значение байта поля PDU Type принимаем равным 0x01.
3. MR (Message Reference) – порядковый номер сообщения, определяется самим модулем. В PDU значение поля устанавливается равным 0x00.
4. DA (Destination Address) – номер телефона получателя сообщения.
Поле DA состоит из трёх частей и имеет следующий вид:
Количество цифр в номере получателя | Тип номера получателя | Номер получателя |
---|---|---|
1 байт | 1 байт | 0…6 байт |
4.1 Количество цифр в номере получателя подсчитывается без учета знака «+» и представляется в шестнадцатеричном формате.
Например, для номера +70123456789 значение байта «Количество цифр в номере получателя» равняется 0x0B (11 в десятичной системе счисления).
4.2 Тип номера получателя.
В случае международного формата номера байт «Тип номера получателя» устанавливается равным 0x91, в случае местного формата – 0x81.
4.3 Номер получателя.
Поле «Номер получателя» формируется следующим образом:
а) в случае международного формата номера знак «+» отбрасывается;
б) если количество цифр в номере нечетное, в конце добавляется «F»;
в) цифры номера попарно переставляются местами.
Например, для номера +70123456789 поле «Номер получателя» будет иметь вид: 0721436587F9, а целиком поле DA – 0B910721436587F9.
5. PID (Protocol Identifier) – идентификатор протокола.
В нашем случае значение поля PID необходимо устанавливать в значение 0x00.
Подробнее об особенностях данного поля можно прочитать в ETSI GSM 03.40, пункт 9.2.3.9.
6. DCS (Data Coding Scheme) – кодировка сообщения.
Вот это и есть то самое поле, которое нас больше всего сейчас интересует! Для отправки сообщений кириллическими символами необходимо использовать кодировку UCS2.
Значение поля DCS в нашем случае следует установить равным 0x18 – это и есть секретная комбинация, позволяющая отправить flash-SMS кириллическими символами (0x08 – обычное SMS).
7. VP (Validity Period) – время жизни сообщения.
Время жизни сообщения – время, по истечении которого сообщение уничтожается (стирается из памяти Центра SMS), если не было доставлено адресату.
Это поле связано с битами VPF поля PDU Type, существует три варианта их совместного использования.
7.1 Поле VP не используется (помните, мы договаривались, что и не будем его использовать в нашем примере?).
В этом случае длина поля VP — 0 байт, биты VPF должны быть установлены в значение 00 (как мы уже и сделали).
7.2 Поле VP содержит данные о времени жизни в относительном формате.
В этом случае длина поля VP — 1 байт, биты VPF должны быть установлены в значение 10 (в двоичной системе).
Возможные значения поля VP в случае использования относительного формата времени и формулы для расчета соответствующего времени жизни сообщения приведены в следующей таблице:
Значение VP шестнадцатеричное | Значение VP десятичное | Соответствующее значению VP время | Максимальное время жизни |
---|---|---|---|
1..8F | 0… 143 | (VP + 1) * 5 минут | 12 часов |
90..A7 | 144… 167 | 12 часов + (VP – 143)*30 минут | 24 часа |
A8..C4 | 168… 196 | (VP – 166) * 1 день | 30 дней |
C5..FF | 197… 255 | (VP – 192) * 1 неделю | 63 недели |
7.3 Поле VP содержит данные о времени жизни в абсолютном формате.
В этом случае длина поля VP — 7 байт, биты VPF должны быть установлены в значение 11(в двоичной системе).
Назначение байт в поле VP при использовании абсолютного формата времени преведено в этой таблице:
1-й байт | 2-й байт | 3-й байт | 4-й байт | 5-й байт | 6-й байт | 7-й байт |
---|---|---|---|---|---|---|
Год | Месяц | День | Час | Минуты | Секунды | Часовой пояс |
При этом каждый байт содержит по два десятичных числа, переставленных местами. Например, байт 2 в случае месяца мая будет иметь значение 0x50.
Год представлен последними двумя цифрами.
Часовой пояс указывает разницу между местным временем и временем по Гринвичу (GMT), выраженную в четвертях часа. При этом первый бит указывает знак этой разницы: 0 – разница положительная, 1 – разница отрицательная. То есть байт 7 в случае часового пояса GMT+3 будет иметь значение 0x21.
Так как мы решили не использовать поле VP и установили два бита VPF поля PDU Type в значение 00, то в пакете PDU нашего примера поле VP будет отсутствовать.
8. UDL (User Data Length) – длина поля UD в байтах.
В случае использования интересующей нас кодировки UCS2 значение поля UDL можно вычислить, умножив количество символов в передаваемом сообщении на 2 (каждый символ кодируется двумя байтами). Для сообщения «Привет!» поле UDL равно 0x1A (26 в десятичной системе).
9. UD (User Data) – сообщение
Для отправки сообщения кириллицей необходимо использовать кодировку UCS2, в этой кодировке каждая буква или символ кодируется двумя байтами.
Таблица кодировки UCS2 — тут
Сообщение «Привет!» в кодировке UCS2 будет выглядеть так:
П: 041F
р: 0440
и: 0438
в: 0432
е: 0435
т: 0442
,: 002C
: 0020
Х: 0425
а: 0430
б: 0431
р: 0440
!: 0021
Привет!: 041F04400438043204350442002C002004250430043104400021
Процесс отправки SMS-сообщения
Как только пакет PDU сформирован, процесс отправки SMS не представляет труда и состоит из двух простых шагов:
1. Ввод команды отправки SMS с указанием количества байт в пакете PDU за исключением поля SCA. Звучит не очень дружелюбно, но если не используется номер Центра SMS, то поле SCA равно 0x00 (как у нас) и это число равно количеству байт в пакете PDU минус один. Для «Привет!» эта величина — 39:
AT+CMGS=39
Важно, чтобы эта команда завершалась символом 'r' (0x0D), без добавок.
После этого GSM-модем выдает приглашение '>' ввести данные пакета PDU.
2. Ввод данных пакета PDU.
В случае сообщения «Привет!» пакет PDU выглядит так:
0001000B91хххххххххххх00181A041F04400438043204350442002C002004250430043104400021 (в текстовом виде),
где хххххххххххх – поле номера получателя, у которого переставлены местами цифры и добавлен символ «F» на конце в случае нечетного количества цифр в номере (как описано раньше).
Для номера +79123456789 поле номера получателя будет иметь вид: 9721436587F9,
а весь пакет PDU с сообщением «Привет!», отправляемый на этот номер:
0001000B919721436587F900181A041F04400438043204350442002C002004250430043104400021
Ввод данных пакета PDU должен заканчиваться байтом 0x1A
В случае успешной отправки SMS-сообщения модем ответит:
+CMGS: Message_Reference
OK
где Message_Reference — порядковый номер сообщения, установленный модемом (см. описание поля MR пакета PDU).
Автор: ZAQWERTY