IoT その4(更新されたESP32内のWi-Fi情報を確認し、ThingsBoardのWi-Fi情報とリンクさせる)
こんにちは、Ideagearの鈴木陽介です。
前回は、EspTouchというスマホアプリからESP32内のWi-Fi情報(SSIDとパスワード)を更新する方法についてご紹介しました。
その続きとして、今回は、ESP32内に保存されているWi-Fi情報を読み出し、それをArduino IDEのシリアルモニタで確認し、さらに、そのSSIDとパスワードをThingsBoard用のWi-FiのSSIDとパスワードに反映させるところまでを解説します。
最終的なゴールは、EspTouch → Wi-Fi情報更新 → ESP32 → Wi-Fi情報反映 → ThingsBoard Cloud → 温湿度センサーの値をリアルタイムでモニタリングです。
はじめに
前回記事の通り、EspTouchを使ってESP32のWi-Fi情報を更新できたので、あとはThingsBaordにつなぐなんて余裕じゃん!
と、思っていましたが、実際にやってみると、
あれ?そのSSIDとパスワードってどうやってThingsBoardに伝えるの?
そもそもESP32にちゃんと保存されてるの?
保存されているとしてどこに保存されていて、どうやって読み出すの?
読み出した後に、ThingsBoardにどうやって反映させるの?
などなど、できるのは間違いないとしても、その戦術と言いますか、実際の作業として何をどうすれば良いかという部分は、意外とスタディしないとわからない部分が多いことに気づきました。
まさに、「言うはやすし行うは難し」ですが、下記参考記事が秀逸でした!
参考記事
ESP32のWi-fi設定方法調査
参考記事のソースコードを実行すると、下記のようにESP32に保存されているSSIDとパスワードをシリアルモニタで確認することができます。
Wi-Fi情報の確認
知りたかった情報は、上記記事の「Wi-Fi接続先設定の読み出し方法」の部分に書かれていました。
ポイントは、<Preferences.h>というライブラリーを使うことで、これはESP32にデフォルトでインストールされているようです。
ライブラリー
今回のソースコードは、前回と前々回の記事のものを活用します。
よって、温湿度センサー(DHT11)やThingsBoard Cloudのライブラリーに関しては、下記前々回の記事をご参照ください。
ソースコード
私の前回と前々回の記事、それと参考記事のソースコードをマージさせて下記のようにつくりました。そのままコピペすれば使えます。
配線は、前々回の記事をご確認ください。
#include "WiFi.h"
#include "DHT.h"
#include <ThingsBoard.h>
//Wi-Fi接続先設定をNVSから読み出すための定義
#include <Preferences.h>
Preferences preferences;
//Wi-Fi(ThingsBoard用)
const char* ssid = "xxxx"; //Your SSID
const char* password = "xxxx"; //Your Password
//TOKEN
#define TOKEN "9M2*************aZf" //Your Access token
//DHT
#define DHTPIN 2
#define DHTTYPE DHT11
char thingsboardServer[] = "thingsboard.cloud";
WiFiClient wifiClient;
// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);
ThingsBoard tb(wifiClient);
int status = WL_IDLE_STATUS;
unsigned long lastSend;
void setup()
{
Serial.begin(115200);
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
//Wait for SmartConfig packet from mobile
Serial.println("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
//Wait for WiFi to connect to AP
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
//Wi-Fi接続先設定をNVSから読み出して表示させる
char wifi_ssid[37] = {};
char wifi_key[66] = {};
preferences.begin("nvs.net80211", true);
preferences.getBytes("sta.ssid", wifi_ssid, sizeof(wifi_ssid));
preferences.getBytes("sta.pswd", wifi_key, sizeof(wifi_key));
Serial.printf("sta.ssid : %s\n", &wifi_ssid[4]);
Serial.printf("sta.pswd : %s\n", wifi_key);
//Wi-Fi(ThingsBoard用)
ssid = &wifi_ssid[4];
password = wifi_key;
Serial.printf("ssid : %s\n" , ssid);
Serial.printf("password : %s\n" , password);
//DHT11
dht.begin();
delay(10);
InitWiFi();
lastSend = 0;
}
void loop()
{
if ( !tb.connected() ) {
reconnect();
}
if ( millis() - lastSend > 1000 ) { // Update and send only after 1 seconds
getAndSendTemperatureAndHumidityData();
lastSend = millis();
}
tb.loop();
}
void getAndSendTemperatureAndHumidityData()
{
Serial.println("Collecting temperature data.");
// Reading temperature or humidity takes about 250 milliseconds!
float humidity = dht.readHumidity();
// Read temperature as Celsius (the default)
float temperature = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
Serial.println("Sending data to ThingsBoard:");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" *C ");
tb.sendTelemetryFloat("temperature", temperature);
tb.sendTelemetryFloat("humidity", humidity);
}
void InitWiFi()
{
Serial.println("Connecting to AP ...");
// attempt to connect to WiFi network
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
void reconnect() {
// Loop until we're reconnected
while (!tb.connected()) {
status = WiFi.status();
if ( status != WL_CONNECTED) {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
Serial.print("Connecting to ThingsBoard node ...");
if ( tb.connect(thingsboardServer, TOKEN) ) {
Serial.println( "[DONE]" );
} else {
Serial.print( "[FAILED]" );
Serial.println( " : retrying in 5 seconds]" );
// Wait 5 seconds before retrying
delay( 5000 );
}
}
}
上記プログラムの説明:
- ESP32に保存されたSSIDとパスワードを読み出す。
- ThingsBoard用のSSIDとパスワードの変数へ読み出した値を代入する。
- ThingsBoardへ接続するプログラムを実行する。
解説:
ThingsBaordにつなげる用のWi-FiのSSIDとパスワードは上書きする前提ですので、コンパイル時の初期化では、「xxxx」という適当な文字を入れておきます。
ただ、今回はThingsBoardのトークン自体は上書きせずに固定で使う前提ですので、TOKENの部分には、実際にThingsBoardから発行された20桁の数字と文字の羅列を入れてください。
※「****」となっている部分は目隠しです。実際のトークン番号を入れてください。
最終的には、このTOKEN情報も外部から書き換えられるようにしたいですが、これに関しては次回の記事でご説明します。
動作確認
まず、前回記事の通り、まずはEspTouchからWi-FiのSSIDとパスワードをESP32に送ります。
※EspTouchの使い方は前回記事をご確認ください。
次に、Arduino IDEのシリアルモニタを開きます。
下記の通り、ThingsBoardに接続され、DHT11の湿度と温度が表示されたら成功です!
ThingsBaord Cloud上でもモニタリングできています。
具体的な操作方法は、下記動画でもご確認ください。
まとめ
いかがでしたでしょうか?
実を言えば、今回のような方法はセキュリティ上のリスクがあります。
たとえば、<Preferences.h>ライブラリーを用いた参考記事のようなソースコードを知っていれば、当該ESP32にmicroUSBケーブルを挿し込み、パソコンからそのスケッチを書き込み、Arduino IDEのシリアルモニタからSSIDとパスワードを確認することができてしまいます。
つまり、その場で使われているWi-FiのSSIDとパスワードがわからなくても、ESP32を介して盗み出して使うことができてしまいます。
そのため、参考記事はそこまで想定し、Wi-Fi接続先設定の削除方法まで書かれているのでぜひご一読ください。
ただ、実際の運用上は、ESP32がデバイスや製品に完全に組み込まれている場合、修理やメンテナンスなどで筐体をこじ開ける以外はこのようなリスクはぼぼありません。
かと言って、たとえば、機器の電源が落ちるたび(実際上は電源をONした時)にWi-Fiの設定情報をクリアするようにプログラミングをしておくと、電源のON/OFFのたびにWi-FiのSSIDとパスワードを設定しなければならず、ユーザビリティが下がってしまいます。
一方で、SSIDとパスワードを別の不揮発性メモリの領域に保存したとしても、この種のリスクは完全にゼロにはなりません。
つまりは、セキュリティの問題は、運用方法を含めて総合的に判断しなければならないと思います。
前回と今回で、外部からESP32のSSIDとパスワードを書き換え、それを読み出して扱う方法を学びました。
次は、いよいよ外部からThingsBoard CloudのTOKENを更新する方法について学びます。
Discussion