ESP32からLINE Notifyに通知を投げる手順の備忘録

先日、「[ニューノーマルにカラオケをハックせよ Sponsored by JOYSOUND #protoout](https://protoout.connpass.com/event/191371/)」というハッカソンが行われ、そこに参加してきました。
その際に作成したシステムを参考に、ESP32からLINE Notifyに通知を投げてみましたので、その備忘録を残しておきます。
（よくある仕組みなので、ほかの記事等Web上にやたら転がっている内容です）

# 当日作成したシステム
当日作成したのは、超音波距離センサーで距離を測り、一定値より近ければobnizからLINE Notifyに通知を飛ばすというものでした。
[カラオケでもソーシャルディスタンス](https://protopedia.net/prototype/1960)

こちらは一緒のチームの方のところにセンサー＆マイコンがあったのですが、私のところには無かったので、あるもので作り変えてみました。

# 材料
- 開発用PC
- USBケーブル（PC－ESP32開発ボードの接続）
- ESP32開発ボード
- ブレッドボード
- ケーブル（オス－オス、3本）
- ボタン（Grove）　※4ピンケーブルも

obnizがESP32開発ボードに、超音波距離センサーがボタンに変更になっています。
また、ESP32開発ボードとボタンを無理やり接続しています。

# 接続
ESP32開発ボードをブレッドボードに刺し、ボタンと接続します。

- 電圧：3.3Vか5V
- GND
- デジタル信号：IO4に接続
![DSC_0005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/1cbcf280-2fd8-0015-7eff-3fa0ef544a24.jpeg)

# LINE側の設定
こちらの情報はそこらじゅうにありますが、画像が載っていてわかりやすいのは[こちら](https://www.smilevision.co.jp/blog/tsukatte01/)かも。
※写真を撮るために新たに設定しなおすとトークンが変わっちゃうから、ここでは画像は無しです

1. [LINE Notify](https://notify-bot.line.me/ja/)にログイン
2. 「マイページ」を選択
3. 「トークンを発行する」を選択
4. 「トークン名」を入力<br/>ここで入力した名前が、飛んでくるメッセージの先頭に[xxxx]と表示されます
5. 通知の送信先を選択<br/>自分だけでよければ「1:1でLINE Notifyから通知を受け取る」を選択し、グループの場合はそのグループを選択（事前に作成する必要あり）
6. 「発行する」ボタンを選択
7. 発行されたトークンをメモっておく<br/>後で使いますので、絶対に忘れないように（後から確認できません）

# Arduino側のプログラム
こちらはスケッチの「WiFiClientSecure」をベースにします。

## CAの削除
今回は証明書を使わないため、ばっさり証明書関連のコードを削除します。
以下、削除する部分。

```c
const char* test_root_ca= \
（省略）
     "-----END CERTIFICATE-----\n";
```

```c
  client.setCACert(test_root_ca);
```

## Wi-Fiの設定
アクセスポイントのSSIDとパスワードを設定します。
それぞれの環境に合わせて、修正してください。

```c
const char* ssid     = "my-ssid";     // change
const char* password = "my-password"; // change
```

## LINE Notify関連の設定
まず、LINE NotifY関連の変数を用意します。

```c
const char* host = "notify-api.line.me";
const char* token = "my-line-notify-token"; // change
```

元のソースでは「server」となっているところを「host」に書き換えています。
また、トークンは、先ほどメモっておいたものに書き換えてください。

## センサー関連の設定
今回は、ボタンを押したら通知が飛ぶようにします。
まずピン番号を指定します。今回は4ピンに接続しています。

```c
#define BUTTON_PIN 4
```

さらに、ボタンを押したときに送られるメッセージを設定しておきます。

```c
const char* message = "Push!";
```

また、1回ボタンを押すと大量に通知が飛んでしまうため、制御のためのフラグを用意しておきます。

```c
static int Status = LOW;
```

そして初期化時に、PINの初期化を行います。

```c
  pinMode(BUTTON_PIN, INPUT);
```

## ループ内での処理
ループ内では、大きくは以下のような処理を行います。

1. ボタンのステータスを取得
2. 前回ボタンが押されていなかった、かつ、今回ボタンが押されたら、LINE Notifyに通知を送る
3. ボタンのステータスを保存

LINE NotifyへはWeb APIで直接通知を送ります。
結果を受け取る際、ヘッダ部分を本体部分に分けて受け取っています。
受け取った内容は、シリアルモニタで確認できます。

```c
  int buttonState = digitalRead(BUTTON_PIN);

  if ((Status == LOW) && (buttonState == HIGH)) {
    String query = String("message=") + String(message);
    String request = String("") +
                 "POST /api/notify HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Authorization: Bearer " + token + "\r\n" +
                 "Content-Length: " + String(query.length()) +  "\r\n" + 
                 "Content-Type: application/x-www-form-urlencoded\r\n\r\n" +
                  query + "\r\n";
    client.print(request);
  
    while (client.connected()) {
      String line = client.readStringUntil('\n');
      Serial.println(line);
      if (line == "\r") {
        break;
      }
    }
  
    String line = client.readStringUntil('\n');
    Serial.println(line);
  }

  Status = buttonState;
  delay(500);
```

LINE Notifyとの送受信処理は[こちら](https://next.rikunabi.com/journal/20170719_t12_iq/)を参考にさせていただきました。

# 通知画面
こんな感じに通知が飛びます。
※こちらは、トークン名が「sensor_user」、通知メッセージが「ソーシャルディスタンスを守ってください。」の場合
![Screenshot_20201026-180520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/d5e6d910-b40c-9b4b-1758-d04381ed6950.png)

# 注意事項
- トークンは1ユーザ1つしか作れません
- 1トークンに結び付けられるグループ（または本人）は1つです

# 感想
CAの設定無しでつながるとは思ってませんでした。
LINE Notifyにつながってしまえば、後は簡単です。

なお、ソース全体は[こちら](https://github.com/mine820/Arduino/blob/master/LINE_Notify/LINE_Notify.ino)です。