AWS日記37 (AWS IoT)

# はじめに
今回は [AWS IoT](https://aws.amazon.com/jp/iot/) を試します。
AWSコンソールから Raspberry Pi のLEDを点滅させます。


# AWS IoTの設定

### AWS IoT ポリシーの作成
![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/43f30bd9-c018-2fa9-27f3-8371194bcaac.jpeg)

![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/2ea0d36f-3a77-c543-4561-ac8c651c52a6.jpeg)

 - ポリシー名を入力し、アクションとポリシーリソースを 「 * 」 に設定し、「作成」をクリックします。


### モノを作成
 - IoT：Internet of Things（モノのインターネット） の「モノ」を作成します。
![03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/4126cf0b-3de4-1d95-2d25-1fa025e7f583.jpeg)



![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/02e48730-b061-637d-0b98-f8f2ac344f15.jpeg)


![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/dcb64353-ad36-98a2-70c6-dae6c9e444ab.jpeg)

 - モノの名前を設定します。
 - ここで設定した値を、後述する main.js 内の "clientId" の値などに設定します。

### デバイス証明書を設定
![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/299b11eb-e382-3872-40f3-8bbb9a9c6ced.jpeg)


### 証明書にポリシーをアタッチ
![08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/9841378a-1c8d-38f9-ff03-a628221466bd.jpeg)

 - 先ほど作成したポリシーを選択します。


### 証明書とキーをダウンロード
![09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/d36a2ddd-14a5-bd7b-b2fc-0c1951b456ef.jpeg)

 - デバイス証明書、キーファイル、ルートCA証明書をダウンロードします。
 - ダウンロードしたファイルは、後述する main.js と同じディレクトリに配置します。

### デバイスデータエンドポイントの確認
![10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/36a1d6f5-3a0c-34b8-0f43-2a0791615643.jpeg)

 - エンドポイントをコピーし、後述する main.js 内の "host" の値に設定します。


# Raspberry Piの設定

### 準備
 - [OSインストール](https://www.raspberrypi.com/software/)します。
 - LEDや抵抗などの配線を行います。

### Node.js と npm のインストール

```bash
sudo apt install nodejs
sudo apt install npm
```

### プロジェクト作成、初期化

```bash
mkdir iot-led-blink && cd iot-led-blink
touch main.js
npm init
```

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

```bash
npm install rpi-gpio --save
npm install aws-iot-device-sdk --save
```

### ファイルの配置
 - ダウンロードした xxxxx-private.pem.key, xxxxx-certificate.pem.crt, AmazonRootCA1.pem を main.js と同じディレクトリに配置します。


### main.js の編集

```js
const awsIot = require("aws-iot-device-sdk");
const gpio = require("rpi-gpio");

const PIN = 8;
const BLINK_LIMIT = 3;
const SLEEP_LIMIT = 6;
let   BLINK_COUNT = 0;
let   SLEEP_COUNT = 0;
let   BLINK_FLAG  = false;
let   LED_FLAG    = false;

const device = awsIot.device({
  keyPath: "xxxxx-private.pem.key",
  certPath: "xxxxx-certificate.pem.crt",
  caPath: "AmazonRootCA1.pem",
  clientId: "iot_blink_test",
  host: "xxxxx.iot.ap-northeast-1.amazonaws.com",
});

device.on("connect", function () {
  console.log("connect");

  device.subscribe("$aws/things/iot_blink_test/shadow/update/delta");

  device.publish(
    "$aws/things/iot_blink_test/shadow/update",
    JSON.stringify({
      state: {
        reported: {
          led: "off",
        },
      },
    })
  );

  gpio.setup(PIN, gpio.DIR_OUT, () => {
    gpio.write(PIN, true);
  });
});

device.on("message", function (topic, payload) {
  console.log("message", topic, payload.toString());

  const shadow = JSON.parse(payload.toString());

  if (shadow.state && shadow.state.led) {
    console.log("led", shadow.state.led);

    BLINK_FLAG = shadow.state.led === "on";

    device.publish(
      "$aws/things/iot_blink_test/shadow/update",
      JSON.stringify({
        state: {
          reported: {
            led: shadow.state.led,
          },
        },
      })
    );
  }
});

gpio.setup(PIN, gpio.DIR_OUT, () => {
  setInterval(() => {
    if (BLINK_FLAG) {
      if (LED_FLAG) {
        gpio.write(PIN, false);
        LED_FLAG = false;
        BLINK_COUNT += 1;
        if (BLINK_COUNT >= BLINK_LIMIT) {
          BLINK_COUNT = 0;
          SLEEP_COUNT = 0;
        }
      } else {
        if (SLEEP_COUNT >= SLEEP_LIMIT) {
          gpio.write(PIN, true);
          LED_FLAG = true;
        } else {
          SLEEP_COUNT += 1;
        }
      }
    } else {
      gpio.write(PIN, true);
      LED_FLAG = true;
    }
  }, 100);
});
```

### 実行

```bash
node main.js
```


# AWSコンソールから操作

### シャドウを確認
![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/e751e155-85d0-467f-c1b9-702ac24fefec.jpeg)

 - Raspberry Pi 側で実行すると、 Device Shadow 一覧に Classic Shadow が出ます。

![11_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/82884676-4822-7f9b-665e-98ca213b9b30.jpeg)

 - 「Classic Shadow」 をクリックします。

![12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/e531cf29-389a-d319-0b51-eaeeb628aa98.jpeg)

 - 「編集」 をクリックします。


### シャドウを編集
![13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/4f8509f4-a2fc-8880-e0c2-087bee9ae201.jpeg)

 - 上記の通り "desired" を追加し 「更新」 をクリックします。

### 確認
![15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/6cd1139e-a107-9132-92aa-656e007469e2.jpeg)

 - 上記の通り Device Shadow の状態が変更されます。
 - Raspberry Pi のLEDが点滅します。


# 終わりに
AWS IoT を試しました。
[AWS Mobile SDK](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sdks.html#iot-mobile-sdks)を利用して、Android や iOS でも AWS IoTを利用できるため、今後試していこうと思います。

##### 以下の記事を参考にしました

[Raspberry PiとAWS IoTでLチカしてみた](https://dev.classmethod.jp/articles/raspberry-pi-aws-iot-l-chika/)

[Raspberry PiのGPIOピン配置を確認する](https://www.bioerrorlog.work/entry/raspberry-pi-pinout)