Raspberry PiとAWS IoTでLチカしてみた

2020.04.16

Raspberry Pi(ラズベリーパイ)とAWS IoTでLチカしてみたいと思います。AWS IoTでシャドウ(Thing Shadow)を更新すると、MQTTで接続しているRaspberry Piが差分を受け取り、LEDをON/OFFする仕組みを構築します。

Raspberry Pi & AWS IoT Core

環境情報

次のようなMacbookとRaspberry Piの環境で開発しています。また、Raspberry Piをリモートから操作するため、MacbookからRaspberry PiにVNCとSSHで接続できるようにしています。

Macbook

項目 内容
モデル MacBook Pro (13-inch, 2018, Four Thunderbolt 3 Ports)
OS macOS Catalina 10.15.4(19E287)
プロセッサ 2.3 GHz クアッドコアIntel Core i5
メモリ 16 GB 2133 MHz LPDDR3

Raspberry Pi

項目 内容
モデル Raspberry Pi 4 Model B
OS Raspbian 10 (Raspbian GNU/Linux 10 buster)
SDカード SanDisk Ultra microSDHC 32GB SDSQUAR-032G-GN6MN
電源 電源アダプター USB Type-C 5.1V/3A

その他(部品)

Raspberry Pi 4 Lチカ セット

  • ブレッドボード ×1
  • ジャンパーワイヤー(オス-メス) ×2
  • LED ×1
  • 抵抗器 1KΩ ×1

Raspberry PiだけでLチカ

まずは、Raspberry PiだけでLチカできることを確認します。後ほど「AWS IoT Device SDK for JavaScript」を使用したいので、Node.jsで開発することにします。

配線

次の画像のようにRaspberry Piからブレッドボードへ配線します。

Raspberry Pi ブレッドボード 配線

Node.jsをインストール

Raspberry Piに最新のNode.jsとnpmをインストールします。Raspberry Piのターミナルを使用するかSSHで接続して作業します。

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -

Nodeとnpmをインストールします。

sudo apt-get install -y nodejs

インストールされたNodeとnpmのバージョンを確認します。

node -v # v12.16.2
npm -v # 6.14.4

Lチカ用のコードを実装

プロジェクト用のディレクトリを用意して、GPIOの操作で使用するライブラリをインストールします。

mkdir raspberry-pi-sample
cd raspberry-pi-sample
npm init
npm install rpi-gpio --save

1秒毎に8番ピンをON/OFFするコードを実装します。

main.js

const gpio = require("rpi-gpio");

const PIN = 8; // 8番ピン(GPIO14)

let LED = true;

gpio.setup(PIN, gpio.DIR_OUT, () => {
  setInterval(() => {
    if (LED) {
      gpio.write(PIN, false);
      LED = false;
    } else {
      gpio.write(PIN, true);
      LED = true;
    }
  }, 1000);
});

Lチカしてみる

Raspberry Pi上でコードを実行します。

node main.js

LEDが1秒毎に点灯と消灯を繰り返します。

Raspberry Pi Lチカ

Raspberry PiとAWS IoTでLチカ

今度はRaspberry PiとAWS IoTをMQTTで接続して、サブスクリプション要求により受け取る差分を処理して、LEDをON/OFFしてみます。まずは、AWS IoTに接続するための準備から始めます。

AWS IoTでポリシーを作成

AWS IoT Coreのマネジメントコーンソールからポリシーを作成します。

AWS IoT Core ポリシー

適当なポリシー名を入力します。アクションにiot:*リソースに*に入力、効果は許可にチェックをしてポリシー作成します。

AWS IoT ポリシー作成

AWS IoTでモノを作成

AWS IoT Coreのマネジメントコーンソールから単一のモノを作成します。

AWS IoT Core モノ

適当なモノの名前を入力して次へ進みます。

AWS IoT モノ作成

AWS IoTで証明書を作成

モノに証明書を追加します。次の画面が表示されるので「1-Click 証明書作成 (推奨)」で証明書を作成します。

AWS IoT Core 証明書作成

証明書の作成が完了したら、次の画面で証明書や秘密鍵をダウンロードします。また、証明書を有効化して先ほど作成したポリシーをアタッチしておきます。

AWS IoT Core 証明書ダウンロード

AWS IoTのエンドポイントを取得

AWS IoT CoreのマネジメントコンソールからAWS IoT Coreへ接続するためのエンドポイントを取得します。

AWS IoT Core エンドポイント

AWS IoT Device SDK for JavaScriptをインストール

npmでAWS IoT Device SDK for JavaScriptをインストールします。

npm install aws-iot-device-sdk --save

Lチカ用のコードを実装

サブスクリプション要求により受け取る差分を処理して、LEDをON/OFFするコードを実装します。秘密鍵や証明書のパスはあらかじめダウンロードしたファイルのパスを設定します。raspberry-pi-sampleはモノを作成した際の名前に変更してください。

main.js

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

const PIN = 8; // 8番ピン(GPIO14)

const device = awsIot.device({
  keyPath: "xxxxxxxxx-private.pem.key", // 秘密鍵
  certPath: "xxxxxxxxx-certificate.pem.crt", // 証明書
  caPath: "amazon-root-ca1.pem", // CA証明書
  clientId: "raspberry-pi-sample", // ClientID
  host: "xxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com", // エンドポイント
});

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

  device.subscribe("$aws/things/raspberry-pi-sample/shadow/update/delta");

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

  gpio.setup(PIN, gpio.DIR_OUT, () => {
    gpio.write(PIN, true); // 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);

    const led = shadow.state.led !== "on";

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

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

MQTTのトピックはAWS IoTの予約されたトピックを使用しています。

Lチカしてみる

Raspberry Pi上でコードを実行します。

node main.js

AWS IoTでシャドウを確認します。

AWS IoT シャドウ編集

desired"led": "on"を書き込んで保存します。

{
  "desired": {
    "led": "on"
  },
  "reported": {
    "led": "off"
  }
}

保存するとdeltaに差分が追加されます。

{
  "desired": {
    "led": "on"
  },
  "reported": {
    "led": "off"
  },
  "delta": {
    "led": "on"
  }
}

Raspberry Piで差分を処理してreportedが更新されます。

{
  "desired": {
    "led": "on"
  },
  "reported": {
    "led": "on"
  }
}

処理が終わるとLEDが点灯します。

Raspberry Pi LED点灯

desired"led": "off"を書き込んで保存します。

{
  "desired": {
    "led": "off"
  },
  "reported": {
    "led": "on"
  }
}

LEDが消灯します。

Raspberry Pi LED消灯

まとめ

Raspberry PiとAWS IoTでLチカすることができました。API Gatewayから実行するLambdaでシャドウのdesiredを更新することで、WEBアプリからLEDをON/OFFすることもできそうです。他にもRaspberry Piにスイッチを接続して、LEDのON/OFFを制御するケースも考えられると思います。

参考資料