🐟

(Miniviz #1) ESP32で温度・湿度を測定してMinivizにて可視化する

に公開

Minivizとは?

Miniviz(ミニビズ)は個人開発した、IoTのPoCを加速させるためのBIプラットフォームです。
データ送信から格納・可視化・通知までをワンストップで簡単に実現することができます。

主な機能は以下の3つ

  • データベース機能
  • グラフ機能
  • 外部アラート機能

https://qiita.com/taiyyytai/items/f14e6f01fba2ee226a92

https://miniviz.net/

やること

今回は温度・湿度センサーを用いてデータを送信し、グラフを作成するサンプルを作成します。

必要なもの

ESP32
USBケーブル(データ転送用)
温度・湿度センサー(DHT11など)
ジャンパーワイヤー
ブレッドボード(オプション)

手順

  1. ESP32開発環境のセットアップ(PlatformIO)
  2. センサー接続・ソースコード実装(温度・湿度の取得・データ送信)
  3. データ送信確認・グラフ作成・通知設定

1. ESP32開発環境のセットアップ(PlatformIO)

Vscodeの拡張機能PlatformIOを使用してESP32の開発環境をセットアップします。

  1. PlatformIO IDEをダウンロード・インストール
  2. Visual Studio Code拡張機能としてインストールする方法が推奨されます
  3. Visual Studio Codeを起動し、PlatformIO拡張機能が有効になっていることを確認
  4. プロジェクトの作成
  • PlatformIOのホーム画面から「New Project」を選択
  • プロジェクト名を入力(例:esp32-miniviz)
  • Boardとして「ESP32 Dev Module」を選択
  • Frameworkとして「Arduino」を選択

platformio.iniファイルの例

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
lib_deps = adafruit/DHT sensor library@^1.4.6
monitor_speed = 115200

DHTライブラリの追加

温度湿度センサーDHT用のライブラリをインポートをしておきます。

2. センサー接続・ソースコード実装(温度・湿度の取得・データ送信)

センサーの接続

DHT11などの温度・湿度センサーをESP32に接続します。

DHT11の接続例:

DHT11              ESP32
------             ----------------
(1) VCC  --------> 3.3V
(2) DATA --------> GPIO4
(3) NC   --------> -
(4) GND  --------> GND

配線例

見にくいですが、イメージとして

データ送信サンプルを実行

Miniviz APIにデータを送信するESP32用のコードを作成します。

-> ソースコードは巻末に記載

プロジェクトIDとトークン取得

Minivizのアカウント作成 -> プロジェクト作成 -> プロジェクトIDとトークンを取得しておく

詳細はクイックスタートを確認してください

ソースコード実装・ビルド

src/main.cppファイルに以下の内容を記述します(PROJECT_IDとTOKENは実際の値に置き換えてください)
ビルドとアップロードを実行してください。シリアルモニターでPOSTリクエストが成功していることを確認してください。
サンプルコードは末尾に記載しています。

3. データ送信確認・グラフ作成

データ送信確認

サイドバーのDatabaseを開くとデータがパースされて表示されていると思います。

グラフの作成

  • Visualizeメニューからグラフを作成
  • グラフタイプを選択(ラインチャート推奨)
  • データソースとして温度・湿度を選択
  • グラフが正常に表示されることを確認

Slack、メールで通知できる!!

Minivizには外部アラート機能もあるので、必要に応じて通知も可能!

ソースコード

送信間隔は90秒に設定されています。

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

//----------------------------------------
// Configuration
//----------------------------------------
const int PIN_DHT = 4;
DHT dht(PIN_DHT, DHT11);

const char *ssid = "WIFI_SSID";
const char *password = "WIFI_PASSWORD";

// Miniviz API
const char *project_id = "MINIVIZ_PROJECT_ID";
const char *token = "MINIVIZ_API_TOKEN";

String endpoint = String("https://api.miniviz.net/api/project/") +
                  project_id + "?token=" + token;

// Deep Sleep (90 seconds)
const uint64_t SLEEP_INTERVAL_US = 90ULL * 1000000ULL;


//----------------------------------------
// Wi-Fi Connection
//----------------------------------------
void connectWiFi()
{
  Serial.println("Connecting to Wi-Fi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  int retry = 0;
  while (WiFi.status() != WL_CONNECTED && retry < 30) {
    delay(300);
    Serial.print(".");
    retry++;
  }
  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Wi-Fi connected");
  } else {
    Serial.println("Wi-Fi connection failed");
  }
}

//----------------------------------------
// NTP Time Synchronization
//----------------------------------------
void syncTime()
{
  Serial.println("Syncing NTP...");
  configTime(0, 0, "ntp.nict.jp", "time.google.com");

  struct tm timeinfo;
  while (!getLocalTime(&timeinfo)) {
    delay(200);
    Serial.print("*");
  }
  Serial.println("\nTime synced");
}

//----------------------------------------
// UNIX Timestamp in Milliseconds
//----------------------------------------
uint64_t getTimestampMs()
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return (uint64_t)tv.tv_sec * 1000ULL + (tv.tv_usec / 1000ULL);
}

//----------------------------------------
// POST to Miniviz
//----------------------------------------
void sendToMiniviz(float temp, float humid)
{
  if (WiFi.status() != WL_CONNECTED)
    connectWiFi();

  HTTPClient http;
  http.begin(endpoint);
  http.addHeader("Content-Type", "application/json");

  uint64_t ts = getTimestampMs();

  String body = "{";
  body += "\"timestamp\":" + String(ts) + ",";
  body += "\"label_key\":\"esp32_home\",";
  body += "\"payload\":{";
  body += "\"temperature\":" + String(temp) + ",";
  body += "\"humidity\":" + String(humid);
  body += "}}";

  int code = http.POST(body);
  Serial.println("HTTP code: " + String(code));
  Serial.println(http.getString());
  http.end();
}

//----------------------------------------
// Setup
//----------------------------------------
void setup()
{
  Serial.begin(115200);
  delay(200);

  dht.begin();
  connectWiFi();
  syncTime();
}

//----------------------------------------
// Loop (exits after one iteration due to DeepSleep)
//----------------------------------------
void loop()
{
  float t = dht.readTemperature();
  float h = dht.readHumidity();

  Serial.printf("Temperature: %.2f°C  Humidity: %.2f%%\n", t, h);

  sendToMiniviz(t, h);

  Serial.println("Entering deep sleep...");
  esp_deep_sleep(SLEEP_INTERVAL_US);
}

Discussion