- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
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:
Календарь 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-сервере.