SlackのIncoming WebHooksを使って鍵の管理をするBotを作った

## 背景
鍵が開いているかどうかSlack上で把握できれば便利だと思ったので、作ってみた。
<img width="200" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279777698390212720/IMG_6271.png?ex=66d5ad5c&is=66d45bdc&hm=43636ceca81da76b4aad9140bcdd3382bbd6f52daf547a64f9f00625c830ae88&"><img width="400" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279775883204366338/IMG_6078.jpg?ex=66d5abab&is=66d45a2b&hm=8a8d4f06f16e42ec76ec48b2868ea48ef11950ea835df3148afaf7b0fb961c85&">


このシステムを作るにあたってこの方の記事を参考にさせていただきました。

https://qiita.com/ik-fib/items/b4a502d173a22b3947a0

:::note 
:::
## 環境
使用したマイコンはM5の[Atom Lite](https://www.switch-science.com/products/6262?srsltid=AfmBOorp0ACj9R8fXnj32094udGvYAHhdWHNiajKHXEP--L2-ANCtdCH)
開発環境はArduino IDE

## 作り方
Web版のSlackでbotを追加したいワークスペースにログインして、[ここ](https://w1721350570-fkd384638.slack.com/apps)のページの検索欄に"incoming webhook"と入力、一番上に出てくるアイコンをクリックする。
<img width="800" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279841609013268541/image.png?ex=66d5e8e1&is=66d49761&hm=8014eb726ffb7e5fb9706034ed13584ebcb4041f2aaabd8162d72390000224ac&">
Slackに追加をクリック
<img width="800" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279842256915927164/image.png?ex=66d5e97c&is=66d497fc&hm=1d4f3e6171f8126c24b212f05e5b83046e125b3b8a45e977c97c556251e78810&">
botを追加したいチャンネルを選択して「Incoming Webhookインテグレーションを追加」をクリックする。
バグなのか、チャンネルを選択するプルダウンメニューがうまく出てこないことがある。そういうときはブラウザの別のタブを開くと直る。
<img width="800" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279842257305866240/image.png?ex=66d5e97c&is=66d497fc&hm=094e1c78779627b9a1c24b026e63f94aaab46f1748148db9205d15bc6e25c338&">
<img width="800" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279840732550660219/image.png?ex=66d5e810&is=66d49690&hm=ff6fa91b7a4592f03493a3c2d4b312175cb566abc948185822d943e4674741d3&">
Webhook URLが表示されるページに遷移されるので、これをメモする。
このURLが第三者に漏れると勝手にメッセージを送信される恐れがあるので注意する。
<img width="800" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279844177940713514/image.png?ex=66d5eb46&is=66d499c6&hm=35c5842d1a82f13434534dc88cba2dab823a59faede00ed89743824727d98ac0&">
ソースコードの7行目にメモしたURLを書いておく。

HTTPのボディにJson形式の文字列を指定して送信するとbotがテキストを送信してくれる。
細かい仕様に関しては[参考にさせていただいた記事](https://qiita.com/ik-fib/items/b4a502d173a22b3947a0)に詳しく書いてある。

・大学のWi-Fiは長時間接続し続けられない仕様？があるのでボタンを押してからWi-Fiに接続するようにしてある。
## ソースコード
~~~sorcecode.ino
#include "M5Atom.h"
#include <HTTPClient.h>
#include <WiFi.h>

#define SSID "yourssid"
#define PASS "yourpw"
#define END_POINT "https://hooks.slack.com/services/example"//さっきメモしたURLをここに入力する

#define BUTTON_B 22
#define BUTTON_W 21

void rgbLED(uint8_t r, uint8_t g, uint8_t b);
void wifi_connect();
void post2server(String icon, String text);

void setup() {
  M5.begin(true, false, true);
  pinMode(BUTTON_B, INPUT);
  pinMode(BUTTON_W, INPUT);
  Serial.begin(115200);
}

void loop() {
  rgbLED(0, 0, 0);
  while(!digitalRead(BUTTON_B)){
    if(digitalRead(BUTTON_B)){
      wifi_connect();
      post2server("closed_lock_with_key", "鍵を閉めました:x:");
      delay(5000);
    }
  }
  while(!digitalRead(BUTTON_W)){
    if(digitalRead(BUTTON_W)){
      wifi_connect();
      post2server("unlock", "鍵を開けました:o:");
      delay(5000);
    }
  }
}

void rgbLED(uint8_t r, uint8_t g, uint8_t b){
  int rgb;
  rgb = (r << 16) + (g << 8) + b;
  M5.dis.drawpix(0, rgb);
}

void wifi_connect(){
  int icount = 0;
  rgbLED(255, 255, 0);

  WiFi.begin(SSID, PASS);

  while (WiFi.status() != WL_CONNECTED) {

    if(icount%2)rgbLED(0, 0, 0);
    else rgbLED(255, 255, 0);

    icount++;
    delay(500);
    if ( icount > 20 ) {                     
      ESP.restart();
      break;
    }
    
  }
  rgbLED(0, 0, 0);
}

void post2server(String icon, String text){
  HTTPClient http;

  if ((WiFi.status() == WL_CONNECTED)) {

    http.begin(END_POINT);

    // start connection and send HTTP header and body
    http.addHeader("Content-Type", "application/json;charset=utf-8");
    String send_data = String("{\"icon_emoji\": \":" + icon + ":\",\"text\": \"" + text + "\"}");
    int httpCode = http.POST(send_data);

    if (httpCode > 0) {
      if(httpCode >= 400) {
        rgbLED(255, 0, 0);
        Serial.print("通信エラー:post2server,httpCode ->");
        Serial.println(httpCode);
      }
      if (httpCode == HTTP_CODE_OK) {
        const String& payload = http.getString();
        if(payload == "ok"){
          rgbLED(0, 255, 0);
          Serial.println("送信成功");
        }else{
          rgbLED(255, 0, 0);
          Serial.println("送信失敗");
        }
      }
    }else {
        rgbLED(255, 0, 0);
        Serial.print("通信エラー:post2server,httpCode ->");
        Serial.println(httpCode);
    }

    http.end();
  }else{
    rgbLED(255, 0, 0);
    Serial.println("通信エラー:インターネットの接続がありません。");
  }
}

~~~

## 回路図
<img width="420" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279775882713759857/IMG_6112.jpg?ex=66d5abab&is=66d45a2b&hm=3d480be35adca3a810d79c23433a5b6495e29b8b7f89f968581af41a896fb044&"><img width="600" src="https://cdn.discordapp.com/attachments/1155481204733247530/1279837689784569917/IMG_1539.png?ex=66d5e53b&is=66d493bb&hm=a4004cf0c3abc1644ee6802cc0072966dbe26c0e9bab1788b64f62ca8dcc4b3d&">
G22、G21はAtom LiteのGPIO22、21に接続することを表しています。