LINEで手軽にIoT！　opnizを使ってLINE BotからM5ATOM Liteをコントロールしてみる

# はじめに

先日LINEアドベントカレンダーにて「[LINEで手軽にIoT！　opniz × LINE Notifyを試してみる](https://qiita.com/miso_develop/items/bf79b14b838017587fe5)」という記事を投稿させて頂きました。
この記事ではLINE Notifyを用いて「M5ATOM -> LINE」という方向のアクセスを行いました。

本記事ではLINE Messaging APIを用いて「M5ATOM <-> LINE」と双方向のアクセスを試してみます。

なお本記事では上記の記事同様マイコンデバイスにはM5ATOM Liteを使用します（M5ATOM Matrixでも大丈夫です）。
M5ATOMへの[opniz Arduino Library](https://github.com/miso-develop/opniz-arduino-m5atom)書き込み方法は本記事では省略しますので、必要な場合は「[こちら](https://qiita.com/miso_develop/items/bf79b14b838017587fe5#m5atom-lite%E3%81%B8%E3%81%AEopniz%E3%82%B9%E3%82%B1%E3%83%83%E3%83%81%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF)」をご覧ください。



## LINE -> M5ATOM の動作

LINEからM5ATOMへアクセスするケースでは、LINEに入力した色にあわせM5ATOMのLEDを変化させてみます。
あわせてBotからの応答メッセージもLINEに返してみます。

こんな感じです。
![image](https://user-images.githubusercontent.com/22117028/146635666-0c2f3a4c-a32f-4ac4-ad7a-ff1f9bee34bc.gif)

## M5ATOM -> LINE の動作

M5ATOMからLINEへアクセスするケースです。
前回の記事同様にM5ATOMのボタンを押したらLINEにメッセージとスタンプを送るようにします。

前回の記事ではLINE Notifyにて実装していましたが、今回はこの部分もMessaging APIで実装します。

こんな感じです。
![image](https://user-images.githubusercontent.com/22117028/146635671-61fc9bd0-c1be-46d4-a5a9-6dc11eec8bd7.gif)

# 実装

処理のイメージは以下のようになります。
![image](https://user-images.githubusercontent.com/22117028/146534458-4d3cfa51-7beb-4ddc-96fa-71437b7bbbcc.png)
![image](https://user-images.githubusercontent.com/22117028/146516717-5b5a9042-b00a-45b9-a60d-b15438ce4ee4.png)

手順としては、

* [M5ATOM Liteへのopnizスケッチ書き込み（本記事では省略）](https://qiita.com/miso_develop/items/bf79b14b838017587fe5#m5atom-lite%E3%81%B8%E3%81%AEopniz%E3%82%B9%E3%82%B1%E3%83%83%E3%83%81%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF)
* [LINE DevelopersコンソールにてLINE Botを作成](#line-developersコンソールにてline-botを作成)
* [opniz Node.js SDK & LINE Bot SDKプログラムの作成](#opniz-nodejs-sdk--line-bot-sdkプログラムの作成)

という流れで進めます。

## LINE DevelopersコンソールにてLINE Botを作成

この部分は既にさまざまな記事にて解説されています。
私が最初にBotを作ったときも、久しぶりにBotを作るときもまず参照する「[1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d#1-bot%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)」という記事がおすすめです。

この記事の「1. Botアカウントを作成する」から「Botと友達になろう」までを実施するとLINE Botを作成できます。
画面のキャプチャや項目名称が現環境と少し差異がありますが、雰囲気でなんとかなると思います。

## opniz Node.js SDK & LINE Bot SDKプログラムの作成

作成したLINE Botの中身の動きの実装を行います。
少しコードが長いのでいくつかポイントを抜粋して説明します。

まず`config`に格納する「`<CHANNEL_SECRET>`」「`<CHANNEL_ACCESS_TOKEN>`」をLINE DevelopersコンソールのBot情報から取得し差し替えます。
先ほどの記事の「[Channel Secretとアクセストークンの確認](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d#channel-secret%E3%81%A8%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E7%A2%BA%E8%AA%8D)」を参考にしてみてください。

```js:index.js（config部抜粋）
const line = require("@line/bot-sdk")
const express = require("express")
const { Opniz } = require("opniz")

const config = {
	channelSecret: "<CHANNEL_SECRET>",            // ここを差し替える
	channelAccessToken: "<CHANNEL_ACCESS_TOKEN>", // ここを差し替える
}
```

次にLINEからのメッセージをうけ、M5ATOMのLEDを制御する部分です。
メッセージ（色名）をもとにカラーコードを取得し、`await opniz.dis.drawpix(0, colorCode)`というメソッドでカラーコードを指定しM5ATOMのLEDを制御します。
最後にLINEへの応答メッセージを生成しレスポンスを返します。

ここではopniz（M5ATOM）のコードは`await opniz.dis.drawpix(0, colorCode)`のみです。
このようにシンプルにM5ATOMを制御することができます。

```js:index.js（LINEメッセージをもとにM5ATOMのLEDの色変更部）
// LINE Botでのメッセージハンドリング
const client = new line.Client(config)
const handleEvent = async (event) => {
	if (event.type !== "message" || event.message.type !== "text") return null
	
	const message = event.message.text.trim() // メッセージ（色名）取得
	const colorCode = colorTable[message] // 色名をカラーコードに変換
	
	colorCode && await opniz.dis.drawpix(0, colorCode) // M5ATOm LiteのLED色変更
	
	const replyMessage = colorCode ? // 応答メッセージを生成
		`LEDを${message}にします！` :
		"「赤、 青、 緑、 白、 オフ」のいずれかを指定してください！"
	
	return client.replyMessage(event.replyToken, {
		type: "text",
		text: replyMessage
	})
}
```

最後にM5ATOMのボタンを押したらLINEへメッセージ送信する部分です。
まず`pushMessage`というLINE Botに対してブロードキャストでメッセージ送信する関数を定義しています。
そしてこの関数を`opniz.onbutton = pushMessage`にて`onbutton`メソッドにバインドしています。

前回の記事でも同様の処理をしていますが、LINE Notifyを使用していたのでLINE NotifyのエンドポイントへHTTP POSTをしていました。
今回はLINE Bot SDKを使用しているので、SDKで用意されている`client.broadcast()`メソッドで簡単に実装できました。

```js:index.js（M5ATOMのボタンを押したらLINEへメッセージ送信）
// LINE Botからメッセージ送信
const pushMessage = async () => {
	await client.broadcast([
		{
			type: "text",
			text: "opnizのボタンが押されたやで！",
		},
		{
			type: "sticker",
			packageId: "11537",
			stickerId: "52002735",
		},
	])
}



const opniz = new Opniz.M5Atom({ port: 3000 }) // opnizインスタンス生成
opniz.onbutton = pushMessage // M5ATOMのボタンが押されたらメッセージ送信
```

### ソースコード全文

<details><summary><b>╭╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╮<br>&nbsp;&nbsp;&nbsp;╏&nbsp;&nbsp;&nbsp;&nbsp;ソースコードを表示（ここをクリックすると展開されます）&nbsp;&nbsp;&nbsp;╏<br>&nbsp;&nbsp;&nbsp;╰╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╯</b></summary><div>

```js:index.js
const line = require("@line/bot-sdk")
const express = require("express")
const { Opniz } = require("opniz")

const config = {
	channelSecret: "<CHANNEL_SECRET>",            // ここを差し替える
	channelAccessToken: "<CHANNEL_ACCESS_TOKEN>", // ここを差し替える
}

const colorTable = {
	"赤": "#00ff00",
	"青": "#0000ff",
	"緑": "#ff0000",
	"白": "#ffffff",
	"オフ": "#000000",
}



// LINE Botでのメッセージハンドリング
const client = new line.Client(config)
const handleEvent = async (event) => {
	if (event.type !== "message" || event.message.type !== "text") return null
	
	const message = event.message.text.trim() // メッセージ（色名）取得
	const colorCode = colorTable[message] // 色名をカラーコードに変換
	
	colorCode && await opniz.dis.drawpix(0, colorCode) // M5ATOm LiteのLED色変更
	
	const replyMessage = colorCode ? // 応答メッセージを生成
		`LEDを${message}にします！` :
		"「赤、 青、 緑、 白、 オフ」のいずれかを指定してください！"
	
	return client.replyMessage(event.replyToken, {
		type: "text",
		text: replyMessage
	})
}



// LINE Botからメッセージ送信
const pushMessage = async () => {
	await client.broadcast([
		{
			type: "text",
			text: "opnizのボタンが押されたやで！",
		},
		{
			type: "sticker",
			packageId: "11537",
			stickerId: "52002735",
		},
	])
}



const opniz = new Opniz.M5Atom({ port: 3000 }) // opnizインスタンス生成
opniz.onbutton = pushMessage // M5ATOMのボタンが押されたらメッセージ送信

const connect = async () => {
	while (!(await opniz.connect())) console.log("connect...") // opniz接続
	console.log("connected!")
}
connect()



// Botサーバ起動
const requestHandler = async (req, res) => res.json(await handleEvent(req.body.events[0]))
const app = express()
app.post("/", line.middleware(config), requestHandler)
app.listen(3001)
```

</div></details>



## プログラムの実行

それでは実行してみましょう。

まずは関連npmパッケージをインストールします。

```sh:パッケージインストール
npm install opniz @line/bot-sdk express
npm install -D ngrok
```

次に上記のコマンドでインストールしたngrokというトンネリングアプリを使ってPCの3001番ポートをHTTPトンネリングします。
`Forwarding`というレコードにHTTPS URLが表示されますので、これを再びLINE DevelopersコンソールよりWebhook URLに登録します。

```sh:ngrokの実行
$ npx ngrok http 3001

ngrok by @inconshreveable(Ctrl+C to quit)
Session Status                online
Session Expired               Restart ngrok or upgrade: ngrok.com/upgrade
Version                       2.3.40
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx.ngrok.io -> http://localhost:3001
Forwarding                    https://xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx.ngrok.io -> http://localhost:3001

Connections                   ttl     opn     rt1     rt5     p50     p90     
                              1       0       0.00    0.00    17.13   17.13   
```

**[LINE Developersコンソール　Webhook設定]**
![image](https://user-images.githubusercontent.com/22117028/146529222-ef9ec2b7-17cb-4cf4-a90e-8cf5d286e4ee.png)

そしてプログラム実行します。
`connected!`と表示されればM5ATOM Liteと正常に接続できている状態です。

```sh
$ node index.js
connected!
```

### LINEからM5ATOMのLEDを制御

まずは「LINE -> M5ATOM」のアクセスをためしてみます。

LINE Botへ「赤、青、緑、白、オフ」のいずれかのメッセージを送ってみます。
するとM5ATOMのLEDが指定した色に変化し、LEDの色を変更した旨のメッセージが返ってきます。
![image](https://user-images.githubusercontent.com/22117028/146635666-0c2f3a4c-a32f-4ac4-ad7a-ff1f9bee34bc.gif)

### M5ATOMのボタンを押してLINEへメッセージ送信

つづいて「M5ATOM -> LINE」のアクセスをためしてみます。

前回記事と同様、M5ATOM Liteのボタンを押したらLINEへメッセージとスタンプが送られます。
![image](https://user-images.githubusercontent.com/22117028/146635671-61fc9bd0-c1be-46d4-a5a9-6dc11eec8bd7.gif)



# おわりに

LINE Messaging APIを通してLINEとM5ATOMで双方向の制御を実現できました。
ここまでできてしまえば、もうなんでもできるんじゃないでしょうか。

ひとつLINE Messaging API使用の注意点があります。
LINEのメッセージは[「応答メッセージ」と「プッシュメッセージ」に分けられます](https://developers.line.biz/ja/docs/messaging-api/sending-messages/)。
「応答メッセージは」無制限で利用可能ですが「プッシュメッセージは」[フリープランだと月あたり1000回までという制限](https://www.linebiz.com/jp/service/line-official-account/plan/)があります。

「M5ATOM -> LINE」の方向のアクセスでは制限がある「プッシュメッセージ」を用いていますのでこのあたり注意が必要です。

なお前回記事で用いたLINE Notifyも同様に制限は設けられていますが、[1時間あたり1000回まで](https://notify-bot.line.me/doc/ja/)とあってないような制限です。
プッシュを多用したいケースではLINE Messaging APIではなくLINE Notifyの使用を検討してみるとよいでしょう。