LINE Thingsで歩数計Botを作ろう

# はじめに
**どこかでハンズオンをするために書いた記事です。**内容は以下のような感じです。

1. m5stackで歩数計を作る
2. LINE Thingsの自動通信を使って歩数計とLINEをBluetooth通信させる
3. 一定歩数ごとにLINE通知するシステムを構築

図で表すとこんな感じです。各番号が上記で説明した内容に対応しています。

![歩数計.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/17285e13-3eed-4c04-3a32-b4c73f54c878.jpeg)


このハンズオンで用いる開発ツール・環境は以下です

- 歩数計
    - [m5stack gray](https://www.switch-science.com/catalog/3648/)
    - [Arduino IDE](https://www.arduino.cc/en/Main/Software)
        - [ESP32 Bord](https://github.com/espressif/arduino-esp32)
        - [sparkfun/SparkFun_MPU-9250-DMP_Arduino_Library](https://github.com/sparkfun/SparkFun_MPU-9250-DMP_Arduino_Library/tree/master/examples)
        - [M5Stack Library](https://github.com/m5stack/M5Stack)
- LINE Bot
    - [適当なアカウント](https://developers.line.biz/ja/)
    - [LINE Things](https://n0bisuke.github.io/linethingsgen/)
    - [Node.js](https://nodejs.org/ja/)
        - [express](https://expressjs.com/ja/)
        - [line-bot-sdk-nodejs](https://github.com/line/line-bot-sdk-nodejs)
    - [ngrok](https://ngrok.com/)
- その他
    - [Git for Windows](https://gitforwindows.org/)（Windowsユーザーの場合）
    - [Visual Studio code](https://code.visualstudio.com)（あると便利）
        - [vscode-arduino](https://github.com/microsoft/vscode-arduino)（ついでに入れちゃおう）

それぞれのツールについての解説は今回は省略します。説明は操作手順にのみ重点を置きます。
また、今回用いるソースコードは[githubで公開](https://github.com/ufoo68/linethings-pedometer-hands-on)されています。以下のコマンドで入手してください。

```bash
git clone https://github.com/ufoo68/linethings-pedometer-hands-on.git
```

# 参考にした記事

- [M5Stack Grayに搭載の加速度センサMPU-9250の歩数計機能を利用](https://qiita.com/tanopanta/items/7ec96bf4801eddedac39)
- [LINE Things Messageを使ってみよう #linethings #linedc](https://qiita.com/n0bisuke/items/7f3da133a2363b549e3e)
- [1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)
- [LINE Things とM5Stack で子どもの帰宅／外出を通知できる仕組みを作ってみた](https://qiita.com/sumihiro3/items/965998815a0b975a465a)

# M5Stackで歩数計を作る
M5Stackは[M5Stack](https://m5stack.com/)という会社が開発したマイコンボードです。中には[espressif](https://www.espressif.com/)という会社の[ESP32](https://www.espressif.com/en/products/hardware/esp32/overview)というWiFi/Bluetooth搭載のチップが内蔵されています。M5Stackのいいところはハンダ付けなしでモジュールを拡張することができるところです。その名前の通り、モジュールを下に積み重ねる（スタックする）ことでデバイスを拡張させてきます。今回はM5Stack grayに予め搭載されている**MPU9250**という9軸（加速度・ジャイロ・地磁気）のモーションセンサーを用います。

## まずは環境のセットアップ
M5Stackのソフトウェアを開発する方法は何通りかありますが、ここでは`Arduino IDE`を使います。[ここのリンク先](https://www.arduino.cc/en/Main/software)からダウンロードを行ってください。
インストールが完了したら次にESP32のボード開発用のライブラリをインストールしていきます。まずは下の一行をコピーしてください。
`https://dl.espressif.com/dl/package_esp32_index.json`
コピーしたら`Ctrl + ,`で環境設定（Preference）を開いて下図のような赤枠に囲ってあるところにペーストしてください。
![2019-08-11 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/0176efa9-409a-cb80-0ca9-70739589a242.png)
そしたらそのまま`OK`を押して戻ります。次にメニューバーから`ツール->ボード->ボードマネージャー`の順番で選択していき下図のような画面を開きます。そのとき上の入力欄に`ESP32`と打ったら一つだけヒットするものが出てくるのでインストールしてしまいます。
![2019-08-11 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/6064ad56-0a7b-b132-335e-29fab24ef5b2.png)
インストールが完了したら次にM5Stack用のライブラリをインストールします。`Ctrl + Shift + i`で下図のような画面を起動します。同様に入力欄を`M5Stack`でソートして赤枠で囲っているところを探してインストールしてください。
![2019-08-11 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/869626ec-a562-8a4c-777c-6e0a2e87540c.png)
これでM5Stack開発用の環境のセットアップは完了です。また、M5Stackにコード（Arduinoではスケッチという）を書き込むときは下のような感じでボードの設定をしてください。多分細かいパラメーターの設定はデフォルトで問題ないと思います。
![2019-08-11 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/958de618-b733-ff7c-0267-1e49d8c272b8.png)
また、Arduinoの開発はもちろんこのArduino IDEで行ってもいいとは思いますが、vscodeで開発を行うためのExtensionsがあります。恐らく上記のどこかでリンク先を示してあります。方法は[こちらの記事](https://qiita.com/narikei/items/847613a8f01a9e1527d7)などを参考にしてください。

## 歩数計のライブラリを使えるようにする
次にM5Stackで歩数計を作ります。まず、歩数を図る方法は主に2つの方式に大別されます[^1]。
[^1]: https://www.promotion173.com/entry/manpokei-shikumi

1. 電気スイッチが開閉し振動回数を記録する振り子方式
2. 加速度センサー方式

前者の**1.**が所謂昔の万歩計に使われているような方式ですが、この方法では万歩計をただ上下に降るだけでも「歩き」認識してしまいます（多分昔ポケットピカチュウを持っていた方ならよく知っているはず）。「歩き」にはそれ特有のモーションが存在し、それをモーションセンサーで検出する方法を用いることでより正確に「歩き」を検出することができます。この場合は後者の**2.**の方式になります。M5Stackには折角9軸のモーションセンサーが搭載されているのでそれを使わない手はありません。

上記でも述べましたが、M5StackにはMPU9250が搭載されています。MPU9250用のライブラリは先程インストールしたM5Stack用のライブラリに含まれていますが、センサーからの生データから「歩き」のモーションを計算するアルゴリズムをゼロから考えるのは面倒なので[SparkFunのMPU9250用ライブラリ](https://github.com/sparkfun/SparkFun_MPU-9250-DMP_Arduino_Library)を使って歩行検出のライブラリ（Pedometer）を使おうと思います。直接ソースコードをArduinoのライブラリに追加する方法として、まずは先程のgithubのレポジトリをZipでダウンロードします。
![2019-08-11 (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/c108a088-ca2d-91bc-0b14-cb2ec2a8079f.png)
次にArduino IDEのメニューバーから`スケッチ->ライブラリをインクルード->.ZIP形式のライブラリをインストール`を選びます。そして先程インストールした.zipフォルダを選択します。
![2019-08-11 (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/d3936382-24cc-6413-0b54-095b4e0db329.png)
ここでセットアップは完了。と言いたいところですが、このライブラリはM5Stack専用に作られていないので少し中のファイルをイジる必要があります。先程インストールされたライブラリは`Arduino/libralies/SparkFun_MPU-9250-DMP_Arduino_Library-master`に格納されていると思うので一旦そこまでフォルダを移動します。ArduinoというフォルダはArduino IDEをインストールしたときに自動的にDocumentsに作られていると思います。
まず、`library.properties`を開いて以下のように書きかえます（といっても一番下の行を`architectures=*`に変えただけです。）。

```library.properties
name=SparkFun MPU-9250 Digital Motion Processing (DMP) Arduino Library
version=1.0.0
author=SparkFun Electronics
maintainer=SparkFun Electronics <TechSupport@SparkFun.com>
sentence=Driver for InvenSense's MPU-9250 9-DOF IMU (3-axis gyroscope, 3-axis accelerometer & 3-axis magnetometer)
paragraph=The <a href="https://www.invensense.com/products/motion-tracking/9-axis/mpu-9250/">MPU-9250</a> is a system-in-package featuring acceleration full-scales of ±2 / ±4 / ±8 / ±16 (g), rotational full-scales of ±250 / ±500 / ±1000 / ±2000 (°/sec) and a magnetic field full scale of ±4800 µT. The MPU-9250 includes an I<sup>2</sup>C serial bus interface that supports speeds up to 400 kHz.
category=Sensors
url=https://github.com/sparkfun/MPU-9250_Breakout
architectures=*
```

次に`/src/util/inv_mpu.c`を開いて以下のように書き換えます（`#define min(X,Y) ((X) < (Y) ? (X) : (Y))`を#defineとかしているところに追加）。

```diff:/src/util/inv_mpu.c(39-49行目)
#include <Arduino.h>
+ #define min(X,Y) ((X) < (Y) ? (X) : (Y))
#define MPU9250
#include "arduino_mpu9250_i2c.h"
#include "arduino_mpu9250_clk.h"
#define i2c_write(a, b, c, d) arduino_i2c_write(a, b, c, d)
#define i2c_read(a, b, c, d)  arduino_i2c_read(a, b, c, d)
#define delay_ms  arduino_delay_ms
#define get_ms    arduino_get_clock_ms
#define log_i     _MLPrintLog
#define log_e     _MLPrintLog 
```
これでライブラリのセットアップは完了です。

## スケッチを書き込む
M5Stack用のスケッチはハンズオン用のサンプルコードの`m5stack-linethings/m5stack-linethings.ion`に入っています。このスケッチの内容をこのまま書き込んでしまえば歩数がM5Stackの画面に表示されるシステムが一旦完成します。この歩数計に関係する部分のスケッチは以下です。

```c:m5stack-linethings.ino(74-82行目)
stepCount = imu.dmpGetPedometerSteps();
stepTime = imu.dmpGetPedometerTime();
if (stepCount != lastStepCount) {
  lastStepCount = stepCount;
  M5.lcd.clear();
  M5.Lcd.setCursor(0,0);
  M5.lcd.print("Walked " + String(stepCount) + " steps");
  M5.lcd.print(" (" + String((float)stepTime / 1000.0) + " s)");
  ...
}
```

ここでは、歩数が増える度に表示するステップ数を変更しています。

# LINE Thingsと連携する
LINE Thingsを利用するためには専用のLINE Botを作成する必要があります。まずは[LINE Developers](https://developers.line.biz/ja/)にログインします。ログインが完了したら、右上のアイコンをクリックして「プロバイダー新規作成」を選択します。
![2019-08-11 (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/91eba529-ecd3-f459-0ca7-a4ad20946c40.png)
次にチャンネルを新規作成します。**Messaging API**を選択します。
![2019-08-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/493f304d-f549-836f-39cd-f0cab6ae5539.png)
とりあえず適当な名前をつけたら**LIFF**のタブを選択して「追加」します。このとき、重要となるのは「オプション」の**BLE feature**です。「ON」を選択してください。
![2019-08-15 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/d2d84523-0ef3-bff8-76bc-7839c3bdbed7.png)
これでLINE Thingsと連携ができるLINE Botができました。また、**アクセストークン**と**チャンネルシークレット**という２つのキーが今後必要になります。**チャンネル基本設定**のタブから「Channel Secret」と「アクセストークン（ロングターム）」を探してください。アクセストークンは最初何も発行されていないと思うので「再発行」をしてください。

## シナリオを登録する
今回はLINE Thingsの自動通信機能を用います。この機能を用いることで`デバイス -> INE Bot`への通信が可能になります。要はデバイスを用いたPush Messageができるということです[^2]。
[^2]: https://developers.line.biz/ja/docs/line-things/about-auto-communication/
自動通信を有効にするにはAPIを用いてシナリオを登録する必要があります。CURLやPostmanでAPIを直接叩く方法でも構いませんが、ここは楽をするために@n0bisukeさんの[専用ツール](https://n0bisuke.github.io/linethingsgen/)を用いて開発をシナリオの登録を行いましょう。
まずは[リンク先](https://n0bisuke.github.io/linethingsgen/)←にアクセスします。そしたら「Setting」のタブを選択して「アクセストークン」の入力欄にそのままキー値をペーストして「保存」をクリックします。
![2019-08-15 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/c618291e-a7d7-2012-bad9-e51d32cae19e.png)
次に「Create Product」のタブを選択してLIFFアプリを選択します。登録したLIFF名を選んでください。そしたら適当な「トライアルプロダクトの名前」を入力して「作成」をクリックします。そのとき下に表示された「サービスUUID」をどこかにメモしておきます。
![2019-08-17 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/2f2e26f9-bc5b-a358-17ca-aaa7252e68c4.png)
最後に「Create Senario」のタブに移動して先程作成したトライアルプロダクトの名前を選択します。設定は下図のような感じで「シナリオセットの登録/更新」をクリックします。
![2019-08-17 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/2d1e5bc3-d442-6eca-d5b9-59b5c18159ed.png)
これでシナリオの登録は完了です。そしたら先程メモしたサービスUUIDを使います。M5Stackのスケッチに戻って12行目あたりの`define`の文字列をサービスUUIDに変更して再び書き込みます。

```c:m5stack-linethings.ino(12行目)
#define USER_SERVICE_UUID "Change your service uuid"
```

また、LINEアプリにLINE Thingsを有効化させるためには以下のQRコードを読む必要があります。
![qr_code-311f3503.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/88284802-2dbc-1564-6577-0dd22eef9754.png)

# LINE Botをつくる
LINE Thingsの自動通信との連携のためのLINE Botを作成します。以下のコマンドを実行してください。

```bash
cd linethings-pedometer-hands-on
npm i
```

次に同じ`linethings-pedometer-hands-on`ディレクトリ内に`.env`というファイルを作成します。

```:.env
CHANNEL_SECRET="チャンネルシークレット"
ACCESS_TOKEN="アクセストークン"
PORT=3000
```

`CHANNEL_SECRET`、`ACCESS_TOKEN`には前回の項目でメモした**チャンネルシークレット**と**アクセストークン**を入力します。

これでサンプルコードを実行するための環境構築は完了しました。しかしMessaging API用のサーバを立てるためには**https**で始まるURLが必要になります。今回は**ngrok**というツールを用いてhttpsのURLを取得します。まずは以下のコマンドを実行してngrokをインストールします。

```
npm i -g ngrok
```
インストールしたら同じカレントディレクトリのターミナルをもう一つ立ち上げて以下のコマンドを実行します。

```
ngrok http 3000
```
そしたら以下のように画面表示されるので、以下の`https://`で始まっているURLをコピーします。

```
ngrok by @inconshreveable                                                                                                                    (Ctrl+C to quit)
Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.3.34
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://xxxx.ngrok.io -> http://localhost:3000
Forwarding                    https://xxxx.ngrok.io -> http://localhost:3000
```

そしたらもう一方のターミナルで以下のコマンドを実行してサーバーを立ち上げます。

```
node index
```
後は先程コピーしたURLを「Webhook URL」に登録します。前回の項目で作成したLINE Bot用のチャンネル基本設定に戻ります。
「Webhook送信」を「利用する」に選択して、「Webhook URL」に`コピーしたURL+/webhook`を登録します。
![2019-08-17 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/d4457a3e-31db-409a-dc80-943cf6754f2d.png)


# ペアリングしよう
LINE Thingsを有効にすると以下のような項目がLINEアプリの「設定」ページに追加されています。
![iOS の画像 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/47ccafde-d2a0-64a2-d7e4-d68cec7bc8bd.png)
「LINE Things」のページは以下のようになっています。先程登録したデバイスが「連携可能なデバイス」として表示されるのでタップしてペアリングを開始してください。LINE Things登録から連携までには少し時間がかかる場合があります。なかなか現れない場合はスマホの再起動を試すのも一つの手です。
![iOS の画像 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/032b96da-2eeb-ad8c-2f4f-22d2b3a0ccec.png)
あとは実際にポケットにM5Stackを入れた状態で歩いてみて動作を確かめてみてください。しかしUSBケーブルで給電した状態で試すのは難しいと思うので[M5Stack用電池モジュール](https://www.switch-science.com/catalog/3653/)を買うことをオススメします。

# さいごに
今回はM5Stackで試しましたが、最近は[M5StickC](https://www.switch-science.com/catalog/5517/)が出たみたいなのでそちらの実装バージョンも別途記事を書こうと思います。こちらの方はまたモーションセンサーのICが異なるみたいなのでスケッチも書き換える必要があるようですね。。。