Разработка системы для сбора SMS со смартфонов

В этом посте я хочу поделиться своим опытом разработки достаточно интересной клиент-серверной системы, архивирующей события смартфонов и предоставляющей к ним централизованный доступ через web-интерфейс. К событиям можно отнести SMS-сообщения, звонки, изменение географических координат и другие. Кому не ясна область применения подобной системы, читайте текст на вводной странице сайта: http://www.altermoby.com. На данный момент реализован только сбор SMS-сообщений на смартфонах Nokia, но модульность системы позволит добавить поддержку новых событий и мобильных платформ в ближайшее время. Система была реализована одним человеком (мной) в течение полугода на досуге.

Скриншот с сайта:

screenshot

К идее реализации подобной системы я пришёл во время работы в небольшой фирме, реализующей нечто похожее. Обе системы позиционируются легально: моя система (AlterMoby) как средство архивации собственных событий, либо событий людей, знающих о том, что ведётся сбор их персональных данных; та система – как помощник при присмотре за своими детьми (во втором случае возникают вопросы, так как во многих странах слежка за собственными детьми противозаконна).

Та система перехватывала SMS-сообщения и звонки пользователя, сразу отправляя их на сервер. Недостаток такого подхода заключался в том, что во время наступления события пользователь часто продолжал пользоваться своим смартфоном, что делало отправку данных невозможной (данные просто терялись). Как следствие, та система страдала от сбоев и нестабильной работы. Уже тогда мне, как одному из её разработчиков, стало очевидно, что события должны накапливаться во временном хранилище смартфона, ну а потом отправляться в моменты простоя телефона. Увольняясь из той фирмы (тогда я подавался во freelance), твёрдо решил реализовать собственную систему сбора событий, делая упор на гибкости и стабильности работы. Прошёл почти год, когда я, наконец, решил приступить к реализации. Разработка велась по вечерам, после основной работы.

Клиентская часть AlterMoby писалась под Symbian S60 3rd edition (с этой платформой я успел неплохо познакомиться ранее, кроме того это был и есть лидер рынка смартфонов). Выбор языка разработки тут не стоял – только Symbian C++, поскольку была необходимость в использовании всех доступных интерфейсов ОС. Кроме того, программный агент должен быть достаточно производительным, чтобы не тормозить интерфейс и без того не быстрого аппарата.

Были аккуратно закодированы модуль логирования (включается / выключается директивой препроцессора), модуль конфигурации, читающий параметры работы в хеш-таблицу при запуске агента.

К хранению временных данных я подошёл ответственно. С одной стороны они не должны бесконтрольно разбухать при отсутствии связи с сервером, с другой – должны размещаться как можно компактней. Для хранения событий был выбран принцип кругового буфера, который располагается в файле. Такой подход позволяет записывать и считывать порции данных в порядке очереди, что подходило для моей задачи. События записываются в бинарном виде для максимизации скорости и компактности. Объёмные данные (в случае SMS-сообщений таковых нет, для звонков могут быть записями разговоров) оформляются как приложения к событиям и пишутся в отдельные файлы. Код работы с файловым хранилищем был оформлен в соответствующий класс базы событий. Код агента выполняется в единственном потоке, потому базу событий не потребовалось защищать примитивами синхронизации. Всё благодаря прекрасной концепции активных объектов в Symbian.

Далее реализовал модуль перехвата SMS-сообщений. Это достаточно простая задача, легко реализуемая стандартным API. Этот модуль отслеживал входящие и исходящие сообщения и записывал из в базу событий.

Отправку событий реализовал в виде класса, единственный экземпляр которого просыпается раз в минуту, чтобы проверить наличие данных. В заданный период времени (или сразу после наступления события – зависит от конфигурации) отправитель компрессирует порцию данных (размер тоже определяется конфигурацией) из хранилища и отправляет её на сервер по HTTP (multipart/form-data) в бинарном виде. Соединение происходит по IAP (точке доступа), заданной в конфигурации. Кроме того поддерживается работа агента в автономном режиме, когда отправитель неактивен, и пользователь отправляет на сервер события со своего PC (предварительно перенесённые со смартфона). Это удобно, когда смартфон по разным причинам не может (или не должен) выходить в сеть.

Заканчивая реализовывать клиентскую часть, я задумался о дистрибуции инсталляционного пакета (sis, sisx) с агентом. Дело в том, что каждый телефон требует персональную конфигурацию, следовательно, было удобным внести файл конфигурации внутрь инсталляционного пакета. С другой стороны, это требует возможности сборки индивидуального инсталлятора для каждого телефона клиента, но при таком подходе не будет возможности подписать приложение у Nokia. В качестве альтернативы, можно было распространять инсталляционные пакеты без конфигурации, с тем, чтобы конфигурационные файлы ставились вручную отдельно. Не самый удобный вариант с точки зрения пользователя. Учитывая политику Nokia в отношении приложений без GUI, тем более, собирающих персональные данные пользователя, я принял решение игнорировать подпись инсталляционных пакетов и распространять их в неподписанном виде. Пользователь всегда сможет скачать сертификат на свой смартфон на любом из многих сайтов (раньше было только у китайцев) и подписать им инсталляционный пакет (не говоря уже о немалой группе пользователей со взломанной защитой).

