作ったきっかけ
自宅で仕事をすることも多いのですが、子ども達が学校から帰宅したり外出しても全く気付かず在宅の保護者としては失格状態なので、手軽に通知してくれる仕組みが欲しいところでした。
そんな折の2019年4月に、LINE アプリとBLE 機器を連携できる新サービス「LINE Things」に自動通信機能がリリースされたので、「これで出来るんじゃね?」ということで早速作ってみました。
作ったもの
こちらです。
先日リリースされたLINE Things の自動通信機能を試してみた
— sumihiro3 (@sumihiro3) May 19, 2019
M5Stack と Grove のスライドボリュームを使って、子どもの帰宅/外出を通知してくれるヤツですね。
こちらの記事どおりで、ほぼ出来ちゃいます。https://t.co/TDzFwlyEPn#linethings #line_api pic.twitter.com/KkxSzeZKj1
準備したもの
- M5Stack
- GROVE - スライドボリューム
- LINE アプリをインストールしたスマートフォン
- 適当な段ボール
- カッター、定規、テープなど
- PC
私のようにM5Stack を買ってみたものの使い道が定まらずに温存しておられる方であれば、1,000円程度で作れますので是非お試しください!
ソースコードはこちらで公開しています。
システム構成
処理の流れ
処理の流れは単純です。
- M5Stack に繋がったスライドボリュームの値が変わると、BLE を介してスマートフォンへ送信
- スマートフォンからLINE Things へ値を送信
- LINE Things から Messaging API を経由
- サーバーへのWebhook として通知(ngrok 経由)
- LINE Messaging API に向けてメッセージ送信
- LINE アプリへメッセージ送信
LINE Things を使うには
LINE Things を利用するにはLINE Messaging API の設定等いくつか準備作業が必要ですが、LINE の公式ブログ記事に詳しく書いてありますので、そちらを参考にしてください。
今回の作品向けに変えた部分は以下となります。
デバイス側
ユーザー(子ども)がスライドボリュームを操作して取得できる値が変わったら(スライドの位置が左右変わったら)、画面に表示する画像(SDカード内に格納)を切り替えてBLE 経由でLINE アプリに値を送信しています。
(前略)
// 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 を利用して外部からアクセスできるようにしました。
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 とスライドボリュームを嵌め込められるように細工して、テープなどを使って固定すれば完成です!
まとめ
今回はLINE Things の自動通信機能を使ってみたかったので単純な機能しかありませんが、小学生の子どもが2人いるので、どちらからの通知かを見分けられるようにしたい(2台作るのではなく)ですし、録音しておいた音声(おやつあるよ、ピアノは16時からだよ とか)を再生して、連絡漏れがないようにもしたいですね。
また、LINE Things の自動通信機能はとても簡単にBLE デバイスとスマートフォン(LINE アプリ)と連携が構築できました。アイデア次第で色んな課題を解決したり、新しい使い方が実現できたりすると思うので、皆さんも是非お試しください。