В современных условиях, когда сотовый аппарат уже не является простым средством голосового общения, пользователям предлагают на выбор самые разнообразные программы для соединения телефона с персональным компьютером. Современные аппараты бизнес-класса, как правило, обладают большой встроенной телефонной книгой, календарем напоминаний и даже списком задач. Кроме телефонов, существуют персональные цифровые помощники (PDA), или наладонные компьютеры. Все эти мобильные устройства также несут в себе довольно большие объемы текстовой и иной информации, которую сложно было бы вводить вручную. Естественно, встал вопрос о поддержании актуальности информации (телефонных книг, расписания) во всех мобильных устройствах. Поначалу такие задачи решались довольно разрозненно, но в итоге был разработан протокол обмена объектами OBEX (OBject EXchange), позволяющий не только передавать и принимать текстовую информацию, но и пересылать интернет-страницы, графику, музыку, мультимедийные данные и просто двоичные файлы.
Одним из первых телефонов, поддерживающих протокол OBEX для передачи не только визитных карточек и календарных заметок, но и мелодий сигнала вызова и экранных логотипов, был Siemens S25. После появления протокола OBEX вышла спецификация Ir-MC (Infrared Mobile Communication), ставшая наиболее популярным стандартом соединения посредством ИК-связи. Была принята технология BlueTooth, также используемая протоколом OBEX.
Вот уже больше года я являюсь владельцем довольно неплохого, хотя и устаревшего по современным меркам, телефона Ericsson R320s. При анонсе аппарата Ericsson сообщал, что это первый телефон в мире, соответствующий спецификациям Ir-MC 1.1, и, естественно, умеет с помощью прилагаемого в комплекте к телефону программного продукта XTND Connect PC фирмы Extended Systems синхронизироваться с программой-органайзером Microsoft Outlook, а при покупке полнофункционального пакета получает возможность синхронизироваться с большинством применяемых в мире программ-органайзеров. В дальнейшем будем называть R320 еще и OBEX-сервером, или просто сервером, а XTND Connect PC — OBEX-клиентом, или просто клиентом.
Выяснилось, однако, что клиент XTND не умеет корректно передавать набранные на русском языке записи из телефона в Outlook и обратно. Более того, оказалось, что примененная в R320 кодировка текста некорректно понимается КПК Palm и некоторыми сотовыми трубками других производителей.
Я взялся за программирование самодельного приложения в конце октября 2001 года. Один из участников форума iXBT — Alek Winner помог мне, прислав отклики телефона на команды компьютера и программу PortMon98, позволяющую просматривать события Windows, связанные с работой COM-порта, в том числе и операции чтения/записи вместе с передаваемыми данными.
Сначала с сайта Ассоциации IrDA я скачал описание протоколов, а с сайта Ericsson — описание форматов, поддерживаемых телефоном.
В отличие от протокола общения с модемами Hayes OBEX не использует текстовые команды, описанные в материале отправка SMS через телефон, подключенный к компьютеру.
Протокол использует всего несколько операторов. Ниже приводится их описание:
80h | Выбор отвечающего устройства, выяснение характеристик и установление связи. | |
81h | Завершение сессии связи. | |
02h | 82h, если пакет последний | Запись объекта. |
03h | 83h, если пакет последний | Чтение объекта. |
04h | и 84h | Зарезервирован. |
85h | Выбор каталога по умолчанию на принимающей стороне. | |
FFh | Отмена текущей операции. | |
06h-0Fh | Зарезервированы и в будущем не должны использоваться до уточнения спецификации протокола. | |
10h-1Fh | Определяются пользователем и применяются по усмотрению разработчиков устройств. |
Биты 5 и 6 зарезервированы и в командах должны быть нулевыми. Бит 7 в командах чтения, записи и резервной 04 означает последний передаваемый пакет.
У операторов также весьма немного заголовков-параметров:
C0h | Количество объектов (используется командой установления соединения). |
01h | Имя объекта (обычно имя файла). |
42h | Тип объекта (текст, html, двоичный и т. д.). |
C3h | Длина объекта в байтах. |
44h | Время и дата в формате ISO 8601. |
C4h | Время и дата используются только для совместимости со старыми форматами — 4-байтовая длина. |
05h | Текстовое описание объекта. |
46h | Имя сервиса, для которого выполняется операция. |
47h | Заголовок http. |
48h | Начало тела объекта. |
49h | Конец тела объекта (применяется чаще для динамически создаваемых объектов). |
4Ah | Имя OBEX-приложения, с которым идет диалог. |
CBh | Идентификатор соединения. Используется при общении с несколькими устройствами. |
4Ch | Дополнительная информация приложения в запросе или ответе. |
4Dh | Запрос авторизации. |
4Eh | Ответ авторизации. |
4Fh | Класс OBEX-объекта. |
10h-2Fh | Зарезервированы, включая все комбинации двух старших битов. |
30h-3Fh | Определяются пользователем, включая комбинации из двух старших битов. |
Интерпретация двух старших битов заголовка-параметра.
00 (00h) | Текст Unicode, завершенный нулевым байтом. Длина объекта — 2-байтовое беззнаковое целое. |
01 (40h) | Последовательность байт. Длина объекта — 2-байтовое беззнаковое целое. |
10 (80h) | Длина — один байт. |
11 (C0h) | Длина — 4 байта. Старший байт — первый в последовательности. |
Ну и, наконец, отклики на операторы этого «птичьего языка». В большей части они описывают отклики на Интернет-запросы, но попадаются и необходимые для доступа к справочникам телефона.
OBEX | http-эквивалент | Значение |
00h-0Fh | Нет | Резерв |
10h (90h) | 100 | Запрос на продолжение. |
20h (A0h) | 200 | Успешное завершение. |
21h (A1h) | 201 | Создан. |
22h (A2h) | 202 | Разрешен. |
23h (A3h) | 203 | Неавторитарная информация. |
24h (A4h) | 204 | Нет содержимого. |
25h (A5h) | 205 | Сброс содержимого. |
26h (A6h) | 206 | Частичное содержание. |
30h (B0h) | 300 | Возможен многовариантный выбор. |
31h (B1h) | 301 | Перемещен. |
32h (B2h) | 302 | Перемещен временно. |
33h (B3h) | 303 | См. другие. |
34h (B3h) | 304 | Не модифицировано. |
35h (B5h) | 305 | Используя Proxy. |
40h (C0h) | 400 | Неправильный запрос — сервер не распознал. |
41h (C1h) | 401 | Не авторизирован. |
42h (C2h) | 402 | Требуется оплата. |
43h (C3h) | 403 | Доступ запрещен — операция распознана, но отвергнута. |
44h (C4h) | 404 | Не найден. |
45h (C5) | 405 | Недопустимый метод. |
46h (C6h) | 406 | Неприменимо. |
47h (C7h) | 407 | Требуется Proxy-разрешение. |
48h (C8h) | 408 | Время запроса истекло. Тайм-аут операции. |
49h (C9h) | 409 | Конфликт. |
4Ah (CAh) | 410 | Утерян. |
4Bh (CBh) | 411 | Требуется указание длины. |
4Сh (CCh) | 412 | Условие неверно. |
4Dh (CDh) | 413 | Запрос слишком велик. |
4Eh (CEh) | 414 | Запрошенный адрес слишком длинный. |
4Fh (CFh) | 415 | Неподдерживаемый тип данных. |
50h (D0h) | 500 | Внутренняя ошибка сервера. |
51h (D1h) | 501 | Не поддерживается. |
52h (D2h) | 502 | Нерабочий шлюз. |
53h (D3h) | 503 | Сервис недоступен. |
54h (D4h) | 504 | Время ожидания отклика шлюза истекло. |
55h (D5h) | 505 | Неподдерживаемая версия http. |
60h (E0h) | - | База данных переполнена. |
61h (E1h) | - | База данных закрыта. |
Прошу прощения за несколько вольное толкование терминов, но, когда речь идет о решении задачи связи телефонной книги, календаря и списка дел телефона с компьютером, такой перевод, думаю, будет уместен.
Протокол OBEX клиент-серверный. Другими словами, на одной половине дисплея высвечивается запрос, на другой — ответ и (или) встречный запрос.
Формат запроса выглядит так:
Оператор | Длина запроса | Параметр 1 | Параметр 2 | Параметр 3 | ... | Последний параметр |
Формат отклика выглядит так:
Код отклика | Длина отклика | Параметр 1 | Параметр 2 | ... | Последний параметр |
Спецификация IrMC определяет несколько уровней обмена информацией:
- Уровень 1: Клиент передает на сервер один объект, сохраняемый с оригинальным именем. Никакой автоматизации не подразумевается.
- Уровень 2: Клиент может получать и отправлять на сервер целый набор (каталог) объектов.
- Уровень 4: Клиент может записывать, удалять и модифицировать объекты на сервере. Для объектов предусмотрены статические индексы.
- Уровень 8: Клиент может получить список измененных объектов с последнего момента синхронизации и работать только с этими записями для сокращения времени синхронизации. Вводятся уникальные индексы — номера для объектов.
- Уровень 16: То же, что и уровень 8, но с поддержкой статических индексов.
Фактически эти уровни соответствуют степени автоматизации сервера по учету изменений содержимого.
Для мобильных устройств в спецификации определяется каталог хранения данных по умолчанию — telecom, т. е. все файлы-объекты хранятся в этом каталоге. При этом каталог telecom не является текущим по умлочанию и в него нужно переходить командой 85h или же обращаться к объектам с указанием пути до них.
В описании AT-команд и форматов данных OBEX для телефона Ericsson R320s сказано, что телефон хранит данные в файлах:
Имя | Описание содержимого | Применимые команды |
telecom/devinfo.txt | Серийный номер, версия ПО, поддерживаемые кодировки, поддерживаемый уровень обмена информацией, поддерживаемые операции | Чтение |
telecom/rtc.txt | Текущаее время и дата. | Чтение/запись |
telecom/pb.vcf | Вся телефонная книга. Доступ на уровне обмена типа 2. | Чтение/запись |
telecom/pb/luid/.vcf | Новая телефонная запись. Создает для нее уникальный номер в базе | Запись |
telecom/pb/0.vcf | Личная телефонная запись | Чтение/запись |
telecom/pb/############.vcf | Телефонные записи со статическим уровнем доступа 3 типа. Вместо ############ нужно подставить номер. | Чтение/запись |
telecom/pb/luid/*.vcf | Доступ по уникальным индексам уровня 4 обмена данными | Чтение/запись |
telecom/pb/info.log | Поддерживаемые характеристики - кодировки, длины полей (телефона и имени), общее количество, а также занятых и свободных записей. | Чтение |
telecom/pb/luid/###.log | Лог-файл изменений телефонной книги. Но в моем телефоне он не меняется. Вместо ### нужно подставить дату, по которую нужно показать изменения | Чтение |
telecom/pb/luid/cc.log | Счетчик изменений телефонной книги. Он показывает количество произведенных операций: создания, изменения и удаления записей. | Чтение |
telecom/cal.vcs | Все календарные записи. Доступ на уровне обмена типа 2. | Чтение/запись |
telecom/cal/luid/.vcs | Новая календарная запись. Создает для нее уникальный номер в базе | Запись |
telecom/pb/############.vcs | Календарные записи со статическим уровнем доступа 3 типа. Вместо ############ нужно подставить номер. | Чтение/запись |
telecom/cal/luid/*.vcs | Доступ по уникальным индексам уровня 4 обмена данными. | Чтение/запись |
telecom/cal/info.log | Поддерживаемые характеристики — кодировки, длины полей (телефона и имени), общее количество, а также занятых и свободных записей. | Чтение |
telecom/cal/luid/###.log | Лог-файл изменений календаря. Но в моем телефоне он не меняется. Вместо ### нужно подставить дату, по которую нужно показать изменения | Чтение |
telecom/cal/luid/cc.log | Счетчик изменений календаря. Он показывает количество произведенных операций: создания, изменения и удаления записей. | Чтение |
Характерное для содержания файлов OBEX-сервера:
telecom/devinfo.txt | telecom/cal/info.log | telecom/pb/info.log |
MANU:ERICSSON MOD: R320s SW-VERSION:010628 1056 prgCXC125193 SW-DATE:20010628T1056 HW-VERSION: SN:520069-61-011987-3-13 IRMC-VERSION:1.1 PB-TYPE-RX:VCARD2.1 PB-TYPE-TX:VCARD2.1 CAL-TYPE-RX:VCAL1.0 CAL-TYPE-TX:VCAL1.0 MSG-TYPE-RX:NONE MSG-TYPE-TX:NONE NOTE-TYPE-TX:NONE NOTE-TYPE-RX:NONE ERROR-LOG:NO INBOX:SINGLE MSG-SENT-BOX:NO X-EMELODY-TYPE-TX:EMELODY1.0 X-EMELODY-TYPE-RX:EMELODY1.0 X-XTRA:telecom/calendar.tx | Total-Records:9 Last-Used-Index:* Free-Records:91 Maximum-Records:100 IEL:0x08 HD:YES SAT:CC DID:4B323154 X-IRMC-FIELDS: VERSION:1.0 DTSTART: DTEND: AALARM: CATEGORIES:MEETING;PHONE CALL;MISCELLANEOUS; SUMMARY;CHARSET=ISO-8859-1;CHARSET=UTF8:=36 LOCATION;CHARSET=ISO-8859-1;CHARSET=UTF8:=20 X-IRMC-LUID:=12 | Total-Records:90 Last-Used-Index:* Free-Records:229 Maximum-Records:319 IEL:0x08 HD:NO SAT:CC DID:000057F9 X-IRMC-FIELDS: VERSION:2.1 N:=18 FN:=18 TEL:=20 X-IRMC-LUID:=12 ICL:NO OCL:NO MCL:NO |
telecom/calendar.txt | Telecom/cal/luid/07122001.log | telecom/pb/luid/21012001.log |
Ericsson IrMC 1.1 synchronization --------------------------------- Calendar 1.0 Team ----------------- Jцrgen Birkler Lars Novak Kristina Ahlgren Magnus Svensson Jan Gajdos Andreas Jцnsson Bjцrn Ekberg Phone Book Team --------------- Carl Gustavsson Jцrgen Birkler Debug: Small uint32:123 Medium uint32:15446 Large uint32:124345653 | SN:520069-61-011987-3-13 DID:4B323154 Free-Records:91 Total-Records:9 Maximum-Records:100 * | SN:520069-61-011987-3-13 DID:000057F9 Free-Records:229 Total-Records:90 Maximum-Records:319 |
telecom/rtc.txt | telecom/cal/luid/cc.log | telecom/pb/luid/cc.log |
20011207T011122 | 533 | 111 |
Файл telecom/calndar.txt — это т. н. «пасхальное яйцо» разработчиков OBEX-сервера. Но самое интересное, что файл devinfo.txt и большая часть файлов info.log статичны. Другими словами, за исключением количества записей эти файлы не меняются. Таким образом, при смене SIM-карты на более емкую (в плане длины имени и номера телефона) максимально возможная длина имени по-прежнему будет равняться 18 символам, а телефона — 20 цифрам.
Теперь о форматах поддерживаемых записей.
Данные календаря и телефонной книге хранятся в виде, описаном на сайте IMC. То, что поддерживает сервер R320 выглядит так:
Телефонная запись |
«BEGIN:VCARD «N;»»;«»:« «FN;«»;«»:« «TEL» «X-IRMC-LUID:» «END:VCARD» |
Календарная запись |
«BEGIN:VEVENT» «DTSTART:» «DTEND:» «AALARM:» «CATEGORIES:» «SUMMARY;»»;«»:« «LOCATION;»»;«»:« «X-IRMC-LUID:» «END:VEVENT» |
Календарь |
«BEGIN:VCALENDAR» «VERSION:» «PRODID:» «BEGIN:VEVENT» «END:VEVENT» «BEGIN:VEVENT» «END:VEVENT» ... «END:VCALENDAR» |
Значение полей:
Поле | Значение |
«QUOTED-PRINTABLE», «BASE-64», «8BIT» | |
«ISO-8859-1», «UTF-8» | |
Строка. Длина — в зависимости от СИМ-карты. Бывает до 25 байт, бывает до 14 | |
Имя в том виде, в котором Вы хотите, чтобы оно отображалось (Фамилия-Имя или Имя-Фамилия) | |
Строка. Длина зависит от СИМ-карты. Длина от 1 байта до максимально допустимого числа цифр в номере | |
Уникальный номер записи. При записи данных как новых поле может не указываться | |
Формат ГГГГММДДTЧЧММСС. Буква T в середине — разделитель даты и времени | |
«MEETING», «PHONE CALL», «MISCELLA-NEOUS» | |
Строка. Максимально 36 байт. По-русски — 18 байт. С применением греческих символов и латиницы — 18 байт (выявлено опытным путем. Ошибка Ericsson) | |
Строка. Максимально 20 байт. По-русски — 10 байт. С применением греческих символов и латиницы — 10 байт (выявлено опытным путем. Ошибка Ericsson) | |
«1.0» для календаря или «2.1» для телефонных записей | |
«Ericsson Calendar 1.0» | |
Символ конца строки 0Dh и перевода каретки 0Ah |
Формально сервер поддерживает много кодировок, но применительно к записям в календаре и телефонной книге использует всего две — ISO-8859-1 и UTF-8. Обе являются опубликованными стандартами, но алгоритм перекодировки я на всякий случай приведу.
ISO-8859-1 содержит только символы английского алфавита и знаки препинания. При чтении доступны греческие символы, похожие на русские буквы. Ниже записаны их коды в поле имени и вид на экране:
Д — CE94h Ф — CEA6h Ё — C389h Л — CE9Bh П — CEA0h Й — C3B9h Г — CE93h |
Однако при попытке записать их в теле имени поле ломается. Поэтому для ввода таких имен рекомендую использовать Hayes-команду AT+CPBW, которая успешно записывает подобные символы, в отличие от OBEX-записи, где код буквы искажается.
UTF-8 перекодируется следующим образом: если символ из первой половины кодовой таблицы (английские символы), то его код не меняется, если же код содержит русские буквы, то для его обработки из кодировки Windows-1251 можно делать простое преобразование.
Для символов C0h-EFh — буква в UTF8 будет кодирована так: старший байт D0h, младший байт <значение в коде W1251>-30h. Для символов F0h-EFh — буква в UTF8 будет кодирована так: старший байт D1h, младший байт <значение в коде W1251>-70h. Кодировка буквы Ё уникальна: для Ё UTF8-код — D081h, для ё UTF8-код — D191h.
Таким образом, запись «Статья про OBEX» по таблице UTF8 в кодировке QUOTED-PRINTABLE и на экране телефона будет выглядеть так:
=D0=A1=D1=82=D0=B0=D1=82=D1=8C=D1=8F =D0=BF=D1=80=D0=BE OBEX |
Рассмотрим примеры визитной карточки и одной записи календаря (VEVENT).
BEGIN:VCARD VERSION:2.1 N;QUOTED-PRINTABLE;CHARSET=UTF-8:=D0=AF=D0=BC=D1=89=D0=B8=D0=BA=D0=BE=D0=B2 FN;QUOTED-PRINTABLE;CHARSET=UTF-8:=D0=AF=D0=BC=D1=89=D0=B8=D0=BA=D0=BE=D0=B2 TEL:3332233322 X-IRMC-LUID:000000000000 END:VCARD |
Ямщиков: 3332233322 |
BEGIN:VCALENDAR VERSION:1.0 PRODID:Ericsson Calendar 1.0 BEGIN:VEVENT DTSTART:20011208T081000 DTEND:20011208T082500 AALARM:20011208T081000 CATEGORIES:PHONE CALL SUMMARY;QUOTED-PRINTABLE;CHARSET=ISO-8859-1:Zvonok v institut po povodu stipendi LOCATION;QUOTED-PRINTABLE;CHARSET=ISO-8859-1:3627795 X-IRMC-LUID:002500000212 END:VEVENT END:VCALENDAR |
Zvonok v institut po povodu stipendi: 3627795 |
Теперь рассмотрим типичный диалог компьютера и телефона при обмене записями.
Шаг | Комментарий |
Инициализация OBEX-соединения | Обычно это команда AT+CPROT=0. Или, как в R320, R520 и более современных моделях Ericsson — AT*EOBEX |
Отклик телефона | Обычно «CONNECT» |
Открытие OBEX-сессии | 16-ричная команда открытия сессии OBEX. 80h |
Отклик телефона | Код успешной операции A0h |
Запрос характеристик | Команда чтения объекта (83h) с параметром — имя файла telecom/devinfo.txt. Но этот этап на R320 я пропускаю, поскольку там все характеристики, описанные в файле известны, да и файл прошит жестко |
Отклик телефона | Код успешной операции 90h и начало содержимого запрошенного файла |
Запрос на продолжение | Команда чтения объекта (83h) без параметров |
Отклик телефона | Код успешной операции A0h и конец содержимого запрошенного файла. |
Запрос информации о телефонной книге | Команда чтения объекта (83h). Читаем файл telecom/pb/info.log. Из него можно взять инормацию о количестве использованных записей и оставшемся свободном месте. |
Отклик телефона | Код успешной операции A0h и содержимое файла. |
Чтение телефонной книги | Команда чтения объекта (83h). Читаем файл telecom/pb.vcf. Быстрее получается читать базу со всеми записями и оборвать чтение при обнаружении последнего (количество оговорено в файле info.log) значащего элемента командой FFh |
Отклик телефона | Код успешной операции 90h и начало содержимого запрошенного файла. |
Запрос на продолжение | Команда чтения объекта (83h) без параметров |
Отклик телефона | Код успешной операции 90h и начало содержимого запрошенного файла. Книга длинная и предыдущий пункт вместе с этим повторяется несколько раз |
Запрос на отмену операции | Команда отмены (FFh) без параметров |
Отклик телефона | Код успешной операции A0h |
Запрос информации о календаре | Команда чтения объекта (83h). Читаем файл telecom/cal/info.log. Из него можно взять инормацию о количестве использованных записей и оставшемся свободном месте |
Отклик телефона | Код успешной операции A0h и содержимое файла |
Чтение телефонной книги | Команда чтения объекта (83h). Читаем файл telecom/cal.vcs. Быстрее получается читать базу со всеми записями, чем считывать их по отдельности |
Отклик телефона | Код успешной операции 90h и начало содержимого запрошенного файла |
Запрос на продолжение | Команда чтения объекта (83h) без параметров |
Отклик телефона | Код успешной операции 90h и часть содержимого запрошенного файла. Книга длинная и предыдущий пункт вместе с этим повторяется несколько раз |
Запрос на продолжение | Команда чтения объекта (83h) без параметров |
Отклик телефона | Код успешной операции A0h и конец содержимого запрошенного файла |
Запрос о записи новой карточки в телефонную книгу | Команда записи объекта (02h). Пишем файл telecom/luid/pb/.vcf. Указываются параметры длины и имени файла |
Отклик телефона | Код успешной операции 90h |
Отправка содержимого новой карточки | Команда записи объекта (02h) и карточки от BEGIN до END |
Отклик телефона | Код успешной операции 90h |
Отправка признака конца карточки | Команда записи объекта (82h) и признака 49h |
Отклик телефона | Код успешной операции A0h с параметром в виде уникального номера новой карточки |
Запрос о записи измененной карточки в календарь | Команда записи объекта (02h). Пишем файл telecom/luid/cal/001C00000211.vcs. Указываются параметры длины и имени файла |
Отклик телефона | Код успешной операции 90h |
Отправка содержимого новой карточки | Команда записи объекта (02h) и карточки от BEGIN до END |
Отклик телефона | Код успешной операции 90h |
Отправка признака конца карточки | Команда записи объекта (82h) и признака 49h |
Отклик телефона | Код успешной операции A0h с параметром в виде уникального номера карточки |
Отправка команды закрытия OBEX-сессии | 16-ричная команда открытия сессии OBEX. 81h |
Отклик телефона | Код успешной операции A0h. И текстовая строка «OK» после выхода из OBEX-режима |
Это была теория обмена данными с телефоном. Теперь практически применяемый на OBEX-сервере формат команд. Он не то чтобы отличается от стандарта, просто в запросах указываются неочевидные параметры.
Описание | 16-ричное представление | Комментарии |
Команда для входа в OBEX-режим | 41 54 2A 45 4F 42 45 58 0D 0A | AT*EOBEX |
Отклик | 43 4F 4E 4E 45 43 54 0D 0A | CONNECT |
Запрос на открытие сессии | 80 00 13 10 00 40 00 46 00 0C 49 52 4D 43 2D 53 59 4E 43 | Указывается версия протокола OBEX 1.0 (10 00h), максимальная длина пакетов 16384 байта (40 00h) и имя сервиса «IRMC-SYNC». Естественно, что после команды 80h двухбайтовая величина — длина запроса. Недокументировано: можно не указывать никаких параметров, а просто отправить один байт 80h для начала OBEX-сессии. |
Отклик на открытие сессии | A0 00 07 10 00 00 FF | Успешная операция, отклик длиной 7 байт. Версия OBEX — 1.0, а максимальная длина пакетов сервера — 255 байт. |
Запрос на чтение файла devinfo.txt | 83 00 2E 01 00 2B 00 74 00 65 00 6C 00 65 00 63 00 6F 00 6D 00 2F 00 64 00 65 00 76 00 69 00 6E 00 66 00 6F 00 2E 00 74 00 78 00 74 00 00 | После 83h два байта — длина пакета. 01h — параметр имени. После него — длина имени в байтах. Далее — в формате UNICODE имя файла telecom/devinfo.txt, заканчивающееся нулевым байтом. На каждый символ имени отводится два байта, первый из которых равняется нулю, согластно правилу кодирования английских символов. Вместо devinfo.txt можно указывать любой другой файл. Формат команды не меняется. |
Первый отклик на этот запрос | 90 00 CE 48 00 CB | Признак успешного выполнения операции (ожидание дальнейших пакетов с информацией) и два байта длины всего ответа. После этого параметр начала тела запрошенного объекта с указанием длины этого объекта. |
Последующие отклики | 90 xx xx .................... | Собственно, собержимое объекта. 90h меняется на A0h, когда приходит последний пакет с содержимым запроса. |
Запрос на запись файла telecom/pb/luid/.vcs | 02 00 3D 01 00 2D 00 74 00 65 00 6C 00 65 00 63 00 6F 00 6D 00 2F 00 70 00 62 00 2F 00 6C 00 75 00 69 00 64 00 2F 00 2E 00 76 00 63 00 66 00 00 C3 00 00 00 7C 4C 00 08 11 03 31 31 31 | Команда 02h для начального пакета записи файла с указанием длины этого пакета. Далее параметр 01h с содержимым — имя файла в кодировке UNICODE (рассмотрено выше). Далее используется параметр длины объекта C3 с характеристикой в 4 байта. И после этого используется параметр 4C (доп. параметры приложения) с указанием длины параметра и строкой (11 03 31 31 31). Для чего используется этот параметр — неясно, но формат очень напоминает общий вид OBEX-пакета, поэтому можно предположить, что 11h — это команда изменения содержимого, скажем cc.log, а 31 31 31 —это текущее значение cc.log. Так по крайней мере выходит при просмотре трассировки обмена клиента XTND и R320. |
Отклик на этот запрос | 90 00 03 | Признак успешного выполнения операции (ожидание дальнейших пакетов с информацией) и два байта длины всего ответа. |
Следующий пакет при записи файла | 02 xx xx 48 yy yy ............... | Команда 02h для непоследнего пакета записи файла с указанием длины этого пакета. Далее параметр 48h с содержимым карточки. Важно! В документации не говорится, что тело передаваемой карточки должно оканчиваться символами 0D0Ah (конец строки+перевод каретки). Также следует обратить внимание на то, что заголовок 48 должен присутствовать во всех пакетах, сождержащих тело карточки. И длина, указываемая в качестве параметра — длина передаваемого в этом пакете элемента карточки. Другими словами, каждый нефинальный пакет карточки как бы считается стартовым. Почему так сделали — непонятно. При чтении ничего подобного нет. Иначе телефон сообщит о «конфликте». |
Отклик на этот запрос | 90 00 03 | Признак успешного выполнения операции (ожидание дальнейших пакетов с информацией) и два байта длины всего ответа. |
Последний пакет при записи файла | 82 00 06 49 00 03 | Команда 82h для последнего пакета записи файла с указанием длины этого пакета. Далее параметр 49h — указатель, конца тела файла. |
Отклик на последний пакет | A0 00 19 4C 00 16 01 0C 30 30 30 30 30 30 30 30 30 30 30 36 02 03 31 31 31 | Признак успешного выполнения операции (последний пакет) и два байта длины всего ответа. После этого возварщаются дополнительные параметры приложения (признак 4Ch). Параметр 01h с длиной 0Ch (12 байт) возвращает уникальный номер, присвоенный карточке. Параметр 02h с длиной 3 байта: похоже возвращает текущее значение cc.log. Это значение нужно подставлять в соответствующий параметр 11h при записи (см выше). Так сделано в XNTD Connect PC. |
Запрос на закрытие сессии | 81 00 03 | Команда закрытия сессии 81h и длина этого пакета. Недокументировано: можно не указывать никаких параметров, а просто отправить один байт 81h для начала OBEX-сессии. |
Отклик на запрос | A0 00 03 0D 0A 4F 4B 0D 0A | Успешный отклик A0 (последний пакет отклика) с указанием длины пакета. И уже в Hayes-режиме работы модема символы новой строки, «OK» и снова символы новой строки. |
По описанным выше командам и откликам на них были написаны две программки. Первая — ObexReader предназначена для чтения объектов из телефона. Работает она просто: после запуска вы отдаете команды в окне терминала и просматриваете отклики на них. После подачи команды AT*EOBEX или AT+CPROT=0 и получения отклика «CONNECT» нажатие на клавишу «Открытие сессии OBEX» отправляет на телефон команду 80h, и назначение клавиш меняется. Теперь в строке команды можно вводить и читать имя файла, а командой «Закрытие сессии OBEX» закрыть сессию. В архиве, на который указывает ссылка, находятся исходный текст программы и исполняемый файл. Относительно упомянутой раньше программы работы с SMS — в разработанных программах работы с OBEX-протоколом переделан модуль Serial.Pas, который теперь получает в качестве параметров не строки, оканчивающиеся нулевым байтом, а обычные строки с любыми символами. Программа ObexReader держит открытым COM-порт все время, пока работает.
Вторая программа — ObexConnect. Собственно это программа чтения и записи календаря и телефонной книги. Программа инициализирует COM-порт, считывает/записывает данные и закрывает порт. Но остается на экране. То же происходит при создании новой записи в телефоне: открывается порт, записываются данные и COM-порт закрывается.
Программа ObexConnect позволяет записывать файлы для дальнейшего импорта в MS Outlook с записями телефонной книги и календаря. Для того чтобы сделать эти файлы, нужно просто отметить пункт «Записывать файл» — старый файл будет переписан.
Согласно получаемым от PortMon98 трассам COM-порта, мои программы работают с портом несколько лучше, чем клиент XTND. По словам Alek'а Winner'а, зарубежная разработка использует «поллинговый опрос компорта (стиль некорректного программирования, отжирающего ресурсы)». В данном случае ничего похожего вроде бы не происходит, поэтому не бывает и эффектов непрорисовки экрана. Вдобавок клиент XTND еще в Hayes-режиме опрашивает сервер командой AT+CGMI и требует IMEI (серийный номер) командой AT+CGSN. Для чего программе синхронизации данных нужен серийный номер, получаемый в Hayes-режиме, непонятно, поскольку в OBEX-режиме программа считывает файл devinfo.txt, который также содержит IMEI телефона. Да и вообще логику работы программы после прочтения диалога клиента XTND понять становится совсем сложно. Привожу начало диалога по синхронизации телефонной книги (запросы с компьютера, оставшиеся без ответа со стороны телефона):
> Открытие COM-порта
>AT+CGM
>AT+CGMI
>AT*EOBEX
>80 ... (Открытие OBEX-сессии)
>чтение файла telecom/devinfo.txt
>чтение файла telecom/pb/info.log
>чтение файла telecom/devinfo.txt (второй раз)
>чтение файла telecom/devinfo.txt (третий раз)
>чтение файла telecom/pb/info.log (второй раз)
>чтение файла telecom/pb/luid/cc.log
>чтение файла telecom/pb.vcf
>чтение файла telecom/pb/info.log (третий раз)
>AT+CGMI (это не завершая OBEX-сессию! Сессия, почему то обрывается, выдается правильный ответ)
>AT+CGSN
>AT*EOBEX (после этого сессию они открыть забывают!)
>попытка записи файла telecom/pb/luid/000000000001.vcf без указания параметра длины объекта (естественно запрос не распознан)
>закрытие сессии 81 ... (естественно запрос не распознан, поскольку сессия не открыта)
> Закрытие COM-порта
> Открытие COM-порта
>AT+CGM
>AT+CGMI
>AT*EOBEX
>80 ... (Открытие OBEX-сессии)
>02 ... (нормальная запись файлов)
>...
>81 ... (Закрытие OBEX-сессии)
> Закрытие COM-порта
Нажав кнопку «Отмена», я оборвал процесс синхронизации, когда началась передача записей на телефон, но клиент XTND не отправил команду отмены текущей операции, а просто не стал передавать очередной пакет и вместо него отослал команду закрытия OBEX-сессии.
Естественно, поначалу в этом потоке нелогичных запросов разобраться было сложновато. Но в итоге получилась программа, которая не переспрашивает несколько раз OBEX-сервер о его характеристиках, а работает в пределах жестко определенных правил протокола. В моей программе остались некоторые артефакты в виде сообщений в строке статуса «Вывалились из OBEX-сессии». Ранее они служили для индикации неясных ситуаций (вроде той, что происходила в середине приведенного диалога), а сейчас просто индицируют переход от опроса модема к записи данных в режиме добавления карточки в телефонную книгу.
Можно предположить, что при синхронизации еще и календаря количество запросов клиента XTND к файлу devinfo.txt увеличится вдвое и число некорректных запросов после прочтения всех данных также изменится. Непонятно также, зачем производится переоткрытие COM-порта при переходе от чтения к записи данных. Может быть, это связано с тем, что программисты хотели высвободить ресурс на время обработки полученных от телефона и программы-органайзера данных о внесении дополнительных записей, однако между закрытием и повторным открытием порта времени проходит меньше, чем требуется для чтения файла devinfo.txt. Может, причина в том, что в моем OutLook'е всего 150 записей и P-III 500 МГц их слишком быстро обрабатывает, — но факт остается фактом: программа могла бы работать примерно вдвое быстрее. Ускорить ее можно (благо для R320 идет урезанная версия) вообще не обращаясь к файлу devinfo.txt, поскольку информация, хранящаяся в нем, статична (согласно файлу «прошивки», который можно скачать, например, отсюда). Статичность информации в этом и других файлах обусловлена, по-моему, тем, что R320 действительно был первым, протокол обмена только-только был разработан, и, следовательно, часть функций реализована «для галочки».
Теперь о совместимости разработанных программ с другими телефонами. Проверял я ObexReader и ObexConnect только с Ericsson R520. В принципе, ObexRead с ним работает, но при выдаче команды AT*EOBEX (AT+CPROT перестала поддерживаться в новых Ericsson'ах) автоматически формирует команду открытия OBEX-сессии, так что подавать дополнительно 80h не нужно.
В R520 при получении команды AT*EOBEX телефон выводит на экран приблизительно такую заставку, обозначающую вход в режим, который обычно используется для синхронизации. В R320 эта заставка тоже предусматривалась (если верить текстовым меткам в инженерном меню и файле прошивки, ссылка на который приведена выше), но аппарат ее не показывает. Может быть, при правильном подборе параметров команды открытия OBEX-сессии телефон все-таки будет отображать нечто подобное.
ObexConnect, естественно, не должен нормально работать с R520, поскольку этот телефон уже полностью соответствует спецификациям IrMC, предоставляет уровень 16 обмена информацией, правильно ведет файлы info.log, использует общепринятые кодировки символов и т. д. А самое главное — программы, описанные в этом материале, разрабатывались с учетом необходимости синхронизировать записи R320 с органайзером ПК на русском (поскольку входящее в комплект телефона ПО эту функцию не поддерживает), а с R520 и t39 идет версия 4.5 (и выше), которая корректно интерпретирует для MS Outlook русские буквы, принимаемые от R520. К сожалению, XTND Connect версии 4.5 с R320 не работает, поэтому и пришлось самому делать программку.
И еще об одном недостатке программы: пока я не знаю команды входа в OBEX-режим по ИК-соединению. Само соединение идентифицируется командой ATI, в ответ на которую R320 в зависимости от того, как он подключен к ПК, выдает или «R320 IR modem» или «R320 cable modem». Независимо от того, к какому COM-порту присоединен ИК-модуль (проверялось с модулем ASUS IRM-100 и внешним устройством TekRam IR Mate 210B), XTND Connect каким-то образом работает в обход той функции прослушивания порта, которую использует PortMon98. Также не было возможности проверить работу R320 с BlueTooth-модемом (есть вроде такой в природе, наверное, именно он поставляется в комплекте с BlueTooth HandsFree Ericsson HPB-15), поскольку ни самого модема, ни карты, которой его можно было бы подключить к настольному ПК, у меня нет.
И, наконец, должен сообщить, что доступ в OBEX и Hayes-режимах к пунктам быстрого меню и именам профилей в Ericsson R320 на русском языке невозможен. Поэтому организовать на экране в режиме синхронизации какую-нибудь кириллическую надпись вместо имени профиля не удается - получаются иероглифы. Однако с помощью AT*-команд на Эрикссонах можно установить мелодию, информирующую пользователя о начале и завершении синхронизации. Также невозможно стандартными средствами считать с Ericsson R320 список электронных посланий и диктофонные записи, хотя протоколы, описанные в этом материале, используются для передачи звуковых файлов между КПК.
Теперь несколько слов о снятии с себя ответственности
Во время почти полуторамесячных экспериментов по чтению данных в OBEX-режиме мне однажды удалось каким-то образом уничтожить каталог telecom со всем содержимым. Но не вообще все данные, а только для OBEX-запросов. Другими словами, телефон отображал все имена, все записи календаря, но в OBEX-режиме при чтении с ПК любого файла сообщал об ошибке («не найден»). Избавился я от нее полным сбросом, выключением телефона, вытаскиванием батарейки и повторным включением. Это я к тому, чтобы не получилось как в известной истории об открытии метода завешивать мобильные телефоны (для передачи SMS), о котором в конце ноября рапортовал один специалист. Покопавшись в интернет-конференциях, я понял, что эксперименты по передаче SMS со своей Nokia 6210 через компьютер специалист предположительно начал в начале ноября. Он нашел ошибку у Nokia, однако если бы содержимое настроечного SMS для WAP'а не было специально (специально ли?) испорчено, то сенсации бы не получилось. Так и в 320-м Эрикссоне. OBEX-режим у него как бы вторичен, поэтому разрушить записи можно лишь операцией записи. В любом другом случае информация не повреждается, но становится недоступной с компьютера.
Вот, собственно, и все, к чему я пришел после всех экспериментов. Осталось немного: сделать модуль, который будет получать от программы-органайзера данные об имени и телефонах, ему соответствующих, сравнивать эти данные с информацией, полученной от аппарата, дописывать в телефон недостающие и удалять ненужные записи. Надеюсь, этот материал пригодится тем, кто захочет разработать собственную программу синхронизации данных между КПК и программой-органайзером. Как пользователь Палм'а m100 я знаю, что он теоретически может быть согласован с MS Outlook, но в комплекте поставляется только программа связи с фирменной оболочкой Palm Desktop, а для синхронизации с другими приложениями требуется программа типа XTND Connect (Extended Systems выпускает и такое приложение). Хочу верить, что примеры перекодирования символов R320 в кодировку Windows помогут разработать на Palm'ах приложение, позволяющее редактировать телефонные записи на русском языке.
Удачи!