ミニチュアIoT家電をAWS IoT + SORACOM Beamで制御してみよう


#はじめに
この記事は、[JAWS Festa 東海道 2016](http://jft2016.jaws-ug.jp/)で行われる「[IoTハンズオン「ミニチュアIoT家電をAWS IoT + SORACOM Beamで制御してみよう」](http://jaws-ug-tokaido.connpass.com/event/40394/)」のハンズオン用資料です。

<hr>
このハンズオンは、SORACOM Beam経由でAWS IoTに接続するため、まずはSORACOM Airでインターネット接続しておく必要があります。そのため「[SORACOM x RaspberryPi ハンズオン 〜超音波センサー編〜](https://github.com/soracom/handson/blob/master/ultrasonic-sensor/seminar.md)」ハンズオン用テキストを使って、SORACOMユーザーアカウントの作成からSORACOM Air SIMでインターネットに接続するところまで行ってください。
以下に示す1章から3章までを実施してください。

* [1章 ユーザーコンソールを使用してAir SIMを管理する](https://github.com/soracom/handson/blob/master/ultrasonic-sensor/seminar.md#section1)
* [2章 Raspberry Piへの接続](https://github.com/soracom/handson/blob/master/ultrasonic-sensor/seminar.md#section2)
* [3章 Air SIMを使って、インターネットに接続する](https://github.com/soracom/handson/blob/master/ultrasonic-sensor/seminar.md#section3)

<hr>

#[Step 1]ミニチュアIoT家電「LEDのあかり」をつくる

####[Step 1.1]部品・材料の確認
以下の図にある部品を確認してください。
![Kobito.rdjENy.png](https://qiita-image-store.s3.amazonaws.com/0/4092/66b41c7f-92a0-1786-aeb5-726bb04d265f.png "Kobito.rdjENy.png")
**あと、紙コップ1個いります！**

まずは、抵抗の片方の足を切ります。
![Kobito.7d97YQ.png](https://qiita-image-store.s3.amazonaws.com/0/4092/72f9a6c1-70ee-aae4-8228-e3647f473165.png "Kobito.7d97YQ.png")



LEDのみじかい足と抵抗をねじってつなぎます。
![Kobito.0xpd1T.png](https://qiita-image-store.s3.amazonaws.com/0/4092/975f5253-6e70-1e4e-7f0c-d5322815350e.png "Kobito.0xpd1T.png")

黒い線を抵抗に、青い線をもう一方につなぎます。つないだらセロテープで固定しましょう。
![Kobito.oANSRY.png](https://qiita-image-store.s3.amazonaws.com/0/4092/2cd9d2c6-bff0-5978-5323-cf71fe99bff6.png "Kobito.oANSRY.png")


黒い線と青い線同士をつなぎます。
![Kobito.7sLQAo.png](https://qiita-image-store.s3.amazonaws.com/0/4092/f1059010-5734-4a72-a7fe-47099676bf26.png "Kobito.7sLQAo.png")

以下のようにラズベリーパイにつなぎます。LEDのマイナス側と抵抗を11番ピンに、LEDのプラス側を20番ピンに接続します。
![Kobito.5KbKQ2.png](https://qiita-image-store.s3.amazonaws.com/0/4092/c465c01f-4a02-8235-2d72-270222f1682b.png "Kobito.5KbKQ2.png")

####[STEP 1.2]Lチカ動作確認
LED点滅のPythonソースを以下のコマンドでダウンロードし、実行して動作の確認をします。

```python
$ curl -O https://gist.githubusercontent.com/yoshidaken1/b4821b8520c098ec96d166e3f812a53b/raw/8a543683f7f8df3e7cb15ce6ed1ba426b3100597/blink.py
$ python blink.py
```

LEDが点滅したら、`[Ctrl]+C`キーを押してブレイクします。

####[STEP 1.3]LEDあかりの完成
接続確認ができたので、LEDあかりのデコレーションを行います。
![Kobito.rFARtv.png](https://qiita-image-store.s3.amazonaws.com/0/4092/703d012e-fec2-8c84-9e0a-cc3e43c2d87f.png "Kobito.rFARtv.png")

紙コップに切り目を入れます。カッターで十字に切り目を入れてください。
![Kobito.CFtAbB.png](https://qiita-image-store.s3.amazonaws.com/0/4092/71ea96ee-4f34-28b5-7b5d-252798f4b3af.png "Kobito.CFtAbB.png")

LEDあかりの完成です！!
![Kobito.HoyNB6.png](https://qiita-image-store.s3.amazonaws.com/0/4092/96a4cef3-c52b-917b-c814-174267d474ab.png "Kobito.HoyNB6.png")
一旦、ケーブルを抜くとピンポン玉をコップに入れやすいです。
あと、紙コップのフチに切り目を入れるとケーブルを納めやすいかも。


#[Step 2]AWS-IoTのThingsでラズパイにプッシュを行う

AWS-IoTでThingsを作成し、MQTTのやりとり(Pub/Sub)を行います。

##[Step 2.1]AWS-IoT Thingsを作成
まず[AWSマネジメントコンソール](https://aws.amazon.com/jp/console/)からAWS IoTの管理画面にアクセスします。
![Kobito.UjO87j.png](https://qiita-image-store.s3.amazonaws.com/0/4092/4ed2ade5-ed52-8c1d-da04-eaefd142af80.png "Kobito.UjO87j.png")
 
[Get started]ボタンをクリックして始めます。
![Kobito.EsQmhx.png](https://qiita-image-store.s3.amazonaws.com/0/4092/53023ef3-88c7-768d-0b83-ca07cb64fbb4.png "Kobito.EsQmhx.png")

[Create Things]ボタンが選択された状態になり、Thingの作成のため、[Name]欄に任意の名前を入れて、[Create]ボタンをクリックします。ここでは「MyNewThing」としました。
![Kobito.8HDeWC.png](https://qiita-image-store.s3.amazonaws.com/0/4092/c559a5f5-1db2-dacd-8ef4-7574bcae040b.png "Kobito.8HDeWC.png")
thingが作成され表示されています。
[View Thing]ボタンをクリックします。REST API endpointなどの詳細が表示されます。
![AWS_IoT01.png](https://qiita-image-store.s3.amazonaws.com/0/4092/7e972a57-85d6-c4ee-0182-5887d83aad38.png "AWS_IoT01.png")


##[Step 2.2]キーペア(公開鍵、秘密鍵)のダウンロード及び証明書をダウンロードして作業PCで表示させる
AWS IoTでは通信を行う際にTLSによる暗号化を行って通信を行います。
TLS通信の際に必要な証明書やキーペアのダウンロードを行います。
先ほど登録したMyNewThingの詳細を表示している画面の右下の[Connect a device]というボタンを押下します。
![Kobito.vE8A90.png](https://qiita-image-store.s3.amazonaws.com/0/4092/fe715b89-427f-94a9-9a89-0f89943695ea.png "Kobito.vE8A90.png")

次の画面ではThingとAWS IoTとの通信は何を使って行うかの確認画面が表示されます。今回はPythonを使うのですが、とりあえず[Node.js]をチェックします。[Generate certificate and policy]というボタンが表示されるので選択し、証明書とポリシーを作成します。
しばらく待つと以下の画面になります。
![Kobito.47ECql.png](https://qiita-image-store.s3.amazonaws.com/0/4092/7d9a3641-12d5-963e-cef4-c7649573802c.png "Kobito.47ECql.png")

３つのリンクが現れます。

* 公開鍵のダウンロード（今回使わない）
* 秘密鍵のダウンロード
* 証明書のダウンロード

各リンクをクリックし、作業PC上に保存しておきます。作業PC上に「awsiot_MyNewThing」などのフォルダを作成しそちらに一括して保存しておきます。


* xxxxx-public.pem.key->公開鍵（今回使わないけど念のためダウンロード）
* xxxxx-private.pem.key->秘密鍵
* xxxxx-certificate.pem.crt->証明書

[Comfirm & start connecting]ボタンをクリックします。

![AWS_IoT02.png](https://qiita-image-store.s3.amazonaws.com/0/4092/5307ad21-36c5-2088-3c41-d92b336b076d.png "AWS_IoT02.png")


Thingの接続情報が表示されますので、作業PCにコピーしておきます。これも作業PC上に「awsiot_MyNewThing」などのフォルダを作成しそちらに一括して保存しておきます（ファイル名はなんでも構いません。「MyNewThing.json」などとしておきます）。
[Return to Thing Detail]ボタンをクリックしResources画面に戻ります。PolicyとCertificationが一覧にリストアップされています。
![AWS_IoT03.png](https://qiita-image-store.s3.amazonaws.com/0/4092/53173af6-a10d-dca1-eeea-317096e7560d.png "AWS_IoT03.png")

ダウンロードしたファイルをエディタで表示させ、コピー＆ペーストできる状態にしておきます。
* 秘密鍵のファイル xxxxx-private.pem.key
* 証明書のファイル xxxxx-certificate.pem.crt

##[Step 2.3]ルート証明書をブラウザで表示させておく
SSL/TLS通信ではサーバーから取得したデジタル証明書が正当なものであるか確認する必要があります。幾つかの認証局はルート証明書としてブラウザなどに最初から登録されているため、我々が通常見るようなサイトを閲覧する際にわざわざルート証明書をダウンロードする必要はありません。ただし、今回は通信をするのがブラウザではないため、対象のルート証明書だけ予めダウンロードする必要があります。
作業PCのブラウザ画面にて以下のURLにアクセスしルート証明書を表示させておきます。あわせて作業PC上に「awsiot_MyNewThing」などのフォルダを作成しそちらに保存しておきます。ファイル名は「root-CA.crt」にします。


* [https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem)

次のステップでは、上記３つの鍵もしくは証明書のテキストをSORACOM Beamの証明書設定欄にペーストし設定します。

##[Step 2.4]SORACOM Beamの設定
SORACOM BeamはSORACOMコンソールの「グループ」に設定します。Beamを利用したいSORACOM Air SIMに対し所属グループを設定させることで利用可能になります。

ブラウザから[SORACOMコンソール](https://console.soracom.io/)にアクセスし、ナビゲーションメニューから「グループ」を選びます。
![Kobito.sShpxD.png](https://qiita-image-store.s3.amazonaws.com/0/4092/676f2cf8-81dc-9a4a-e35f-f9a62241c227.png "Kobito.sShpxD.png")
「追加」ボタンをクリックし、グループ作成ダイアログからグループ名を「awsiot」として「グループ作成」ボタンをクリックします。できあがった「awsiot」のグループ名をクリックし以下の設定画面を表示させます。
![Kobito.SkWCzL.png](https://qiita-image-store.s3.amazonaws.com/0/4092/d18a265d-0e95-087e-963d-cebb1b9acc65.png "Kobito.SkWCzL.png")
「SORACOM Beam設定」をクリックし、「＋」ボタンをクリックして「MQTTエントリポイント」を選びます。
![Kobito.3SE9Ce.png](https://qiita-image-store.s3.amazonaws.com/0/4092/b916d0e8-8277-f5f6-ddf6-78ecc8e26ff0.png "Kobito.3SE9Ce.png")

「SORACOM Beam - MQTT 設定」ダイアログにて、以下の表のように設定します。

| 項目 | 内容 |
|----|----|
| 設定名 | awsiot |
| ポート番号 | 8883 |
| ホスト名 | 「MyNewThing.json」ファイルのhostキーの文字列 |

ホスト名を「[Step 2.1]キーペア(公開鍵、秘密鍵)のダウンロード及び証明書をダウンロードして作業PCで表示させる」でテキストエディタでコピーしておいたJavaScriptのソース（作業PC上の「awsiot_MyNewThing」フォルダ内の「MyNewThing.json」ファイル）のhostキーの文字列を使います。

![Kobito.iq6xgq.png](https://qiita-image-store.s3.amazonaws.com/0/4092/9d12babf-0b6f-5661-62d8-7d45ed271bbf.png "Kobito.iq6xgq.png")
__※「[Step 2.1]キーペア(公開鍵、秘密鍵)のダウンロード及び証明書をダウンロードして作業PCで表示させる」でテキストエディタでコピーしておいたNode.jsのソース（作業PC上の「awsiot_MyNewThing」フォルダ内の「MyNewThing.js」ファイル）のhostキーの文字列__
![Kobito.3jfRNp.png](https://qiita-image-store.s3.amazonaws.com/0/4092/310352b0-a634-f522-5ddb-86c451af68de.png "Kobito.3jfRNp.png")

次に、SORACOM Beam - MQTT 設定」ダイアログをスクロールし、「証明書」トグルボタンをONにし、「＋」ボタンをクリックして証明書の設定を行います。
![Kobito.m4YrqL.png](https://qiita-image-store.s3.amazonaws.com/0/4092/be2f88a3-6ec0-aafe-673a-11a2ff6f3275.png "Kobito.m4YrqL.png")

「認証情報ID」を任意のもの（例えば「awsiot」など）にして、３つの鍵もしくは証明書情報をペーストします。

| 項目 | 内容 |
|----|----|
| 「認証情報ID」 | awsiot |
| 「秘密鍵 (key)」 | 秘密鍵のファイル xxxxx-private.pem.keyのテキスト |
| 「証明書 (cert) 」 | 証明書のファイル xxxxx-certificate.pem.crtのテキスト |
| 「CA証明局」 | ブラウザで表示させておいたルート証明書のテキスト |

![Beam認証情報設定.png](https://qiita-image-store.s3.amazonaws.com/0/4092/18a848ea-a3c4-dea7-4a81-de80650e8edf.png "Beam認証情報設定.png")


３つの鍵もしくは証明書情報をペーストしたら右下の「登録」ボタンをクリックします。認証情報が設定されているのを確認して右下の「保存」ボタンをクリックし設定を完了します。
![Kobito.h1nCIA.png](https://qiita-image-store.s3.amazonaws.com/0/4092/5585e023-969c-7d03-3797-e473edb52f89.png "Kobito.h1nCIA.png")

SIMのグループ割り当て
Beamの設定を行ったグループを作成することができたら、SIM管理画面から、SIMを選択して、操作→所属グループ変更を押します。

![Kobito.y5PGkY.png](https://qiita-image-store.s3.amazonaws.com/0/4092/06705938-367a-3cf0-93b6-d62a87bee4ae.png "Kobito.y5PGkY.png")



##[Step 2.5]Pythonソースを用いてAWS-IoTのThingでMQTT Publish/Subscribeする

作業PCのラズパイSSH接続のターミナル画面に戻ります。MQTTのPythonライブラリPahoをインストールしておきます。

```bash
$ sudo pip install paho-mqtt
```

AWS-IoT Thing(MQTT Broker)のデータを受け取り（Subscribe:購読）、LEDに反映させるサンプルソース`sub_led.py`を`python_awsiot`ディレクトリ内などに作成します。

* [sub_led.py](https://gist.github.com/yoshidaken1/80c51dc1b9ef297b91ebe8caf25b95ff#file-sub_led-py)


サンプルソース`sub_led.py`を入力し終えたら、以下のコマンドで実行してみましょう。うまく接続されていれば上記のようなログ表示が1行表示されます。


```bash:Subscribe側待ち受けのターミナル画面
$ python sub_led.py
status 0

```

次に、新しいターミナル画面を開きSSH接続します。
そこでLEDを1秒おきにオン・オフするデータを送る（Publish:発信)サンプルソース`sub_led_onoff.py`を`python_awsiot`ディレクトリ内に作成します。

* [pub_led_onoff.py](https://gist.github.com/yoshidaken1/80c51dc1b9ef297b91ebe8caf25b95ff#file-pub_led_onoff-py)


サンプルソース`pub_led_onoff.py`を入力し終えたら、以下のコマンドで実行してみましょう。1秒おきにトピック宛に0または1が送信されています。


```bash:Publish側送信のターミナル画面
$ python pub_led_onoff.py
pub:nic/52/2f/5226/led/01 0
pub:nic/52/2f/5226/led/01 1
pub:nic/52/2f/5226/led/01 0
pub:nic/52/2f/5226/led/01 1
pub:nic/52/2f/5226/led/01 0
^C ←中止する際は[Ctrl+C]
```

この時、LEDが1秒おきに点滅すればSORACOM Beam経由でLEDのオン・オフ情報がpub/subできていることになります。

以上で、AWS IoT Thingを使ってLEDのオン・オフを行うことができました！

##[Step 2.6]作業PCなどからPublishしてLEDをオン・オフさせる
最後に作業PCなどから作成したAWS-IoT ThingにPublishしてLEDをオン・オフさせてみます。作業PCの`awsiot_MyNewThing`などのフォルダに保存した秘密鍵・デバイス証明書・ルート証明書を指定すれば、以下の方法でPub/Subさせることができます。

* Mosquitto Clientコマンド
* AWS IoT SDK for Pythonを利用したPython3ソース
* AWS IoT SDK for JavaScriptを利用したnode.jsソース

Mosquitto Clientは、Mac/Winともにコマンド類のインストールが必要になります。Pythonソースの場合TLS1.2対応Open SSLライブラリの関係上Python 2.7では動かずPython3.4が必要になります（工夫次第でいけそうですが時間の都合上断念orz）。
今回は、node.jsソースを使いました。node.jsですとフロントエンドを揃えてブラウザ上で実装もしやすいので、ハンズオン後ぜひブラウザ実装をやってみてください。

※作業PCにnode.jsの実行環境がないMac/Winの場合、インストールしていただくかEC2やVirtualBoxなどでnode.jsの実行環境をご用意くださいm(_ _)m




作業PCにある`awsiot_MyNewThing`などのフォルダに以下に示す`pub_led.js`を作成します。
`pub_led.js`は、AWS IoT SDK for JavaScriptを使っているので、あらかじめnpmでライブラリをインストールしておきます。

```bash
$ npm install aws-iot-device-sdk
$ vim pub_led.py
```

device変数のjson部分を自分の`MyNewThing.json`に差し替えます。

```python:pub_led.js
var awsIot = require('aws-iot-device-sdk');
//json部分を差し替える
var device = awsIot.device(
{
    "host": "-------------.iot.ap-northeast-1.amazonaws.com",
    "port": 8883,
    "clientId": "MyNewThing",
    "thingName": "MyNewThing",
    "caCert": "root-CA.crt",
    "clientCert": "**********-certificate.pem.crt",
    "privateKey": "**********-private.pem.key"
}
);
var topic = "nic/52/2f/5226/led/01";
// Device is an instance returned by mqtt.Client(), see mqtt.js for full
// documentation.
device.on('connect', function() {
    console.log('connect');
    //device.publish('nic/52/2f/5226/led/01', JSON.stringify({ test_data: 1}));
    //device.publish(topic, '1');
    //device.publish(topic, '0');
    if(process.argv.length > 2){ 
        //引数が3あればargv[2]をpayloadとしてpublishする
        device.publish(topic, process.argv[2]);
        console.log("pub:", topic,process.argv[2]);
    }else{
        //引数なしの場合0（オフ）をpublishする
        device.publish(topic, 0); 
        console.log("pub:", topic, 0); 
    }   
});

```
保存したらnodeコマンドで実行します。コマンド引数に1を入れるとLEDがオン、0を入れるかコマンド引数なしだとLEDがオフになります。

```bash:引数が1だとオン、0だとオフ。
$ node pub_led.js 1
connect
pub: nic/52/2f/5226/led/01 1
^C ←[Ctrl+C]で中止
```

以上で、外部からのオン・オフが可能になりました。
SORACOM Beamでは、認証情報（秘密鍵、デバイスの証明書、ルート証明書）をSORACOM側に置いておくため（クラウド側へのオフロード）、デバイス側で認証情報を保持しておく必要がありません。
遠隔地に設置するシチュエーションが多いラズパイ側に認証情報をバラ撒くよりもSORACOM Beamで一括しておいたほうが安全といえます。