Далее стал выбирать технологию реализации серверной части AlterMoby. Со времён университета я полюбил функциональное программирование, потому решил реализовать сервер на Lisp. Выбор Lisp был во многом связан тем, что мне требовался мощный и выразительный язык, чтобы реализовать серверную часть (включая web-интерфейс) в одиночку за приемлемое время. Тут были две всем известные альтернативы: Common Lisp и Scheme. От второго решил отказаться в силу отсутствия множества сторонних библиотек, которые так необходимы для решения реальных задач. Выбор компилятора почти не стоял – у SBCL, кажется, нет реальных бесплатных альтернатив, как в плане надёжности, так и производительности. В качестве редактора пришлось использовать Emacs (из-за поддержки SLIME). Не люблю этот редактор (в отличие от того же vim), но выбора не было.

Для практики программирования на Common Lisp реализовал модуль конфигурации, читающий s-выражение из текстового файла, а также систему логирования. Последняя разбивает журнал на файлы (частота задаётся в конфигурации), которые затем компрессируются (bz2). Ротацию не реализовал умышленно – хочу сохранять весь журнал, тем более что используемая компрессия чрезвычайно эффективна.

Далее реализовал приём сообщений от клиентских агентов. Долго выбирал web-сервер, в итоге остановился на Hunchentoot, о чём нисколько не жалею. В качестве СУБД решил использовать PostgreSQL (побоялся полагаться на MySQL, желая не беспокоиться о производительности при будущем масштабировании). Для привязки к данным использовал легковесную библиотеку Postmodern.

Теперь оставалась самая туманная для меня часть, а именно web-интерфейс. Совсем не имея опыта в web-программировании, я решил использовать Weblocks (выбор был совсем невелик). Соорудив примитивный каркас, выводящий заглавную страницу, я обнаружил неприемлемые искажения при просмотре в IE6, 7. На форуме посоветовали забыть про детище Microsoft. Но если шестую версию IE уже можно игнорировать, то седьмую – никак нельзя. Потому я решил расстаться с Weblocks и опираться только на HTML, JavaScript и CSS. Учитывая мою неподготовленность на этом поприще, пришлось осознанно отказаться не только от continuations, но и от такой распространённой вещи, как AJAX.

Итак, я поставил себе задачу реализовать вебсайт, основанный на классических технологиях WEB 1.0, грамотно спроектированный (чтобы не особо чувствовались технологические ограничения). Сайт должен поддерживать все современные браузеры, а также IE6-8. Кроме того, он должен адекватно функционировать при отключённом JavaScript (используемом, в основном, для упрощения работы с формами). В итоге я справился с поставленной задачей, кроме одного пункта: IE6 поддерживается не полностью (к сожалению, полная поддержка потребовала бы масштабной реорганизации сайта, и я решил от неё отказаться).

Во время работы над вебсайтом стала задача генерации инсталляционных пакетов для клиентов. Linux-версия утилиты makesis.exe, собранная из исходников энтузиастов, работать отказалась. Я очень боялся, что мне не удастся корректно запустить оригинальную версию под Wine. В итоге, мои страхи оказались беспочвенными - makesis.exe заработала как часы. Позже, когда я стал запускать код сервера в виде демона, makesis.exe работать отказался. Решение проблемы нашлось в переменных окружения, задаваемые в скрипте запуска демона (в /etc/init.d/).

По окончанию работы над сайтом пришло время задуматься об его внешнем виде. Мои рабочие CSS (благоразумно вынесенные в отдельные файлы, как и JS) давали неудовлетворительную цветовую гамму и дизайн. Сайт оставлял после себя впечатление поделки школьника. В вопросах эстетики я всегда оставался некомпетентным (рисовать не умел с детства), потому решил нанять специалиста, который бы смог мне сделать логотип и сверстать страницы. Такой человек довольно быстро нашёлся. В течение недели он нарисовал приличный логотип и макет страниц. На второй неделе он начал верстать, и тут у него начались проблемы, особенно с IE. В итоге, мы расстались, и я сверстал сайт сам, основываясь на его макете и картинках. Сейчас сайт имеет достаточно приличный вид.

Следующие две недели ушли на написание справки (на английском и русском) и подключение форума поддержки (на phpBB3). Форум использует порт 80, а сервис – порт 443 (SSL). На днях куплю SSL-сертификат.

Итак, за полгода времени, выделяемого урывками на досуге, я получил систему, готовую для коммерческого использования. Разумеется, она нуждается в длительном тестировании, потому ближайшие 2-3 месяца сервис будет оставаться бесплатным. Тестеры, welcome.

добавить комментарий: