E=mс2bedded Pro

 

 

 

Лазерная гравировка и резка фанеры, материалов из древесины, стекла

LaseroPolis.ru

 

 

Светодиодное

освещение

LUXOPOLIS.RU

Светодиодные лампочки G4/G9

12V 2W 300lm

 

Изготовление визиток

в виде печатных плат

http://vizitkanaplate.ucoz.ru/

 

 

 

Контакты:

E-mail: embedded_pro@mail.ru

 

 

 

AppNotes:

Сотовая связь

Отправка коротких SMS  в формате PDU

Отправка длинных SMS  в формате PDU

Получение и декодирование SMS

Распределённые вычислительные сети

Обзор распределённых вычислительных сетей

Принципы построения распределённых вычислительных сетей

Встраиваемые решения

Обзор встраиваемых операционных систем

Обзор микропроцессоров ARM Cortex-A

BSP QNX Neutrino для платы phyFLEX-iMX6 от PHYTEC

 

Главная  / Отправка коротких SMS в формате PDU

 

Отправка коротких SMS в формате PDU

25 апреля 2014 г.

Форматы SMS

SMS можно отправлять в двух форматах – текстовом и PDU. Текстовый формат чрезвычайно прост и везде достаточно подробно описан. Но из-за своей простоты он содержит несколько ограничений. Например, из текстового режима нельзя отправить сообщение русскими буквами. Кроме того, в текстовом режиме нельзя рулить параметрами сообщения, такими, например, как его тип. К тому же, некоторые телефоны/модемы вообще не поддерживают текстовый режим.

Для обхода ограничений текстового режима, а так же там, где он вообще не поддерживается, используется режим PDU. Это достаточно сложный и запутанный режим, но зато пользователю доступен весь потенциал SMS. Вот его мы и рассмотрим.

В режиме PDU с помощью одного SMS можно отправить максимум 140 байт информации. Для отправки используются две основные кодировки: 7-битная и UCS2. 7-битная используется только для отправки ASCII символов, т.е. символов с кодом от 32 (20h) до 127 (7Fh). Это означает, что русских букв там нет, зато при отправке 7-битная кодировка упаковывается в 8-битный вид, что позволяет упаковать в отведённые нам 140 байт целых 160 ASCII-символов.

В кодировке UCS2 (по сути тот же Unicode) каждый символ кодируется двумя байтами, поэтому становится возможна отправка сообщений на языках отличных от английского, но длина сообщения сокращается до 70 символов (140/2=70).

Форматы и принципы кодировок будут описаны ниже, сейчас же рассмотрим PDU-режим подробнее.

 

Что есть PDU?

PDU это Packet Data Unit – единица (блок, модуль) пакетных данных. По сути, это просто текстовая строка, состоящая из шестнадцатеричных байт, которая содержит в себе все параметры сообщения. Эта строка и передается модему/телефону.

Теоретически, все сотовые телефоны и GSM-модемы поддерживают приём/отправку сообщений в этой форме.

Сообщение в PDU-режиме представляет собой такую формулу:

 

SMS = «SCA» + «TPDU»,

где:

SMS — целиком сформированное сообщение;

SCAService Center Address - номер телефона SMS-центра, через который отправляется SMS;

TPDUTransport Protocol Data Unit - единица данных транспортного протокола.

По сути TPDU и есть наша цель. Именно этот блок содержит номер получателя, текст сообщения и несколько служебных полей.

Данную формулу можно сократить до SMS = TPDU, т.е. не указывать SMS-центр. Это работает в большинстве случаев, т.к. номер SMS-центра обычно уже указан в SIM-карте и не меняется, но об этом чуть позже.

Итак, всё, что нам нужно – правильно закодировать сообщение в формат PDU. Слово «правильно» в предыдущем предложении – это ключевое слово, т.к. на всё неправильное модем выдаст сообщение «ERROR: 304» и всё. В чём именно ошибка он вам не скажет. Поэтому подробно разберём формат для отправки сообщения.

 

Полный «Привет!!!»

Итак, для начала будем отправлять сообщение «Привет!!!» на номер +79123456789. В этом случае каждый символ сообщения кодируется двумя байтами Unicode. Так же, для начала, отправлять сообщение будем в полном виде, т.е. с указанием SMS-центра. Как обойтись без этого будет сказано позже.

