ESP32活用① ESP32とブラウザでお話しする(8)MQTTで通信
今までの処理で、ESP32マイコン・ボードとPCのブラウザとの間の通信が行えることを確認しました。今回は、ESP32のマイコン・ボードで測定した温度の値などをPCに送信します。PCとの通信には、IBMがIoTの実現のための通信手段として積極的に推進しているMQTTを利用します。このMQTT(MQ Telemetry Transport)は、IBMの開発者向けのページに「MQTTの基本知識」としてわかりやすい説明があります。次のアドレスでアクセスできます。
https://www.ibm.com/developerworks/jp/iot/library/iot-mqtt-why-good-for-iot/index.html
●今回はESP32マイコンからPCに通信できることを示す
今回は、ESP32のマイコンからPCにMQTTで通信できることを示します。このMQTTのプログラムは、別の連載シリーズで初めてMQTTに接する方もシンプルな仕組みで動作を確認しながら進めていきたいと思っています。
ESP32-WROOM-32DではpubsubClientライブラリをインストールすると、MQTTでデータの送信、受信が行えるようになります。
●通信のためのサンプル・プログラム
●ライブラリのインクルード
MQTTの通信のために利用するために必要となるライブラリは、PubSubClientライブラリとして用意されています。ここライブラリを読み込むために、最初に次の記述を行います。
#include <PubSubClient.h> |
●Clientのオブジェクトの生成
MQTT の手順で、Wi-Fiなどのネットワーク通信を用いて各デバイス間の通信を行います。データを送信する各デバイスは、ブローカと呼ばれるサーバにデータの種類を示すtopicなどと共に短い送信データを送ります。サーバは、受信を要望するデバイスにサーバで受信したデータのうち、要求に該当するデータを要求してきたデバイスに送信します。
このネットワークの処理のため、WiFiClientのクラスからこのプログラムで実際に利用するWiFiClientのオブジェクトをespClientとして作ります。
Clientからブローカへの通信を行うPublish、ブローカへデータの受信を要求するSubscribeの処理などの、MQTTの通信を行うためのPubsubClientのクラスから実際に処理を行うオブジェクトclientを作成します。このclientの生成時には、WiFiClientのオブジェクトのespClientを引数としています。この処理で、setup()関数の中でclient.setclient(espClient)の記述を省略できます。
WiFiClient espClient; PubSubClient client(espClient); |
MQTTの処理は、次の記事でも扱っています
https://www.denshi.club/pc/arduino/esp8266-iot3mqtt.html
●Setup()関数に追加する事項
インスタント化したオブジェクトclientの接続先のサーバを、アドレスとポート番号を設定して通信できるようにします。
client.setServer(mqtt_server, 1883); |
併せて、Setup()関数内でcallback関数の設定を次のように行います。
client.setCallback(callback); |
Clientは、ブローカ(サーバ)からのメッセージを受信するとCallback関数が呼び出されます。受信データを示すtopic、payload、lengthの3項目が呼び出される関数に引数として渡されます。受信データの処理をこのCallback関数の中にユーザが記述します。
topic : デバイス間の通信データの識別を行うための階層構造を識別するデータ payload : ブロッカから送られたメッセージ・データ length : メッセージ長 |
●受信データの処理
ブローカからの具体的な受信処理はPubSubClientライブラリで行い、データを受信するたびにCallback関数を呼び出し、この関数の中でユーザが必要な処理を行います。今回は、受信データを次に示すようにArduinoのシリアルモニタに表示するようにしています。
void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); // 見出しを表示 Serial.print(topic); // データの識別コードを表示 Serial.print("] "); for (int i = 0; i < length; i++) { // メッセージを表示 Serial.print((char)payload[i]); } Serial.println("CallBack"); // CallBack関数内で表示されたことを示す } |
今回、ESP32-WROOM-32Dのマイコン・ボードからは測定日時と測定温度をPublishで送信しているだけで、マイコン・ボードへは送信データのコールバックだけですので、その値をモニタするだけとなっています。実際にSubscribeでデータを受信する場合は、この関数の中で必要な処理を記述します。
●再接続の処理
サンプル・プログラムの再接続のための関数reconnect()を次に示します。この関数では、最初に接続の有無を調べ、接続されていない場合client.connect("ESP32Client01")の接続のための関数で接続します。ここではClientIDをESP32Client01と設定しています。このクライアントIDはユニークに設定します。
void reconnect() { while (!client.connected()) { // 非接続のあいだ繰り返す Serial.print("Attempting MQTT connection... "); // Attempt to connect if (client.connect("ESP32Client01")) { // 接続を試み成否により次の処理を行う Serial.println("connected"); // 接続が行われたとシリアルモニタに表示 // Once connected, publish an announcement... client.publish("ESP32/01/temp", "from Arduino ----reconnect"); client.subscribe("ESP32/01/temp");// ... and resubscribe } else { Serial.print("failed, rc="); // 接続できなかったことをシリアルモニタに Serial.print(client.state()); // クライアントの状態を5から-4のコードで表示 Serial.println(" try again in 2 seconds"); delay(2000); } } } |
●測定したデータ、測定日時の送信処理
データの送信はclient.publish()関数で行います。第1の引数でtopic、データ種別を示す階層化された識別コードでデータの種類を示し、第2の引数は日時の場合と温度の場合の2種類用意しました。最初の送信メッセージは現在時刻を年月日時分秒で表示し、温度はfloatの実数をsnprintf()関数の文字列にして送信しています。
●日時のデータのpublish
snprintf(msg, 75, "%04d/%02d/%02d(%s)%02d:%02d:%02d:", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, wd[tm->tm_wday], tm->tm_hour, tm->tm_min, tm->tm_sec); Serial.println(msg); client.publish("ESP32/01/temp", msg); // シリアルモニタに直接測定データを出力する際、floatのデータはデフォルトの小数以下2桁に変換されている。 ここから温度のデータを文字列にして送信。 このメッセージmsgは実数のデータをそのまま送っているので8桁表示の小数以下6桁の値になっている。 snprintf (msg, 75, "ESP32/01/temp %lf", tpary[kp]); Serial.print("Publish message: "); Serial.println(msg); client.publish("ESP32/01/temp", msg); // |
このMQTTの処理を追加したプログラムは、esp2lcdwifi3010.txtの名のテキスト・ファイルとして添付しています。このファイルをダウンロードしてArduino IDEでコンパイルしてください。
コンパイルの前には、IDEのライブラリマネージャでリストの中にあるpubsuclientライブラリをインストールしてください。ライブラリのインストールやMQTTを利用するためのmosquittoの詳しい話は、次のシリーズで詳しく説明する予定です。今回は結果を示すだけとなります。
●追加したプログラムの先頭部
先頭にはpubsubclientライブラリを利用するために#include <PubSubClient.h>が追加されています。ページの最後には新しいオブジェクトを追加するための命令が追加されています。
WiFiClient espClient; PubSubClient client(espClient); |
それ以外の追加分は、新しいプログラムをダウンロードして確認してください。
●実行すると
ブローカとの接続ができないときの処理も確認するために、ブローカの起動前にESP32-WROOM-32Dのマイコンのプログラムを起動し、シリアルモニタを確認し次の結果を得ました。
●setup()のシリアルモニタ表示
最初のシリアルモニタのsetup()関数の処理を追ってみます。Wi-Fiに接続されると“Connected ・・・のメッセージが表示されSSID、自身のIPアドレスが表示されます。その後HTTP server startedでHTTPサーバがスタートしたことが表示されます。そのほかの初期化、スタート処理を行ってsetup()を終えます。
●loop()関数のシリアルモニタ表示
ブローカが起動していないので、client.connectedは成立しません、そのため、関数reconnect()が呼び出されます。この関数の中で未接続の間、接続するまで2秒ごとに接続のチェックを行います。接続されたらconnectedを表示しこの関数を抜け出し、未接続の場合" try again in 2 seconds"を表示して、接続できるまで繰り返します。ここでは2回繰り返して接続しています。
reconnectのシリアルモニタの表示はreconnect()関数の処理を終えたことを示しています。
次に、配列の指標****kp***の表示の後に、配列の値、温度の値を表示しています。
date data に続いて年月日時分秒の表示、Publish messageに続いて温度が表示されます。この二つはPublish メッセージのモニタです。
●コールバックの受信データ
シリアルモニタのMessage arrivedの後ろのCallBackの表示は、このESP32からPublishに対するブロッカからのコールバックです。一つ目は測定時の温度データ、次は配列に格納された日時、次は配列に格納された温度データです。
●Mosquittoの設定
MQTTとそれが実装されたMosquittoのインストール、操作方法などの詳細は次の別シリーズで説明します。ここでは動作確認し通信ができることの確認にとどめます。
mosquittoのインストールは、次のページからダウンロード・ページに進み必要なファイルを入手できます。
●ブローカの起動
ブローカは、PCのWindows10上で起動します。ウィンドウズのコマンド画面で、カレントディレクトリをC:\Program Files\mosquittoに変更し、次のコマンドでブローカを起動します。
>cd C:\Program Files\mosquitto >mosquito -v |
-v はログ表示のためのオプションです。
●データを受信するサブスクライバ(Subscriber)の起動
今回は、テストですので、ブローカと同じPCのWindows10の別のコマンド画面で起動します。起動のために次のコマンドを入力します。
>cd c:\Program Files\mosquitto >mosquitto_sub -h localhost -t ESP32/01/temp -v |
-hはhostname でブローカのサーバのホスト名またはIPアドレスを設定します。
-tは データを識別するtopicを設定します。/で階層化しています。
-vは ログの表示をしています。
ESP32のマイコンからの温度の測定データ、配列からの日時、温度のデータが順番に表示されます。
これで、ESP32-WROOM-32Dのマイコンで測定したデータをWi-Fi経由でPCのサーバ(ブローカ)へ送り、スクライバのPCへと送信できることが確認できました。
① リアルタイムではWebブラウザで測定データを表示、必要に応じてマイコンに指令が送れることも確認できました。
データをESP32のバッファに蓄えられたので、経過をWebブラウザに表示することをこれからの計画としています。
② MQTT、MosquittoでESP32のマイコンからWi-Fi経由の送受信が比較的容易にできることが今回確認できました。別シリーズとなりますが、ESP32などのマイコンからWi-Fiなどを経由してデータを集積し利用する方法を検討する予定です。
(2020/2/3 V1.0)
<神崎康宏>