AWS IoT で固定IPの振られていないPCを緊急停止してピンチを回避する（サンプルコード付き）



# はじめに
* 仕事やプライベートでも[AWS IoT](https://aws.amazon.com/jp/iot/)を活用するシーンが増えている今日このごろです。
* AWS IoTを使えば、簡単にMQTTのPub/Subが実現できます。自分としては、なんとなく読めるJavaのSDKも用意されてるので、デバイス側の実装も容易です。
* Subscribeを活用したデバイス側の実装としては、以下のような構成で固定IPの振られていない自宅PC（デバイス）に、Subscribeをトリガに処理するといったことが考えられます。
![skitch.png](https://qiita-image-store.s3.amazonaws.com/0/39596/aca0b50d-134e-c525-fb89-e4f194a35f35.png "skitch.png")

* 例えばリモートから自宅PCを緊急停止してピンチを回避することが可能だったりします。今まで、外出中に急に母親からLINEで「あなたの部屋掃除しておくね」とか言い出された時に ＼(^o^)／ｵﾜﾀ となってた人必見です。
* ということで、AWS IoTの簡単な使い方を説明しつつ、IoTとは少し違ったカタチでAWS IoTを活用する方法を紹介します。
* 因みに、今回はDeviceShadowは登場しません。
* 今回は自宅PCをWindowsと仮定して実装していますが、ちょっとアレンジすればラズパイでも使えますし、シャットダウン以外の処理でも流用可能です。

# 実現すること概要
* 自宅PCの常駐プログラムが一定時間毎にPublishすることでPCのステータスチェックを知る機能と、常駐プログラムが特定TopicのSubscribeを行い、SubscribeをトリガにOSシャットダウンを知らせるPublishして、シャットダウンコマンドの実行を行う機能を実現します。
* 以下 3Topicのやりとりで実現します。
	* topic/healthcheck：常駐プログラムが定期的にPublishするTopic。
	* topic/shutdown：常駐プログラムがSubscribeするTopic。当該Topicを受け取るとシャットダウンコマンドが実行される。
	* topic/shutdownNotify：常駐プログラムがシャットダウンコマンド実行直前にPublishするTopic。

![貼り付けた画像_2017_02_24_0_02.png](https://qiita-image-store.s3.amazonaws.com/0/39596/cd772e78-c060-a915-a56b-b5d0800b2ff0.png "貼り付けた画像_2017_02_24_0_02.png")


* 使ったソースはGithubで公開しておきます。
https://github.com/ukitiyan/desktop-iot


# AWS IoTのセットアップ

## Thingsの登録
* Register Thingsを選択します。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/b14bca32-a5a8-88f0-93fa-a9c839d9cf02.png "AWS_IoT.png")

* Nameは適当に指定してください。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/bf787330-9e9f-365e-a93c-77155b069218.png "AWS_IoT.png")

## Ruleの作成
* 自宅PC（デバイス）から定期に生存情報を送信して、AWS IoT経由でSNSでEMail送信するための設定情報としてRuleを作成します。
* トップのRuleメニューからCreate a ruleを選択します。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/04870b2e-d7d5-6aab-8932-d02094744eec.png "AWS_IoT.png")

* RuleNameとActionの条件である、Attribute、Topic filterを指定し、Add ActionからSNSを指定して、Create roleしてください。
![貼り付けた画像_2017_02_22_1_06.png](https://qiita-image-store.s3.amazonaws.com/0/39596/8c945681-942e-24ae-ed03-a25985378895.png "貼り付けた画像_2017_02_22_1_06.png")

* Add ActionからSNSを指定するのも以下のとおりです。（簡単です。）
![貼り付けた画像_2017_02_22_1_04.png](https://qiita-image-store.s3.amazonaws.com/0/39596/7ae08acd-9718-a766-e242-f7ba041bdbcc.png "貼り付けた画像_2017_02_22_1_04.png")

* この時点でAWS IoTに「topic/healthcheck」TopicがPublishされるとRuleが発動して、SNS経由でEmailが送信されるはずです。
* AWS IoTにはTestSimulatorが用意されているので、そこからPublishしてEmailが受信されるか確認しましょう。
<img src="https://qiita-image-store.s3.amazonaws.com/0/39596/3fa25c68-642e-2eec-c800-1be5e9d0ba90.png" width="700" />

## Thingsに紐付ける証明書の作成・ダウンロード
* デバイスからはAWS IoTから発行される証明書を利用して、AWS IoTに接続するため、証明書の作成・ダウンロードを行います。
* Create Certificateを選択します。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/03c45ade-1d50-52fa-c59f-81ac66da59bd.png "AWS_IoT.png")

* 証明書をダウンロードして有効化してます。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/6cba802a-bdb5-5b6f-e795-bbbb8abf200b.png "AWS_IoT.png")

