Воскресенье, 27.07.2025, 12:57
 
Главная Регистрация Вход
Приветствую Вас, Сторонний · RSS
Меню сайта
Категории каталога
Программирование на C/C++/C# [7]
Education [0]
Программирование на BASIC [0]
Программирование на Pascal [0]
Программирование на Delphi [0]
Программирование на Assembler [0]
IT [7]
Общеобразовательная
Мини-чат
Наш опрос
Вы за блог на нашем сайте?
1. Мне все равно...
2. Да!
3. Нет.
Всего ответов: 27
 Каталог статей
Главная » Статьи » Программирование на C/C++/C#

Возьми ОпСоСа под контроль!
Возьми ОпСоСа под контроль!

Мингулов Денис

Хакер, номер #070, стр. 070-126-1

(denis@mingulov.com)

Обработка логов для смартфонов на Symbian OS

В логах не хранятся данные по USSD-запросам («звонки» по номерам *xxx#), так что ты не сможешь автоматически учитывать включение/выключение услуг с их помощью, но можешь пытаться анализировать SMS.

Money, money, money...

Сейчас практически у всех есть сотовый телефон. За его использование надо платить, и чем интенсивнее общение по мобиле, тем больше денег оно требует.

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

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

Если ты захочешь взять у оператора детализацию тарифицированных действий, то даже за плату не везде это поможет. У некоторых операторов может не хватать каких-нибудь данных в детализации, например номеров входящих звонков, и остается неизвестным, был ли звонок платный или нет. К тому же, вдруг какого-нибудь звонка или SMS не было на самом деле?

В смартфонах все события, которые могут быть тарифицированы, сохраняются во внутренних логах. Наиболее распространены такие телефоны на базе Symbian OS. И ты можешь сам анализировать логи своего телефона.

Все смартфоны на Symbian OS

Посмотреть описание каждого ты можешь здесь: www.symbian.com/phones - или на других сайтах.

Доступны: Nokia N-Gage, N-Gage QD, 7650, 3650/3600, 3660/3620, 6600, 7610, 9210/9290(i); Siemens SX1; Sendo X; SonyEricsson P800, P900; Motorola A920, A925.

Ожидаются: Nokia 6620, 6630, 6260, 9500, 7700; Panasonic X700; Samsung SGH-D710; SonyEricsson P910; BenQ P30; Motorola A1000.

Японские (не GSM): FOMA F900i, F2102V, F2051, F900iT.

Начинаем программировать

В августовском номере «Хакера» мы напечатали статью о программировании под Symbian для начинающих. Продолжим - опять возьмем пример HelloWorld и на его базе сделаем новую программу.

Получить доступ к лог-серверу и узнать о произошедших событиях довольно просто.

В документации к SDK ты можешь прочитать про Log Engine. Вкратце, доступ к логам возможен только асинхронно, то есть не напрямую при выполнении программы, а отдельным запросом параллельно, с помощью Active Objects (так в Symbian OS реализована многозадачность).

Подключи к .h-файлу следующие заголовки: <logcli.h> , <logview.h> , <f32file.h> и <logwrap.h> . Свой класс для доступа к логам делай наследником CActive и заводи следующие переменные:

Наши переменные

CLogViewRecent* iRecentLogView;

RFs iFs;

CLogClient* iLogClient;

CLogViewEvent* logViewEvent;
CLogClient* logClient;

CLogFilterList* filterList;

CLogFilter* filter;

В реализации класса используй стандартное наследование от CActive. Примеры можешь посмотреть здесь (для Series 60 SDK 2.1): \Symbian\7.0s\Series60_v21\Examples\base\ipc\async.

В ConstructL() подцепляемся к серверу логов:

iFs.Connect();

iLogClient = CLogClient::NewL(iFs);

iLogViewEvent = CLogViewEvent::NewL(*iLogClient);

filter = CLogFilter::NewL();

Для звонков используй такой фильтр, для (HS)CSD используй KLogDataEventTypeUid, факсов - KLogFaxEventTypeUid, SMS - KLogShortMessageEventTypeUid, GPRS - KLogPacketDataEventTypeUid.

filter-> SetEventType( KLogCallEventTypeUid );

logViewEvent-> SetFilterL(*filter, status);

В DoCancel не забудь прекратить все открытые запросы: iRecentLogView-> Cancel();

В RunL при отсутствии ошибок (iStatus == KErrNone) реализуй запрос (пример запроса последнего номера):

TBuf<256> iTelNumber;

const CLogEvent& event = iRecentLogView-> Event();

iTelNumber.Copy(event.Number());

А вот сама функция GetLastes:

// прерываем старый запрос

iRecentLogView-> Cancel();

// делаем запрос

if (iRecentLogView-> SetRecentListL(KLogNullRecentList,iStatus)) SetActive();

Запрос произвольного номера делается аналогично.

Обработай!

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

Для работы с файлами нужно подключить заголовочный файл <f32file.h> и подсоединить к проекту библиотеку efsrv.lib. Вначале подсоединись к файл-серверу (создай сессию) - RFs::Connect(). Затем используй RFile - Open, Close, Read, Write, Seek.

Пример работы с файлами

RFs fsSession;

User::LeaveIfError(fsSession.Connect());

RFile file;

User::LeaveIfError(file.Open(fsSession,strFileName,EFileRead|EFileShareAny));

TBuf8<512> buf;

file.Seek(ESeekCurrent,0);

User::LeaveIfError(buf,512);

file.Close();

fsSession.Close();

Сколько потратили?

Итак, после обработки логов ты имеешь все данные за определенный период. Теперь хотелось бы узнать, сколько было потрачено денег.

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

Обычно звонки с местных сотовых бесплатны. Узнать принадлежность телефонного номера какому-нибудь региону в негеографических зонах (таких, как +7-9EF) можно на сайте www.mtt.ru/info (справа в справочной информации). Там же можно найти международные и междугородные коды. А вот «городские» телефонные номера, принадлежащие оператору сотовой связи, придется искать самому.

Учитывай возможность сокращенного набора номера - 8 вместо +7, 8-2 для выхода в область, отсутствие кода страны и города, бесплатные номера вроде 112 и 01.

Звонок может тарифицироваться поминутно, посекундно, посекундно со второй минуты, каждые 10 секунд и как угодно еще. Кроме того, наша программа должна учитывать возможность наличия платы за соединение.
Все точно так же для SMS и MMS - их цена тоже может варьироваться, ведь обычно длинные SMS оплачиваются как несколько коротких.

Помни, что данные о длительности звонка на твоем телефоне могут не совпадать с данными оператора, как и твои часы с часами оператора при отслеживании изменения тарифа.

Делаем базу данных для тарифа

Различаем виды звонков

Для всех звонков, совершенных на номера > = strPhoneFirst и < strPhoneLast, будут использоваться соответствующие тарифы.

const TInt KStrPhoneLength=32;

TInt32 iTariffLen; // всего тарифов поддерживается

TInt32 *arrayTariff; // массив тарифов для входящих звонков

TBuf<KStrPhoneLength> strPhoneFirst; // первый телефонный номер

TBuf<KStrPhoneLength> strPhoneLast; // следующий за последним телефонный номер

При таком задании базы можно использовать сокращенные номера, например, +7-902 как strPhoneFirst и +7-903 как strPhoneLast - в это множество попадут все номера от +7-902-000-0000 до +7-902-999-9999.

О каждом тарифе по его номеру мы узнаем, какой он - для входящего или исходящего звонка, SMS или MMS. В TInt32 iTariffNum храним номера тарифов верхнего уровня, зависящих от времени.

Зависимость от времени

TInt32 iTariffCostLen; // длина массива с ценами

CTimeTariff *arrayTariffCost; // номера тарифов с ценами

В CTimeTariff задается промежуток времени - с днем недели, флагом праздничного дня

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

Если же событие лежит на границе тарифов (например, звонок в 23:58 на 10 минут, а с 00:00 начинается льготное время), то надо знать, как оно будет учитываться – по одному тарифу или двум. В некоторых тарифах цена минуты разговора в этом случае не будет меняться до конца звонка. Так что в CTimeTariff также задаем флаг, что делать в такой ситуации.

Цены

TInt32 iQuant; // единица тарификации - в секундах

TInt16 iCostLen; // длина массива с ценами

TReal *arrayCost; // массив цен

TInt32 iNext; // что делать, если звонок больше: n - кольцо с n-ой (0 - считать с начала, =iCostLen-1 - повторять последнюю)

Для SMS достаточно знать стоимость одного сообщения - TInt16 iCost.

Кроме того, не забудь, что надо включить в нашу базу абонентскую плату.

Особенности подсчета стоимости GPRS

К сожалению, у многих операторов очень непростая тарификация GPRS, и со стороны пользователя узнать, сколько было потрачено, можно лишь приблизительно, ведь из логов ты можешь узнать только время начала соединения, длительность и общий трафик - полученный и посланный. А операторы предпочитают делить эту большую сессию на подсессии по 15-20 минут, так как соединение с GPRS может длиться месяцами, если нет никаких проблем.

Таким образом, большая сессия из лога телефона в 4 часа 10 минут может быть поделена на 16 подсессий по 15 минут и одну 10-минутную, для каждой из них будет отдельно учтен бесплатный порог и сделано округление.
Оператор может считать входящий и исходящий трафик по отдельности (возможно, по разным тарифам), кроме трафика, взимать плату и за время соединения...

Допустим, 1 Мб стоит 10 рублей без НДС. Известно, что минимальная плата у этого оператора - 1 рубль. Так надо ли считать, что каждые 100 кб стоят 1.18 рублей, или же каждые 850 кб (примерно) стоят рубль?

Полные данные о тарификации GPRS можно узнать только из полной детализации, если она доступна.

Тариф GPRS

TInt32 iQuant; // единица тарификации - в байтах

iCostLen, *arrayCost и iNext - аналогично звонкам

TBool iInOut; // флаг различия входящего/исходящего трафика - считать ли сумму по отдельности или учитывать только входящий трафик

Бесплатный порог, как и для голосовых звонков, задаем 0-ым значением соответствующего элемента массива arrayCost.

Дополнительные услуги

Для дополнительных услуг возможны платы за подключение и отключение, абонентская и за использование. Самая распространенная дополнительная услуга - АОН, затем «любимый» номер.

Тариф дополнительной услуги

TReal costTurnOn; // стоимость подключения

TReal costTurnOff; // отключения

для абонентки данные аналогичны звонкам, только единица тарификации - в секундах от 86400 (сутки)

TReal costOneUse; // одно использование, если iCostLen=0

Основную работу по проверке выгодности дополнительных услуг придется делать вручную (только стоимость можно будет брать из базы), так как они могут быть всевозможные.

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

Программа online

Желательно, чтобы твоя программа висела в памяти и ловила notify от сервера логов, обрабатывая новые данные. Их сохраняй (накопленные и проанализированные) сам - вдруг сервер логов удалит часть.

При этом ты можешь использовать лог-сервер для узнавания номера при входящем звонке. Например, для распознавания - бесплатный ли этот звонок для тебя или нет?

Кто звонит?

CCallerId *cCallIncoming создан заранее

cCallIncoming-> GetLatest();

User::WaitForAnyRequest();

В cCallIncoming-> iTelNumber лежит номер телефона.

На рисунке «Nokia 9500» ты можешь увидеть пример работы программы в этом случае - ты должен сам следить за тем, чтобы пользователь мог ответить на звонок, разрешая стандартным программам телефона дальнейшую обработку звонка.

Развитие

Вот ты и готов сам проверять своего оператора. Нашу прогу можно всячески улучшить: встроить проверку подключения роуминга, проверку включения/выключения дополнительных услуг при помощи SMS или звонков по специальным номерам оператора...

Сделай это все сам, ты можешь! Удачи!

Пример тарифа

Абстрактный тариф - посекундный с 61 секунды, все входящие бесплатно, исходящие все: $1.2 первая минута, $0.6 - вторая, $0.3 - посекундно с третьей, бесплатный порог - 10 секунд. АОН: либо $1 в день, либо $0.3 за один входящий звонок. Подключение этой услуги в любом варианте бесплатно, отключение - $1.

Вот так будут заданы его параметры:

iQuant = 1 секунда
iCostLen = 60 + 60 + 1 = 121 секунда

arrayCost:

секунды с 1-й по 10 = 0 (бесплатный порог)

11 секунда = 1.2 (первая минута)

12-60 секунды = 0 (поминутно - оплачено на 11 секунде)

61 секунда = 0.6 (вторая минута - нет бесплатного порога)

62-120 секунды = 0 (поминутно - вторая минута оплачена на 61 секунде)

121 секунда = 0.3/60 = 0.005 (посекундно с третьей минуты)

iNext = iCostLen-1 = 120 (далее посекундно)

Сделаем возможность бесплатного звонка на 112: strPhoneFirst = _L("112") и strPhoneLast = _L("1120") - так никакой другой номер, кроме 112, учитываться не будет.

Два варианта дополнительной услуги АОН прописываем по отдельности:

costTurnOn = 0, costTurnOff = 1

1) iQuant = 86400, iCostLen = 1, arrayCost[0] = 1

