пятница, 29 июня 2012 г.

Как я AT командами телефона шатал. Часть 2


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

Немного о том, что же делать дальше.
А дальше надо как то раскодировать все то, что было получено с телефона, программно (на PHP в моем случае). Не вручную же сидеть переводить с кодовыми табличками.


Получив какую-нибудь входящую (!!, важно) смс-ку в PDU формате из телефона, начинаем ее разбирать по мануалу (для исходящей другой алгоритм разбора). Например (пробелы расставил для наглядности)
07919762020082F8 44 14 D03C5EB37C0E1BDF6E9F0F 00 08 21505291421061 8C 050003360601042D0422041E002004120410042800200053004D0053002D041A0423041F041E041D0020041D041000200421041A04180414041A0423002100200422043E043B044C043A043E0020044104350433043E0434043D044F0020043F043E04370432043E043B044F043504420020043F043E0434043A043B044E044704380442044C002004110415

Начинаем читать. 


Первые 2 символа 07, значит пропускаем следующие 7 пар (!) символов (номер смс-центра нам неинтересен), потом идет PDU байт 44, затем длина номера отправителя 14 (переводим в десятичную, получаем 20), значит пропускаем  20 + 2 символа (!), потом идет PID 00 и DCS 08, SCTS 7 пар и наконец длина сообщения 8C.

Но сообщение может начинаться не сразу с текста, вполне может идти несколько байт заголовка (выделено жирным). На его наличие указывает бит 6 (UDHI) байта PDU.
Если заголовок есть - откусим его, только надо знать сколько откусывать. Длину заголовка содержит первый же байт сообщения - 05. Значит выкидываем следующие 5 пар символов и получаем уже наконец свой закодированный текст.

Проблема первая


И тут я столкнулся с проблемой, как перевести UCS-2 в человекочитаемый UTF-8. Пробовал iconv, mb_convert_encoding, в итоге оказалось что на моем компе что то с пыхой, и правильную команду я уже нашел, только результат она вывела кривой и я прошел мимо. Входная строка для примера была такая "04350436" (слово "еж")

Как перевести UCS-2 в UTF-8 в PHP:
$result = iconv("UTF-16", "UTF-8", pack("H*", $input));
На выходе получам искомое слово "еж"
Остается выяснить, почему в пыхе на сервере все ок, а на моем компе под Debian какой то шлак вроде string(3) "㔄"
Немного проб и ошибок и я добился результата и на своем компе, только теперь с помощью команды
$result = mb_convert_encoding(pack("H*", $input), "UTF-8", "UTF-16");
Видимо что то с iconv не то. Идем дальше.
К этому моменту  я уже наваял PHP-класс работы с телефоном. Программная часть более-менее стабильна, оставалось несколько проблем


Проблема вторая


При свежезагруженном телефоне (Siemens CX70 в моем случае) его нужно инициализировать какой-то волшебной последовательностью байт. Последовательность эта выяснена путем прослушки COM-порта во время работы программы AT Enabler и представляет из себя несколько посылок:
1101000204168011, 11010001203101FCCB, 0201000204058011, 1701000204108011, 1701000A203C41545E535157453D300D95EC
Посылки приведены в виде HEX-дампов. Что там в них содержится я не копал. Телефон на каждую посылку отвечает похожим сообщением примерно той же длины. Так вот, собственно проблема состоит в том, что телефон не выдает символ перевода строки в конце своего ответа, т.е. узнать весь ли ответ прочитан оказалось как-то сложно.
В принципе можно вслепую послать эти байты и потом проверить результат, послав АТ и приняв ОК. Однако проблема неблокирующего чтения, или хотя бы настройки каких-то таймаутов все  равно стоит.

Как управлять таймаутами чтения COM-порта из PHP я пока не нашел. Есть только вариант настроить порт из консоли. Вот так
stty -F /dev/ttyUSB0 -icanon min 0 time 10
Что сие значит? Согласно мануалу, min задает минимальное кол-во прочитанных знаков, после которого активируется таймаут. time задает собственно таймаут в десятых долях секунды (1 = 0.1 сек, 5 = 0.5 сек, 10 = 1 сек и т.д.), и работает все это с опцией -icanon.

Теперь все то же самое нужно реализовать на Assembler в проекте GSM-реле =)

Комментариев нет:

Отправить комментарий