## Policyの作成
* 証明書のPolicyを作成します。
* トップのSecurity-PoliciesメニューからをCreate a Policyを選択します。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/5a66ddfa-91df-5b13-aa30-85727fe15068.png "AWS_IoT.png")

* PolicyNameの入力、statement（Action「iot:*」、ResourceARN「*」、Effect「Allow」）を設定し、Createを選択します。
![skitch.1.png](https://qiita-image-store.s3.amazonaws.com/0/39596/f0a763f2-2e61-f237-db4c-38249e05352b.png "skitch.1.png")


* 先程作成した証明書にPolicyをAttacheします。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/5782463e-392c-4029-9aad-fbb25bf0e84b.png "AWS_IoT.png")
<img src="https://qiita-image-store.s3.amazonaws.com/0/39596/55410ec3-d6a3-d727-a535-e60114d0dd89.png" width="350" />

## エンドポイントの確認
* エンドポイントをチェックして、控えておいてください。
![AWS_IoT.png](https://qiita-image-store.s3.amazonaws.com/0/39596/4007d342-dd56-0a58-03ef-b23b9041f752.png "AWS_IoT.png")

# 自宅PCに常駐させるJavaプログラムのセットアップ

## 証明書の配置
* 先程AWS IoTからダウンロードした証明書をPCの適当な場所に配置します。
	* 例： C:/aws/xxxxxx-certificate.pem.crt
	* 　　 C:/aws/xxxxxx-private.pem.key
* 以下からJavaのソースをcloneします。
https://github.com/ukitiyan/desktop-iot

* 必要に応じてapplication.ymlの以下を編集して、ビルドしてください。（もちろん編集せずに起動時に環境変数で渡してもOKです。）
	* clientEndpoint：AWS IoTで取得したendpoint
	* clientId：任意のClientId
	* certificateFile：xxxxxx-certificate.pem.crtの配置パス
	* privateKeyFile：xxxxxx-private.pem.key
	* thingName：AWS IoTで設定したThingsName

<script src="https://gist.github.com/ukitiyan/476714ca9bcffc5ada70c8c45c0e686d.js"></script>

* target/desktop-iot-0.0.1-SNAPSHOT.jarがビルドされるので、以下のコマンドで実行します。（jre8は入ってる前提です。）

```
java -jar target/desktop-iot-0.0.1-SNAPSHOT.jar
```

# 動作確認
## 3600秒（1時間）毎に「topic/healthcheck」TopicがPublishされるか
* 自宅PCに配置したプログラムは、3600秒（1時間）毎に「topic/healthcheck」TopicをPublishします。
* プログラム実行してから、1時間後にSNSに設定したEmail宛に`{"status": "Active"}`のようなメッセージが受信されるか確認します。

## AWS IoTに「topic/shutdown」TopicをPublishすると自宅PCがシャットダウンするか
* 自宅PCに配置したプログラムは、「topic/shutdown」TopicをSubscribeしていて、Topicを受信すると「topic/shutdownNotify」TopicをPublishしてから、OCシャットダウンコマンドを実行します。
* Publish用のアプリを作っても良いですが、今回もTestコンソールを使って、当該TopicをPublishします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/39596/0343aa29-9950-0ba1-e802-ceb1cfea0379.png" width="700" />
* 「topic/shutdownNotify」がPublishされること、その後「topic/healthcheck」Topicが送信されなくなることを確認します。
* おそらく無事にPCがシャットダウンされ、難を逃れたはずです。

# まとめ
* 冗談っぽい内容が混じってますが、AWS IoTの基礎や可能性について、触れられたと思います。
* AWS IoT SDKのJavaサンプルも確認しときましょう。
https://github.com/aws/aws-iot-device-sdk-java
* 次回はDeviceShadowとか、引き続きAWS IoTついて触れてみたいと思います。