Итак, SMS = SCA + TPDU. Начнём с SCA.

 

Формируем номер SMS-центра (он же SCA)

Формат номера SMS-центра прост и состоит из трёх блоков:

 

1 байт

1 байт

От 0 до 6 байт

Длина всего блока SCA

Тип номера SMS-центра

Номер SMS-центра

 

Длина блока SCA – это «длина типа номера SMS-центра» + «длина номера SMS-центра».

Тип номера – это формат номера телефона SMS-центра. В большинстве случаев это международный формат, например «+79123456789». Международному формату соответствует шестнадцатеричный байт 91h. То есть, у нас тип номера всегда будет равен «91».

Номер SMS-центра — тут разработчики решили, что просто так указать номер SMS-центра будет не правильно, и придумали следующее: из номера убирается всё, кроме цифр, затем, если количество символов в номере нечётное, номер дополняется в конце буквой «F» и становится чётным. Затем, каждая пара цифр в номере переставляется местами.

Поясню на примере: Пусть номер SMS-центра будет «+79107899999» (русский провайдер МТС). Приведём его в соответствие формату PDU: убираем плюс перед номером, считаем количество символов – получилось 11. Нечётное число, значит, дописываем в конец букву «F». Получается «79107899999F». Затем переставляем местами цифры в каждой паре. Получится «9701879999F9». Вот он, искомый номер SMS-центра.

Затем объединяем всё до конца: берём тип номера SMS-центра, добавляем к нему сам номер и в начало вставляем количество получившихся БАЙТ в шестнадцатеричном виде. Т.е. для нашего случая с номером +79107899999 получим такую строку: «07919701879999F9». То есть: «07» (длина) + «91» (тип, 1 байт) + «9701879999F9» (номер, 6 байт). Длина равна «07» потому что 1 байт типа + 6 байт номера. Обязательно «07», а не «7» — все байты переводятся в текстовый вид целиком, с лидирующим нулём, если он есть.

ВАЖНО! Фраза «количество получившихся байт» выделена специально, т.к. это очень важно! Разработчики всё запутали, поскольку в номере получателя сообщения указывается не количество байт, а количество цифр в номере: бред и путаница. Так что тут нужно быть очень внимательным.

 

Формула TPDU

Теперь пришла очередь рассмотреть вторую часть PDU-формата. Для неё тоже есть формула:

 

TPDU = «PDU-Type» + «TP-MR» + «TP-DA» + «TP-PID» + «TP-DCS» + «TP-VP» +

+ «TP-UDL» + «TP-UD»

 

Выглядит страшно, но ничего, сейчас разберёмся:

PDU-Type   – тип сообщения. Поле флагов, о нём речь пойдёт дальше. В некоторых источниках упоминается как SMS-SUBMIT-PDU;

TP- MR     TP-Message-Reference – назначение этого поля для меня осталось загадкой, надеюсь, что когда-нибудь всё прояснится. Поэтому ставим TP-MR = «00»;

TP- DA      TP-Destination-Address – номер телефона получателя сообщения;

TP- PID     TP-Protocol ID – идентификатор протокола. Особого интереса не представляет. Тоже всегда равен «00»;

TP- DCS   TP-Data-Coding-Scheme – схема кодирования данных. Указывает, в каком формате представлено сообщение;

TP- VP      TP-Validity-Period — время действия сообщения (если сообщение не будет получено абонентом в течение этого времени, SMS-центр его удалит);

TP-UDL    – TP-User-Data-Length – длина сообщения;

TP- UD     TP-User-Data – непосредственно текст SMS, закодированный согласно полю TP-DCS.

В принципе, сложного ничего нет. Пойдём по порядку:

PDU-Type – поле флагов. Один байт, состоящий из 8 бит, которые осуществляют некоторую настройку сообщения. Посмотрим на табличку:

 

Бит

7

6

5

4

3

2

1

0

Название

TP-RP

TP-UDHI

TP-SRR

TP-VPF

TP-VPF

TP-RD

TP-MTI

TP-MTI

 

Расшифруем поля:

 

Бит

Значение

TP-RP

Reply path

TP-UDHI

User data header indicator

TP-SRR

Status report request. Если бит равен 1 – запрашивается отчет о состоянии

