Мне телеграмма

38760b59acef4b9a8e66b9687f81ed2f.png
Как помнит внимательный читатель, у меня дома живет контроллер, который автоматизирует некоторые банальные процессы вроде мигания светом, что, без сомнения, и положено всякому контроллеру на основе Arduino.

Но проблема не в этом. А в том, что уведомления о различных событиях я выбрал получать по электронной почте, потому что так было проще всего в самом начале. Теперь же я замучился периодически выгребать кучу статусов из почтового ящика (это необязательно, но для порядка надо), и подумал, что раз есть такой прекрасный Telegram, то почему бы не воспользоваться его талантами в своих целях.

Далее приводятся мои экзистенциальные переживания на тему скрещивания PushingBox, IFTTT и Telegram синей изолентой для получения малобюджетной (и столь же малоумной) системы уведомлений.

TL/DR

Дорогие друзья! Нет, у меня нет домашнего сервера. И нет, я не планирую ставить сервер для обслуживания системы уведомлений Arduino Uno. Только если совсем прижмет.

Для начала пара слов о предыдущей конфигурации. В далекие времена, в одном из рукавов далекой-далекой галактики бесплатные почтовые сервера разрешали отправлять почту через SMTP по HTTP. То есть, с этой задачей достаточно легко справлялась плата Arduino Uno в дуэте с Ethernet-шилдом.

Потом все дружно перешли на HTTPS/SSL (надеюсь, я правильно излагаю) и пришлось изобретать что-то другое, так как в HTTPS Arduino Uno уже не умеет. Выходом из положения стал сервис уведомлений PushingBox, который получает от Arduino Uno обычный HTTP-запрос, а его параметры использует для отправки письма-уведомления (отправлять письма PushingBox умеет сам).

К слову, эта штука мне понравилась даже больше — работает гораздо быстрее общения с POP/SMTP-сервером.

Что еще лучше, PushingBox умеет выполнять и HTTPS-запросы. И, следовательно, дружит с современными веб-сервисами. Собственно, я уже размышлял на тему, что, наверное, надо сделать своего Telegram-бота и попробовать подружить его с PushingBox, как вдруг увидел, что Telegram уже успешно работает с сервисом автоматизации IFTTT.

И тут я не устоял. Дело в том, что IFTTT настолько же для меня интересен, насколько и бесполезен. Т.е. 99.9% его возможностей мне просто негде применять: в соцсетях неактивен, смартлампочки не покупаю, скучная, словом, личность.

Так что решил, конечно, дать IFTTT шанс.

Для произвольных взаимодействий с внешним миром у IFTTT есть сервис Maker, который умеет отправлять и принимать HTTP-запросы. Для решаемой задачи, разумеется, более актуально второе.

Далее, для работы с Telegram у IFTTT есть вообще специализированный сервис, который позволяет отправлять в чат или группу сообщения, картинки, музыку. Самое главное для меня — возможность отправки сообщения в приватный чат. Мне ведь не нужно, чтобы статусы читал совсем уж кто угодно.

Остается только все связать:

Arduino → PushingBox → IFTTT → Telegram.

Отправка запроса с уведомлением в PushingBox лично у меня выглядит примерно так (статусов, конечно, больше и, конечно, добавлена инициализация Ethernet):

#include 
#include  // для PROGMEM

char servermail[] = "api.pushingbox.com"; // PushingBox

// строки состояния в PROGMEM
const char statusString_0[] PROGMEM = "Room_softlight_ON";
const char statusString_1[] PROGMEM = "Kitchen_softlight_ON";
const char statusString_2[] PROGMEM = "Humidifier_ON";

// табличка указателей на строки состояния
PROGMEM const char * const statusString[] =
{
  statusString_0,
  statusString_1,
  statusString_2,
};

char statusStringBuf[40];    // буфер для чтения строк состояния

void sendMail(byte statusStringN) {

  mail.stop();
  if (mail.connect(servermail, 80)) {
    strcpy_P(statusStringBuf, (char*)pgm_read_word(&(statusString[statusStringN])));
    mail.print("GET /pushingbox?devid=КЛЮЧ_PUSHINGBOX&status=");
    mail.print(statusStringBuf);
    mail.println(" HTTP/1.1");
    mail.print("Host: ");
    mail.println(servermail);
    mail.println("User-Agent: Arduino");
    mail.println();
  }
  delay(1000);
  mail.stop();
}


Как легко видеть, уведомление передается в параметре &status, которым затем следует манипулировать в пределах PushingBox. Для этого сначала щелкаем My Services и добавляем сервис Custom URL с необходимыми параметрами (они указаны в агитке IFTTT) и запоминающимся именем.

Раз:

d8991ab132374d6684d065e56945bfd8.jpg

Два:

ccce3f082e8c411fb8cc00fb965a7f02.jpg

Три:

