воскресенье, 13 мая 2012 г.

Как я AT командами телефона шатал

Выдался свободный выходной и таки дотянулись мои руки до Siemens CX70, который давно уже лежал мертвым грузом на столе. И захотел я пообщаться с ним через его последовательный интерфейс, задачу упрощал имеющийся в наличии дата-кабель

Проблемы начались сразу же. Подключил телефон, а он - ноль эмоций, батарея такая древняя, что кажется уже разлагается. Меряю напряжение - 1.6В (батарея 3.6В), ладно, оставляю заряжаться, через минут 10 экран оживает и демонстрирует сиське индикатор заряда! Отлично!
Не так отлично, как если бы телефон умел работать без батареи от одного только дата-кабеля, но хотя бы так.

Включаю!

Старичок загрузился, ставлю дрова на кабель, появился новый ком-порт, расчехляю программу Terminal, коннекчусь, лихорадочно набираю AT<Enter> и, конечно, получаю отлуп (а иначе сказки-то и не было бы).. т.е. вообще ничего, тишина.



после непродолжительных поисков оказалось, что телефону нужна какая-то магическая комбинация на вход, чтоб заработал UART. Особо я этот вопрос не изучал, но вот оно, спасительное сообщение http://forum.easyelectronics.ru/viewtopic.php?p=21112#p21112
Запустил я AT Enabler, оно радостно сообщило, что "Siemens CX70 found", снова пробую AT - мне в ответ OK! Супер! Идем дальше
(как оказалось потом нужно было при каждом коннекте телефона к кабелю запускать AT Enabler, а та в свою очередь работает только при свежезагруженном телефоне)

А дальше была цель научиться читать и писать собщения. В общем-то сама по себе отправка не сложнее любой другой команды: пишешь в терминал команду AT+CMGS=<длина сообщения>, оно тебе в ответ пригласительный курсор ">", ты ему в ответ сообщение + спецсимвол окончания передачи 0x1A и получаешь либо ERROR, либо OK. Сложность тут в другом - правильно сформировать это самое сообщение. Вот если бы формат был вроде "79025552200|вася, приходи пить пиво|тут какие то служебные байты", то и писать было бы не о чем. Но не все так просто, т.е. там вообще ОЧЕНЬ все непросто.. на первый взгляд. Когда я увидел структуру сообщения первый раз мне захотелось схватиться за голову и бежать, крича "только не мой мозг, е#%ные инопланетяне!". Но, накатив немного пива, и прочитав доходчивое объяснение формата PDU с примером (http://www.ixbt.com/mobile/review/comp-sms.shtml) я уже через 15 минут успешно отправил смс-ку сам себе.

Переписывать тут статью с ixbt смысла нет, расскажу только о граблях.

грабли первые: SCA и OA/DA

первым байтом идет длина поля SCA, причем длина эта являет собой количество 16-ричных байт, т.е. например для номера телефона +1 235 566 7890 получаем запись 07 91 2153657698F0, т.е. длина 07 это количество байт 91 21 53 65 76 98 F0. Однако для телефона получателя длина уже означает число цифр в номере телефона (обычно 10 цифр, т.е. 0A + 1 байт региональности, т.е. 0B)

грабли вторые: поле SCA

хотя поле SCA у меня и было составлено по всем правилам, с ним мессага не отправлялась, пришлось отказаться от использования этого поля, заменив его на 00 (было 07919762929090F, стало 00)

грабли третьи: длина сообщения в AT-команде

длина сообщения вычисляется без учета первого байта, указующего длину SCA (т.е. тупо число 16-ричных байт уменьшаем на единицу). к примеру имеем PDU-сообщение "Привет"
0001000B919162358319F300080C041F04400438043204350442
количество 16-ричных байт здесь - 26, однако нужно уменьшить до 25, сбросив со счетов первый байт 00

кодировки

С кодировками ад! точнее с 7-битной, но начнем с UCS2. С ней все просто, в статье на ixbt рассказывается про какие то вычисления, но ничего вычислять не надо. К примеру с телефона командой AT+CMGR=4 было получено сообщение
+CMGR: 1,,37
07919762929090F0240B919762152439F100080121038111852112041D04300020043B04350433043A043E0439
разбираем. 
 - 07919762929090F0 - SCA
 - 24 - PDU 
 - 0B 91 9762152439F1 - OA - номер получателя
 - 0008 - PID+DSC, обычное сообщение, кодировка UCS2
 - 01210381118521 - SCTS
 - 12 - UDL - длина в байтах
 - 041D04300020043B04350433043A043E0439 - сообщение с UCS2

разбираем сообщение
поскольку кодировка 2-байтовая, разбиваем кашу на блоки по 2 байта
041D 0430 0020 043B 0435 0433 043A 043E 0439
далее каждый блок ищется в кодовой таблице1 в колонке Unicode, если чего то найти не получается - есть полный перечень Unicode символов2

С 7-битной же придется покопаться.
В статье не очень доходчиво объяснен этот момент, говорят какие-то биты переставлять с конца следующего байта на начало предыдущего, каждый раз беря на 1 бит больше.. ахтунг какой-то. На самом деле нужно представить это себе несколько иначе: надо 16-ричное представление перевести в двоичное, поделить на группы по 8 бит, состыковать все группы в обратном порядке в один большой двоичный поток, разбить на 7-битные отрезки начиная с конца, перевести в символы, согласно кодам символов ISO 8859-5 (или ASCII-table) и прочесть получившееся сообщение по буквам в обратном порядке.. ну не пиздец ли.. зато более-менее понятен порядок действий

Пример для закрепления
С телефона получено сообщение (номера изменены и телефон вообще не мой :))
+CMGR: 1,,34
07919740240256F2040B919740322152F800009090016113444411D93008FDA6D5416B10BD2C2EBB5C2E
отбросив поля, которые нас сейчас не интересуют, получаем код сообщения D93008FDA6D5416B10BD2C2EBB5C2E

Итак, первое, что нужно сделать, это представить hex в bin, берем виндовый калькулятор и переводим каждый HEX-байт в двоичное представление. Получаем
11011001
00110000
00001000
11111101
10100110
11010101
01000001
01101011
00010000
10111101
00101100
00101110
10111011
01011100
00101110
теперь составляем длинную строку из всех этих байт, только задом наперед
001011100101110010111011001011100010110010111101000100000110101101000001110101011010011011111101000010000011000011011001
а теперь, начиная с конца делим на группы по 7 бит
0 0101110 0101110 0101110 1100101 1100010 1100101 1110100 0100000 1101011 0100000 1110101 0110100 1101111 1101000 0100000 1100001 1011001
получили лишний 0 в начале - можно смело удалять
теперь каждый из этих 7-битных "байт" переводим в HEX и смотрим по ASCII-таблице код символа
получаем в итоге сообщение "...ebet k u4oh aY", читать задом наперед :)

Доп.инфо

1. Кодовая таблица http://www.webclub.ru/archive/markup_refs/article-40.html#tab
2. Полная таблица Unicode http://unicode-table.com/ru/
3. AT-команды. Бааальшой справочник, годное курево http://www.ivtechno.ru/files/at_com.pdf

1 комментарий: