LINE から Raspberry Pi の LED を操作する 3 つのパターンを試した

## 作った物

こんなものを、3 つのパターンで作ってみました。

https://twitter.com/n_mikuni/status/1462308120894443522?s=20

## はじめに

2021 年にあった SORACOM のイベントで、個人的に印象的だったのは [SORACOM IoT Meetup #4 〜LINE 通知を使いこなそう！〜](https://blog.soracom.com/ja-jp/2021/11/18/soracom-iot-meetup-4-report/) や [SORACOM UG の LINE DC とのコラボレーションイベント](https://soracom-ug.jp/soracomug-linedc-handson1/) です。このイベントで紹介していたのは、LINE は開発者が簡単に bot を作れるため、SORACOM と組み合わせることでデバイスの温度・位置といった様々な情報を簡単に通知できることでした。これも個人の感想ですが、このイベントをもって、デバイスからデータが送信された時に [LINE Notify](https://notify-bot.line.me/ja/) を使って通知する方法はすごく整理されたなと感じました。前述のイベントでは [SORACOM Orbit](https://soracom.jp/services/orbit/) と [SORACOM Beam](https://soracom.jp/services/beam/) を組み合わせていましたし、[SORACOM Funk](https://soracom.jp/services/funk/) と AWS Lambda などの FaaS を組み合わせる方法や、[SORACOM Harvest Data](https://soracom.jp/services/harvest/) へ格納したデータをもとに [SORACOM Lagoon から通知](https://users.soracom.io/ja-jp/docs/lagoon-v2/alert-notification-channel/#line) する方法もあります (他にも [SORACOM Funnel](https://soracom.jp/services/funnel/) を使ったり [SORACOM Krypton](https://soracom.jp/services/krypton/) を使ったり、要件によって色々な構成が考えられます)。

![devices-to-line.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/4203955b-5744-59fb-bb6d-a2c8e7237efb.png)


一方で、LINE は利用者に通知を送るだけでなく、利用者からのメッセージを受け取って処理もできます。前述のイベントでも、LINE からハウスの窓開閉や給水の制御をする事例が紹介されていました。この、LINE からメッセージが送信された時にデバイスを遠隔操作する方法については、いろいろ試せそうだなと感じました。たとえば Raspberry Pi に取り付けた LED のオン・オフがしたいような場合、どのようなサービスを使うと良いのでしょうか？

![architecture-question.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/e55df744-849c-08c8-ba20-55096ab49ad1.png)

この、デバイスを遠隔操作するための構成について、実は SORACOM 公式では「双方向通信の 3 パターン」として以下のようにまとめられています。

1. IP アクセスパターン
2. アプリケーションパターン
3. デバイスリードパターン

公式の資料は [こちらのページ](https://soracom.jp/dl-device_to_cloud/) からダウンロードできますし、同じ内容を SORACOM のイベントで紹介したときの [資料](https://www.slideshare.net/SORACOM/b2-soracom-technology-camp-2020) や [動画](https://youtu.be/i6oxhgGdOko) も公開されています。

この記事では、上記の「双方向通信の 3 パターン」を、「LINE から Raspberry Pi の LED を遠隔操作する」というシナリオに落とし込んで試してみようと思います。この記事では「双方向の 3 パターンとは何か」の細かい解説はしませんが、実際に手を動かして実装していくことでどのようなものか感じてもらったり使いたいものを選ぶ参考にしてもらえればと思います。

なお、ひょっとしたらお気づきの方もいるかもしれませんが、この記事の大部分は 2021 年末に公開した [Lambda から SORACOM 経由で Raspberry Pi の LED を操作する 3 つのパターン - Qiita](https://qiita.com/n_mikuni/items/fd1c8497ca5ddb9e90a8) と重複しています。LINE 以外のインターフェイスから Lambda を経由したい場合は前述の記事も参考にしてください。

## 準備するもの

以下を使いました。セットアップ方法について細かく解説しないものもあります。

- AWS アカウント
- LINE アカウント
- SORACOM アカウント
- LINE がインストールされているスマートフォン (LINE 用)
- Raspberry Pi (3B や 4)
- 電子工作グッズ
  - ブレッドボード
  - 330Ω 抵抗
  - LED
  - ジャンパーワイヤー オス - オス 1 本
  - ジャンパーワイヤー オス - メス 2 本

電子工作グッズについては単品で買えば 1000 円もしません。Amazon などでキットも探したのですが、[ドンピシャ](https://www.amazon.co.jp/dp/B00J8W368Y) なのが在庫切れでした。少し値段が張りますが、[ラズパイ４対応　Ｒａｓｐｂｅｒｒｙ　Ｐｉで学ぶ電子工作　パーツセット](https://akizukidenshi.com/catalog/g/gK-15351/) などが良いのではないかと思います。LED やモーターなどを動かすのは楽しいですし、ふと何か作りたくなった時に持っておくと便利です。

### 費用

今回は少しの利用だったため AWS や LINE、 SORACOM はすべて無料枠で収まったはずです。そのためかかった費用は Raspberry Pi と電子工作グッズだけでした。ちなみに、今回は初期費用も掛からないことから SIM なしで SORACOM サービスを使える [SORACOM Arc](https://soracom.jp/services/arc/) を使いましたが、SIM と USB ドングルを使う場合はその分の費用も掛かります。

## 共通の構成

今回、3 パターンの構成を紹介しますが、共通しているのが 4 つあります。

1. LINE から送るメッセージの種類
2. Raspberry Pi から LED を操作する方法
3. LINE から AWS Lambda を呼び出す方法
4. SORACOM プラットフォームと接続していること

### LINE から送るメッセージの種類

LINE からは以下 3 種類のメッセージを送ります。

- 電気ついてる？
- 電気つけて
- 電気消して

![application.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/58723d5c-3c9d-393d-6e0e-e351e1c6a745.png)

シンプルですね。これが例えばエアコンであれば「今何度？」「温度上げて」「温度下げて」とかになるのではないでしょうか。「今の状態の取得」「状態の変更 (オンオフや値の上下)」という指示はよくあるシナリオになるのではないかと思いますので、ぜひ応用してみてください。

### Raspberry Pi から LED を操作する方法

どのパターンでも、共通して [gpiozero](https://gpiozero.readthedocs.io/en/stable/) を利用します。[Raspberry Pi 公式ドキュメントの L チカチュートリアル](https://projects.raspberrypi.org/en/projects/python-quick-reaction-game/2) でも使っていたためです。従って、これから色々なプログラムを Raspbery Pi 上で動かしますが、すべて Python を使おうと思います。他の言語でやってみた事例も、ぜひ見てみたいです。

### LINE から AWS Lambda を呼び出す方法

Raspberry Pi への指示は、共通して AWS Lambda から送ろうと思います。LINE から AWS Lambda を呼び出す方法としては、以下のサーバーワークス様のブログをほとんどそのまま使わせていただき、SQS を間に挟む構成としました。(ブログ転載のご許可をくださり、ありがとうございます！)

[【入門編①】Serverless Framework で 「おうむ返し」LINE Bot を作る - サーバーワークスエンジニアブログ](https://blog.serverworks.co.jp/sls-line-beginner)

`LINE --> Amazon API Gateway --> AWS Lambda -- SQS` までの構成はどのパターンも共通で、SQS からトリガーされる Lambda 以降の構成だけが異なります。そのため、SQS からトリガーする Lambda も含めて AWS へのデプロイは基本的に [Serverless Framework](https://www.serverless.com/) を使っています。Serverless Framework のインストール方法などは [公式からの日本語ブログ](https://serverless.co.jp/blog/25/) もありました。

### SORACOM プラットフォームと接続していること

[SORACOM IoT SIM](https://soracom.jp/store/13217/) や [SORACOM Arc](https://soracom.jp/services/arc/) を利用して接続します。SORACOM プラットフォームと接続することで、双方向通信の各パターンを比較的簡単に実装できます。

### 共通の構成まとめ

共通な部分、およびパターンに応じてカスタマイズする部分をまとめると、以下のようになります。

![line-to-device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/b1bbf548-a554-7efc-b7d9-ca0a28c6c171.png)

## パターン別の構成まとめ

前置きがかなり長くなりましたが、ここからはまず共通部分の構築手順を、そして各パターンの構築手順を紹介します。先にどのような各パターンがどのような構成になるか紹介しておきますので、`(共通手順)` の部分を読んだ後は、興味のあるパターンの手順だけ進めても良いかもしれません。

![summary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/9ff11204-16ee-61e3-7d5a-104156d9dd11.png)

## (共通手順) LINE Messaging API を使うため、チャネルを作成する

LINE 公式ドキュメントの [Messaging APIを始めよう | LINE Developers](https://developers.line.biz/ja/docs/messaging-api/getting-started/) がとても分かりやすいので、「LINE Developersコンソールでチャネルを作成する」の部分をすすめていけば作成できます。

## (共通手順) LINE から AWS Lambda を呼び出す

前述のとおり、以下のサーバーワークス様のブログをほとんどそのまま進めれば LINE から送信したメッセージをオウム返しする bot ができます。

[【入門編①】Serverless Framework で 「おうむ返し」LINE Bot を作る - サーバーワークスエンジニアブログ](https://blog.serverworks.co.jp/sls-line-beginner)

一点注意なのが、`bot_execute.py` 中の `X-Line-Signature` です。これは、[LINE ドキュメントに記載された注意事項](https://developers.line.biz/ja/reference/messaging-api/#webhooks) に記載されているとおり、リクエストヘッダのフィールド名について大文字小文字が変更されることがあるためです。2021 年 11 月に試した時点では `x-line-signature` で送られていたので、変更する必要がありました。

ここで取得した `LINE_CHANNEL_SECRET` と `LINE_CHANNEL_ACCESS_TOKEN` は引き続き利用するので保持しておいてください。

## (共通手順) LINE リッチメニューの設定

LINE から送信するメッセージは「電気ついてる？」「電気つけて」「電気消して」の 3 つです。文字を直接打ってもよいのですが、せっかくですからメニュー化します。

[LINE Official Account Manager](https://manager.line.biz/) にログインして、先ほど作成したチャンネルに対応する公式アカウントへアクセスします。設定方法は、[公式のマニュアル](https://www.linebiz.com/jp/manual/OfficialAccountManager/rich-menus/)がわかりやすいです。私は特に画像を設定せず、アクション A, B, C にそれぞれ送信するメッセージを設定しました。**ここから紹介するサンプルコードではこれらのメッセージがハードコードされているので、サンプルコードをそのまま使いたい場合は画像の例をそのまま「電気ついてる？」「電気つけて」「電気消して」の 3 つを設定してください。**

![line-rich-menu-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/216af8a8-808d-89bf-28e0-3058f7832980.png)

## (共通手順) Raspberry Pi から LED を操作する

この記事では Raspberry Pi のセットアップ方法は解説しません。以下のドキュメントなどを参考にすると良いかと思います。以下のドキュメントを参考にする場合は「Raspberry Pi へのログイン」までで大丈夫です。

https://users.soracom.io/ja-jp/guides/starter-kits/ultrasonic/setup-raspberry-pi/

### Raspberry Pi と LED の接続

はじめて、または久しぶりにフレットボードや LED を触る人は、まず以下の図のように配線して、プログラムを書くことなく LED が点灯することを確認してみると良いでしょう。LED の向きに注意してください。足の長い方が図中の右です。黒い線が GND、赤い線が 3.3V につながっているために、Raspberry Pi の電源が付いていれば、電気が流れて LED が点灯します。

![rasPi-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/a32b2654-7019-bc20-78fb-59d5c2adf4c9.png)

LED が点灯することを確認したら、次は以下のように接続します。この接続では、Raspberry Pi 側から指示があった時 (赤い線につながった GPIO 18 がオンとなったとき) に LED が点灯します。

![rasPi-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/e98d82da-7803-b71a-f665-1351db9b7f24.png)

### Raspberry Pi から LED の操作

Raspberry Pi 上で、以下のファイルを用意します。

```led.py
from gpiozero import LED
from time import sleep

led = LED(18)

led.on()
print(led.value)
sleep(5)
led.off()
print(led.value)
```

ファイルを置いたディレクトリ上で、以下のコマンドを実行すると、3 秒ごとに LED のオン・オフを確認でき、コンソール上で LED のオン・オフを表示できるはずです。

```screen
python3 led.py
```

このように、各パターンにおいて、LED は以下のような方法で操作します。

- LED 状態の取得: `led_state = led.value`
- 点灯: `led.on()`
- 消灯: `led.off()`

## (共通手順) Lambda が利用する SAM ユーザーの認証情報を発行する

今回は Lambda から SORACOM API を呼び出してメタデータの読み書きをしたり、リモートアクセスのための一時的な IP アドレス・ポート番号を作成したりします。Lambda から SORACOM API を呼び出すため、SAM ユーザーおよび認証情報の作成をします。

[Getting Started: SAM ユーザーを作成する | アクセス管理 (SORACOM Access Management: SAM) | SORACOM Users](https://users.soracom.io/ja-jp/docs/sam/create-sam-user/) にしたがって SAM ユーザーを作成します。「[認証キーの生成](https://users.soracom.io/ja-jp/docs/sam/create-sam-user/#%e8%aa%8d%e8%a8%bc%e3%82%ad%e3%83%bc%e3%81%ae%e7%94%9f%e6%88%90)」で生成した認証キーと認証シークレットは次の手順で使うので保持しておいてください。

[SAM ユーザーの権限設定](https://users.soracom.io/ja-jp/docs/sam/create-sam-user/#sam-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E6%A8%A9%E9%99%90%E8%A8%AD%E5%AE%9A) では、以下の権限を設定します。`statements` の配列中の 1 つ目の要素が IP アクセスパターンで利用する権限、2 つ目の要素がデバイスリードパターンで利用する権限です。

```json
{
  "statements": [
    {
      "api": [
        "PortMapping:createPortMapping",
        "PortMapping:deletePortMapping"
      ],
      "effect": "allow"
    },
    {
      "api": [
        "Subscriber:putSubscriberTags",
        "Subscriber:getSubscriber"
      ],
      "effect": "allow"
    }
  ]
}
```

## (共通手順) Raspberry Pi を SORACOM に接続する

SORACOM のサービスを使うことで、遠隔操作がより簡単になります。SORACOM のサービスを使うために、Raspberry Pi を SORACOM へ接続しましょう。

今回は、SIM なしで SORACOM サービスを使える SORACOM Arc を用いました。以下の手順に則ってセットアップできます。

https://users.soracom.io/ja-jp/docs/arc/bootstrap-authkey/

SORACOM の IoT SIM を使う場合は SORACMO Onyx LTE USB ドングルなどを使って、以下のドキュメントの手順でセットアップできます。 

https://users.soracom.io/ja-jp/guides/devices/general/raspberry-pi-dongle/

以下のように SORACOM 上の PING 疎通確認用エンドポイントへ PING を送信して、SORACOM へ接続できていることを確認しましょう。 **各手順において、SORACOM へ接続できている必要があるので注意してください。**

```screen
ping pong.soracom.io
```

## (共通手順) サンプルプログラムのダウンロード

サンプルプログラムは以下の GitHub リポジトリにあります。`raspberry_pi` 配下には Raspberry Pi にて実行するプログラム、`Lambda` 配下には Lambda にて実行するプログラムがあります。Serverless Framework をインストールした PC にてリポジトリのクローン、または zip ファイルのダウンロードと解凍をしてください。

https://github.com/nmikuni/line-lambda-soracom-raspi-led

---

それでは、それぞれのパターンを使って LED の遠隔操作をしてみましょう！

## IP アクセスパターンの構築手順

IP アクセスパターンでは、Raspberry Pi 上で [Flask](https://flask.palletsprojects.com/en/2.0.x/) を使って Web サーバーを建てます。HTTP GET リクエストが来たら LED の状態を返し、PUT リクエストが来たら Body に応じて LED をオンオフするというシンプルな構成です。Flask は Raspberry Pi 上で `pip3 install flask` を実行してインストールします。
Raspberry Pi 上の Web サーバーには、SORACOM Napter でアクセスします。SORACOM Napter は、SORACOM の SIM へインターネット越しにアクセスするため、一時的なグローバル IP アドレス・ポート番号をアクセス元を制限して払い出すオンデマンドでセキュアなリモートアクセスサービスです。一時的なアクセス情報は SORACOM API を呼び出して取得します。図にすると以下のとおりです。

![ip-access.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/8342850b-3a24-d4ae-a27e-cef83fefb696.png)

### Raspberry Pi の準備

Flask は Raspberry Pi 上で `pip3 install flask` を実行してインストールします。その後、以下のコマンドでサンプルプログラムを Raspberry Pi にダウンロードして、`python3 ip_access.py` で実行します。Flask が立ち上がり、IP アクセスを待ち受けます。

```
wget https://raw.githubusercontent.com/nmikuni/line-lambda-soracom-raspi-led/master/raspberry_pi/ip_access.py
```

### AWS の準備

1. ダウンロードしたサンプルコードの `lambda//ip_access_pattern` ディレクトリ配下に移動します。
2. `cp sample.env .env` で ENV ファイルをコピーします。
3. `.env` に、これまでの手順で控えておいた認証情報や IMSI を記載します。
4. `sls deploy` コマンドでデプロイします。

Raspberry Pi と AWS の準備ができたら、LINE から LED を操作しましょう。Raspberry Pi 側のコンソールログを見ても、アクセスが来ていることがわかるかと思います。

## アプリケーションパターンの構築手順

アプリケーションパターンでは Raspberry Pi 上で [paho-mqtt](https://pypi.org/project/paho-mqtt/) を使って MQTT クライアントとしてふるまいます。MQTT ブローカーには AWS IoT を用いて、LED オン・オフの指示を受けたり、自身の LED の状態を報告したりします。また、AWS IoT Shadow を利用することで、LED がとるべき状態 (`desired`)・現時点での LED の状態 (`reported`)・および desired と reported の差分 (`delta`) を管理します。SORACOM Beam を用いることで、AWS IoT の認証情報を Raspberry Pi に持たせることなく AWS IoT と接続できます。図にすると以下のとおりです。

![application.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/d544029a-babd-335c-0540-7d7a5052989b.png)

### AWS IoT と SORACOM Beam の準備

Raspberry Pi から SORACOM Beam 経由で AWS IoT Core へ接続します。以下のドキュメントを参照してください。

https://users.soracom.io/ja-jp/docs/beam/aws-iot-console/

なおこの時、モノの名前は `raspberry-pi`、Device Shadow には名前付きシャドウ `led` を作成してください (別の名前を使った場合は、サンプルコードの修正が必要になります)。

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/627cb850-495b-6d1d-872f-5f19be568a0b.png)
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/930abdc2-29b3-5d9e-8ccf-982e1a5c8ce7.png)

また、SORACOM Beam の「ホスト名」に登録した AWS IoT Core の `xxxxx-ats.iot.ap-northeast-1.amazonaws.com` といったカスタムエンドポイントは後続の手順で使用するので控えておいてください。

Raspberry Pi から `mosquitto_pub -d -h beam.soracom.io -t beamdemo -m "Hello, World"` で AWS IoT へメッセージを送信できれば成功です。なお `mosquitto_pub` は  `sudo apt install mosquitto-clients` でインストールできます。

### AWS IoT Shadow の準備

AWS IoT Core のメニューよりサイドバーの「モノ」=> 「Device Shadow」タブ => 「led」(シャドウ名) を選択します。

![aws-iot-shadow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/4c89d6c1-a7d0-4acc-8dc8-65a93d2fcee2.png)

「編集」をクリックして、以下のように Shadow の初期状態を更新します。

```json
{
  "state": {
    "desired": {
      "led": "0"
    },
    "reported": {
      "led": "0"
    }
  }
}
```

### Raspberry Pi の準備

paho-mqtt は Raspberry Pi 上で `pip3 install paho-mqtt` を実行してインストールします。その後、以下のコマンドでサンプルプログラムを Raspberry Pi にダウンロードして、`python3 application.py` で実行します。成功すれば一定間隔で LED の状態を SORACOM Beam 経由で AWS IoT へ Publish します。

```
wget https://raw.githubusercontent.com/nmikuni/line-lambda-soracom-raspi-led/master/raspberry_pi/application.py
```

### AWS の準備

1. ダウンロードしたサンプルコードの `lambda/application_pattern` ディレクトリ配下に移動します。
2. `cp sample.env .env` で ENV ファイルをコピーします。
3. `.env` に、これまでの手順で控えておいた認証情報や AWS IoT Core のカスタムエンドポイントを記載します。
4. `sls deploy` コマンドでデプロイします。

Raspberry Pi と AWS の準備ができたら、LINE から LED を操作しましょう。Raspberry Pi 側のコンソールログを見ても、MQTT の メッセージが来ていることがわかるかと思います。

なお、今回は SORACOM Beam + MQTT を使いましたが、他にも [SORACOM Inventory](https://soracom.jp/services/inventory/) (LwM2M) や [SORACOM Krypton](https://soracom.jp/services/krypton/) (認証情報を SORACOM から取ってきて用いる) を使った実装も考えられます。

## デバイスリードパターンの構築手順

デバイスリードパターンでは Raspberry Pi の LED 状態を SIM のタグに保管します。Raspberry Pi は一定間隔でメタデータサービスを利用してタグの取得・更新をします。また Lambda から LED 情報の取得・更新をしたいときも SORACOM API を利用してSIM のタグへアクセスします。図にすると以下のとおりです。

![device-lead.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/0bb4ddcc-05c0-e0e7-2c9a-6149becd04b8.png)

### SORACOM の準備

以下のドキュメントを参照してメタデータサービスを有効にします。書き込みもするため、「読み取り専用」のチェックは外して下さい。

https://users.soracom.io/ja-jp/docs/air/use-metadata/

### Raspberry Pi の準備

以下のコマンドでサンプルプログラムを Raspberry Pi にダウンロードして、`python3 device_lead.py` で実行します。成功すれば一定間隔でタグに指定された LED の状態を取得して自身の LED へ反映し、自身の LED 状態をタグへ書き込みます。

```
wget https://raw.githubusercontent.com/nmikuni/line-lambda-soracom-raspi-led/master/raspberry_pi/device_lead.py
```

### AWS の準備

1. ダウンロードしたサンプルコードの `lambda/device_lead_pattern` ディレクトリ配下に移動します。
2. `cp sample.env .env` で ENV ファイルをコピーします。
3. `.env` に、これまでの手順で控えておいた認証情報や IMSI を記載します。
4. `sls deploy` コマンドでデプロイします。

Raspberry Pi と AWS の準備ができたら、LINE から LED を操作しましょう。ほかのパターンと違って面白いのは、Raspberry Pi 側のコンソールログを見ると、LINE から指示されたタイミングとは関係なく、自分のペースでタグの確認・LED の更新をしている点です。

なお、今回はタグを用いましたが、メタデータサービスのユーザーデータや、クラウド上の DB を使うことも考えられます。

## おわりに

ここまでお付き合いくださりありがとうございました。LINE で IoT デバイスを操作するときのヒントになれば幸いです。かなり長文になったにもかかわらずまとめ切れていないところや説明が十分でないところもありますので、疑問点などあればコメントや [Twitter](https://twitter.com/n_mikuni) でご連絡ください。