LXF132:google

Материал из Linuxformat.

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

Содержание

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

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

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

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

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

На странице Настройка для мобильных устройств Календаря Google проверьте, поддерживает ли текстовые оповещения ваш мобильный оператор.

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

Используйте первый выпадающий список для указания способа получения напоминания, а поле и список правее позволят сообщить, когда вы хотите получить его. Для целей тестирования мы выберем отправку 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:

Скорая помощь

Календарь Google записывает в текстовое сообщение только название события, длиной не более 60 символов. Остальное место используется для имени календаря, даты и времени начала/окончания события.

// 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:

Скорая помощь

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

// Изменяем статус ‘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-сервере.

Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию