ESP32をArduinoIDEとNode-REDを使ってAWS IoT Coreでプロビジョニングする

#今回やろうとしていること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/8efe11dc-1e08-f1ad-c83c-9d25afb34264.png)

#はじめに
この記事はエッジデバイスのAWS IoT Coreでのプロビジョニングを経験している人向けに書いております。もしまだの方は

https://qiita.com/hdmn54321/items/2b78b84f9bc852d206d1

を参照してください。

#なぜNode-REDを使うのか
AWS IoT Coreとの通信にはTLS1.2認証が必要です。直接ArduinoのコードでTLS認証を行うものもありますが、上手く動かず、調べても同様の声が多かったのでよく使われているTLSBrokerであるNode-REDを使ったところあっさりできたので記事にしました。Amazon Free RTOSも良さそうなので今後試して記事にする予定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/8f908684-183a-60a4-9433-5eb5a1274839.png)






#準備
##ESP32(NodeMCU)の購入
NodeMCU。通称ESP32。通称中国のEspressif社が2017年から売り出しているマイクロコントローラー。Amazon.co.jpで1000円くらい。

##Arduino IDEのインストール
マイコンのArduinoとはまた別物。Windows, MacOS, Linux対応

##Arduino IDEでESP32用のライブラリーをインストール
・メニューバーの「Arduino」の「Preferences」をクリック→Additional Boards Manager URLsに

```
https://dl.espressif.com/dl/package_esp32_index.json
```

を入力し完了をクリック（今後新たにライブラリーをインストールしたい時はこの文字列をコンマで区切って新しいURLを入力します）。

・メニューバーの「Tools」から「Boards」の「Boards Manager」をクリック「ESP32」を検索しインストール。

##Node-REDインスタンスの立ち上げ
Node-REDはIBMクラウドのサービスで、インスタンスの立ち上げにはIBMクラウドアカウントが必要です。

IBMクラウドアカウント作成からNode-REDインスタンス立ち上げまでの手順は以下の記事に丁寧な解説があります。

https://qiita.com/makaishi2/items/ed9d4412331d7d65fde5

#1. AWS IoTコンソールで「モノの登録」をする

##1-1. 基本情報を入力
「モノの名前」は必須です。ここでは「minagawa_ESP32_NodeMCU」としました。

##1-2. 認証情報をローカルに保存
証明書2つと秘密鍵をローカルの適当なフォルダに保存しておきます。これは後々Node-REDにアップロードします。

#2. Node-REDの設定
画像のような構築をしていきます。一見難しいですが、とても簡単に構築できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/64e7455c-d9c3-7491-5ea1-612035b04e79.png)

##2-1. ノードの設置
左のペインから、「inject」「debug」「mqtt out」「http in」をドラッグ&ドロップで持ってきて以下のように並べます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/0e709953-a4e2-df2c-a381-47e7e7cf493f.png)
それを以下のようにつなぎます。これでノートの設置は完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/6339161c-57e3-cfbd-e09e-4ccf20859231.png)

##2-2. 「timestamp」と「debug」ノードの機能確認
「timestamp」ノードの左端にあるボタンをクリックしてみます。以下の表示が出るのを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/ec1499cd-e328-ab0b-5dd6-b28a6c76f116.png)
右側のペインの虫マーク（デバッグマーク）をクリックして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/3cde7504-0399-81a6-12b8-d2b6d1c747ae.png)
以下のようなタイムスタンプが表示されれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/3582e5e4-f087-8589-51c4-5c5b2a0df145.png)

##2-3. 各ノードの設定
「timestamp」と「debug」の機能が確認できたので、今度は「mqtt out」の設定をしていきます。

###MQTT OUTノードの設定
「mqtt out」ノードをダブルクリックすると以下のようなペインが表示されます。「トピック名」は「/test」としてください。「サーバー名」を適当に決め、その右にあるペンマークをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/bea2b5d5-4f2c-a9cc-bd05-5a5f4dc58375.png)

「Server」欄にはAWS IoTのカスタムエンドポイントを入力。ポートはデフォルトだと「1883」ですが、これだとTLS認証ができないので「８８８３」にします（社内ネットワークを使っている場合はこのポートがブロックされている場合があるので上手くいかない場合はその旨を社内ネットワークadminに聞いてみてください）。

その後「TLS configuration」をクリック。
1で保存したデバイス証明書、サーバー証明書、秘密鍵をそれぞれアップロードします（残りは空で大丈夫）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/2014d51a-1caa-5c93-431b-1f5adcce63d3.png)

「Update」→「Update」→「Done」とクリックしていきます。最後に画面右上にある「Deploy」をクリックして完了です（これが忘れがちなので気をつけてください）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/0a303df9-8f7f-4c80-dc3c-442037803e6e.png)
以下のようにデプロイから「mqtt out」ノードが「disconnected」→「connecting」→「connected」になるまでに5分ほど時間がかかります（場合によってはそれ以上）。「connected」になったら次のステップに進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/36480c9b-9d98-7851-2d2b-2337f470c54c.png)


###MQTT OUTノードの機能テスト
AWS IoT CoreのMQTTテストクライアントを開いて「/test」にサブスクライブします。

その後Node-REDに戻って「timestamp」ノードの左端をクリックします。
以下のようにタイムスタンプが正常に届いたら成功です。
画像

