Pull to refresh

СМС-термометр из связки Google script, Google Doc, Wolfram-Alpha и Sms.ru

Reading time6 min
Views6.4K
Всем привет!
Захотел сделать так, чтобы на мой простенький телефон по утрам приходили оповещения о текущей погоде (разумеется, бесплатно). Потому, что нет обычного термометра, из-за этого насколько тепло нужно одеваться, понятно не всегда.
Кому интересно, как я это реализовал – добро пожаловать под кат.

Поискав что-то подобное на хабре, я наткнулся вот на эту статью за авторством bakatrouble, откуда узнал про сервис sms.ru, про Google script и прочее, за что отдельное спасибо.
Информацию о погоде решил получать с Wolfram-Alpha. Почему вольфрам-альфа? В своё время меня покорила строчка «данные взяты с метеостанции Баландино, 119 км от центра Златоуста». Поэтому мне хотелось брать информацию именно с этого сайта.

Итак, для начала нам нужно завести (если нет) аккаунт на Google, а так же зарегистрироваться на сервисе Sms.ru (если, опять же, нет). Сервис Sms.ru предоставляет на момент написания статьи 5 бесплатных сообщений на свой номер (на их сайте написано «для программистов»).

После успешной регистрации, переходим на гугл-диск (drive.google.com) и создаём новый пустой документ. Даём ему имя и ждём, пока он сохранится на диске.
Теперь переходим на script.google.com, выбираем Blank Project. Даём будущему скрипту какое-нибудь имя (скрипт также сохранится на гугл-диске). Удаляем всё, что там есть.
Теперь вставляем следующий код:

Код скрипта
function responseWeather()
{
//Здесь вписывается: город, телефонный номер для доставки SMS, уникальный ID с sms.ru, код документа Google
 var cityTown= "zlatoust";
 var phoneNum="71111111111";
 var apiID="111111111111111111111111111111111111";
 var docID="11111111111111111111111111111111111111111111";

//Открываем документ, в который будем записывать ответ с вольфрама 
 var serverAv = false;
 while (serverAv == false){
  try {
  DocumentApp.openById(docID);
  serverAv=true;
  } catch (e) {
 Logger.log('Ошибка открытия');
  }
 }
 var docmain = DocumentApp.openById(docID);
 var bodydoc = docmain.getBody();
 bodydoc.clear();//На всякий случай очищаем содержимое
 var response = UrlFetchApp.fetch("http://www.wolframalpha.com/input/?i="+cityTown+"+weather");
 bodydoc.setText(response);
 var textEdit = bodydoc.editAsText();
 textEdit.deleteText(0, 37280); //Удаляем начало документа, оно нам не нужно

/*
 При отладке температура выдаётся в Цельсиях.
 При запуске автоматом от триггера - в Фаренгейтах.
 Аналогично со скоростью ветра - m\s и mph соотв.
 Отмечаем, что будем конвертировать.
*/
 if (textEdit.findText('°C')!=null){
 var degree = '°C';
 var convert = false;
  } else {
 degree = '°F';
 convert = true;
 }
// Находим всю нужную информацию
 textEdit.deleteText(0, textEdit.findText(degree).getStartOffset()-5); 
 textEdit.replaceText('</span><span class="info"><dt></dt><dd class="conditions">', ', ');
 textEdit.replaceText('</dd><dt>', '; ');
 textEdit.replaceText('wind:</dt><dd>', 'wind: ');
 textEdit.replaceText('<span> at </span>', ' at ');
 textEdit.replaceText('humidity:</dt><dd>', 'hum.: ');
 textEdit.deleteText(textEdit.findText("%").getEndOffsetInclusive()+1, textEdit.findText('"  />').getEndOffsetInclusive());
 textEdit.replaceText('<span  class="high">', ' (buf');
 textEdit.replaceText('</span><span class="low">', '...fub'); 
 textEdit.replaceText("</span>", ")</span>");
 textEdit.deleteText(textEdit.findText("</span>").getStartOffset(), textEdit.getText().length-1);

//В начале для метки оставалось несколько символов - теперь они больше не нужны, удаляем
 if (textEdit.findText('>')!=null){
   textEdit.deleteText(0, textEdit.findText('>').getEndOffsetInclusive());
 }
 
//Конвертация
 if (convert==true){
 //Конвертация первого значения температуры
 var buffer1 = textEdit.getText();
 textEdit.deleteText(textEdit.findText(degree).getStartOffset(), textEdit.getText().length-1);
 var len = textEdit.getText().length-1;
 var buffer2 = Number(textEdit.getText());
 bodydoc.clear();
 var result = Math.round((buffer2-32)/1.8);
 textEdit.setText(buffer1);
 textEdit.deleteText(0, len);
 textEdit.insertText(0, result);
 //Конвертация второго значения температуры
 buffer1 = textEdit.getText();
 textEdit.deleteText(0, textEdit.findText("buf").getEndOffsetInclusive());
 textEdit.deleteText(textEdit.findText(degree).getStartOffset(), textEdit.getText().length-1);
 len = textEdit.getText().length-1;
 buffer2 = Number(textEdit.getText());
 bodydoc.clear();
 result = Math.round((buffer2-32)/1.8);
 textEdit.setText(buffer1);
 textEdit.deleteText(textEdit.findText("buf").getEndOffsetInclusive()+1, textEdit.findText("buf").getEndOffsetInclusive()+1+len);
 textEdit.insertText(textEdit.findText("buf").getEndOffsetInclusive()+1, result);
 //Конвертация третьего значения температуры
 buffer1 = textEdit.getText();
 textEdit.deleteText(0, textEdit.findText('fub').getEndOffsetInclusive());
 textEdit.deleteText(textEdit.findText(degree).getStartOffset(), textEdit.getText().length-1);
 len = textEdit.getText().length-1;
 buffer2 = Number(textEdit.getText());
 bodydoc.clear();
 result = Math.round((buffer2-32)/1.8);
 textEdit.setText(buffer1);
 textEdit.deleteText(textEdit.findText('fub').getEndOffsetInclusive()+1,textEdit.findText('fub').getEndOffsetInclusive()+1+len);
 textEdit.insertText(textEdit.findText('fub').getEndOffsetInclusive()+1, result);
 //Конвертация скоррости ветра
 buffer1 = textEdit.getText();
 textEdit.deleteText(0, textEdit.findText('at ').getEndOffsetInclusive());
 textEdit.deleteText(textEdit.findText('mph').getStartOffset(), textEdit.getText().length-1);
 len = textEdit.getText().length-1;
 buffer2 = Number(textEdit.getText());
 bodydoc.clear();
 result = Math.round(buffer2*0.44704);
 textEdit.setText(buffer1);
 textEdit.deleteText(textEdit.findText('at ').getEndOffsetInclusive()+1,textEdit.findText('at ').getEndOffsetInclusive()+1+len);
 textEdit.insertText(textEdit.findText('at ').getEndOffsetInclusive()+1, result);
 textEdit.replaceText('mph', 'm/s');
};
 //Подчищаем...
 textEdit.replaceText('buf', '');
 textEdit.replaceText('fub', '');
 textEdit.replaceText(degree, "*C");
 
 //Дописываем в конец для какого города
 textEdit.insertText(textEdit.getText().length, '  '+cityTown);
  
//Если вдруг текст будет больше одного сообщения, то удаляем концовку
 if (textEdit.getText().length>70){
 textEdit.deleteText(69, textEdit.getText().length-1);
 }
 var textSMS = bodydoc.getText();

 UrlFetchApp.fetch("http://sms.ru/sms/send?api_id="+apiID+"&to="+phoneNum+"&text="+encodeURI(textSMS));
 bodydoc.clear();
}




