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

 

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

5 марта 2014 г.

Работа с модемом

Приём SMS начинается с GSM-модема. Модем управляется AT-командами. Рассмотрим кратко алгоритм получения SMS от модема.

 

Режим PDU

Рекомендую перевести модем в PDU-режим перед всеми операциями командой AT+CMGF=0.

 

Память

У GSM-модемов есть несколько видов памяти, в которых могут храниться SMS-сообщения.

Память модема делится на три логических секции: первая для просмотра, чтения и удаления сообщений, вторая для сохранения и отправки исходящих сообщений и третья для только что полученных сообщений. Обычно модем хранит полученные сообщения в первой секции.

Кроме логического деления на секции у модема ещё есть несколько видов физической памяти: память SIM-карты, внутренняя память модема и прочее. Каждая физическая память назначается определенной логической секции. Таким образом, можно назначить память SIM-карты для чтения и удаления сообщений, а память модема для написания и отправки.

Каждая область физической памяти имеет свое имя, для того, чтобы ей можно было оперировать в командах модема. Вот несколько возможных имен областей:

SM – память SIM-карты;

ME – память модема/телефона;

MT – это общая память SIM-карты и модема, т.е. MT = «SM» + «ME»;

BM – память для широковещательных сообщений сети;

SR – память для отчётов (о доставке и т.п.).

Для чтения сообщений нам понадобится только SM и ME память, либо MT, которая включает в себя и SM, и ME.

Учтите, любое чтение идёт только из памяти, назначенной для первой секции. Это важно.

Для настройки памяти модема существует специальная AT-команда: AT+CPMS.

Формат команды:

 

AT+CPMS=message_storage1[,message_storage2[,message_storage3]]

 

Как видно из формата, вторую и третью секции памяти указывать не обязательно (они в квадратных скобках). Поэтому мы их указывать и не будем.

Итак. Нам нужно настроить первую секцию памяти (для чтения и удаления) и назначить ей соответствующую физическую область памяти. Делается это так:

 

AT+CPMS=”SM”,

либо  AT+CPMS=”ME”,

либо AT+CPMS=”MT.

 

Первый вариант указывает на то, что читать будем из SIM карты, второй – из памяти модема, третий – сразу из обоих. Рекомендую воспользоваться именно третьим вариантом.

В ответ на эту команду модем выдаст нечто вроде (ответ модема выделен жирным шрифтом):

 

AT+CPMS=”MT

+CPMS: 6,100,6,100,0,20

OK

 

Цифры означают количество сообщений в памяти (например 6) и максимально допустимое количество сообщений (например 100) в каждой секции.

Узнать, какая область назначена для какой секции можно командой AT+CPMS?:

 

AT+CPMS?

+CPMS: ”MT”,6,100,”ME”,6,100,”SM”,0,20

OK

 

Самое главное для чтения входящих сообщений – это первая секция, на остальные внимания не обращаем.

 

Чтение

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

Для чтения сообщений существует 2 команды: AT+CMGL и AT+CMGR. Разница их в том, что первая команда выдаёт сразу все сохраненные в памяти сообщения, а вторая – только одно сообщение, индекс которого передается ей в параметрах. Индекс начинается с нуля.

 

AT+CMGL

Синтаксис:

 

AT+CMGL=<status>

 

где <status> – статус сообщения в памяти. Возможные статусы:

 

<status> в текстовом режиме

<status> в режиме PDU

Пояснение

«REC UNREAD»

0

Полученные непрочитанные сообщения

«REC READ»

1

Полученные прочитанные сообщения

«STO UNSENT»

2

Сохраненные неотправленные сообщения

«STO SENT»

3

Сохраненные отправленные сообщения

«ALL»

4

Все сообщения

 

AT+CMGR

Синтаксис:

 

AT+CMGR=<index>

 

где <index> – индекс сохраненного сообщения.

 

AT+CMGL позволят получить сразу все сообщения, причем можно выбрать по статусу — какие именно сообщения нас интересуют. AT+CMGR просто выдает нам указанное сообщение, невзирая на статус. Но нужно знать индекс сообщения.