3c1b684313514c39b1832c03de4bbd65.jpg

Потом нужно добавить сценарий, который будет использовать данный сервис. И вот здесь как раз пригодится содержание параметра &status, которое в PushingBox присваивается почти одноименной переменной $status$. Вообще, любой параметр, передаваемый в PushingBox трансформируется в одноименную переменную, окаймленную значками нашего бакса.

362c4a9d74b7465aa4123bee682c4dff.jpg

Итак, щелчок по My Scenarios, где после ввода имени нужно добавить действие. Для действия, связанного с IFTTT понадобится знать ключ авторизации, который отображается на страничке настроек сервиса Maker в IFTTT (нужно войти и/или зарегистрироваться в IFTTT, чтобы увидеть):

9c09a595a35b4367b8e2ed1bd5f9cdcd.jpg

Так вот, после нажатия Add an Action, следует выбрать сервис типа Custom URL созданный в PushingBox ранее, а в параметре Data указать остаток строки, который должен передаваться IFTTT для срабатывания условия.

26fa8627034d4efe8f3ad2788c13a37f.jpg

Например, согласно инструкции IFTTT, запрос должен выглядеть так:

https://maker.ifttt.com/trigger/{event}/with/key/ключ_авторизации

Из этого уже (при добавлении сервиса) в PushingBox есть maker.ifttt.com/trigger, поэтому остается добавить событие {event} и завершающую часть с ключом авторизации.

Так что в упомянутое выше поле Data смело прописывается следующая комбинация символов:

$status$/with/key/ключ_авторизации

Повторюсь еще раз, в данном случае $status$ не что-то незыблемое. Ваша переменная может называться как угодно. Но в рамках данного примера я буду придерживаться этой терминологии.

Итак, PushingBox и IFTTT связаны. Осталось привязаться к Telegram, и тут начинается тягомотина. Дело в том, что IFTTT (в отличие от PushingBox) реагирует на конкретные условия и выполняет конкретные действия. Ему нельзя сказать передавать все входящие запросы, подходящие под условия, сразу в Telegram.

Нет, нужно на каждое условие добавлять правило обработки. Поэтому описанную ниже процедуру придется повторить по количеству нужных уведомлений.

Так что переходим в IFTTT:

1) Добавляем новый апплет с сервисом Maker — Receive a web request

8c243e21e29948feb34ce433236dbed2.jpg

20eed0423a5b411e934537de9ac4f171.jpg

1398d63e38bc4c13acf534d60b0e4afe.jpg

2) В поле Event name указываем параметр, который передается через переменную $status$ из PushingBox. В моем случае, это, к примеру, может быть Humidifier_ON (или Intercom_unarmed). С точностью до буквы и регистра.

b2251f7ae1a94c09a1ed26be45cb4ae4.jpg

2254f587a3834edf962156bab3608b33.jpg

3) Нажимаем Create trigger и выбираем сервис Telegram для действия по срабатыванию условия. При первом использовании сервиса нужно будет авторизовать бота IFTTT, но это не проблема.

Авторизация:

4dbae1ff7c214e739f0c280f09eeaf15.png

Выбор сервиса:

13fb62853aa54dbb9b2d6c8823de3f2b.jpg

4) В качестве действия — Send message. Здесь уже будут заданы параметры по умолчанию — адрес (чат или группа) и предварительно отформатированное сообщение. Если сообщение вас устраивает — можете пользоваться им или собрать из модификаторов что-то свое. Я же вообще заменил весь текст на более понятное объяснение произошедшего.

d63a9a1a6f324ffb9f0e20383295100d.jpg

64c8bea9866544238a28a6058ec0714b.jpg

Т.е. вместо, скажем,


What: {{EventName}}
When: {{OccurredAt}}
Extra Data: {{Value1}}, {{Value2}}, {{Value3}},

В случае с Humidifier_ON написал «Увлажнитель включен» (а в случае с домофоном, как на скриншоте — «Домофон: разблокирован»). Именно это сообщение я получу от бота IFTTT при срабатывании указанного условия.

22e89dd3ff7b4119bd7b108b1aedb8d4.jpg

Готово:

723ef72a9f084e6b98ff770c5cbe1d3a.jpg

И все эти мучения только для того, чтобы в конце концов увидеть:

c25c4b5a1d2140c59a69cb5069767210.png

Нет, я не спорю. Можно было бы заменить уже Arduino на что-то более продвинутое. Или прикрутить туда ESP8266, для которого уже есть библиотека TelegramBot, которая позволяет отправлять сообщения в Telegram напрямую, без посредников вроде PushingBox или IFTTT.

Возможно, я именно это и сделаю, если PushingBox и IFTTT исчезнут, как AltaVista и Yahoo!… Но пока что моя позиция незыблема: мне проще написать несколько строк кода или сконфигурировать софт, чем брать в руки паяльник.

Простите.

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

© Geektimes