E=mс2bedded Pro

 

 

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

освещение

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 почти ничем не отличается от отсылки коротких. Вся процедура сводится к разбиению длинного сообщения на короткие и добавлению дополнительного информационного блока в поле 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, т.е. только латинские символы):

Поле

Размер

Описание

UDHL

1 байт

Длина блока UDH в байтах

UDH

n байт

Непосредственно UDH-данные

filler

0-6 бит

Наполнитель, который выравнивает text по границе септета

text

m септетов

непосредственно 7-битные символы сообщения

 

Пояснение: этот формат UDH, как уже было написано выше, применяется для сообщений, написанных в ASCII кодировке, т.е. латинскими символами. В этом случае сообщение кодируется в 7-битную кодировку. В 7-битной упаковке за счёт смещения битов каждый 8 байт является началом отдельного блока, с которого можно начинать нормально декодировать символы. Символы при кодировании как бы «размазываются» по соседним байтам, начало в одном, конец в другом. Вот поэтому и нужен наполнитель filler, чтобы после блока UDH выровнять границу начала текста по границе начала септета.

А зачем это нужно? А для совместимости. Если вы будете отправлять длинную SMS на телефон, который с ними работать не умеет, то он сразу начнет декодировать UDH как текст сообщения! Естественно, он из UDH получит бессвязную белиберду, однако если не выровнять символы последующего текста по границе байта, то он вообще весь текст как белиберду декодирует. А правильно выровненный после UDH текст он декодирует нормально, и получится «[белиберда вместо UDH] текст сообщения».

 

Общий формат UDH для текста, закодированного UCS-2 кодировкой (символы юникода, т.е. на любом языке):

Поле

Размер

Описание

UDHL

1 байт

Длина блока UDH в байтах

UDH

n байт

Непосредственно UDH-данные

text

m байт

непосредственно символы в кодировке UCS-2

 

Пояснение: здесь всё гораздо проще – поскольку 7-битного сжатия нет, не нужно извращаться с выравниванием текста по границам байта. Главное не забывать, что в UCS-2 один символ кодируется двумя байтами.

Теперь рассмотрим, из чего состоит блок UDH из вышеуказанных табличек. А состоит он из идентификатора, длины и одного или нескольких информационных элементов (IE):

 

Поле

Размер

Описание

IEI

1 байт

Идентификатор информационного элемента

IEDL

1 байт

Длина данных информационного элемента

IED

n байт

Данные информационного элемента

Вот картинка, дающая наглядное представление:

Как я уже говорил, UDH–поле предназначено не только для отправки длинных сообщений. Однако нам оно нужно только для этого, посему упрощаем задачу и рассмотрим информационные элементы именно с точки зрения длинных сообщений. Итак, для отправки длинных сообщений поле UDH будет содержать всего один информационный элемент и выглядеть так:

Поле

Значение

Описание

IEI

00h или 08h

Для отправки длинных сообщений всегда равен либо 00h, либо 08h. Если 00h – то IED1 занимает 1 байт, если 08h – то IED1 занимает 2 байта.

IEDL

03h или 04h

Длина данных информационного элемента – 3 или 4 байта, в зависимости от длины поля IED1

IED1

1 или 2 байта

Номер-ссылка (reference number). Должен быть одинаков для всех частей сообщения

IED2

1 байт

Количество частей в сообщении

IED3

1 байт

Порядковый номер части сообщения

 

Проясним вышесказанное. Итак, у нас есть длинное сообщение. Допустим, разбиваем его на 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 044C 002C 0020 0443 043B 0438 0446 0430 002C 0020 0444 043E 043D 0430 0440 044C 002C 0020 0430 043F 0442 0435 043A 0430 002C 0020 0431 0435 0441 0441 043C 044B 0441 043B 0435 043D 043D 044B 0439 0020 0438 0020 0442 0443 0441 043A 043B 044B 0439 0020 0441 0432 0435 0442 002E 0020 0416 0438 0432 0438 0020 0435 0449 0451

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 044C 0020 0447 0435  0442 0432 0435 0440 0442 044C 0020 0432 0435 043A 0430 0020 002D 0020 0432 0441 0451 0020 0431 0443 0434 0435 0442 0020 0442 0430 043A 002E 0020 0418 0441 0445 043E 0434 0430 0020 043D 0435 0442 002E 0020 0423 043C 0440 0451 0448 044C 0020 002D 0020 043D 0430 0447 043D 0451 0448 044C 0020 043E

41 — PDU-Type, 01 – TP-MR, 8C — TP-UDL

050003FF0402 – UDH: 05 – общая длина UDH, 0003 – идентификатор и длина IE, FF – случайный reference number, 04 – всего 4 сообщения, 02 – это второе сообщение.

SMS №3:

0041020B910000000000F000088C050003FF0403 043F 044F 0442 044C 0020 0441 043D 0430 0447 0430 043B 0430 002C 0020 0438 0020 043F 043E 0432 0442 043E 0440 0438 0442 0441 044F 0020 0432 0441 0451 002C 0020 043A 0430 043A 0020 0432 0441 0442 0430 0440 044C 003A 0020 043D 043E 0447 044C 002C 0020 043B 0435 0434 044F 043D 0430 044F 0020 0440 044F 0431 044C 0020 043A 0430 043D 0430

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 002C 0020 0430 043F 0442 0435 043A 0430 002C 0020 0443 043B 0438 0446 0430 002C 0020 0444 043E 043D 0430 0440 044C 002E

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-данных; FFreference 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 3F 67 97 DD EE BC 1A 94 06 D1 EB F3 35 3B AF 06 CD ED 65 BA 0B A4 45 A7 ED 69 50 79 8E 46 AB DF 20 F4 9B 7E 02 8D D1 65 BA BD 2C A7 9F 40 F6 F2 3A 0C 6A 81 EC 73 F5 1B 24 AE 93 CB 74 10 3D BC 76 81 92 73 F4 9B 1C 06 B9 CB 74 17 A8 DA 96 AB DF 73 F4 09 D4 02 B9 C3 63 B4 5B FD 9E A3 4F A0 37 5C 1D A6 9F 40 73 77 78 8C 0E B3 C3

41 — PDU-Type, 00 – TP-MR, A0 — TP-UDL

060804BD010201 – UDH: 06 – общая длина UDH, 0804 – идентификатор и длина IE, BD01 – случайный reference number, 02 – всего 2 сообщения, 01 – это первое сообщение.

SMS №2:

0041010B910000000000F0000057060804BD010202 2C 50 1A 04 7F DB E9 6F 79 9A 3E 57 87 41 F6 B9 FA CD 02 AD C3 6B 90 7D 4E 0F CB 4F 3A 90 FB 3D 46 9F 58 20 76 99 AC 0E BB C3 EA 30 48 AE 0E 8B 4F A0 75 D8 1D 66 87 59 A0 30 9C 5E 5E 87 59 A0 3A 3B 3D 0E B3 40 E6 B7 3B 2C 3F B9 00

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-данных; BD01reference 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