E=mс2bedded
Pro |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Контакты: E-mail: embedded_pro@mail.ru AppNotes: Сотовая связь Отправка коротких SMS в
формате PDU Отправка длинных SMS в формате PDU Получение и декодирование
SMS Распределённые
вычислительные сети Обзор распределённых
вычислительных сетей Принципы построения распределённых вычислительных
сетей Встраиваемые решения Обзор
встраиваемых операционных
систем Обзор
микропроцессоров ARM
Cortex-A BSP QNX Neutrino
для платы phyFLEX-iMX6 от PHYTEC |
Главная / Отправка длинных SMS в формате PDU Отправка длинных SMS в формате PDU25 апреля Технически,
отсылка длинных SMS почти ничем не отличается от
отсылки коротких. Вся процедура сводится к разбиению
длинного сообщения на короткие и добавлению дополнительного информационного
блока в поле TP-UD (TP-User-Data) и отправка этих
коротких кусочков. После того, как телефон получил все сообщения, по
информации из дополнительного информационного блока он собирает отдельные SMS
в одну длинную. Итак,
приступим к формированию правильной PDU-строки для отправки длинного
сообщения. PDU-Type и TP-MR
PDU-Type – поле флагов. Для отправки
простого сообщения туда нужно было поставить «01». В нашем случае, для отправки длинного сообщения в этом поле должно
быть «41». Т.е. если смотреть по битам, должен быть установлен бит TP-UDHI, который даёт понять телефону, что сообщение
содержит блок UDH (User Data
Header), тот самый дополнительный информационный
блок, в котором будет содержаться информация о частях сообщения. TP-MR (TP-Message-Reference) —
поле,
следующее за PDU-Type.
В случае ошибки
доставки сообщение об ошибке будет содержать этот номер, чтобы мы знали, в
каком из отосланных нами сообщений произошла ошибка. Наверное, для того,
чтобы переотправить, если что. Буржуйские источники
пишут, что поле TP-MR должно быть
разным у каждого короткого сообщения, на которые делится одно длинное. Лично
я пробовал ставить везде одинаковое значение – все кусочки сообщения
отправляет, длинное на телефон приходит. Однако если отправить следом ещё
одно сообщение модем отвечает какой-то ошибкой. В результате я просто
увеличиваю это поле на единичку для каждого следующего сообщения. В этом
случае всё хорошо. Теория поля UDH
Новое поле UDH,
которое содержит информацию о частях сообщения, должно находиться сразу после
поля TP-UDL (TP-User-Data-Length – длина
сообщения). Т.е. поле UDH по сути является частью
поля TP-UD (TP-User-Data), т.е. частью текста
сообщения, для которого отводится 140 байт. UDH–поле
предназначено не только для отправки длинных сообщений, однако далее я буду
рассматривать его именно применительно к нашей задаче. Итак, из чего же
состоит UDH? Смотрим на таблички и вникаем в пояснения: Общий формат UDH для текста,
закодированного 7-битной кодировкой (символы ASCII, т.е. только латинские
символы):
Пояснение: этот формат UDH, как уже было написано выше, применяется для сообщений, написанных в ASCII кодировке, т.е. латинскими символами. В этом случае сообщение кодируется в 7-битную кодировку. В 7-битной упаковке за счёт смещения битов каждый 8 байт является началом отдельного блока, с которого можно начинать нормально декодировать символы. Символы при кодировании как бы «размазываются» по соседним байтам, начало в одном, конец в другом. Вот поэтому и нужен наполнитель filler, чтобы после блока UDH выровнять границу начала текста по границе начала септета. А зачем это нужно? А
для совместимости. Если вы будете отправлять длинную
SMS на телефон, который с ними работать не умеет, то он сразу начнет
декодировать UDH как текст сообщения! Естественно, он из UDH получит
бессвязную белиберду, однако если не выровнять
символы последующего текста по границе байта, то он вообще весь текст как
белиберду декодирует. А правильно выровненный после UDH текст он декодирует
нормально, и получится «[белиберда вместо UDH] текст
сообщения». Общий формат UDH для текста, закодированного
UCS-2 кодировкой (символы юникода, т.е. на любом языке):
Пояснение: здесь всё гораздо проще – поскольку 7-битного сжатия нет, не нужно извращаться с выравниванием текста по границам байта. Главное не забывать, что в UCS-2 один символ кодируется двумя байтами. Теперь рассмотрим,
из чего состоит блок UDH из вышеуказанных табличек. А состоит он из
идентификатора, длины и одного или нескольких информационных элементов (IE):
Вот картинка, дающая
наглядное представление: Как я уже говорил, UDH–поле предназначено не только для
отправки длинных сообщений. Однако нам оно нужно только для этого, посему
упрощаем задачу и рассмотрим информационные элементы именно с точки зрения
длинных сообщений. Итак, для отправки длинных сообщений поле UDH будет
содержать всего один информационный элемент и
выглядеть так:
Проясним вышесказанное.
Итак, у нас есть длинное сообщение. Допустим, разбиваем его на 3 коротких. Тогда IED2
будет равно «03». Первое сообщение будет иметь IED3 равное «01», второе «02» и
третье, соответственно, «03». Теперь о IED1: этот номер-ссылка (reference number) нужен для
того, чтобы телефон при приёме наших трёх коротких сообщений знал, что они
принадлежат к одному и тому же большому сообщению. Для всех частей одного большого сообщения IED1
должен быть одинаковым! Например, вы посылаете на телефон
длинное сообщение, разбитое на 3 коротких, а в это
же время кто-то ещё посылает на этот же телефон другое длинное сообщение.
Короткие сообщения, на которые разбиваются эти два длинных сообщения, приходят в телефон вперемешку, и для того,
чтобы телефон в них не запутался, как раз и применяется поле IED1. Оно будет разное у двух
длинных сообщений, но одинаковое в пределах частей каждого из них. Таким
образом, телефон не перепутает кусочки. IED1 может быть абсолютно любым. Я применяю для его формирования
датчик случайных чисел. Ещё один момент,
связанный с полем IED1
– это его размерность. Она может быть либо 1 либо 2
байта. А зависит это от поля IEI:
если IEI = «00», то
размерность IED1 1
байт, т.е. число от 0 до 255. Если IEI
= «08», то размерность IED1
2 байта, т.е. от 0 до 65535. Этот момент нам позже пригодится, из него
получится отличная военная хитрость. Ну и,
соответственно, IEDL
это длина данных, либо 3 байта (если IEI
= «00») либо 4 байта, (если IEI
= «08»). Таким образом, можно
подсчитать длину IE-блока: она равна 5 байт, если reference
number IED1
кодируется одним байтом, или 6 байт,
если reference number IED1 кодируется двумя байтами. Отсюда получается
длина UDH-блока: байт UDHL,
который идёт перед IE-блоком. Таким образом, полная длина
блока UDH составит 6 или 7 байт
соответственно. Практика
Переходим к водным
процедурам. А именно: будем отправлять длинное сообщение. 1. Для начала формируем весь заголовок PDU как
обычно, только PDU-Type
ставим не 01h
а 41h. Не забываем и про TP-MR – просто увеличиваем его на
единичку для каждого следующего сообщения. 2. Разбиваем длинное сообщение на короткие.
Здесь надо определить количество символов, которые можно отправить коротким
сообщением. Вариантов тут всего два: либо наше сообщение в ASCII-кодировке,
либо в USC-2. На текст сообщения отводится всего 140 байт. Соответственно, в
ASCII кодировке мы можем отправить всего 160 символов (за счёт 7-битной
кодировки), а в USC-2 всего 70. Однако следует
учесть, что блок UDH располагается
именно вначале тех 140 байт, которые отведены для текста сообщения, поэтому,
на текст остается уже не 160 и 70 символов, а меньше. А
сколько именно – будем считать. Сначала вспомним,
что полная длина UDH-блока может быть 6 или 7 байт. Далее: для
ASCII-сообщения: 7-битное кодирование позволяет упаковать 8 символов в 7 байт, отсюда
и получается упомянутая мной выше военная хитрость: мы возьмем UDH-блок
равный 7 байтам. А следом пойдёт кодированный текст. Это даёт нам большой
выигрыш: не нужно выравнивать текст по границе септета. И это же означает,
что мы теряем 8 байт текста. Значит, считаем: 160 – 8 = 152. Итого 152 символа на сообщение. Для
кодировки USC-2: Здесь у нас текст не сжатый, а наоборот: каждый символ текста
кодируется двумя байтами. Если мы возьмём длину UDH равную 7 байтам, то
получим 140-7=133. А 133 на 2 нацело не делится. Значит, берём длину UDH
равную 6 байтам. Тогда всё в шоколаде: 140-6=134, 134/2=67. Итого 67 символов на сообщение. 3. Теперь мы знаем необходимое количество сообщений.
Формируем блок UDH для каждого сообщения в отдельности, в зависимости от типа
текста и от количества сообщений: для
ASCII-сообщения: «06» (длина поля UDH) + «08» (IEI) + «04» (IEDL) + «XXXX» (reference number IED1, случайное двухбайтовое
шестнадцатеричное число) + «NN» (IED2,
количество частей в сообщении) + «nn» (IED3, порядковый номер сообщения); для
кодировки USC-2: «05» (длина поля UDH) + «00» (IEI) + «03» (IEDL) + «XX» (reference number IED1, случайное однобайтовое
шестнадцатеричное число) + «NN» (IED2,
количество частей в сообщении) + «nn» (IED3, порядковый номер сообщения). 4. Компонуем всё вместе, отправляем все сообщения и
наслаждаемся жизнью. Если всё сделано правильно – сообщение склеится как положено. Пример 1. Сообщение
в кодировке USC-2
Будем отправлять
сообщение «Ночь, улица, фонарь, аптека, бессмысленный
и тусклый свет. Живи ещё хоть четверть века - всё будет так. Исхода нет. Умрёшь – начнёшь опять сначала, и повторится всё, как встарь:
ночь, ледяная рябь канала, аптека, улица, фонарь.» на номер 0 (000)
000-00-00. Сообщение длинное,
227 символов, что даёт при разбивке 4 коротких SMS (227/67). Смотрим
внимательно: SMS №1: 0041000B910000000000F000088C050003FF0401 041D 043E 0447 41 —
PDU-Type, 00 – TP-MR, 8C — TP-UDL 050003FF0401 – UDH: 05 – общая длина UDH, 0003 – идентификатор и длина
IE, FF – случайный reference number,
04 – всего 4 сообщения, 01 – это первое сообщение. SMS №2: 0041010B910000000000F000088C050003FF0402
0020 0445 043E 0442 41 —
PDU-Type, 01 – TP-MR, 8C — TP-UDL 050003FF0402 – UDH: 05 – общая длина UDH, 0003 – идентификатор и длина
IE, FF – случайный reference number,
04 – всего 4 сообщения, 02 – это второе сообщение. SMS №3: 0041020B910000000000F000088C050003FF0403
41 —
PDU-Type, 02 – TP-MR, 8C — TP-UDL 050003FF0403 – UDH: 05 – общая длина UDH, 0003 – идентификатор и длина
IE, FF – случайный reference number,
04 – всего 4 сообщения, 03 – это третье сообщение. SMS №4: 0041030B910000000000F000083A050003FF0404
043B 0430 41 —
PDU-Type, 03 – TP-MR, 3A — TP-UDL 050003FF0404 – UDH: 05 – общая длина UDH, 0003
– идентификатор и длина поля данных, FF – случайный reference
number, 04 – всего 4 сообщения, 04 – это четвёртое
сообщение. В данном примере: PDU-Type везде 41,
т.к. это составное сообщение; TP-MR просто увеличивается на единичку,
главное, чтобы они не совпадали; TP-UDL – длина данных, включая длину UDH. UDH начинается для всех одинаково: 05 — общая длина UDH; 00 – идентификатор IE; 03 – длина IE-данных; FF – reference
number, случайное число, одинаковое для всех
коротких сообщений, составляющих одно длинное; 04 – всего 4 сообщения и дальше –
для каждого сообщения свой порядковый номер. Пример 2. Сообщение в кодировке ASCII
Отправляем то же
сообщение, но в транслите: «Noch', ulica, fonar', apteka, bessmyslennyj i tusklyj svet.
Zhivi eshhjo hot' chetvert' veka - vsjo budet tak.
Ishoda net. Umrjosh' - nachnjosh' opjat' snachala, i povtoritsja
vsjo, kak vstar': noch', ledjanaja rjab' kanala, apteka, ulica, fonar'.» 247 символов, разбиваем на 2 сообщения (247/160): SMS №1: 0041000B910000000000F00000A0060804BD010201 CE F7 18 7D 62 81 EA EC F4 38 CC 02 99 DF EE B0 FC C4 02 85 E1 F4 F2 3A CC 02 89 CB F3 79 3B 41 —
PDU-Type, 00 – TP-MR, A0 — TP-UDL 060804BD010201 – UDH: 06 – общая длина UDH, 0804 – идентификатор и длина
IE, BD01 – случайный reference number,
02 – всего 2 сообщения, 01 – это первое сообщение. SMS №2:
0041010B910000000000F0000057060804BD010202
41 —
PDU-Type, 01 – TP-MR, 57 — TP-UDL 060804BD010202 – UDH: 06 – общая длина UDH, 0804
– идентификатор и длина IE, BD01 – случайный reference
number, 02 – всего 2 сообщения, 02 – это второе
сообщение. В данном примере: PDU-Type везде 41,
т.к. это составное сообщение; TP-MR просто увеличивается на единичку. TP-UDL – длина данных, включая длину UDH. UDH начинается для всех одинаково: 06 — общая длина UDH; 08 – идентификатор IE; 04 – длина IE-данных; BD01 – reference
number, двухбайтовое случайное число, одинаковое
для всех коротких сообщений, составляющих одно длинное; 02 – всего 2 сообщения и дальше –
для каждого сообщения свой порядковый номер. Для перевода
текстов SMS в
формат PDU существует
различное множество онлайн кодеров. Вот, например,
ссылка на такой кодер: http://smstools3.kekekasvi.com/topic.php?id=288 Ссылки по теме
http://mobiletidings.com/2009/02/18/combining-sms-messages/ http://mobiletidings.com/2009/02/11/more-on-the-sms-pdu/ http://www.mediaburst.co.uk/blog/concatenated-sms/ http://hiteshagja.wordpress.com/2010/04/04/send-long-sms/ http://isms.ru/article.shtml?art_12 По материалам сайта www.hardisoft.ru Главная / Отправка длинных SMS в формате PDU |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||