В общем, в примере ниже, я использовал AT+CMGL=4 чтобы получить все сообщения, AT+CMGL=0 чтобы получить только непрочитанные и AT+CMGR=2 чтобы получить сообщение с индексом 2:

 

1

 

Пояснения к примеру:

AT+CMGF=0 – переходим в PDU режим;

AT+CPMS=”MT” – переключаем память SIM и модема на чтение сообщений;

AT+CMGL=4 – читаем все сообщения. Модем возвращает нам всё содержимое памяти МТ. Формат такой: каждое сообщение начинается строкой +CMGL с параметрами:

1.    Индекс сообщения;

2.    Статус сообщения (1 = «REC READ», прочитано);

3.    <alpha> – строковый параметр, определяющий ;

4.    Длина сообщения.

Со следующей строки начинается, собственно, само сообщение в PDU формате. На рисунке терминал вывел его в несколько строк, хотя на самом деле модем передаёт его одной строкой. Вот это самое сообщение мы и будем декодировать. Следующее сообщение опять начинается строкой +CMGL и т.п. Идём далее.

AT+CMGL=0 – читаем сообщения со статусом «REC UNREAD», т.е. непрочтённые. Здесь модем вернул просто ОК – это значит, что непрочтённых сообщений нет. Если бы были – он бы их вывел в том же формате, что и до этого.

AT+CMGR=2 – получение сообщения с индексом 2. Ответ начинается с +CMGR и параметров:

1.    Статус сообщения (1 = «REC READ», прочитано);

2.    <alpha> – строковый параметр, определяющий;

3.    Длина сообщения.

И со следующей строки опять-таки идёт PDU.

Примечание: указанные параметры команд и ответов на команды справедливы, только если включен PDU-режим командой AT+CMGF=0. Если модем работает в текстовом режиме, то параметры команд и возвращаемый ими результат отличаются от вышесказанного.

Как видим, сложного ничего нет, приступаем к декодированию текста сообщения.

 

Разбор PDU

Итак, считывать из модема сообщения научились, теперь будем их декодировать. Начнём с простого. Возьмём для примера такое сообщение:

 

07919761989901F0040B919701119905F80000211062320150610CC8329BFD065DDF72363904

 

Что в переводе на русский язык означает «Hello World!». Разберём его по косточкам:

 

TP-SCA

PDU

Type

TP-OA

TP

PID

TP

DCS

TP-SCTS

TP

UDL

TP-UD

07 91 9761989901F0

04

0B 91 9701119905F8

00

00

21106232015061

0C

C8329BFD065DDF72363904

 

TP-SCA (Service Centre Address) – адрес сервис-центра, отправившего сообщение.

Это поле полностью совпадает по своему значению с аналогичным полем передаваемого SMS, но в случае приёма сообщений мало чем может нам пригодиться. Но для проформы мы всё-таки разберём данное поле: первый байт (07) – длина номера, в данном случае длина равна 7 байт. Следующий байт (91) – тип номера, в данном случае 91 – международный. Следующие 6 байт – сам номер сервис-центра, дополненный до четности символом F и переставленными местами парами цифр. Подробнее об этом изложено в статье про отправку SMS.

PDU-Type (PDU Type) – важный байт типа сообщения, состоящий из различных флагов, разберём его состав подробнее:

 

Биты

Описание

0
1

Message Type indicator (TP-MTI)

2

More messages to send (TP-MMS)

3

0

4

0

5

Status report indication (TP-SRI)

6

User data header information (TP-UDHI)

7

Reply path (TP-RP)

 

 

TP-MTI – эти два бита определяют тип SMS. Причём трактовка этих битов зависит от «направления» SMS, т.е. от того, отправляется она или принимается. Вот табличка, описывающая доступные типы сообщения:

 

Бит 1

Бит 0

СЦ –> модем

Модем –> СЦ

0

0

SMS-DELIVER

SMS-DELIVER REPORT

1

0

SMS-STATUS REPORT

SMS-COMMAND

0

