お知らせ
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を実行するとグラフが表示されます。
モバイルバッテリーなどを使い、外に放置すれば外の気温が家のPCで確認できたりします。
温度、湿度がわかれば梅雨~夏場の不快指数なども計算できます。