LINE Things とM5Stack で子どもの帰宅／外出を通知できる仕組みを作ってみた

# 作ったきっかけ
自宅で仕事をすることも多いのですが、子ども達が学校から帰宅したり外出しても全く気付かず在宅の保護者としては失格状態なので、手軽に通知してくれる仕組みが欲しいところでした。

そんな折の2019年4月に、LINE アプリとBLE 機器を連携できる新サービス「LINE Things」に自動通信機能がリリースされたので、「これで出来るんじゃね？」ということで早速作ってみました。

# 作ったもの

こちらです。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">先日リリースされたLINE Things の自動通信機能を試してみた<br>M5Stack と Grove のスライドボリュームを使って、子どもの帰宅／外出を通知してくれるヤツですね。<br><br>こちらの記事どおりで、ほぼ出来ちゃいます。<a href="https://t.co/TDzFwlyEPn">https://t.co/TDzFwlyEPn</a><a href="https://twitter.com/hashtag/linethings?src=hash&amp;ref_src=twsrc%5Etfw">#linethings</a> <a href="https://twitter.com/hashtag/line_api?src=hash&amp;ref_src=twsrc%5Etfw">#line_api</a> <a href="https://t.co/KkxSzeZKj1">pic.twitter.com/KkxSzeZKj1</a></p>&mdash; sumihiro3 (@sumihiro3) <a href="https://twitter.com/sumihiro3/status/1130025671713935360?ref_src=twsrc%5Etfw">May 19, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 準備したもの

- [M5Stack](https://www.amazon.co.jp/exec/obidos/ASIN/B07BW2BLY1/)
- [GROVE - スライドボリューム](https://www.switch-science.com/catalog/1050/)
- LINE アプリをインストールしたスマートフォン
- 適当な段ボール
- カッター、定規、テープなど
- PC

私のようにM5Stack を買ってみたものの使い道が定まらずに温存しておられる方であれば、1,000円程度で作れますので是非お試しください！

ソースコードは[こちら](https://github.com/sumihiro3/line_things_sample/tree/master/SlidePotentionmeter)で公開しています。


# システム構成

![システム構成図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154381/30fc25fc-ec76-484b-f277-9d4bc87c24a8.png)


## 処理の流れ

処理の流れは単純です。

1. M5Stack に繋がったスライドボリュームの値が変わると、BLE を介してスマートフォンへ送信
2. スマートフォンからLINE Things へ値を送信
3. LINE Things から Messaging API を経由
4. サーバーへのWebhook として通知（ngrok 経由）
5. LINE Messaging API に向けてメッセージ送信
6. LINE アプリへメッセージ送信


## LINE Things を使うには

LINE Things を利用するにはLINE Messaging API の設定等いくつか準備作業が必要ですが、[LINE の公式ブログ記事](https://engineering.linecorp.com/ja/blog/line-things-automatic-communication/)に詳しく書いてありますので、そちらを参考にしてください。

今回の作品向けに変えた部分は以下となります。


## デバイス側

ユーザー（子ども）がスライドボリュームを操作して取得できる値が変わったら（スライドの位置が左右変わったら）、画面に表示する画像（SDカード内に格納）を切り替えてBLE 経由でLINE アプリに値を送信しています。

```cpp:SlidePotentionmeter.ino（抜粋）
（前略）
// for SlidePotentionmeter
int adcPin = 22; // select the input pin for the potentiometer
int adcIn = 0;   // variable to store the value coming from the sensor
int lastAdcIn = -1;

（中略）

void loop() 
{
  uint8_t slideValue;
  // read the value from the sensor:
  adcIn = digitalRead(adcPin);
  Serial.println("Current Value : " + String(adcIn));
  Serial.println("Previous value: " + String(lastAdcIn));
  // Compare sensor value with previous reading
  if (lastAdcIn != adcIn) {
    if (adcIn >= 1) {
      // display image
      M5.Lcd.clear();
      M5.Lcd.drawJpgFile(SD, "/itterassyai.jpg");
      slideValue = 1;
    } else {
      M5.Lcd.clear();
      M5.Lcd.drawJpgFile(SD, "/okaeri.jpg");
      slideValue = 0;
    }
    // notify to LINE Things
    notifyCharacteristic->setValue(&slideValue, 1);
    notifyCharacteristic->notify();
    // save sensor value
    lastAdcIn = adcIn;
  }

（後略）
```

GitHub にアップしているファイルには色々とコードが書いてありますが、ほぼLINE Things で提供されているBLE 通信関係処理で、付け足したコードは以下の部分です。

なお、Grove 公式のサンプルコードによるとアナログ値が取得できるらしいのですが、M5Stack のGrove 用ソケットに接続するとデジタルでしか値が取得できませんでした。お分かりになる方がいらっしゃいましたら、コメントなどで教えていただけるとありがたいです。

## サーバー側

LINE Things からLINE Messaging API を経由して通知されるWebhook を受信し、サービスに必要な処理の実行後、LINE Messaging API に向けてメッセージを送信するサーバーです。

今回は個人用途なのでPython + Flask で動く簡易サーバーを構築して自宅のPC で稼働させ、ngrok を利用して外部からアクセスできるようにしました。

```python:main.py（抜粋）

def handle_things_event(event):
    if event["things"]["type"] != "scenarioResult":
        return
    if event["things"]["result"]["resultCode"] != "success":
        app.logger.warn("Error result: %s", event)
        return
    user_id = event["source"]["userId"]
    last_state = data_store.get(user_id, None)
    state = int.from_bytes(base64.b64decode(event["things"]["result"]["bleNotificationPayload"]), 'little')
    # compare previos state
    if state != last_state:
        if state == 1:
            msg = "いってきま〜す！"
        else:
            msg = "ただいま〜♪"
        data_store[user_id] = state
        line_bot_api.reply_message(event["replyToken"], TextSendMessage(text=msg))

```

送信されたスライドボリュームの値が前回と比べて変わったらLINE メッセージを送信するようにしています。
なお、前回の状態はデータベース等で永続化はせずにメモリ内で簡易的に保持しているだけです。

## 筐体など

あとは段ボールにM5Stack とスライドボリュームを嵌め込められるように細工して、テープなどを使って固定すれば完成です！

![中身](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154381/7b165c6c-0347-fb63-5f98-256932ca2fbe.jpeg)


# まとめ

今回はLINE Things の自動通信機能を使ってみたかったので単純な機能しかありませんが、小学生の子どもが2人いるので、どちらからの通知かを見分けられるようにしたい（2台作るのではなく）ですし、録音しておいた音声（おやつあるよ、ピアノは16時からだよ とか）を再生して、連絡漏れがないようにもしたいですね。

また、LINE Things の自動通信機能はとても簡単にBLE デバイスとスマートフォン（LINE アプリ）と連携が構築できました。アイデア次第で色んな課題を解決したり、新しい使い方が実現できたりすると思うので、皆さんも是非お試しください。


# 参考サイト

- [LINE Things 自動通信機能がリリースされました & 使い方紹介](https://engineering.linecorp.com/ja/blog/line-things-automatic-communication/)
- [LINE Things Developer Trial ハンズオン](https://qiita.com/hktechno/items/bb83cc898c75819b2664)
- [LINE Things ドキュメント](https://developers.line.biz/ja/docs/line-things/)
- [LINE Thingsハッカソン@大阪レポート](https://engineering.linecorp.com/ja/blog/line-things-hackathon-report-osaka/)
- [#linethings でバイクの盗難防止装置作ってみた](https://qiita.com/stachibana/items/dac5968255f375792fae)