Raspberry Pi Zero W でLINE BOTを作成する

Raspberry Pi Zero Wは超小型で無線LANまで付いているので、対話可能なデバイスやロボットを作るのにも向いています。
LINE BOTは実体のあるロボットとは異なりますが、対話エンジン部分の実装やノウハウはコミュニケーションロボットのそれに通じるものがありますので、練習がてらにやってみるのに丁度良い題材かと思います。

# 事前に準備するもの

- Raspberry Pi Zero W （WでないZero、Raspberry Pi3などでも同じかも。試してません）
- ディスプレイ、キーボード、マウス（Raspbianセットアップ済みなら不要）
- LINE Messaging APIのChannel SecretとChannel Access Token
- docomo 雑談APIのAPIキー（省略可能。その場合はおうむ返しBOTになります）

# Minetteのご紹介

今回は対話のために必要な機能一式を提供する「Minette」というPython製のBOTフレームワークを利用しています。LINE BOTのみならず汎用的な対話処理を支援するフレームワークなので、これを機にお見知り置きいただけると嬉しいです。

- [BOTフレームワーク Minette for Python のご紹介](http://qiita.com/uezo/items/0c92ba960a6a47b14921)
- [Minette for Python on GitHub](https://github.com/uezo/minette-python)

# Raspbianのインストール

BOTを動かすマシンたるRaspberry Pi Zero Wそのもののセットアップの流れを簡単に。

## microSDのフォーマット

Raspberry Piに挿すmicroSDカードを、FAT32でフォーマットします。SD Memory Card Formatterを使用した手順が紹介されていることが多いようですが、Mac OSX標準のディスクユーティリティで問題ありませんでした。

## NOOBSのコピー

[NOOBSの公式](https://www.raspberrypi.org/downloads/noobs/)からZIPファイルをダウンロード・解凍します。続いて解凍してできたディレクトリの中身を丸ごと、さきほどフォーマットしたmicroSDカードの直下にコピーしてください。
なお、この手順はNOOBS 2.4.3（2017.8.17）をベースにしています。

## 電源の投入〜OSセットアップ

ディスプレイ、マウス、キーボードに接続してOSをセットアップします。WiFiやSSHの有効化もここで済ませてしまえばOSセットアップ後の作業は使い慣れたノートパソコン等でできるので、私は普段そうしています。

## パッケージリストの更新

お約束。更新しておきましょう。

```
$ sudo apt-get update
```

# virtualenvのインストール

必須ではないですが、好きなだけ環境を汚せるように、virtualenvを入れておきましょう。

```
$ sudo apt-get install python-virtualenv
```

入れたら仮想環境のセットアップです。まずは仮想環境の配置先を作ります。任意の場所でOKですが、ホームディレクトリ直下に環境がぞろぞろ並ぶのも綺麗ではないので、私は以下のように隠しディレクトリを作ってその中に作っています。

```
$ mkdir .venv
$ cd .venv
$ virtualenv -p python3 bot
```

1分程度待つと、環境が構築されますので、当該環境のディレクトリの中に移動してから環境を有効にします。

```
$ cd bot
$ source bin/activate
```

プロンプトの前に(環境名)という文字列が付加されたら成功です。

```
(bot) pi@raspberrypi $ 
```

# ライブラリのインストール

今回利用するBOTフレームワークのMinetteと、その依存ライブラリをインストールします。

```
$ pip install pytz
$ pip install requests
$ pip install minette
```

インストールが完了したら、動作確認してみましょう。

```
$ minette
user> hello
minette> You said: hello
```

こんな感じでおうむ返ししてくれたらOKです。

# 雑談APIの設定

事前に用意したdocomo 雑談APIを利用して、雑談BOT化します。環境変数に以下の2つの値を設定しましょう。`.bashrc`などに書き込んでおくと都度設定しなくてよいので楽です。
なお、雑談しなくていいからLINEとのつなぎ方を知りたい、という方はこの手順を飛ばしてもOKです。

```
$ export CHAT_API_KEY="あなたのAPIキー"
$ export DEFAULT_DIALOG_SERVICE="minette.dialog.chat_dialog.ChatDialogService"
```

動作確認。

```
$ minette
user> こんにちは
minette> はいこんにちは
user> おおすげえ
minette> だろ
```

Minetteのセッション管理機能のおかげで、しりとりもできます。

```
user> しりとりしよう
minette> はい、やりましょう。それでは、ロボットのトからスタートです。
user> トナカイ
minette> 衣装
user> うなぎ
minette> 技術
```

# インターネットへの公開

LINE Messaging APIのインバウンドは開発者が指定したWebhookを叩いてメッセージを渡してくれるようになっているので、お手元のRaspberry Pi Zero Wをインターネットからアクセスできるようにしてやる必要があります。

様々な方法があるかと思いますが、ここではお手軽お気楽な感じのngrokを使用した手順を説明します。

## ngrokのインストール

ngrokとは、ざっくり言えば各種プロトコルに対応したルーティング＆トンネリングツール（という認識）です。詳細は[ngrok公式](https://ngrok.com)を見てください。

まずはARM用のバイナリをダウンロードして解凍。

```
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
$ unzip ngrok-stable-linux-arm.zip
```

解凍するとその名も`ngrok`という名前の実行ファイル1個が出現しますので、こいつを以下の通り叩きます。普通に実行するとその後の作業ができなくなってしまうので、バックグラウンド実行するようにしています。

```
$ ./ngrok http 5050 -log=stdout > ngrok.log &
```

動作確認と兼ねて、インターネットURLを確認します。

```
$ curl http://localhost:4040/api/tunnels

{"tunnels":[{"name":"command_line","uri":"/api/tunnels/command_line","public_url":"https://abcd1234.ngrok.io","proto":"https","config":{"addr":"localhost:5050","inspect":true},"metrics":{"conns":{"count":0,"gauge":0,"rate1":0,"rate5":0,"rate15":0,"p50":0,"p90":0,"p95":0,"p99":0},"http":{"count":0,"rate1":0,"rate5":0,"rate15":0,"p50":0,"p90":0,"p95":0,"p99":0}}},{"name":"command_line (http)","uri":"/api/tunnels/command_line+%28http%29","public_url":"http://abcd1234.ngrok.io","proto":"http","config":{"addr":"localhost:5050","inspect":true},"metrics":{"conns":{"count":0,"gauge":0,"rate1":0,"rate5":0,"rate15":0,"p50":0,"p90":0,"p95":0,"p99":0},"http":{"count":0,"rate1":0,"rate5":0,"rate15":0,"p50":0,"p90":0,"p95":0,"p99":0}}}],"uri":"/api/tunnels"} 
```

ずらずらと情報が返ってきましたが、`public_url `の項目で示された`https://abcd1234.ngrok.io`が、ngrokによって払い出されたRaspberry PiにアクセスするためのURLなので、これをコピーするなどして控えておきます。

## LINE developersのWebhook URLに設定

先ほどngrokから払い出されたURLの、`/api`を設定します。

![Webhook URLの設定](http://uezo.net/img/qiita/minette_line/webhook.png)

こんな感じです。なお、サービスをまだ起動してないのでVerifyは押しても失敗します。

# LINE Messaging APIのエンドポイントとして起動

`minette`コマンドでは汎用WebAPIに加えて、LINE Messaging APIのエンドポイントのサンプル実装を起動することができます。

まずは必要なライブラリをインストールしましょう。

```
$ pip install Flask
$ pip install line-bot-sdk
```

続いて、LINE Messaging APIの利用に必要な認証関連情報を環境変数に設定します。

```
$ export LINE_CHANNEL_SECRET="あなたのチャネルシークレット"
$ export LINE_ACCESS_TOKEN="あなたのアクセストークン"
```

これで準備は完了です。エンドポイントを起動しましょう。`-l`オプションをつけます。

```
$ minette -l
```

それでは、動作確認してみましょう。

<img src="http://uezo.net/img/qiita/minette_line/line_run.png" width="375">

こんな感じで動いたら成功です。おつかれさまでした。

雑談だけのBOTはすぐに飽きると思いますので、今後、Minetteを使用した様々なスキル（機能）の追加方法について記事を投稿していこうかと思っています。