Вредные советы, выпуск №4
Не расстраивайтесь, если
Вызывают в школу маму
Или папу.
Не стесняйтесь,
Приводите всю семью…
(Григорий Остер)
Сегодня хочу рассмотреть одну не совсем стандартную задачу. Как и в прошлых выпусках, она базируется на возможностях Tasker и не только. Суть задачи: имеем три Android-смартфона в семье, за их финансовым состоянием должен следить один человек (по непонятным причинам выбор пал на меня). Один из смартфонов имеет две SIM-карты, таким образом, необходимо отслеживать баланс четырех телефонных номеров, все номера предоплаты, и если за одним номером я могу следить сам, то вот с тремя другими не все так просто.
Варианты решения:
- воспользоваться услугами своего банка и подключить автоматическое пополнение номеров на определенную сумму каждый месяц;
- воспользоваться услугами операторов и в ручном режиме через личный кабинет отслеживать состояние баланса;
- сделать один смартфон «сервером», который будет получать уведомления с других смартфонов о том, что баланс счета достиг критической отметки, и либо в ручном режиме предлагать пополнить необходимый номер, либо делать это автоматически (без участия человека);
- какой-то еще вариант.
Первый вариант слишком простой, и мне не подходит, так как, например, один из номеров (телефон первоклашки) нет необходимости пополнять каждый месяц. Второй вариант напрягает тем, что необходим доступ к сети, и все будет происходит в ручном режиме.
Третий вариант интересен и достаточно просто реализуем.
Начнем с того, что необходимо на каждом смартфоне получать текущий баланс, сохранять его, сравнивать с критическим значением и в случае достижения этого значения отправлять данные на «сервер».
Для получения баланса используем USSD-запросы оператора, а вот для обработки этих запросов одного Tasker мало (можно, конечно, реализовать и с его помощью, но это долгий путь). На оба смартфона устанавливаем USSD Dual Widget Pro (существует и бесплатная полнофункциональная версия с небольшими ограничениями), который позволяет получать баланс через USSD-запрос и выводить его в виде виджета на рабочий стол.
Изобретать велосипед я не стал и просто решил взять уже готовые данные из этой программы. Для этого уже необходимы
- Root-права;
- наличие sqlite3;
Необходимые нам данные USSD Dual Widget хранит в своей базе данных по пути /data/data/com.mdnsoft.ussddualwidgetpro/databases/Data.db (путь указан для Pro-версии)
Вот как выглядит эта база изнутри:
Данные выдергиваем в задаче (назовем ее USSDbalance) tasker: Script->Run shell
Для первой SIM-карты:
sqlite3 /data/data/com.mdnsoft.ussddualwidgetpro/databases/Data.db 'select VALUE from vStat param=1 order by _id desc limit 1'
Выполнять с Root-правами.
Сохраняем результат в свою переменную: store output in->%BALANCE1
Для второй SIM-карты:
sqlite3 /data/data/com.mdnsoft.ussddualwidgetpro/databases/Data.db 'select VALUE from vStat param=2 order by _id desc limit 1'
Выполнять с Root-правами.
Сохраняем результат в свою переменную: store output in->%BALANCE2
Самую сложную часть мы выполнили, теперь остались мелочи. Нам необходимо получать данные в свои переменные, после того как они обновляются в базе данных. Решение этой задачи также имеет несколько вариантов, я решил просто «мониторить» файл базы данных на изменения. В Tasker есть функция для этого: Event (событие)->File(файл)->File modified (файл изменен). Но мне не повезло, Tasker не видел нужный мне файл в /data/data/… (на некоторых версиях Android и отдельных прошивках этот баг пока не решен). Казалось бы, это состояние может ввести в ступор или заставит искать иное решение (я сначала впал в ступор, а потом начал искать выход). На помощь как всегда пришел Root и busybox. Вот такая строчка является решением этой задачи:
inotifyd - /data/data/com.mdnsoft.ussddualwidgetpro/databases/Data.db:c | while read code; do am broadcast -a net.dinglisch.android.tasker.ACTION_TASK -e task_name USSDbalance; done &
(можно было задействовать grep и/или awk)
inotifyd - команда из busybox, которая позволяет отслеживать открытие, изменение файлов и так далее;
/data/data/com.mdnsoft.ussddualwidgetpro/databases/Data.db – файл, который мониторим;
:c - ключ который фильтрует только изменения файла (в нашем случае запись в Data.db);
while read code; do am broadcast -a net.dinglisch.android.tasker.ACTION_TASK -e task_name USSDbalance; done - в случае изменения файла, запускаем нашу задачу USSDbalance;
& - в конце строки заставит нашу команду висеть постоянно в памяти и мониторить изменения.
Запуск этой задачи осуществляем после загрузки Tasker: Event (событие)->Tasker->Monitor start boot. Теперь в Tasker’е в переменных живут показания баланса, и остается их только проверять на предмет достижения критического значения: Event (событие)->Variables (переменные)-> Variable Set (переменная установлена) %BALANCE1. Создаем задачу с проверкой: Task->If(если) %BALANCE1 Math.Less than (матем. «меньше чем»), указываем свое значение. Теперь в этой же задаче можем осуществить отправку данных на свой «сервер». Это возможно сделать отправкой SMS-сообщения, но так как в моих тарифных планах это приведет к дополнительным расходам, решил реализовать процесс немного иначе. На моем телефонном номере подключена услуга, которая позволяет получать SMS через emai (использую ее во многих задачах). То есть, отправив email на адрес вида мой_телефонный_номер@sms.имя_оператора.домен, я его получу в виде сообщения (удобно тем, что нет потребности в постоянно включенном режиме передачи данных 2G/3G/WiFi).
Для отправки email из Tasker есть бесплатный вариант, но для этого необходимо установить «прослойку» и один из удобных вам интерпретаторов, например, python. Думаю, многим это может показаться сложным, да и объемы статьи приблизятся к критическому значению. Поэтому предлагаю пойти более легким путем, но легкий путь имеет свою цену: Locale SendSilentMail Plug-In. В текущей задаче после строки проверки критического значения: Plugin->SendSilentMail, настраиваем по своему вкусу (можно, например, отсылать текущее значение «проблемного» баланса).
На этом работа с «клиентами»-смартфонами окончена, от себя могу лишь добавить, что можно задействовать озвучивание текущего баланса при достижении критического уровня, используя советы из пилотного выпуска. А благодаря приемам из второго выпуска «Вредных советов» («Организовываем автоматическое включение Wi-Fi дома»), отправка писем происходит автоматически, как только появится соединение с сетью.
Осталось настроить наш «сервер» на обработку сообщений: Event (событие)->Phone (Телефон)->Text Received (получено текстовое сообщение). Указываем имя отправителя, у меня это SMS_z_Email, содержание не указываем, так как мы его будем обрабатывать внутри задачи.
Создаем задачу под этот профиль:
- Variables (переменные)-> Variable Set (установить переменную) - %SMSTXT to(до) %SMSRB (это внутренняя переменная tasker, в ней хранится текст сообзения sms/mms)
- Task->If (если) %SMSTXT совпадает с нужным вам значением
- Выполнить нужные действия. У меня это автоматическая отправка SMS для пополнения телефонного номера с которого пришел запрос (услуга SMS-банкинг), но перед этим выполняем проверку, так как может прийти несколько запросов от одного «клиента», и чтобы не осуществить задублированные платежи, необходимо все четко проверить.
- Тут идут проверки идентичные пункту 2 для других телефонных номеров.
На деле это работает так: после каждого исходящего звонка (SMS-сообщения) проверяется текущий баланс, если он меньше определенной суммы, то смартфон желает сообщить об этом «серверу». Включается Wi-Fi, пытается установить соединение, если соединение установлено, то отсылается SMS через email на «сервер». Если не удалось соединиться, то письмо с запросом находится в очереди и будет отправлено, как только смартфоны окажутся дома и сработает профиль, определяющий местоположение, включится Wi-Fi и запрос уйдет на «сервер». Смартфон-«сервер» получает SMS-сообщение, анализирует его, совершает отправку SMS услугой SMS-банкинг с пополнением телефонного номера, получает сообщение от банка, анализирует его и при успешном списании сообщает об этом. Можно усложнить задачу, выставить несколько уровней критического баланса, и в случае, если он критически-критичен, осуществить звонок на «сервер» за счет «сервера». В общем, было бы желание, а места для полета фантазии предостаточно.
Возможно, некоторым покажется, что некий СМ варит кашу из топора (в данном контексте это не CyanogenMod, см. рисунок ниже), но сложного в этой задаче и ее решении ничего нет.