1

SMS-SUBMIT REPORT

SMS-SUBMIT

1

1

RESERVED

RESERVED

 

В нашем случае, используется направление Сервис-Центр –> модем, т.к. мы принимаем сообщение. В нашем примере байт PDU-Type равен 04, следовательно Бит 1 = 0 и Бит 0 = 0, значит тип сообщения – SMS-DELIVER. Так и должно быть.

TP-MMS (More Messages to Send) — этот бит информирует принимающую сторону, есть ли ещё сообщения, ожидающие в сервис-центре. Если бит равен нулю, то это значит, что в сервис-центре есть ещё сообщения для доставки. Если 1 — значит в сервис-центре больше сообщений нет. В нашем случае этот бит равен 1, значит в сервис-центре больше нет сообщений для нашей SIM-карты.

TP-SRI (Status Report Indication) — этот бит показывает, будет ли отправлен отчёт о состоянии отправителю. 0 — не будет, 1 — будет. Этот бит относится к биту TP-SRR (Status Report Request) в байте SMS-SUBMIT при отправке. Для чтения сообщения он не пригодится.

TP-UDHI (User Data header Indicator) — этот бит показывает, что содержит блок TP-UD (User Data). Если бит равен 1 — то блок User Data содержит ещё и блок User Data Header, в добавок к сообщению. Если ноль — то блок User Data содержит только сообщение. Для нас это важный бит, поскольку дополнительный блок User Data Header применяется для длинных SMS, в нём содержится информация о количестве частей в SMS и номер текущей части. Передача длинных SMS подробно описана в «Отправка длинных SMS в формате PDU».

TP-RP (Reply Path) — путь для ответа. Это бит говорит, что от принимающего запрашивается ответ. Если путь ответа запрашивается, отвечающее мобильное устройство может попытаться использовать тот же сервис-центр, что и отправитель, для более надёжной доставки ответа: 1 — запрашивается, 0 — не запрашивается

Возвращаясь к нашему примеру и учитывая вышесказанное, анализ байта TP-MTI (04) говорит нам о том, что это принятое SMS (TP-MTI=0,0 — SMS-DELIVER), что на станции больше нет для нас сообщений (TP-MMS=1) и что это одиночная SMS, а не часть длинной (TP-UDHI=0).

TP-OA (Originator Address) – адрес отправителя сообщения. Это поле составное:

 

Длина номера отправителя N

Формат номера

Номер отправителя

1 байт

1 байт

N цифр или полубайт

 

Длина номера отправителя в нашем случае 0Bh, формат номера - 91h.

Длина номера: указывается количество цифр в номере, если это обычный номер телефона или количество полубайт, если это текстовый формат номера в 7-битной кодировке.

Формат номера. Тут тоже не все так просто:

 

Бит

Значение

0
1
2
3

Идентификатор плана нумерации

4
5
6

Тип номера

7

Всегда = 1

 

Рассмотрим тип номера:

 

Биты
6 5 4

Значение

0 0 0

Неизвестно. Сотовая сеть не знает, что за формат у номера

0 0 1

Международный формат номера

0 1 0

Внутренний номер страны. Префиксы страны у номера отсутствуют

0 1 1

Служебный номер сети. Используется оператором.

1 0 0

Номер подписчика. Используется, когда определённое представление короткого номера сохранено в одном или нескольких СЦ как часть более высокоуровневого приложения

1 0 1

Буквенно-цифровой, закодированный в 7-битной кодировке

1 1 0

Сокращенный номер

1 1 1

Зарезервировано

 

 

Нас интересует всего 2 типа номера: 001 и 101, остальное в основном либо не применяется, либо применяется очень редко.

Далее — идентификатор плана нумерации. Применяется для типов номеров 000, 001, 010 и 101. Нет смысла рассматривать всё, так как в сотовых сетях применяется всего 2 плана:

                   1.    Для типа номера 101 (буквенно-цифровой) идентификатор плана нумерации всегда 0000;

                   2.    Для остальных типов идентификатор плана нумерации всегда 0001.