TP-VPF

Validity Period Format – формат поля TP-VP (время действия сообщения). Эти 2 бита описывают, как будет выглядеть поле TP-VP в формуле TPDU:

Бит 4

Бит 3

Формат поля

0

0

Поле TP-VP отсутствует

1

0

Поле TP-VP присутствует и описывает относительный формат (1 байт)

0

1

Поле TP-VP присутствует и описывает расширенный формат (7 байт)

1

1

Поле TP-VP присутствует и описывает абсолютный формат (7 байт)

TP-RD

Reject duplicates

TP-MTI

Тип сообщения. Когда бит 1 равен «0», а бит 0 равен «1» это исходящее сообщение

 

Для нас самым главным является тип сообщения, т.е. 2 бита TP-MTI, они должны быть 01, что указывает на то, что это исходящее сообщение.

Кроме того, имеют некоторое значение биты TP-VPF (4-й и 3-й). Они указывают время жизни сообщения и влияют на размер поля TP-VP в формуле TPDU. Если оба бита равны «0», то поле TP-VP вообще из формулы исключается.

В общем и целом, для нормальной отправки сообщения достаточно в байте PDU-Type установить в «1» только нулевой бит, таким образом, получим байт «01». Его и подставим в формулу.

Возвращаемся к формуле TPDU:

TP-MR количество успешно переданных сообщений от 00h до FFh, устанавливается самим телефоном, поэтому его надо установить при передаче в «00».

TP-DA номер телефона получателя сообщения. Тут примерно такая же история, что и с номером SMS-центра:

 

1 байт

1 байт

От 0 до 6 байт

Длина номера получателя

Тип номера получателя

Номер получателя

 

Тип номера остается таким же, как и для SMS-центра: международный формат записывается как «91».

Номер получателя кодируется так же, как и номер SMS-центра: убираем всё, кроме цифр, дописываем в конец «F», если количество цифр в номере нечётное, а затем переставляем местами цифры в каждой паре. Пример такой же: нам нужно отправить SMS на номер +79123456789. Убираем плюс, цифр получилось 11 – дописываем в конец «F» и переставляем местами цифры, получаем «9721436587F9».

ВНИМАНИЕ! А теперь очередной сюрприз, о котором по-русски нигде не написано. Точнее написано, но не правильно: Поле «длина номера получателя» считается не как количество байт, а как количество цифр в номере без учета добавленного символа «F»!

Применительно к нашему примеру всё поле TP-DA будет выглядеть как «0B919721436587F9», т.е. «0B» (длина, 11 цифр) + «91» (тип) + «9721436587F9» (номер, длина 6 байт, но 11 цифр!!!)

Длина «0B» в шестнадцатеричной системе это 11 в десятичной, т.е. ту букву «F», которую мы добавили для чётности мы не учитываем. Тип номера в длине тоже не учитывается. Надеюсь, к этому времени Ваш разум ещё сохранил некоторую ясность.

TP-PID TP-Protoсol-Identifier – поле идентификации протокола. Предназначено для того, чтобы транспортный протокол мог обмениваться информацией с протоколом высшего уровня. TP-PID описывает высокоуровневые протоколы или взаимодействующие устройства, от которых или для которых предназначена SMS. SMSC (Центр Обслуживания Коротких Сообщений) сети может обеспечивать преобразования SMS в e-mail, сообщения оповещения, формат Телекса и т.д. или наоборот. Однако в нашем случае значения этого поля сообщают приёмнику сообщения о методе замены коротких сообщений. Если значение этого поля 00h, то короткие сообщения не заменяются, а если значение этого поля лежит в пределах 41h..47h, то происходит замена короткого сообщения на сообщение другого формата. Обратите внимание на то, что это происходит на стороне приёмника сообщения! Для нашего случая оставляем это поле равным «00».

TP-DCSTP-Data-Coding-Scheme – схема кодирования данных. Она описывает, как будет закодировано отсылаемое сообщение. Тут достаточно знать только несколько значений:

00h: кодировка 7-бит (160 знаков, но не кириллическая, только латинские символы);

04h: кодировка 8-бит (140 знаков, только латинские символы);

08h: кодировка UCS2 (тот же Unicode), 70 знаков, 2 байта на символ.

