Engineer Blog開発者ブログ

2020.4.23

ESP-WROOM-02でIoT その③ WiFiを使って温度と湿度をグラフ化する

前回は、ESP-WROOM-02にプログラムを書き込み、ディスプレイに情報を表示しました。

今回は、温度と湿度をWiFiで送信しnode.jsとsocket.ioを使ってグラフ化します。

※事前にnode.jsの環境を構築しておく必要があります。Visual Studio Code等を利用すると簡単です。

 

■クライアント側(ESP-WROOM-02)

前回のプログラムにWiFiへの接続、HTTPクライアントでのPOST処理、JSONオブジェクトの作成処理を追加します。

ssidとpasswordは、ご自身のWiFi環境に合わせ修正してください。

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

#include <Adafruit_BME280.h>
#include <Adafruit_SSD1306.h>
#define SEALEVELPRESSURE_HPA (1013.25)
#define OLED_RESET 2

Adafruit_BME280 bme; // I2C
Adafruit_SSD1306 display(OLED_RESET);

const char *ssid = "xxxxxx";
const char *password = "xxxxxxxx";

void setup()
{
  // シリアルポート開始(Serial.print用)
  Serial.begin(9600);

  //OLED(SSD1306)開始
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  // BME280センサー開始
  if (!bme.begin(0x76, &Wire))
  {
    OLEDPrint("BME280 Sensor error. SensorID 0x" + String(bme.sensorID(), HEX), 0, true);
    while (1)
      delay(10);
  }

  Serial.println();

    // WiFi開始
  WiFi.begin(ssid, password);

  OLEDPrint(String("Connecting to \r\n" + String(ssid)), 0, true);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    OLEDPrint("WiFi connected", 0, true);
  }

  delay(2000);
}

const size_t CAPACITY = 300;

void loop()
{
  // 各種センサー情報をJSONオブジェクトに設定
  StaticJsonDocument<CAPACITY> json_doc;
  JsonObject json_object = json_doc.to<JsonObject>();
  json_object["temp"] = bme.readTemperature();
  json_object["prsr"] = bme.readPressure() / 100.0F;
  json_object["attr"] = bme.readAltitude(SEALEVELPRESSURE_HPA);
  json_object["humi"] = bme.readHumidity();
  
  display.clearDisplay();
  OLEDPrint("Temp:" + json_object["temp"].as<String>() + "*C", 0, false); // 温度
  OLEDPrint("Prsr:" + json_object["prsr"].as<String>() + " hPa", 8, false); // 気圧
  OLEDPrint("Attr:" + json_object["attr"].as<String>() + " m", 16, false); // 高度
  OLEDPrint("Humi:" + json_object["humi"].as<String>() + " %", 24, false); // 湿度
  display.display();

  // JSONをシリアライズ
  char json_buf[CAPACITY];
  serializeJsonPretty(json_doc, json_buf, CAPACITY);

  // 受信側のサーバへJSON形式で送信(POST)
  HTTPClient http;
  http.begin("http://192.168.0.2:3000/");
  http.addHeader("Content-Type", "application/json");

  int http_code = http.POST(json_buf);

  if (http_code < 0) //Send the request
  {
    Serial.println("HTTP POST ERROR. CODE:" + String(http_code));
  }

  Serial.println(http.getString());
  http.end(); //Close connection
  
  delay(2000);
}

void OLEDPrint(String str, int cur_y, bool refresh)
{
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, cur_y);
  if (refresh) display.clearDisplay();
  display.println(str);
  if (refresh) display.display();
}

 

■サーバ側(app.js)

"use strict";
var port = 3000;

const bodyParser = require("body-parser")
var app = require("express")();
var http = require("http").Server(app);
var io = require("socket.io")(http);

app.get("/", function (req, res) {
    res.sendFile(__dirname + "/index.html");
});

app.use(bodyParser.json({
    extended: true
}));

// コネクションの確立
io.on("connection", function (socket) {
    socket.on("disconnect", function () {
        console.log("Client disconnected");
    });
});

app.post("/", function (req, res, next) {
    // クライアント側に送るためのfunction
    io.emit("graph_update", req.body);
    //console.log(req.body);
    res.send({});
});

http.listen(port, function () {
    console.log("listening on *:3000");
});

 

■サーバ側(index.html)

<!DOCTYPE html>
<html>
    <head>
        <title>グラフテスト</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.2/moment.min.js"></script>
        <script src="/socket.io/socket.io.js"></script>
    </head>
    <body>
        <script>
            $(document).ready(function () {
                var socket = io();

                // 温度グラフ設定
                var tempChartObj = {
                    type: "line",
                    data: {
                        labels: [],
                        datasets: [{
                            label: "温度",
                            data: [],
                            backgroundColor: [
                                "rgba(255, 99, 132, 0.2)"
                            ],
                            borderWidth: 1
                        }]
                    },
                    options: {
                        responsive : true,
                        maintainAspectRatio : true,
                        legend: {
                            display: true // 凡例表示
                        },
                        scales: {
                            yAxes: [{
                                    scaleLabel: {                 // 軸ラベル
                                    display: true,                // 表示設定
                                    labelString: "温度(℃)",    // ラベル
                                    //fontColor: "red",             // 文字の色
                                    fontSize: 12                  // フォントサイズ
                                },
                                ticks: {
                                    beginAtZero: true,
                                    min: 0,
                                    max: 50
                                }
                            }]
                        }
                    }
                }
                
                // 湿度グラフ設定
                var humiChartObj = jQuery.extend(true, {}, tempChartObj);
                humiChartObj.options.scales.yAxes[0].scaleLabel.labelString = "湿度(%)";
                humiChartObj.data.datasets[0].label = "湿度";
                humiChartObj.data.datasets[0].backgroundColor[0] = "rgba(255, 159, 64, 0.2)";
                humiChartObj.options.scales.yAxes[0].ticks.min = 0;
                humiChartObj.options.scales.yAxes[0].ticks.max = 100;

                // 温度グラフの作成 
                var tempChart = new Chart($("#temp_graph")[0].getContext("2d"), tempChartObj);

                // 湿度グラフの作成 
                var humiChart = new Chart($("#temp_graph2")[0].getContext("2d"), humiChartObj);

                $(function () {
                    // サーバから値を受け取った時の処理
                    socket.on("graph_update", (data) => {
                        // 現在時刻の取得
                        const outputTime = moment().format("HH : mm : ss");
                        // 追加するデータのラベルに時間を付与
                        tempChart.data.labels.push(outputTime);
                        humiChart.data.labels.push(outputTime);
                        // グラフにデータを追加
                        tempChart.data.datasets[0].data.push(data.temp);
                        humiChart.data.datasets[0].data.push(data.humi);
                        // グラフの表示更新
                        tempChart.update();
                        humiChart.update();
                    });
                });
            });
        </script>
        <div class="left" style="width:500px; height:500px; float:left;">
            <canvas id="temp_graph" height="150"></canvas>
        </div>
        <div class="right" style="width:500px; height:500px; float:left;">
            <canvas id="temp_graph2" height="150"></canvas>
        </div>
    </body>
</html>

 

■実行

サーバーを起動し、以下URLを実行するとグラフが表示されます。

http://localhost:3000/

 

モバイルバッテリーなどを使い、外に放置すれば外の気温が家のPCで確認できたりします。

温度、湿度がわかれば梅雨~夏場の不快指数なども計算できます。

 

Contact
お問い合わせ

電話番号0120 - 889 - 236
受付時間:平日 9:00-18:00