Журнал LinuxFormat - перейти на главную

LXF132:google

Материал из Linuxformat
Перейти к: навигация, поиск
Hardcore Linux Проверьте себя на крутом проекте для продвинутых пользователей

Содержание

Google Cal: SMS безвозмездно

Клаудио Танчони опишет, как превратить Google Calendar в службу SMS-уведомлений, не обращаясь к платным сервисам.

Владельцы учетной записи на Gmail также получают доступ к другим инструментам и сервисам Google: Документам, Reader’у и, конечно, Календарю. На данном уроке мы покажем, как превратить последний в SMS-шлюз, посылающий вам SMS при возникновении некого события. Для примера мы настроим простенькую систему (состоящую из web-страницы на PHP, карманной базы MySQL и планировщика Cron), предназначенную для мониторинга сейсмической активности и посылающую нам сообщение при каждом подземном толчке.

Календарь Google не отличается от других похожих продуктов – кроме, конечно, его бесплатности для некоммерческого применения. Посылаемые сообщения также не будут стоить ничего, если ваш тариф не предусматривает платы за входящие SMS (если вы, скажем, находитесь в роуминге, плата может и взиматься).

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


Далее, создадим мероприятие для тестирования системы. Зайдем в основной вид Календаря и щелкнем на колонке с сегодняшней датой пониже красной линии, отображающей текущее время. Введите название мероприятия в появившемся окне и щелкните на Изменить информацию для доступа к странице, где вводятся подробности о мероприятии и создаются напоминания (в области Напоминание). На каждое мероприятие можно назначать до пяти напоминаний.

Используйте первый выпадающий список для указания способа получения напоминания, а поле и список правее позволят сообщить, когда вы хотите получить его. Для целей тестирования мы выберем отправку SMS через 0 минут. Другими словами, вы получите сообщение точно в момент начала встречи. Если вы почему-либо не видите выпадающих меню в области напоминаний, щелкните по Добавить напоминание.

Закончив, нажмите Сохранить и ждите наступления события, следя за вашим сотовым телефоном. Если SMS придет, то ваш телефон работает с Календарем Google! Теперь пойдем дальше и погрузимся чуть глубже в особенности текстовых сообщений.

ПроZendируем тему

Разобравшись, как добавляются текстовые сообщения в браузере, давайте сделаем это, используя код на PHP и Zend Framework.

