Slack bot na ESP8266
W pracy często zamawiamy sobie kebaba na obiad. Kiedy w końcu na recepcję dostawca przywiezie upragnione jedzenie trzeba jakoś powiadomić wszystkich, że kebaby dojechały :P Jak to mówią potrzeba jest matką wynalazków – tak właśnie powstał kebabowy przycisk wysyłający powiadomienie na Slacku :)
Tworzymy aplikację
Aby utworzyć aplikację należy wejść na stronę https://api.slack.com/, a następnie wcisnąć przycisk „Start Building”, a następnie „Create New App”.
W okienku podajemy nazwę bota oraz workspace, do którego chcemy dodać aplikację.
Teraz dodajemy odpowiednie funckjonalności. My chcemy tylko wysyłać wiadomość na kanał, więc wystarczy nam feature o nazwie „Incoming webhooks”. W okienku tworzenia takiego webhooka musimy podać kanał na który będą postowane wiadomości:
Po utworzeniu webhooka dostaniemy jego adres URL, dzięki czemu możemy przetestować jego działanie za pomocą Postmana.
Do postmana importujemy następujący CURL:
curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' URL_DO_WEBHOOKA
Implementacja w ESP8266
Podłączenie
Ja podłączyłem sobie przycisk łączący piny GND oraz D6 (akurat tak pasował :P) + rezystor podciągający 10K pomiędzy pinami D6, a 3V3.
Kod programu
Do implementacji bota wykorzystamy bibliotekę ESP8266HTTPClient (standardowo dołączoną do SDK NodeMCU dla Arduino).
#include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h>
ustalamy pin, do którego podłączony jest przycisk:
#define BUTTON_PIN D6
teraz dodajemy kilka przydatnych stałych:
const char* host = "hooks.slack.com"; const char* fingerprint = "C1 0D 53 49 D2 3E E5 2B A2 61 D5 9E 6F 99 0D 3D FD 8B B2 B3"; const char *ssid = "Nazwa sieci WiFi"; const char *password = "Hasło sieci WiFi"; const char* webhookUrl = "/services/TUTAJ/KLUCZE/API";
poza standardowymi ssid i password ważnymi polami są fingerprint oraz webhookUrl. W webhookUrl podajemy adres URL na jaki ma zostać wysłane zapytanie. Znajdziemy go w sekcji „Incoming webhooks” w ustawieniach aplikacji na samym dole. WAŻNE: Nie podajemy w nim części hosta, czyli https://hooks.slack.com.
Bardzo ważnym parametrem jest fingerprint. Niestery NodeMCU słabo radzi sobie z połączeniami SSL, dlatego też musimy mu podać ręcznie jaki jest fingerprint certyfikatu SSL używanego przez hosta z którym chcemy się połączyć. Taki fingerprint możemy odczytać np. na stronie https://www.grc.com/fingerprints.htm podając w okienku adres hooks.slack.com. Z wyniku musimy usunąć dwukropki i zastąpić je spacjami.
W funkcji setup() standardowo łączymy się z wifi i ustawiamy piny:
void setup() {
Serial.begin(9600);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("Polaczono z WiFi");
pinMode(BUTTON_PIN, INPUT);
}
W funkcji loop jedyną rzeczą, której potrzebujemy jest nasłuchiwanie wciśnięcia przycisku kebabowego:
void loop() {
if(!digitalRead(BUTTON_PIN)) {
sendMessageToAll("Kebaby :)");
}
}
Teraz czas na funkcję sendMessageToAll, która wyśle wiadomość na kanał:
void sendMessageToAll(String message) {
HTTPClient https;
Serial.println("[HTTPS] Wysylanie wiadomosci...");
if(https.begin(host, 443, webhookUrl, true, fingerprint)) {
https.addHeader("Content-Type", "application/json");
Serial.print("[HTTPS] POST...\n");
int httpCode = https.POST("{\"text\":\"<!channel> " + message + "\"}");
if (httpCode > 0) {
Serial.printf("[HTTPS] POST... kod odp.: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = https.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTPS] POST... blad: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
} else {
Serial.printf("[HTTPS] Blad polaczenia\n");
}
}
Są tu 3 ważne wysołania:
https.begin, https.addHeader oraz https.POST.
Pierwsza z nich inicjuje połączenie. Podajemy w niej hosta, port serwera, url, czy request będzie HTTPS? oraz fingerprint certyfikatu.
Kolejna dodaje nagłówek. W naszym przypadku jest to nagłówek „Content-type” z wartością „application/json”, który oznacza, że wysyłamy dane JSONem.
Ostatnia wykonuje zapytanie typu POST na danym połączeniu. Jako parametr przyjmuje zawartość zapytania. W tym momencie serwer zwraca nam odpowiedź, którą logujemy na port szeregowy. Jeżeli kod odpowiedzi HTTP to 200, a wiadomość ok, to na naszym kanale powinna pojawić się nowa wiadomość.
PS. W naszym przypadku mamy małego JSONa i możemy go wysłać jako zahardcodowany string, ale jeżeli potrzebujemy przesłać jakąś większą strukturę danych warto zapoznać się z biblioteką ArduinoJson.



