室内の温度と湿度をDynamoDBに書き込む


HiLetgo ESP32 ESP-32S NodeMCU開発ボード2.4GHz WiFi + Bluetoothデュアルモードの記事で ESP32ボードの動作確認ができました。今度は、室内の温度と湿度をAWS IoTを使って、DynamoDBに書き込んでみました。温度と湿度の取得にはDHT22センサを使用しました。


IoTルールの作成は、別記事「MQTTでAWS DynamoDBに保存」にしました。

なお、AWSアカウントは開設済みで、AWSコンソールには AdministratorAccess のポリシーがアタッチされたIAMユーザでログインしていることが前提です。

IoTデバイスの作成

クライアント証明書の作成

用意したデバイスのみからアクセスできるようにクライアント証明書を作成します。クライアント証明書は、プログラムに埋め込むためにダウンロードしておきます。クライアント証明書は作成とともにAWS IoT Coreに登録されます。

  1. AWSコンソールの AWS IoTManage > Things を開き、Create > Create a single thing を選ぶ。
  2. MySokuteiESP32 と Name フィールドに入力し、他はデフォルトのままにして Nextを選ぶ。
  3. Create certificateを選ぶ。ESP32での接続に a certificate for this thing、a private key、Amazon Root CA1 のダウンロードが必要。ダウンロードしたらセキュアな場所に保存しておく。
  4. ActivateAttach a policy をクリックする。
  5. ポリシーの追加はスキップして、Register Thing をクリックする。

ポリシーの作成

MQTTトピック esp32/pub にパブリッシュする許可を、デバイスに与えるためのポリシーを作成します。今回作成するポリシーでは、次の2つのMQTTポリシーアクション:


   iot:Connect
AWS IoT Core メッセージブローカーに接続するアクセス許可

   iot:Publish
MQTT トピックにパブリッシュするアクセス許可


を許可します。
  1. AWS IoT のサイドメニューから Secure > Policies を選び、Create をクリックする。
  2. SokuteiPolicyName フィールドに入力し、Advanced mode を選ぶ。

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "iot:Connect",
          "Resource": "arn:aws:iot:REGION:ACCOUNT_ID:client/MySokuteiESP32"
        },
        {
          "Effect": "Allow",
          "Action": "iot:Publish",
          "Resource": "arn:aws:iot:REGION:ACCOUNT_ID:topic/esp32/pub"
        }
      ]
    }
    
  3. REGION には使っているリージョン名を入れる(東京リージョンなら、ap-northeast-1)。リージョン名は、AWSコンソールの右上で確認できる。

  4. ACCOUNT_ID を自分のものに変更する。Account Settings で確認できる。

  5. Create をクリックする。

クライアント証明書へのポリシーのアタッチ

デバイスからのアクセス許可は、クライアント証明書にポリシーをアタッチすることで行います。

  1. AWS IoT のサイドメニューから Secure > Certificates を選ぶ。そして、いま作成した証明書を選び、Actions > Attach policy を選ぶ。
  2. SokuteiPolicy にチェックを入れて、Attatch をクリックする。

ここまででESP32をAWS IoTに接続するためのAWSコンソールでの設定が完了。トピック esp32/pub にパブリッシュが可能である。

Arduino IDEの設定

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

MQTTライブラリ、および、ArduinoJsonライブラリをインストールします。Arduino IDEのライブラリマネージャから行うことができます。

  1. Arduino IDEを起動する。
  2. スケッチ > ライブラリをインクルード > ライブラリを管理 を選ぶ。
  3. MQTT で検索し、Joel Gaehwiler の最新バージョンをインストールする。
  4. 同様に ArduinoJson もインストールする。
  5. 閉じる をクリックする。

ESP32の設定とプログラムの書き込み

次のようなプログラム:

  • ローカルネットワークのWiFiに接続して、先ほどダウンロードしたクライアント証明書を使って、AWSエンドポイントのMQTTブローカーに接続
  • JSON形式のメッセージをトピック esp32/pub に、繰り返しパブリッシュ