Если старшим полубайтом указать не «0», а «1» – то сообщение получится типа Flash – т.е. не осядет в мобильнике получателя, а сразу же выведется ему на экран. Это может быть полезной возможностью:

10h: Flash-сообщение, кодировка 7-бит;

14h: Flash-сообщение, кодировка 8-бит;

18h: Flash-сообщение, кодировка UCS2.

По поводу кодировок речь пойдет дальше.

ВНИМАНИЕ! Некоторые мобильные устройства могут не воспринимать кодировку 7 бит! При этом необходимо использовать кодировку 8 бит, т.е. при подготовке сообщения не использовать алгоритм сжатия, описанный ниже. Все остальные правила остаются при этом прежними

TP-VP – TP-Validity-Period – время жизни сообщения. Обращаю внимание, что данное поле нужно указывать только при соответствующем включенном параметре TP-VPF в PDU-Type! Так, как в нашем случае, я его не указал, то это поле просто не указываем.

Если кому понадобится, то вот некоторые значения поля при задании относительного формата времени жизни сообщения (TP-VPF = 10b):

·     0Bh - один час;

·     23h - три часа;

·     47h - шесть часов;

·     8Fh - двенадцать часов;

·     A7h - один день;

·     C4h - один месяц (30 дней);

·     FFh - максимальный срок хранения (63 недели).

Эти значения кодируется одним байтом в соответствии со следующей таблицей:

 

Значение TP-VP, десятичное

Формула расчёта TP-VP

Максимальное время

Шаг задания времени

0 …143

(TP-VP + 1) * 5 минут

12 часов

5 минут

144 .. 167

12 часов + (TP-VP – 143)*30 минут

24 часа

30 минут

168 .. 196

(TP-VP – 166) * 1 день

30 дней

1 день

197 .. 255

(TP-VP – 192) * 1 неделю

63 недели

1 неделя

 

TP-UDL длина сообщения. Указывается в байтах. Для сообщений на русском языке используется кодировка UCS2 (тот же Unicode), т.е. каждая буква кодируется двумя байтами. Соответственно сообщение из 9 букв «Привет!!!» будет иметь длину 18 байт, т.е. «12» в шестнадцатеричной системе счисления. Для сообщений в 7-битной кодировке указывается количество символов в сообщении, т.е. для фразы «Hello!!!» длина будет равна «08» не смотря на то, что перекодированная в 8-битное представление эта фраза занимает не 8, а 7 байт.

TP-UD — TP-User-Data – непосредственно текст SMS, закодированный согласно полю TP-DCS, т.е. либо используется кодировка 7-бит, либо UCS2. Для примера, сообщение «Привет!!!» в кодировке UCS2 будет выглядеть так: «041F04400438043204350442002100210021».

К кодировкам вернёмся позже, пока что резюмируем полученные знания:

Исходя из формулы

 

TPDU = « PDU-Type » + «TP-MR» + «TP-DA» + «TP-PID» + «TP-DCS» + «TP-VP» +

+ «TP-UDL» + «TP-UD»,

 

получаем подстановкой наш текст сообщения:

 

TPDU = «01» + «00» + «0B919721436587F9» + «00» + «08» + «12» +

«041F04400438043204350442002100210021»

 

Памятуя о том, что SMS = «SCA» + «TPDU», добавим в начало адрес SMS-центра и получим полноформатное PDU-сообщение «Привет!!!» на номер +79123456789 через SMS-центр +79107899999:

 

07919701879999F901000B919721436587F9000812041F04400438043204350442002100210021

 

Вот именно такую последовательность цифр и нужно отправить телефону/модему, чтобы он отправил сообщение. Но об отправке поговорим позже. Сейчас рассмотрим краткий формат отправки.

 

Краткий «Привет!!!»

Краткость, как известно, сестра таланта. Посему возьмём это на вооружение и освоим более краткий формат отправки SMS. А именно: из формулы SMS = SCA + TPDU исключается SCA. То есть мы не будем указывать телефону/модему номер SMS-центра, так как в 99,9% случаев он уже настроен в SIM-карте. А раз он настроен, значит, нечего его писать – телефон/модем сам догадается, что SMS-центр нужно взять из настроек SIM-карты. Но для того, чтобы он догадался, надо ему подсказать, а именно вместо SCA подставить «00».