###HTTP INノードの設定
こっちの設定は簡単です。「http in」をダブルクリックします。「Method」は「GET」、「URL」には適当なトピック名（ここでは「/minagawatopic」としました）を入力して「Done」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/05b1f98a-34b3-ba85-4b78-838bd6dd0e92.png)

##2-4. Node-RED全体の機能テスト
現在開かれているNode-REDのURLの.netの部分までをコピーします。

それを適当なブラウザの検索窓に貼り付けて

```
「https://xxxxxxxxxxxxxx.xxxxxxxx.net/minagawatopic?temp=25」
```

というふうに書き換えてEnterを押します。「.net」以下の「/minagawatopic」の部分は先程HTTP INノードで設定したトピック名、「?」マーク以降は送信したいJSONの情報です。

先程のAWS IoT CoreのMQTTテストクライアントで無事メッセージが届いているか確認します。

#3. ArduinoIDEでNode-REDにHTTPリクエスト送信

##3-1. ESP32でHTTPリクエスト（GET）をするためのコードを持ってくる
このページ

https://randomnerdtutorials.com/esp32-http-get-post-arduino/#http-get-1

から持ってきました。この記事の最後にコードがあります。それをコピーしてArduino IDEの「File」から「New」を選んで貼り付けます。

また「Tools」で「ESP32 Dev Module」を選択。

##3-2. コードの編集
コードの序盤にあるWifiの認証情報とHTTPリクエストを送る先のURLを書き入れます。URLには先ほどブラウザで試したのと同様に「Node-REDのURL/設定したトピック?送りたいJSON」という形式で入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/e8402720-3932-6e3e-8921-d94e937fd238.png)

##3-3. コードの実行
チェックマークの右にある矢印マークをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/e1aca1c1-feab-7b72-6bc7-3f90e2462c61.png)
コンパイルが終わって「Connecting...」とWindowの下部に表示が出るのでESP32の「Boot Button」を長押しします。この長押し作業は最初のアップロード時のみ必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/4e1f240d-5e17-b8d2-aab7-3ed82204e074.png)
プログラムが動き始めたら「Tools」の「Serial Monitor」でリアルタイムlogを確認できます。もし文字化けしている場合は画像右下にあるサンプリングレート「baud」をコードに記載してあるレートと同じにして再度トライしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001699/fca4676f-3d44-4888-7a92-15f4931c21ea.png)

#4. AWS IoT Coreでメッセージの確認
ここまでの設定がうまく言っていればAWS IoT CoreのMQTTテストクライアントから「/test」にサブスクライブすると5秒おきに温度データがJSONファイルで届いているのが確認できるはずです。

#今回使ったコード
________________________________________________________________

```cpp
/*
  Rui Santos
  Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-get-post-arduino/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

//Your Domain name with URL path or IP address with path
String serverName = "http://192.168.1.106:1880/update-sensor";

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 5 seconds (5000)
unsigned long timerDelay = 5000;

void setup() {
  Serial.begin(115200); 

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}

void loop() {
  //Send an HTTP POST request every 10 minutes
  if ((millis() - lastTime) > timerDelay) {
    //Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
      HTTPClient http;

      String serverPath = serverName + "?temperature=24.37";
      
      // Your Domain name with URL path or IP address with path
      http.begin(serverPath.c_str());
      
      // Send HTTP GET request
      int httpResponseCode = http.GET();
      
      if (httpResponseCode>0) {
        Serial.print("HTTP Response code: ");
        Serial.println(httpResponseCode);
        String payload = http.getString();
        Serial.println(payload);
      }
      else {
        Serial.print("Error code: ");
        Serial.println(httpResponseCode);
      }
      // Free resources
      http.end();
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}
```



________________________________________________________________

#Lチカがしてみたい人向けのコード
以下のコードはこのサイト

https://dronebotworkshop.com/esp32-intro/

から持ってきたものです。

```cpp
/*
  ESP32 Blink
  esp32-blink.ino
  Rewrite of classic Blink sketch for ESP32
  Use LED on GPIO2
   
  DroneBot Workshop 2020
  https://dronebotworkshop.com
*/

// LED on GPIO2
int ledPin = 2;

void setup()
{
    // Set LED as output
    pinMode(ledPin, OUTPUT);
    
    // Serial monitor setup
    Serial.begin(115200);
}

void loop()
{
    Serial.print("Hello");
    digitalWrite(ledPin, HIGH);
    
    delay(500);
    
    Serial.println(" world!");
    digitalWrite(ledPin, LOW);
    
    delay(500);
}
```


#参考資料

Node-REDの使い方を詳しく解説した記事

https://qiita.com/akkijp/items/b7954c80d53c24153f70

英語になりますが、以下のビデオはESP32の基礎を学ぶには最適です。Lチカなどの基礎コードあり。

https://www.youtube.com/watch?v=xPlN_Tk3VLQ&t=1930s&ab_channel=DroneBotWorkshop

ESP32でHTTPリクエストをする（英語）

https://randomnerdtutorials.com/esp32-http-get-post-arduino/

主に以下のUdemyのコースで学んだものを記事にしました（英語）

https://www.udemy.com/course/exploring-aws-iot/learn/lecture/20534884#overview