を作成して、ESP32に書き込みます。

  1. Arduino IDE で ファイル > 新規ファイル を選ぶ。
  2. 新規タブ を選び、新規ファイルの名前secrets.h を入力し、OKをクリックする。
  3. 以下の secrets ファイルをペーストする。

    #include <pgmspace.h>
    #define SECRETS
    #define THINGNAME ""
    
    const char WIFI_SSID[] = "";
    const char WIFI_PASSWORD[] = "";
    const char AWS_IOT_ENDPOINT[] = "xxxxx.amazonaws.com";
    
    // 証明書
    static const char AWS_CERT_CRT[] PROGMEM = R"CRT(
    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    )CRT";
    
    // プライベートキー
    static const char AWS_CERT_PRIVATE[] PROGMEM = R"PRK(
    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----
    )PRK";
    
    // ルートCA証明書
    static const char AWS_CERT_CA[] PROGMEM = R"RCA(
    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    )RCA";
    
  4. THINGNAMEMySokuteiESP32 を設定する。

  5. Wifiに接続するため、SSIDPASSWORD を設定する。

  6. AWS_IOT_ENDPOINT は、AWS IoT のサイドメニューから Settings のページで確認できる。

  7. 証明書、プライベートキー、ルートCA証明書をそれぞれ secrets.h ファイルに書き込む。

  8. メインスケッチのタブを開き、以下のコードをペーストする。ファイル > 保存 を選んで、プロジェクト名を設定して保存する。

#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include "WiFi.h"

// ESP32からパブリッシュするMQTTトピック
#define AWS_IOT_PUBLISH_TOPIC   "esp32/pub"

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(256);

void connectAWS()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.println("Wi-Fiに接続中..");

  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }

  // AWS IoTの認証情報を使用するようにWiFiClientSecureを設定
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  // AWSエンドポイントのMQTTブローカーに接続
  client.begin(AWS_IOT_ENDPOINT, 8883, net);

  Serial.print("AWS IoTに接続中..");

  while (!client.connect(THINGNAME)) {
    Serial.print(".");
    delay(100);
  }

  if(!client.connected()){
    Serial.println("AWS IoTがタイムアウトしました!");
    return;
  }

  Serial.println("AWS IoTに接続しました!");
}

void publishMessage()
{
  StaticJsonDocument<200> doc;
  doc["time"] = millis();
  doc["temp"] = "20.1";
  doc["hum"] = "60.5";
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer); // JSON形式のデータを生成

  client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
}

void setup() {
  Serial.begin(9600);
  connectAWS();
}

void loop() {
  publishMessage();
  client.loop();
  delay(10000);
}

プログラムの書き込みは、こちらの記事を参照

デバイスからパブリッシュされたデータの確認

  1. AWSコンソールの Services から DynamoDB を開く。
  2. サイドメニューの Tables から作成されたテーブルを選ぶ。
  3. Itemsタブを選ぶと、デバイスから送信されたデータが記録されていることを確認できる。

室内の気温と湿度の記録

温湿度センサ DHT11 on arduino-esp32を参考に温度センサーとESP32を接続し、温度と湿度が取得できることを確認しておきます。ここでは DHT11の代わりにDHT22を使用し、DHT22のOUTは16番ピンに接続しました。

  1. 先頭の #include 行の後ろに次のコードを追加する。

    #include "DHTesp.h"
    #define DHTPIN 16
    DHTesp dht;
    
  2. publishMessage() 関数を次のコードに置き換える。

    void publishMessage()
    {
      TempAndHumidity newValues = dht.getTempAndHumidity();
      if (dht.getStatus() != 0) {
        Serial.println("DHT22 error status: " + String(dht.getStatusString()));
      }
      float temp = newValues.temperature;
      float hemi = newValues.humidity;
      Serial.print(temp);
      Serial.print(" ");
      Serial.println(hemi);
    
      StaticJsonDocument<200> doc;
      doc["time"] = millis();
      doc["temp"] = temp;
      doc["hum"] = hemi;
      char jsonBuffer[512];
      serializeJson(doc, jsonBuffer); // JSON形式のデータを生成
    
      client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
    }
    
  3. setup() 関数を次のコードに置き換える。

    void setup() {
      Serial.begin(9600);
      dht.setup(DHTPIN,DHTesp::DHT22);
      connectAWS();
    }
    
  4. マイコンに書き込む をクリックする。

  5. 書き込みが完了すれば、DynamoDB の payload に現在の温度と湿度が10秒毎に書き込まれる。



以上のように、ESP32 を AWS IoT に接続して、DHT22を使って測定した温度・湿度を DynamoDB に書き込むということが、とても簡単にできることが分かりました。

参考