Непосредственно сам номер — может быть двух видов, либо набор цифр, например “79101234567”, либо текст, например “InternetSMS”. На вид указывает тип номера из предыдущего байта.

Цифровой номер кодируется по стандартной схеме кодирования номеров, о ней можно прочитать в материале «Отправка коротких SMS в формате PDU».

Текстовый номер – просто строка текста, сжатая в 7-битную кодировку.

Как уже говорилось, длина номера – это либо количество цифр, либо количество полубайт. Т.е. для номера 79101234567 длина будет равна 11 (0Bh, как в примере), а для номера “InternetSMS” – 20 (14h). Почему 20? Потому, что «InternetSMS» (без пробела) это 11 символов. В 7-битной кодировке они упакуются в 11*0.875 = 9.625 байт. Умножаем на 2 чтобы получить полубайты, получаем 19.25. Округляем в большую сторону, т.е. в 20 полубайт.

Для ясности, разберём ещё один пример с текстовым номером: 09D0D432BB2C03. Здесь 09h — длина (9 полубайт), D0h — формат номера. А дальше — сам номер (длиной 5 байт, т.е. 10 полубайт!). По нормальному это «Tele2» - 5 символов. При кодировании получается 5*0.875 = 4.375. Умножаем на 2 чтобы получить полубайты, получаем 8.75. Округляем в большую сторону — 9 полубайт. Но полубайтами мы не оперируем, поэтому номер в действительности не 9, а 10 полубайт, т.е. 5 байт.

Тут настало время сделать небольшое отступление. Строго говоря, текстовый номер передаётся вовсе не в кодировке ASCII, как может показаться, а в специальной кодировке GSM 03.38. Эта кодировка во многом схожа с кодировкой ASCII за небольшим исключением: латинские буквы, цифры, пробел и часть спецсимволов находятся на тех же самых позициях, а вот некоторые символы находятся не на привычном месте. Самый яркий пример - символ « с кодом 00h.

Нет также некоторых спецсимволов вроде [, ], {, }, ~, |, но зато присутствуют символы греческого алфавита.

 

Кодировка GSM 03.38:

 

x0

x1

x2

x3

x4

x5

x6

x7

x8

x9

xA

xB

xC

xD

xE

xF

0x

@

£

$

¥

è

é

ù

ì

ò

Ç

LF

Ø

ø

CR

Å

å

1x

Δ

_

Φ

Γ

Λ

Ω

Π

Ψ

Σ

Θ

Ξ

ESC

Æ

æ

ß

É

2x

SP

!

"

#

¤

%

&

'

(

)

*

+

,

-

.

/

3x

0

1

2

3

4

5

6

7

8

9

:

;

< 

=

> 

?

4x

¡

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

5x

P

Q

R

S

T

U

V

W

X

Y

Z

Ä

Ö

Ñ

Ü

§

6x

¿

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

7x

p

q

r

s

t

u

v

w

x

y

z

ä

ö

ñ

ü

à

1B 0x

 

 

 

 

 

 

 

 

 

 

FF

 

 

CR2

 

 

1B 1x

 

 

 

 

^

 

 

 

 

 

 

SS2

 

 

 

 

1B 2x

 

 

 

 

 

 

 

 

{

}

 

 

 

 

 

\

1B 3x

 

 

 

 

 

 

 

 

 

 

 

 

[

~

]

 

1B 4x

|

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1B 5x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1B 6x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1B 7x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

В таблице жёлтым цветом выделены следующие управляющие коды:

LF (0Ah) – перевод строки;

CR (0Dh) – возврат каретки;

ESC (1Bh) – управляющий символ «Отказ»;

SP (20h) – пробел;

FF (1Bh + 0Ah) – смена листа, может заменять собой символ LF;

CR2 (1Bh + 0Dh) – управляющий символ, зарезервированный для дальнейшего развития таблицы;

SS2 (1Bh + 1Bh) – управляющий символ, зарезервированный для дальнейшего развития таблицы.

