Blynkの代わりをいろいろと探していたのですが全然見つからず、一周回ってMQTTの現状を調べてみたら、パブリックMQTTブローカやスマホアプリもいろいろあることがわかって、MQTTに回帰することにしました。
「IoT OnOff」というアプリで温度・湿度・気圧を表示した画面
MQTTは軽いので、1秒更新でも大丈夫みたいです。
パブリックMQTTブローカー
パブリックMQTTブローカーは、ユーザー登録などの事前手続きをしなくても利用できる手軽なブローカーです。
ここでやりとりされるデータは誰もが見ることができるため、機微な情報をこの場所で扱うことは適切ではありません。
探せばもっとたくさん見つかると思いますが、先程の「IoT OnOff」アプリのブローカーリストには次の3つが登録されていました。
ポート番号がMQTT標準の「1883」や「8883」でなく「8080」や「443」になっているのは、このアプリがデフォルトでWebSocketsを使用してブローカーにアクセスするためです。
MQTT対応スマホアプリ
Apple App StoreやGoogle Play Storeで「mqtt」を検索すると、結構いろんなアプリが表示されます。(やっぱりGoogle Play Storeの方が数が多いですが...)
Google Play Store
ところが、両方のストアに登録されているアプリは少なく、今のところ良さそうに感じたのが「IoT OnOff」でした。
今回のテスト環境
ハードウェア(MQTTクライアント)
- M5Stack Atom Lite
- M5Stack用温湿度気圧センサユニット Ver. 3(ENV Ⅲ)
ソフトウェア(MQTTクライアント)
- Arduino IDE 1.8.15 (開発環境)
- Arduino core for the ESP32 1.0.6(ボード)
- PubSubClient 2.8.0 (ライブラリ)
MQTTクライアントライブラリ。対応バージョンはMQTT 3.1.1。 - Adafruit SHT31 Library 2.0.0 (ライブラリ)
- UNIT_ENV 0.0.2 (ライブラリ)
気圧センサQMP6988のライブラリが入っています。
MQTTブローカー
- HIVEMQ Public Broker (broker.hivemq.com)
HIVEMQは商用サービスやソフトウェア提供も行なっているMQTT専業企業です。
次のサイトでこのPublic Brokerの使用状況が確認できます。
MQTTスマホアプリ(MQTTクライアント)
以下は、用意されているウィジットのキャプチャです。
Blynkと比べるとかなり少なく、ゲージ(Circle)は字が小さくて見づらいし、グラフもあまりできが良くないのですが、全体的な作りは悪くなく今後のアップデートに期待する感じです。
アプリの設定
Settings > Configuration > Device
Settings > Configuration > MQTT Broker
DashBoard > Test
DashBoards > Test > Value (温度)
DashBoards > Test > Value (温度) > Subscribe
※Device IDを付加することでユニークなTopicにしています。
DashBoards > Test > Value (湿度)
DashBoards > Test > Value (湿度) > Subscribe
※Device IDを付加することでユニークなTopicにしています。
DashBoards > Test > Value (気圧)
DashBoards > Test > Value (気圧) > Subscribe
※Device IDを付加することでユニークなTopicにしています。
ソースコード
※2021年11月9日更新 client.loop();
を加えました。
#include <Adafruit_SHT31.h> // 温湿度センサーライブラリ #include <QMP6988.h> // 気圧センサーライブラリ #include <WiFi.h> // WiFiライブラリ #include <PubSubClient.h> // MQTTライブラリ #define WIFI_SSID "2.4GHzのSSID" #define WIFI_PASS "2.4GHzのSSIDのパスワード" // MQTT設定 #define MQTT_TOPIC_ID "デバイスIDをここに設定します" // トピック識別用ID #define MQTT_DEVICE_ID MQTT_TOPIC_ID "-1" // デバイスID(ユニークなID) #define MQTT_BROKER_ADDR "broker.hivemq.com" // MQTTブローカーのアドレス #define MQTT_TOPIC_TEMP MQTT_TOPIC_ID "/test/temperature" // 温度のトピック #define MQTT_TOPIC_HUMI MQTT_TOPIC_ID "/test/humidity" // 湿度のトピック #define MQTT_TOPIC_PRES MQTT_TOPIC_ID "/test/pressure" // 気圧のトピック // グローバル変数/オブジェクト Adafruit_SHT31 sht31 = Adafruit_SHT31(); // SHT3x用オブジェクト QMP6988 qmp6988; // QMP6988用オブジェクト WiFiClient wclient; // WiFi接続用オブジェクト PubSubClient client(MQTT_BROKER_ADDR, 1883, wclient); // MQTT接続用オブジェクト float temperature, humidity, pressure; // 温度、湿度、気圧の変数 unsigned long lastSend = 0; // 前回の送信時間 // 計測 void measurement() { temperature = NAN; // 温度の変数 humidity = NAN; // 湿度の変数 pressure = NAN; // 気圧の変数 // 計測 while (isnan(temperature) || isnan(humidity) || isnan(pressure)) { // 変数に値が入るまでループする delay(100); // 100ミリ秒待つ temperature = sht31.readTemperature(); // 温度を取得 humidity = sht31.readHumidity(); // 湿度を取得 pressure = qmp6988.calcPressure() / 100.0; // 気圧を取得 } // 値の四捨五入 temperature = ((int)((temperature*100+5)/10))/10.0; // 温度を少数第2位で四捨五入 humidity = (int)(humidity*10+5)/10; // 湿度を少数第1位で四捨五入 pressure = (int)(pressure*10+5)/10; // 気圧を少数第1位で四捨五入 // ログ表示 Serial.printf("temperature : %.2f\n", temperature); Serial.printf("humidity : %.2f\n", humidity); Serial.printf("pressure : %.2f\n", pressure); Serial.println(); } // WiFiに接続 void connectWiFi() { if (WiFi.status() != WL_CONNECTED) { // WiFiが繋がっていなかったら Serial.print("\nConnecting to " WIFI_SSID); // ログにWiFiのSSIDを表示 WiFi.begin(WIFI_SSID, WIFI_PASS); // WiFiに接続 while (WiFi.status() != WL_CONNECTED) { // WiFiが繋がるまでループ delay(1000); // 1秒待つ Serial.print("."); // ログに「.」を表示 } Serial.println("connected"); // ログに「WiFi connected」を表示 } } // データ送信 void sendData() { while (!client.connected()) { // MQTTブローカーの接続確認 Serial.print("Attempting MQTT connection..."); if (client.connect(MQTT_DEVICE_ID)) { // MQTT接続ブローカーに接続 Serial.println("connected"); } else { Serial.print("Retying in 5 seconds - failed, rc="); Serial.println(client.state()); delay(5000); } } // MQTTブローカーにデータを送信(パブリッシュ) client.publish(MQTT_TOPIC_TEMP, String(temperature).c_str()); // 温度 client.publish(MQTT_TOPIC_HUMI, String(humidity).c_str()); // 湿度 client.publish(MQTT_TOPIC_PRES, String(pressure).c_str()); // 気圧 client.loop(); // 接続維持用 } // 初期化 void setup() { Serial.begin(115200); delay(100); // センサー関連 Wire.begin(26, 32); // SDA:26 SCL:32でI2Cを初期化 sht31.begin(0x44); // SHT3xの初期化 qmp6988.init(); // QMP6988の初期化 } // メイン void loop() { unsigned long now = millis(); // 起動してからの時間取得 // millis()オーバーフロー対策(約50日で0に戻る) if (now < lastSend) lastSend = 0; // 前回の送信時間を0にする // 1秒毎にデータ送信 if (now - lastSend > 1000) { // 1秒より経っていたら measurement(); // 計測 connectWiFi(); // WiFiの接続確認 sendData(); // データ送信 lastSend = now; // 前回時間更新 } }