Вставляете в соответствующие переменные необходимые данные.
Переменная cityTown – город транслитом, для которого хотите получать погоду; phoneNum – номер, который вы зарегистрировали на Sms.ru и, соответственно, на который будут отправляться бесплатные СМС (без плюса и каких-либо разделителей); apiID – уникальный идентификатор для сервиса Sms.ru, смотреть на соответствующем сайте:


docID – уникальный идентификатор документа (не скрипта!) на гугл-диске. Найти можно в адресной строке:


После того, как все необходимые переменные заполнены, запускаем скрипт. При первом запуске скрипт запросит разрешение на работу с ссылками и документами на гугл-диске. Разрешаем всё. Скрипт должен отработать, и на телефон придёт сообщение.
Теперь осталось задать автоматический запуск. Для этого нажимаем на значок (1), выбираем необходимый интервал (2).



Так как мне нужно было знать погоду рано утром перед выходом на работу, я выставил таймер на 7 часов утра. Для себя я ещё выставил оповещения на почту в случае ошибки отработки кода – в интервале «незамедлительно».
Сохраняем триггер. Теперь всё готово, каждое утро будет приходить сообщение о текущей погоде.

Несколько замечаний по поводу кода. Я знаю javascript поверхностно, а google-script ещё меньше – поэтому, если есть какие-то замечания по оптимизации, буду рад узнать. По поводу конвертации из Фаренгейта в Цельсий. Видимо, Вольфраму передаются данные о местоположении запроса, и он подстраивает выводимые данные под регион. Поэтому, когда отладка скрипта идёт в онлайн-режиме (при запуске вручную), гугл передаёт, что я из России, а Вольфрам отвечает Цельсием и метрами в секунду. При запуске от триггера – Гугл говорит, что я в Калифорнии, из-за чего Вольфрам выдаёт Фаренгейты и мили в час.

На будущее я планирую ещё сделать запрос погоды через MMS – отправкой сообщения на почтовый ящик с текстом «город погода» и получением ответного сообщения. Может быть, спорное решение, просто у меня подключен давнишний пакет и MMS не особо дорогие.

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

UPD 03.11.14: Немного подправил скрипт, неправильно работала петля проверки доступности Google Doc (иногда возвращает ошибку при открытии документа). Теперь всё должно работать стабильнее.

UPD 22.11.14: При выставлении времени триггера учтите, какой часовой пояс использует Google. Например, у меня до перевода часов, Google выдавал часовой пояс, совпадающий с моим (+6). Потом для интереса я удалил этот триггер и выставил по-новому. В этот раз мне выдали другой часовой пояс, поэтому пришлось выставлять время в соответствии с ним. В моём случае запуск с 6 до 7 утра превратился с 5 до 6 вечера.


Так что будте внимательны.
Tags:
Hubs:
-1
Comments7

Articles

Change theme settings