Zend (http://framework.zend.com) – это коллекция библиотек, предлагающая хорошо документированный набор классов и методов для работы с Календарем Google. Если у вас есть учетная запись Google, зарегистрированный в Календаре Google телефон и минимальная установка Zend Framework на вашем сервере web-приложений, ничто не мешает запустить данную примочку.

Наша задача теперь – отправлять текстовые сообщения всегда, когда выполняется заданное условие. И это легко сделать с помощью PHP-библиотек Zend.

Тут вы можете начать недоумевать, зачем вам мучаться с Календарем Google при наличии прекрасных доступных сервисов SMS-шлюзов. Основная причина в том, что эти шлюзы не бесплатны; и хотя возможности безвозмездной посылки текстовых сообщений из Календаря Google несколько ограничены, с небольшими доделками это будет отлично работать на вас.

Для следующего примера займемся web-страницей, динамически обновляемой новым содержимым. А мы хотим, чтобы при появлении нового содержимого оно подчищалось, урезалось и посылалось нам на телефон, с помощью вскрытых возможностей отправки SMS в Календаре Google.

Используемая нами HTML-страница, обновляемая каждые несколько минут, содержит таблицу с землетрясениями в обратном хронологическом порядке, чтобы последние события были вверху. Данные приходят с официальной web-страницы, обновляемой геологическим сейсмическим институтом на http://cnt.rm.ingv.it/earthquakes_list.php?lang=eng. Для нашего примера разместим таблицу с этой страницы на http://gcal-smsdemo.co.cc/earthquakes.php. При новом проявлении сейсмической активности строка об этом добавится в начале HTML-таблицы.

Первым шагом применим для чтения web-страницы функцию PHP curl_exec, затем выполним синтаксический разбор HTML-кода для проверки, не зарегистрировано ли новое землетрясение в начале таблицы.

 /* Забираем html-документ для разбора */
 $ch = curl_init(“http://gcal-smsdemo.co.cc/earthquakes.php”);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
 $html = curl_exec($ch);
 curl_close($ch);

Функция curl_init() инициализирует сессию Curl и принимает URL как параметр. Curl_setopt() задает параметры для curl_exec(). CURLOPT_RETURNTRANSFER, TRUE велит следующей функции, curl_exec(), вернуть результат как строку (вместо булевского значения по умолчанию).

Далее, извлечем строки из таблицы с использованием DOM:

 /* Новый объект dom */
 $dom = new domDocument;
 /* Загружаем html в объект */
 $dom->loadHTML($html);
 /* Массив таблиц по тэгу */
 $tables = $dom->getElementsByTagName(‘table’);
 /* Забираем все строки из первой таблицы на странице */
 $rows=$tables->item(0)-> getElementsByTagName(‘tr’);

После загрузки HTML-страницы в объект DOM удобный метод getElementsByTagName() загружает все таблицы в массив $tables (на нашей демо-странице она только одна). Используя метод во второй раз, мы сохраняем все строки таблицы, которые вернул getElementsByTagName(‘tr’), в массиве $rows. Помните, что item(0) означает первую таблицу, так как индексы отсчитываются с 0.

Пускай теперь на web-страницу только что добавилась строка с Id 8211226050, и нам нужно забрать ее, почистить, сжать и использовать наш трюк с Календарем Google для отправки SMS-сообщения. Давайте посмотрим, как это сделать.

Интересующая нас строка таблицы расположена на втором месте (в массиве $rows это элемент с номером один). Здесь важно отметить, что нам доступны только 60 символов SMS вместо обычных 160 [в русской кодировке вообще 74, – прим. пер.]. Так как не все колонки таблицы имеют одинаковую ценность, отберем только часть из них, чтобы уложиться в этот лимит.

Интересные моменты

Интереснее всего будут Seismic District [Район землетрясения], Date [Дата], Time(UTC) [Время] и Mag(nitude) [Сила]. Параметры Depth [Глубина], Lat(itude) [Широта] и Lon(gitude) [Долгота] – более технические, и мы попытаемся немного поманипулировать строками, чтобы их тоже втиснуть, отказавшись от Id. Следующий код просмотрит массив $rows и создаст строку $smstxt с посылаемым текстом.

 /* Выбираем ка ж дую колонку по тэгу */
 $cols=$rows­>item(1)­>getElementsByTagName(‘td’);
 /* соз даем строку $smstext */
 /* Location(9) + Magnitude(7) + TimeDate (3)(2) +
    Latitude (4) + Longitude(5) + Depth (6) */
 $smstext=substr($cols­>item(9)­>nodeValue,0,8) .
    “ “ . $cols­>item(7)­>nodeValue . “ “ .
    $cols­>item(3)­>nodeValue . “ “ .
    $cols­>item(2)­>nodeValue . “ “ .
    $cols­>item(4)­>nodeValue . “ “ .
    $cols­>item(5)­>nodeValue . “ “ .
    $cols­>item(6)­>nodeValue . “Km”;

Массив $cols содержит 10 элементов (0–9) с данными о последнем сейсмическом событии. Используя нужные индексы и функцию substr(), мы легко создаем SMS-сообщение.

После отработки кода над предыдущей таблицей, $smstext будет содержать нечто вроде Chile-Ar Mb:6.2 11:25:38 2010/02/28 -34.739 -70.866 35Km. Отметим, что это меньше, чем 60 символов, частично благодаря substr($cols->item(9)->nodeValue,0,8), которая урезает поле Seismic District до восьми символов. Строка укорочена, и наше текстовое сообщение почти готово к отправке.

На следующем шаге применим логику, чтобы сообщение о сейсмическом событии посылалось однократно. Календарь Google не в состоянии определить, было ли отправлено SMS. Поэтому заведем небольшую базу MySQL для отслеживания уже посланных сообщений. Это может показаться лишним усложнением на пути к цели, но зато, когда база данных будет настроена, проверка, были ли сообщение уже отправлено, будет очень простой, потому что база не принимает одну и ту же запись более одного раза. А значит, в Календарь Google событие добавится только один раз, и он не будет зря бомбить наш телефон «эсэмэсками».

База данных в нашем примере будет содержать одну таблицу с именем sms, о двух колонках: smstext и status.

 CREATE TABLE IF NOT EXISTS `sms` (
   `smstext` varchar(160) NOT NULL,
   `status` varchar(32) NOT NULL,
   PRIMARY KEY (`smstext`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

База сообщений

Поле status поможет нам отслеживать, было ли послано SMS, а smstext будет хранить его текст. Давайте вернемся к PHP-коду. Он вставляет текстовое сообщение в таблицу sms базы данных и сигнализирует об ошибке, если такое уже существует.

 /** Соединяемся с БД **/
 $con = mysql_connect(‘localhost’, ‘username’,’pa$$w0rd);
 if (!$con) {
 die(‘Could not connect:. mysql_error());
 }
 mysql_select_db(“smsdemo_DB”, $con);
 /* Обезопасимся от инъек ций и спец. символов */
 $smstext = mysql_real_escape_string($smstext);
 /** DB sms INSERT **/
 $sql_ins_sms=”INSERT INTO sms (smstext, status)
 VALUES
 ($smstext,’pending’);
 if (!mysql_query($sql_ins_sms,$con)) {
  print(“Warning:. mysql_error() .<br />\n”);
 } else print(“1 sms added<br />\n”);

Метод mysql_real_escape_string() предупреждает вторжения в базу данных. Его следует использовать всегда, когда переменная содержит сведения из Интернета (разбора HTML) или введенные непосредственно пользователем (через формы). Оператор INSERT записывает в таблицу сообщение ($smstext), а также статус pending, означающий постановку сообщения в очередь на отправку. Следующим шагом будет запрос базы данных на наличие сообщений в очереди, и если таковые имеются – их отсылка. Этот код не отслеживает возможные ошибки, но вы можете позже добавить конструкции try/catch для обслуживания проблем с соединением и тому подобного. Сейчас же мы постараемся придерживаться краткого и лаконичного кода.

Ну вот, мы готовы использовать PHP для общения с Календарем Google. Для этого надо скачать и установить в поддиректорию минимальный Zend Framework. Также будем предполагать, что библиотеки Zend расположены в папке с именем Zend. Сперва загрузим некоторые классы Zend:


 // Gcal Hack: Загружаем нужные классы Zends 
 require_once ‘Zend/Loader.php’;
 Zend_Loader::loadClass(‘Zend_Gdata’);
 Zend_Loader::loadClass(‘Zend_Gdata_ClientLogin’);
 Zend_Loader::loadClass(‘Zend_Gdata_Calendar’);
 Zend_Loader::loadClass(‘Zend_Http_Client’);

Эти классы PHP хранятся в папке Zend_Gdata; они позволят нам выполнять аутенфикацию, создавать новые мероприятия и удалять существующие, просматривать их, а также многое другое. Для начала войдем в нашу учетную запись Календаря Google с помощью такого кода:

 // Подключаемся к сервису
 $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
 $user = ‘username’; // без ‘@gmail.com’ на конце
 $pass = ‘pa$$w0rd;
 $client = Zend_Gdata_ClientLogin::getHttpClient ($user,
 	 $pass, $gcal);

$client будет хранить объект Zend_Http_Client со всеми деталями текущей аутенфикации клиента.

Далее проверим, нет ли сообщений со статусом pending в нашей таблице sms, и получим их, используя SELECT. Если в очереди есть какие-либо сообщения, первое из них будет выбрано для отправки:

 // Создаем объект gcal
 $gcal = new Zend_Gdata_Calendar($client);
 // Получаем ожидающие события из таблицы sms
 $sql_sel_pending = “SELECT * FROM sms WHERE
 	 status=’pending’ LIMIT 0,1”;
 $result = mysql_query($sql_sel_pending);
 $row = mysql_fetch_array($result);
 if (!$row) die(“No pending event, exiting....<br>\n”);
 // Устанавливаем заголовок
 $title = $row[‘smstext’];
 print(“title:. $title .<br />\n”);

В этом коде $gcal – объект Zend_Gdata_Calendar, представляющий событие нашего календаря с полем title (название), временем начала/конца и всем прочим, что используется при планировании мероприятия. Порция кода PHP/MySQL получает текстовые сообщения из очереди оператором SELECT и обрабатывает результат с помощью функции mysql_fetch_array(), которая возвращает массив с соответствующими строками, а $title в результате будет хранить текст, который надо послать.

Играем со временем

Календарь Google обычно подразумевает установку напоминаний о событиях, которые произойдут в будущем. Чтобы обойти это и обеспечить отправку сообщений на ваш телефон в реальном времени, нужно взять текущее время и добавить к нему небольшой сдвиг, чтобы Google считал ваше событие фактом ближайшего будущего. Пара минут (120 секунд) будет в самый раз.

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

 // Задаем время
 date_default_timezone_set(‘UTC’);
 $safeTimeToWait = 120; // добавить секунд
 $now = time(); // секунд с 1/1/1970
 $smsSchedTime = $now + $safeTimeToWait;
 print (“sms scheduled sending time is:.
 date(“Y-m-d H:i”,$smsSchedTime) .<br />\n”);
 $sdate_yy = $edate_yy = date(“Y”,$smsSchedTime);
 $sdate_mm = $edate_mm = date(“m”,$smsSchedTime);
 $sdate_dd = $edate_dd = date(“d”,$smsSchedTime);
 $sdate_hh = $edate_hh = date(“H”,$smsSchedTime);
 $sdate_ii = $edate_ii = date(“i”,$smsSchedTime);
 $start = $end = date(DATE_ATOM, mktime($sdate_hh,
 	 $sdate_ii,
 	 0,
 	 $sdate_mm,
 	 $sdate_dd,
 	 $sdate_yy));

Самая важная переменная тут – это $smsSchedTime: она задает время отправки текстового сообщения. Она получается сложением текущего времени (возвращаемого функцией time()) и $safeTimeToWait.

Готовность к отправке

Оператор print затем покажет результирующее время отправки. Переменная $sdate_ содержит текущий год (yy), месяц (mm), день (dd), час (hh) и минуты (ii). Мы должны задать время начала равным времени окончания, потому что это не реальное мероприятие. Далее мы задаем событие как происходящее через две минуты в будущем и включаем текстовое напоминание:


 // Конструируем объект-событие
 $event = $gcal->newEventEntry();
 $event->title = $gcal->newTitle($title);
 $when = $gcal->newWhen();
 $when->startTime = $start;
 $when->endTime = $end;
 $event->when = array($when);
 // Настраиваем и включаем SMS-напоминание
 $minutes = 0;
 $method = “sms”;
 $reminder = $gcal->newReminder();
 $reminder->method = $method;
 $reminder->minutes = $minutes;
 $when = $event->when[0];
 $when->reminders = array($reminder);
 $gcal->insertEvent($event);
 print(“Gcal Event Added, user: $user<br />\n”);

Здесь создается объект $event, устанавливается title (телосообщения), затем загружаются времена startTime и endTime (эти две переменные одинаковы и хранят время отправки нашего «сейсмического» SMS). Вас не должно смущать $minutes = 0. Это означает, что мы не хотим получать напоминания от Google заранее. $method = «sms» задает способ, которым мы хотим быть проинформированы, а затем событие gcal вставляется в календарь при помощи $gcal->insertEvent($event). Наконец, изменим статус нашего сообщения с pending на sent в таблице sms:


 // Изменяем статус ‘field’ с pending -на -> sent
 $sql_update_status = “UPDATE sms
 	 SET status = ‘sent’
 	 WHERE smstext =$title’”;
 if (!mysql_query($sql_update_status,$con)) {
 print(‘Error:. mysql_error());
 } else {
 print(“sms: $title [status=sent]<br />\n”);
 }
 /** закрываем соединение с БД **/
 mysql_close($con);

Страница PHP теперь готова и может быть просмотрена он лайн на http://gcal-smsdemo.co.cc/smsdemo.php. Нам нужен кто-то или что-то, вызывающее созданную страницу. К счастью, Cron для этого идеально подходит! Настроим задание Cron на выполнение каждые 10 минут или около того (так как известно, что страница сейсмического института обновляется каждые несколько минут), и можно еще перенаправить стандартный вывод и стандартные ошибки в файл журнала. Запись crontab может выглядеть примерно так:

0,10,20,30,40,50 * * * * curl --silent --show-error --connect-timeout 30 --max-time 40 http://gcal-smsdemo.co.cc/smsdemo.php >> curl.log 2>&1

Параметры silent и show-error сделают вывод команды curl лаконичным, но более значимым в случае ошибок. Connect-timeout и max-time нужны на случай обычной опасности временного сбоя DNS, который может подвесить команду на неопределенный срок. Поэтому здесь, если что-то пойдет неправильно, мы просто прикроем команду через 30 секунд, если не будет ответа от web-страницы (упал сервер) или вся операция (полное время запуска PHP-страницы) занимает слишком долгое время (более 40 секунд).

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

Что нам надо: LAMP + Zend

Linux Apache MySQL PHP (LAMP) – это наиболее популярная серверная платформа. Установить сервер LAMP на вашем компьютере относительно просто (см. по ссылке http://ru.wikipedia.org/wiki/LAMP).Мы настоятельно рекомендуем сперва попробовать ее бесплатно в Интернете. Поищите слова «бесплатный хостинг LAMP».

Zend Framework – открытый объектно-ориентированный каркас приложений для PHP5. Для его использования на вашем LAMP-сервере скачайте минимальный пакет Zend, распакуйте его и загрузите папку /ZendFramework-1.9.7-minimal/library/Zend куда-нибудь в директорию /public_html на вашем web-сервере.

Персональные инструменты
купить
подписаться
Яндекс.Метрика