А как же тильды с обратными слешами, квадратные и фигурные скобки? Всё очень просто - для этого используются Escape-последовательности и каждый такой символ на самом деле состоит из двух. Например, символ « выглядит как <ESC> + «(», т.е. 1Bh + 28h.

Всё выше сказанное относится не только к символьному номеру источника SMS, но и к тексту самой SMS, если она закодирована не в Unicode. Подробнее о кодировке GSM 03.38 можно прочитать на Wikipedia: http://en.wikipedia.org/wiki/GSM_03.38

Итак, вернёмся к нашему примеру: у нас поле TP-OA = «0B 91 9701119905F8». 0Bh – в номере 11 цифр или символов, 91 — международный формат номера. Далее идёт «9701119905F8» – непосредственно сам номер. Пары переставлены местами, номер дополнен до чётного количества символом F, всё по схеме кодирования номера. Получается, номер отправителя 7-910-119-95-08.

TP-PID (Protocol identifier) – идентификатор протокола. В случае отправки SMS с телефона/модема на телефон/модем данный байт всегда будет равен 00. Для тех, кому интересно, что же это поле означает, могу ответить, что оно описывает высокоуровневые протоколы или сетевые устройства, куда должна быть отправлена, или откуда пришла SMS. Другими словами, Сервисный Центр оператора сотовой связи может поддерживать дополнительные услуги, такие как конвертирование SMS в e-mail, отправка SMS на пейджер, телекс. В этом случае данное поле указывает на что-то типа шлюза, через который пойдет SMS дальше и превратится уже не в SMS а во что-то другое. Нам это поле не нужно, поэтому оно, как и положено, равно 00h.

TP-DCS (Data coding scheme) – схема кодирования данных. Описывает, как закодирована наша SMS, т.е. поле TP-UD. Опишу только то, что нам пригодится: 00h — 7-битная сжатая кодировка; 04h – 8-битная кодировка; 08 — UCS2 (Unicode); 10, 14 и 18 — то же, только сообщение класса 0, т.е. Flash, сразу появляющееся на экране мобильного устройства.

TP-DCS в нашем примере равно 00h, что означает простое сообщение в 7-битной кодировке.

TP-SCTS (The service centre time stamp) – штамп времени сервисного центра. Проще говоря, это время, когда сервис-центр получил SMS, т.е. время отправки. Данное поле составляет 7 байт, которые означают следующее:

 

Байт

Назначение

0

Последние две цифры года

1

Месяц

2

День

3

Час

4

Минутa

5

Секундa

6

Временная зона

 

Причём в каждом байте цифры переставлены местами, как и в номерах сервисного центра и отправителя.

Применительно к нашему сообщению данное поле можно декодировать так: 21106232015061 = Год: 12, Месяц: 01, День: 26, Час: 32, Минута: 01, Секунда: 05, Временная зона: 16.

TP-UDL (User Data Length) — длина пользовательских данных, включая User Data header, если он есть. Если SMS закодирована 7-битной кодировкой, то данное поле указывает количество символов в сообщении. Если кодировка UCS2 – то поле указывает количество байт в сообщении.

В нашем примере TP-UDL равно 0Ch, т.е. 12 в десятичном счислении. Поскольку TP-DCS в нашем примере равно 00h, что означает простое сообщение в 7-битной кодировке, то сообщение содержит 12 символов. Так и есть, в сообщении “Hello World!” 12 символов. Однако если посчитать количество байт сообщения (поле TP-UD), то их будет 11 а не 12, сказывается сжатие при 7-битной кодировке. Этот момент важно учитывать.

TP-UD (User Data) – поле пользовательских данных. Здесь находится сам текст сообщения. В случае, если SMS длинная, т.е. разбита на несколько сообщений, данное поле начинается с заголовка TP-UDH. На наличие этого заголовка указывает бит TP-UDHI поля PDU-Type. По поводу поля TP-UDH подробно описано в «Отправка длинных SMS в формате PDU».

У нас TP-UD = “C8329BFD065DDF72363904”, что после декодирования 7-битной кодировки даёт нам искомое “Hello World!”.

 

 

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

 

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