Остальные параметры не меняются и подставляются точно так же. Следовательно, наш полный «Привет!!!» в кратком формате будет иметь вид:

 

0001000B919721436587F9000812041F04400438043204350442002100210021

 

Начинается с «00», а затем сразу идёт поле «PDU-Type» и т.д.

Гораздо удобнее, не нужно производить лишней работы. Единственное «НО»: не все телефоны/модемы понимают «00» вместо SCA. Для таких устройств нули нужно опускать и начинать сообщение сразу с поля «PDU-Type». Лично мне таких устройств не попадалось, но помнить об этом стоит.

 

О кодировках. UCS2 (Unicode)

Начнём с кодировки UCS2, поскольку именно она позволяет нам отправлять сообщения на русском языке. Тут всё очень просто: тот же Unicode. Каждый символ имеет двухбайтовое представление. Т.е. для английских символов однобайтовой кодировки в начало добавляется байт 00H. Для русских (те, что начинаются с C0h в Windows-кодировке) можно создать такое правило: из байта вычитается C0h и прибавляется 410h (кроме букв «ё» и «Ё», которые в Unicode имеют коды 0451h и 0401h соответственно).

Т.е. получается такая таблица кодировок:

 

 

Windows

UCS2

 

Windows

UCS2

 

Windows

UCS2

А

C0

04 10

К

CA

04 1A

Х

D5

04 25

Б

C1

04 11

Л

CB

04 1B

Ц

D6

04 26

В

C2

04 12

М

CC

04 1C

Ч

D7

04 27

Г

C3

04 13

Н

CD

04 1D

Ш

D8

04 28

Д

C4

04 14

О

CE

04 1E

Щ

D9

04 29

Е

C5

04 15

П

CF

04 1F

Ъ

DA

04 2A

Ё

A8

04 01

Р

D0

04 20

Ы

DB

04 2B

Ж

C6

04 16

С

D1

04 21

Ь

DC

04 2C

З

C7

04 17

Т

D2

04 22

Э

DD

04 2D

И

C8

04 18

У

D3

04 23

Ю

DE

04 2E

Й

C9

04 19

Ф

D4

04 24

Я

DF

04 2F

а

E0

04 30

к

EA

04 3A

х

F5

04 45

б

E1

04 31

л

EB

04 3B

ц

F6

04 46

в

E2

04 32

м

EC

04 3C

ч

F7

04 47

г

E3

04 33

н

ED

04 3D

ш

F8

04 48

д

E4

04 34

о

EE

04 3E

щ

F9

04 49

е

E5

04 35

п

EF

04 3F

ъ

FA

04 4A

ё

B8

04 51

р

F0

04 40

ы

FB

04 4B

ж

E6

04 36

с

F1

04 41

ь

FC

04 4C

з

E7

04 37

т

F2

04 42

э

FD

04 4D

и

E8

04 38

у

F3

04 43

ю

FE

04 4E

й

E9

04 39

ф

F4

04 44

я

FF

04 4F

 

Здесь приведены только большие буквы. Символы Unicode можно посмотреть в программе «Таблица символов», которая есть в Windows и находится в меню «Пуск» — «Программы» — «Стандартные» — «Служебные» — «Таблица символов», а полную интерактивную таблицу Unicode - на сайте http://unicode-table.com/ru/

Таким образом, написание русских сообщений в кодировке UCS2 не представляет никакой сложности – бери букву, перекодируй её в двухбайтовое представление и отправляй…

Однако в UCS2 можно отправить только 70 символов в одном SMS. Если необходимо отправить больше – тут уж придётся пожертвовать русским языком и отправлять латинскими символами. Они обычно кодируются одним байтом, от 0 до 7Eh. Точнее, даже не байтом, а 7 битами байта. Вот тут и кроется очередная бредовая хитрость: поскольку для того, чтобы закодировать символ нужно всего 7 бит, а в байте их 8, применяется специальный алгоритм, который упаковывает 7-битные символы в 8-битовое представление. За счёт того, что используются свободные биты, длина сообщения в этой кодировке составляет максимум 160 символов, которые в упакованном формате занимают максимум 140 байт.

 

7-битная, упакованная

