M5StickCにENV HAT(気温、湿度、気圧)をサーバーにアップする その5(Beebotte+MQTT編)

現時点での情報です。最新情報はM5StickC非公式日本語リファレンスを確認してください。

概要

ENV HAT(気温、湿度、気圧)の情報を1分ごとにBeebotteにアップしました。また基礎編をベースにしていますので、基礎部分の解説は省いています。

Beebotteとは?

IoT向けクラウドサービスで、さまざまな機能がありますがMQTTでデータを送信して、グラフ化する機能を利用しました。

MQTTの他にRESTでも利用できますが、ESP32の場合にはMQTTで接続したほうが電力や、通信量は少なくなると思います。またMQTTを利用していますので、送信の他にBeebotteからの受信や、外部サーバーとの連携などかなり複雑なことができます。

RESTでの通信例は別の記事になります。

事前作業

Beebotteで事前にChannel作成と、resource作成をしておきます。

resourceは名前の他に型名が指定できます。

型名備考
any送信するデータタイプがわからない場合や、変わる場合
number数値
string文字列
booleantrue or false
objectanyと同じ
functionJavaScriptを保存
arrayobjectの配列
alphabeticアルファベット
alphanumeric英数字
decimal10進数の数値
rateレート。0-1の値
percentageパーセンテージ。0-100の値
emaile-mailアドレス
gpsGPSアドレス
JSONでlongitudeとlatitudeの値を持つ
cpuCPU利用率
JSONでuser、sys、nice、idle、irqの値を持つ
memoryメモリー利用量
JSONでmemtotal、memfree、cached、dirtyの値を持つ
netifネットワーク利用量
JSONでrx_bytes、rx_packets、tx_bytes、tx_packetsの値を持つ
diskディスク利用量
JSONでsize、usedの値を持つ
temperature気温
humidity湿度
body_temp体温
pressure気圧
speed速度
weight重量
conductivity導電率

気温と湿度、気圧の型があるので、それぞれ作成します。tmp(temperature型)、hum(humidity型)、 pressure(pressure型)。リソースの名前はあとで変更するのが面倒なので、最初によく考えて命名しましょう。

また、スケッチの中では、外部に公開してまずいものは、Preferencesに保存しているので、本体内部にあらかじめ保存しておきます。

スケッチ

/*
    note: need add library Adafruit_BMP280 from library manage
    Github: https://github.com/adafruit/Adafruit_BMP280_Library

    note: need add library PubSubClient from library manage
    Github: https://github.com/knolleary/pubsubclient

*/

#include <M5StickC.h>
#include <Preferences.h>
#include <WiFi.h>
#include "DHT12.h"
#include <Adafruit_BMP280.h>
#include <PubSubClient.h>

Preferences preferences;
char wifi_ssid[33];
char wifi_key[65];

DHT12 dht12;
Adafruit_BMP280 bmp280;
unsigned long nextUpdate = 0;

WiFiClient wifiClient;
PubSubClient client(wifiClient);

char beebotte_token[40];
char beebotte_channel[40];

boolean reconnect() {
  uint64_t chipid = ESP.getEfuseMac();
  String clientId = "ESP32-" + String((uint16_t)(chipid >> 32), HEX);
  Serial.print("MQTT clientId=");
  Serial.println(clientId);

  if (client.connect(clientId.c_str(), beebotte_token, "")) {
    Serial.println("MQTTに接続");
  }
  return client.connected();
}

void publish(const char* resource, float data) {
  String json = "";
  json += "{";
  json += "\"channel\":\"" + String(beebotte_channel) + String( "\"," );
  json += "\"resource\":\"" + String(resource) + String( "\"," );
  json += "\"write\": true,";
  json += "\"data\":" + String(data);
  json += "}";

  String topic = String(beebotte_channel) + String("/") + String(resource);
  client.publish(topic.c_str(), json.c_str());
  Serial.println(topic);
  Serial.println(json);
}

void setup() {
  // M5StickC初期化
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0, 2);
  M5.Lcd.println("ENV TEST");

  // Wi-Fiアクセスポイント情報取得
  preferences.begin("Wi-Fi", true);
  preferences.getString("ssid", wifi_ssid, sizeof(wifi_ssid));
  preferences.getString("key", wifi_key, sizeof(wifi_key));
  preferences.end();

  // Wi-Fi接続
  Serial.printf("接続中 - %s ", wifi_ssid);
  WiFi.begin(wifi_ssid, wifi_key);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" 接続完了");

  // I2C初期化
  Wire.begin(0, 26);

  // bmp280初期化
  if (!bmp280.begin(0x76)) {
    Serial.println("bmp280センサーが見つかりません");
    while (1);
  }

  // MQTT情報取得
  preferences.begin("Beebotte", true);
  preferences.getString("token", beebotte_token, sizeof(beebotte_token));
  preferences.getString("channel", beebotte_channel, sizeof(beebotte_channel));
  preferences.end();

  // MQTT初期化
  randomSeed(micros());
  client.setServer("mqtt.beebotte.com", 1883);
}

void loop() {
  // 気温
  float tmp = dht12.readTemperature();
  M5.Lcd.setCursor(0, 20, 2);
  M5.Lcd.printf("Temp: %2.1f C", tmp);

  // 湿度
  float hum = dht12.readHumidity();
  M5.Lcd.setCursor(0, 40, 2);
  M5.Lcd.printf("Humi: %2.0f %%", hum);

  // 気圧
  float pressure = bmp280.readPressure() / 100.0F;
  M5.Lcd.setCursor(0, 60, 2);
  M5.Lcd.printf("pressure: %6.1f hPa", pressure);

  // 1分に1度データ送信
  if ( nextUpdate < millis() ) {
    // シリアル出力
    Serial.printf("Temp: %2.1f C\n", tmp);
    Serial.printf("Humi: %2.0f %%\n", hum);
    Serial.printf("pressure: %6.1f hPa\n", pressure);

    // MQTT
    if (!client.connected()) {
      // 接続していない場合には接続
      reconnect();
    }
    publish("tmp", tmp);
    publish("hum", hum);
    publish("pressure", pressure);

    // 時間更新(60秒後)
    nextUpdate = millis() + 60000;
  }

  // 1秒待機
  delay(1000);
}

PubSubClientライブラリを利用させてもらいました。接続プロトコルはMQTTのため、送信データ形式を少し触るだけで、他のMQTTサービスにデータ送信することができると思います。

まとめ

Beebotteは無料で使える範囲も多く、送受信両方使えるため使いやすいサービスです。有料オプションも比較的安価なのでおすすめです。

MQTTはもう少し掘り下げたいと思いますが、グラフ化シリーズはこれぐらいにしたいと思います。他になにか良いサービスがあれば教えて欲しいです。AWS IoT Things Graphは思ったより高くなりそうなので、試していないです。

続編

コメント