2) iQuant = 0, iCostLen = 0, costOneUse = 0.3

CD

На компакт-диске лежат полные исходные коды программы под Series 60.

WWW

На сайте www.mingulov.com/ru ты можешь найти различную информацию и ссылки на полезные сайты по программированию для Symbian. Там же и исходник продемонстрированного примера.

INFO

Для поддержки многозадачности в программах под Symbian OS используются Active Objects.

INFO

Стандартом программирования под Symbian является окончание названия функции на L, если там может произойти исключение с последующим непредвиденным выходом.

WARNING

Считаешь, что слишком много платишь за телефон? Желаешь контролировать расходы? Хотел бы выбрать наилучший тариф? Не доверяешь оператору сотовой связи? Выгодно ли тебе подключать дополнительные услуги? Какой «любимый» номер выбрать? Вопросов много. Обычно смартфоны хранят логи по всем произошедшим событиям - и звонкам, и сообщениям, и работе с GPRS. Я покажу тебе создание программы для смартфонов под Symbian, которая ответит на все вопросы о твоих реальных затратах на мобильную связь.




Источник: http://www.xakep.ru/magazine/xa/070/126/1.asp
Категория: Программирование на C/C++/C# | Добавил: Artem_3A (10.04.2008) | Автор: Мингулов Денис
Просмотров: 1140 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Сделать бесплатный сайт с uCoz
Форма входа
Поиск
Друзья сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0