Теперь поговорим об алгоритме упаковки 7-битной строки в 8-битное представление. Он достаточно прост, хотя может потребовать времени, чтобы вникнуть. Объяснять буду на примере кодирования строки «Hello!!!».

Поскольку для кодирования символа ASCII используется 7 бит (биты от 0 до 6), значит, старший, 7-й бит всегда равен 0. Вот он-то и используется для упаковки. Т.е. последовательность такая:

1. Получаем первый байт: берётся семь бит первого символа (биты 7-0); из семи бит второго символа самый младший (0-й) бит переносится в старший разряд первого байта, получается так: (0-й бит второго символа)+(7 бит первого символа);

2. Далее получаем второй байт: от второго символа у нас теперь осталось 6 бит, дополняем их до целого байта, а именно берём из третьего символа уже два младших бита (1-й и 0-й) и переносим их в старшие разряды второго байта. Получается так: (1-й и 0-й биты третьего символа)+(6 бит второго символа);

3. Получаем третий байт: от третьего символа забрали 2 бита, осталось 5. Значит, чтобы получить полный третий байт, надо из четвёртого символа забрать 3 младших бита …

4. И так далее, по аналогии.

Картинка ниже иллюстрирует данный процесс:

 

Вот как выглядит последовательность байт фразы «Hello!!!» в 7-битной кодировке:

48 65 6C 6C 6F 21 21 21

А вот эта же фраза, но уже перекодированная в 8-битную:

C8 32 9B FD 0E 85 42

Как видно, получилось на целый байт меньше! Грубо говоря, кодирование каждых 8 символов даёт выигрыш в один байт. Вот так и получается, что в 140 байт влезает 160 символов.

ВНИМАНИЕ! Ещё раз обращаю внимание на то, что при отправке сообщений в 7-битной кодировке в поле TP-UDL (Длина сообщения) указывается количество символов в сообщении, а не количество байт, получившихся после упаковки! То есть для «Hello!!!» TP-UDL будет равно «08», хотя байтов у нас получилось семь!

 

Отправка SMS

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

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

1. Переводим модем в PDU-режим. Для этого отсылаем ему команду «AT+CMGF=0». Если получаем в ответ «OK» — значит всё в порядке, режим поддерживается и включен.

2. Затем, даём команду «AT+CMGS=<длина сообщения>». Эта команда требует пояснения: <длина сообщения> в данном случае подразумевает не длину всего сообщения, а длину блока TPDU! То есть длину без учета номера SMS-центра! Длина считается в байтах.

Возвращаясь к первому примеру (полноформатное PDU-сообщение «Привет!!!» на номер +79123456789 через SMS-центр +79107899999), где сообщение выглядело как:

 

07919701879999F901000B919721436587F9000812041F04400438043204350442002100210021

 

Для его отправки мы должны дать команду «AT+CMGS=31», т.е. начало «07919701879999F9» в длину не входит, ибо это номер SMS-центра.

Если номер SMS-центра не указывается, и вместо него подставляется «00», то этот байт тоже не учитывается. Т.е. для нашего короткого «привета»:

 

0001000B919721436587F9000812041F04400438043204350442002100210021

 

Длина всё равно будет 31. Да, кстати: в данном случае, в команде телефону/модему, длина сообщения указывается десятичной цифрой.

3. После команды «AT+CMGS=<длина сообщения>», если всё нормально, телефон/модем ответит приглашающей кавычкой «>». Теперь передаём ему непосредственно всё сформированное нами сообщение. Вместе с номером SMS-центра, или «00» вместо него. То есть всё, что мы кодировали. Заканчиваться строка должна спецсимволом «Ctrl+Z», имеющим ASCII-код 1Bh.

4. Если всё нормально модем ответит «+CMGS: <номер>», а получателю придёт долгожданная SMS. <Номер> — это внутренний порядковый номер SMS.

Если же мы где-то ошиблись – тогда модем ответит «ERROR: 304». Тогда придётся всё проверять сначала.

Для более подробного ознакомления с форматом PDU можно изучить следующие документы:

 

Формат PDU или как сформировать и распаковать SMS. Документ в формате pdf

Developer’s Guide. SMS with the SMS PDU-mode. Документ в формате pdf

How to handle SMS messages. Документ в формате pdf

 

По материалам сайта www.hardisoft.ru

 

Главная  / Отправка коротких SMS в формате PDU