Help us understand the problem. What is going on with this article?

esp8266でSlackBotを作ってIFTTTからのメッセージを待ち受けする

More than 1 year has passed since last update.

esp8266のSlackBotをIFTTT経由で操作する

背景

GoogleHomeからesp8266を制御しようとしたときに、IFTTT-Slack経由が一番ラクにできそうだったのでトライしてみた。

用意するもの

esp8266(WROOM02)

参考サイトをみてSlackBotをつくる

Arduino(ESP8266)にSlack Botを乗せてみた

ちょっとだけトラブル発生

参考サイト通りにやると人間の投稿には反応できるけど、IFTTTからのメッセージには反応してくれない。
シリアルログをみるとIFTTTからのメッセージは添付扱いになっているため、すこし階層が深くなっている模様。

対策版

かなりやっつけだけど「root["attachments"][0]["pretext"]」でIFTTTからのメッセージを参照できた。
ソースコードは以下。

// https://github.com/urish/arduino-slack-bot

#include <Arduino.h>
#include <Hash.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>
#include <Servo.h>

#define WIFI_SSID "あなたのSSID"
#define WIFI_PASSWORD "あなたのWIFIパスワード"

#define SLACK_SSL_FINGERPRINT "AC 95 5A 58 B8 4E 0B CD B3 97 D2 88 68 F5 CA C1 0A 81 E3 6E" // If Slack changes their SSL fingerprint, you would need to update this
#define SLACK_BOT_TOKEN "スラックボットのTOKEN"
#define DEFAULT_CHANNEL "チャンネルID?"

ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;

long nextCmdId = 1;
bool connected = false;
bool helloSaid = false;

void webSocketEvent(WStype_t type, uint8_t *payload, size_t len) {
  switch (type) {
    case WStype_DISCONNECTED:
      Serial.printf("[WebSocket] Disconnected :-( \n");
      connected = false;
      break;

    case WStype_CONNECTED:
      Serial.printf("[WebSocket] Connected to: %s\n", payload);
      break;

    case WStype_TEXT:
      Serial.printf("[WebSocket] Message: %s\n", payload);
      processSlackMessage((char*)payload);
      break;
  }
}

void processSlackMessage(char *payload) {
  StaticJsonBuffer<2000> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(payload);
  if (!root.success()) {
    Serial.println("[Json] Parse failed");
    return;
  }

  if(root.containsKey("type")) {
    if(strcmp("hello", root["type"]) == 0) {
      helloSaid = true;
    } else if (strcmp("message", root["type"]) == 0) {
      if(root.containsKey("attachments")) {
        if(strcmp("IFTTT経由メッセージのキーワード", root["attachments"][0]["pretext"]) == 0) {
          // キーワードを見つけたときの処理
        }
      }else if(root.containsKey("text")) {
        if(strcmp("通常メッセージのキーワード", root["text"]) == 0) {
          // キーワードを見つけたときの処理
        }
      }
    }
  }
}

bool connectToSlack() {
  // Step 1: Find WebSocket address via RTM API (https://api.slack.com/methods/rtm.start)
  HTTPClient http;
  http.begin("https://slack.com/api/rtm.start?token=" SLACK_BOT_TOKEN, SLACK_SSL_FINGERPRINT);
  int httpCode = http.GET();
  if (httpCode != HTTP_CODE_OK) {
    Serial.printf("HTTP GET failed with code %d\n", httpCode);
    return false;
  }

  WiFiClient *client = http.getStreamPtr();
  client->find("wss:\\/\\/");
  String host = client->readStringUntil('\\');
  String path = client->readStringUntil('"');
  path.replace("\\/", "/");

  // Step 2: Open WebSocket connection and register event handler
  Serial.println("WebSocket Host=" + host + " Path=" + path);
  webSocket.beginSSL(host, 443, path, "", "");
  webSocket.onEvent(webSocketEvent);

  return true;
}

void sendPing() {
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["type"] = "ping";
  root["id"] = nextCmdId++;
  String json;
  root.printTo(json);
  webSocket.sendTXT(json);
}

void sendMessage() {
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["type"] = "message";
  root["channel"] = DEFAULT_CHANNEL;
  root["text"] = "fuga";
  String json;
  root.printTo(json);
  webSocket.sendTXT(json);
}

void setup() {
  servo.attach(servoPin);
  servo.write(angle);
  Serial.begin(9600);
  while (!Serial) {
    delay(100);
  }
  Serial.setDebugOutput(true);

  WiFiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);
  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(100);
  }

  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
}

unsigned long lastPing = 0;

void loop() {
  webSocket.loop();

  if (connected) {
    // Send ping every 5 seconds, to keep the connection alive
    if (millis() - lastPing > 5000) {
      if(helloSaid) {
        sendPing();
      }
      lastPing = millis();
    }
  } else {
    // Try to connect / reconnect to slack
    connected = connectToSlack();
    if (!connected) {
      delay(3000);
    }
    lastPing = millis();
  }
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした