M5Stack Core2 for AWS - ESP32 IoT開発キットを 買おうとしていたところで, 気づいたら売り切れていたので
代わりに買ってみたのがこのM5Stack Core2 IoT開発キット。
“for AWS"でないから Microsoft Azule IoT Hubに接続してみる。
Microsoft Azule IoT
Azure IoT (モノのインターネット) は、何十億もの IoT 資産を接続、監視、制御する、Microsoft によって管理される一連のクラウド サービスです。
M5Stack用のチュートリアルがあるんでこの通りに始めてみる。
Azure ESP32 IoT DevKit Get Started
What you need
- A ESP32 device.
- A computer running Windows 10 or macOS 10.10+.
- An active Azure subscription.
M5Stack Core2 + BME280センサー + Windows 10 WSL + PlatformIO + VSCode の環境でやってみる。
開発環境に必要な拡張機能をインストール
ここでAzule IoT Workbench拡張をVSCodeにインストールする。
We recommend Azure IoT Device Workbench extension for Visual Studio Code to develop on the ESP32 devices.
以下の手順通りに Windowsインストーラ版のArduino IDEを入れた。(すでにインストール済みだった。)
Download and install Arduino IDE. It provides the necessary toolchain for compiling and uploading Arduino code.
Windows: Use Windows Installer version
続いて Visual Studio Codeをインストールする。(すでにインストール済みだった。)
ここまで, すでにインストール済みだったので何もしていない。
続いて Azule IoT Workbench拡張をVSCodeにインストールした。
結果VSCode拡張はこんな状態。(今回と関係ないものが多数あるけどね)
“ファイル > ユーザー設定 > 設定"で出てくる検索ボックスに"arduino"といれて
“Arduino: Additional Urls"の"settings.jsonで編集"をクリックする。
Auduinoパスの設定
Open the project folder
サンプルいらないのでチュートリアルとは違って
“Azure IoT Device Workbench: Create Project…”
を選択した。
プロジェクト名を決めて
Arduinoを選んで
Generic ESP32 boards with Azure IoT Hubを選ぶと
こうなる
Provision Azure service
チュートリアルに戻ってきて
無料試用版 -> “Create Resource Group” を選んでリソースグループを作る。
とりあえず西日本
Iot Hubを新規作成
西日本 -> “F1:Free tire”
IoT Hub名を決める。
ここでちょっとした待ち時間があるので休憩。
続けてIoT Hubデバイスの設定
Config Device Code
チュートリアル通りに進める。
“Copy device connection string.“のところで拡張機能がエラーを出してきたので, WebブラウザからAzure potalにはいってプライマリ接続文字列を確認した。
“Azure IoT Device Workbench: Upload Device Code.“を実行するとM5Stack Core2に書き込まれて実行する。
なぜかVSCodeの出力が文字化けして読めなかったので, シリアルコンソールからM5Stackの出力を見る。
WebブラウザからAzure potalを確認すると, この通りなので毎秒Azure IoT HubにM5Stackから送信されているのが確認できた。
前回の温度/湿度/気圧の測定ソフトウェアをAzure Iot Hubに接続する
正常にAzure IoT Hubに接続できていることを確認できたので
前回の温度/湿度/気圧の測定ソフトウェアを
Azure IoT Hubに接続してブラウザからグラフを見れるようにする。
前回の温度/湿度/気圧の測定ソフトウェアを編集する
/*
* Copyright 2020 Akihiro Yamamoto
*/
#include <M5Core2.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "Esp32MQTTClient.h"
// from azure_iot.cpp
extern void azure_iot_InitWifi();
extern void azure_iot_setup();
extern void azure_iot_push(float temperature, float humidity, float pressure);
#define LGFX_M5STACK_CORE2
#include <LovyanGFX.hpp>
static LGFX lcd;
static const uint8_t BME280_I2C_ADDRESS = 0x76;
static Adafruit_BME280 bme280;
static Adafruit_Sensor *bme280_temperature = bme280.getTemperatureSensor();
static Adafruit_Sensor *bme280_pressure = bme280.getPressureSensor();
static Adafruit_Sensor *bme280_humidity = bme280.getHumiditySensor();
const unsigned long background_color = 0x000000U;
const unsigned long message_text_color = 0xFFFFFFU;
#define INTERVAL 10000
static uint64_t send_interval_ms;
struct TempHumPres
{
float temperature;
float relative_humidity;
float pressure;
};
void releaseEvent(Event &e)
{
}
struct TempHumPres sense()
{
sensors_event_t temperature_event;
sensors_event_t humidity_event;
sensors_event_t pressure_event;
//
bme280_temperature->getEvent(&temperature_event);
bme280_humidity->getEvent(&humidity_event);
bme280_pressure->getEvent(&pressure_event);
struct TempHumPres rv;
rv.temperature = temperature_event.temperature;
rv.relative_humidity = humidity_event.relative_humidity;
rv.pressure = pressure_event.pressure;
return rv;
}
void display(struct TempHumPres val)
{
lcd.setCursor(0, 0);
lcd.printf("温度 %7.2f ℃\n", val.temperature);
lcd.printf("湿度 %7.2f %\n", val.relative_humidity);
lcd.printf("気圧 %7.2f hPa\n", val.pressure);
}
void setup()
{
M5.begin(true, true, true, true);
M5.Buttons.addHandler(releaseEvent, E_RELEASE);
//
lcd.init();
lcd.setFont(&fonts::lgfxJapanGothic_36);
lcd.setTextColor(message_text_color, background_color);
//
while (!bme280.begin(BME280_I2C_ADDRESS))
{
lcd.printf("BME280センサが見つかりません。");
while (1)
{
delay(10);
}
}
//
bme280_temperature->printSensorDetails();
bme280_pressure->printSensorDetails();
bme280_humidity->printSensorDetails();
//
azure_iot_setup();
//
struct TempHumPres val = sense();
display(val);
//
send_interval_ms = millis();
}
void loop()
{
M5.update();
if ((int)(millis() - send_interval_ms) >= INTERVAL)
{
struct TempHumPres val = sense();
display(val);
//
azure_iot_push(val.temperature, val.relative_humidity, val.pressure);
send_interval_ms = millis();
}
else
{
Esp32MQTTClient_Check();
}
delay(10);
}
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
#include <M5Core2.h>
#include <WiFi.h>
#include "AzureIotHub.h"
#include "Esp32MQTTClient.h"
#define DEVICE_ID "M5Stack-Core2-iot"
#define MESSAGE_MAX_LEN 256
// Please input the SSID and password of WiFi
const char *ssid = "************";
const char *password = "************";
/*String containing Hostname, Device Id & Device Key in the format: */
/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>" */
/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>" */
static const char *connectionString = "*************************************************************************************************************************************";
const char *messageData = "{\"DeviceId\":\"%s\", \"messageId\":%d, \"temperature\":%.2f, \"humidity\":%.2f, \"pressure\":%.2f}";
int messageCount = 1;
static bool hasWifi = false;
static bool messageSending = true;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities
static void InitWifi()
{
Serial.println("Connecting...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
hasWifi = true;
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result)
{
if (result == IOTHUB_CLIENT_CONFIRMATION_OK)
{
Serial.println("Send Confirmation Callback finished.");
}
}
static void MessageCallback(const char *payLoad, int size)
{
Serial.println("Message callback:");
Serial.println(payLoad);
}
static void DeviceTwinCallback(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char *payLoad, int size)
{
char *temp = (char *)malloc(size + 1);
if (temp == NULL)
{
return;
}
memcpy(temp, payLoad, size);
temp[size] = '\0';
// Display Twin message.
Serial.println(temp);
free(temp);
}
static int DeviceMethodCallback(const char *methodName, const unsigned char *payload, int size, unsigned char **response, int *response_size)
{
LogInfo("Try to invoke method %s", methodName);
const char *responseMessage = "\"Successfully invoke device method\"";
int result = 200;
if (strcmp(methodName, "start") == 0)
{
LogInfo("Start sending temperature and humidity data");
messageSending = true;
}
else if (strcmp(methodName, "stop") == 0)
{
LogInfo("Stop sending temperature and humidity data");
messageSending = false;
}
else
{
LogInfo("No method %s found", methodName);
responseMessage = "\"No method found\"";
result = 404;
}
*response_size = strlen(responseMessage) + 1;
*response = (unsigned char *)strdup(responseMessage);
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Arduino sketch
void azure_iot_setup()
{
Serial.println("ESP32 Device");
Serial.println("Initializing...");
// Initialize the WiFi module
Serial.println(" > WiFi");
hasWifi = false;
InitWifi();
if (!hasWifi)
{
return;
}
Serial.println(" > IoT Hub");
Esp32MQTTClient_SetOption(OPTION_MINI_SOLUTION_NAME, "GetStarted");
Esp32MQTTClient_Init((const uint8_t *)connectionString, true);
Esp32MQTTClient_SetSendConfirmationCallback(SendConfirmationCallback);
Esp32MQTTClient_SetMessageCallback(MessageCallback);
Esp32MQTTClient_SetDeviceTwinCallback(DeviceTwinCallback);
Esp32MQTTClient_SetDeviceMethodCallback(DeviceMethodCallback);
}
void azure_iot_push(float temperature, float humidity, float pressure)
{
if (hasWifi)
{
if (messageSending)
{
// Send teperature data
char messagePayload[MESSAGE_MAX_LEN];
snprintf(messagePayload, MESSAGE_MAX_LEN, messageData, DEVICE_ID, messageCount++, temperature, humidity, pressure);
Serial.println(messagePayload);
EVENT_INSTANCE *message = Esp32MQTTClient_Event_Generate(messagePayload, MESSAGE);
Esp32MQTTClient_Event_AddProp(message, "temperatureAlert", "true");
Esp32MQTTClient_SendEventInstance(message);
}
}
}
Web アプリで Azure IoT Hub からのリアルタイム センサー データを視覚化する
今回のチュートリアルはこれ。
Web アプリで Azure IoT Hub からのリアルタイム センサー データを視覚化する
IoT ハブへのコンシューマー グループの追加
Web アプリの環境変数を構成する
WSL上のbashなので
export IotHubConnectionString=YourIoTHubConnectionString
export EventHubConsumerGroup="consumer-group"
Web アプリの実行
実行そのまえに編集する。
/* eslint-disable max-classes-per-file */
/* eslint-disable no-restricted-globals */
/* eslint-disable no-undef */
$(document).ready(() => {
// if deployed to a site supporting SSL, use wss://
const protocol = document.location.protocol.startsWith('https') ? 'wss://' : 'ws://';
const webSocket = new WebSocket(protocol + location.host);
// A class for holding the last N points of telemetry for a device
class DeviceData {
constructor(deviceId) {
this.deviceId = deviceId;
this.maxLen = 50;
this.timeData = new Array(this.maxLen);
this.temperatureData = new Array(this.maxLen);
this.humidityData = new Array(this.maxLen);
this.pressureData = new Array(this.maxLen);
}
addData(time, temperature, humidity, pressure) {
this.timeData.push(time);
this.temperatureData.push(temperature);
this.humidityData.push(humidity);
this.pressureData.push(pressure);
if (this.timeData.length > this.maxLen) {
this.timeData.shift();
this.temperatureData.shift();
this.humidityData.shift();
this.pressureData.shift();
}
}
}
// All the devices in the list (those that have been sending telemetry)
class TrackedDevices {
constructor() {
this.devices = [];
}
// Find a device based on its Id
findDevice(deviceId) {
for (let i = 0; i < this.devices.length; ++i) {
if (this.devices[i].deviceId === deviceId) {
return this.devices[i];
}
}
return undefined;
}
getDevicesCount() {
return this.devices.length;
}
}
const trackedDevices = new TrackedDevices();
// Define the chart axes
const chartData = {
datasets: [
{
fill: false,
label: 'Temperature',
yAxisID: 'Temperature',
borderColor: 'rgba(255, 204, 0, 1)',
pointBoarderColor: 'rgba(255, 204, 0, 1)',
backgroundColor: 'rgba(255, 204, 0, 0.4)',
pointHoverBackgroundColor: 'rgba(255, 204, 0, 1)',
pointHoverBorderColor: 'rgba(255, 204, 0, 1)',
spanGaps: true,
},
{
fill: false,
label: 'Humidity',
yAxisID: 'Humidity',
borderColor: 'rgba(24, 120, 240, 1)',
pointBoarderColor: 'rgba(24, 120, 240, 1)',
backgroundColor: 'rgba(24, 120, 240, 0.4)',
pointHoverBackgroundColor: 'rgba(24, 120, 240, 1)',
pointHoverBorderColor: 'rgba(24, 120, 240, 1)',
spanGaps: true,
},
{
fill: false,
label: 'Pressure',
yAxisID: 'Pressure',
borderColor: 'rgba(24, 24, 240, 1)',
pointBoarderColor: 'rgba(24, 24, 240, 1)',
backgroundColor: 'rgba(24, 24, 240, 0.4)',
pointHoverBackgroundColor: 'rgba(24, 24, 240, 1)',
pointHoverBorderColor: 'rgba(24, 24, 240, 1)',
spanGaps: true,
}
]
};
const chartOptions = {
scales: {
yAxes: [{
id: 'Temperature',
type: 'linear',
scaleLabel: {
labelString: 'Temperature (ºC)',
display: true,
},
position: 'left',
},
{
id: 'Humidity',
type: 'linear',
scaleLabel: {
labelString: 'Humidity (%)',
display: true,
},
position: 'left',
},
{
id: 'Pressure',
type: 'linear',
scaleLabel: {
labelString: 'Pressure (hPa)',
display: true,
},
position: 'right',
}]
}
};
// Get the context of the canvas element we want to select
const ctx = document.getElementById('iotChart').getContext('2d');
const myLineChart = new Chart(
ctx,
{
type: 'line',
data: chartData,
options: chartOptions,
});
// Manage a list of devices in the UI, and update which device data the chart is showing
// based on selection
let needsAutoSelect = true;
const deviceCount = document.getElementById('deviceCount');
const listOfDevices = document.getElementById('listOfDevices');
function OnSelectionChange() {
const device = trackedDevices.findDevice(listOfDevices[listOfDevices.selectedIndex].text);
chartData.labels = device.timeData;
chartData.datasets[0].data = device.temperatureData;
chartData.datasets[1].data = device.humidityData;
chartData.datasets[2].data = device.pressureData;
myLineChart.update();
}
listOfDevices.addEventListener('change', OnSelectionChange, false);
// When a web socket message arrives:
// 1. Unpack it
// 2. Validate it has date/time and temperature
// 3. Find or create a cached device to hold the telemetry data
// 4. Append the telemetry data
// 5. Update the chart UI
webSocket.onmessage = function onMessage(message) {
try {
const messageData = JSON.parse(message.data);
console.log(messageData);
// time and either temperature or humidity are required
if (!messageData.MessageDate || (!messageData.IotData.temperature && !messageData.IotData.humidity && !messageData.IotData.pressure)) {
return;
}
// find or add device to list of tracked devices
const existingDeviceData = trackedDevices.findDevice(messageData.DeviceId);
if (existingDeviceData) {
existingDeviceData.addData(messageData.MessageDate, messageData.IotData.temperature, messageData.IotData.humidity, messageData.IotData.pressure);
} else {
const newDeviceData = new DeviceData(messageData.DeviceId);
trackedDevices.devices.push(newDeviceData);
const numDevices = trackedDevices.getDevicesCount();
deviceCount.innerText = numDevices === 1 ? `${numDevices} device` : `${numDevices} devices`;
newDeviceData.addData(messageData.MessageDate, messageData.IotData.temperature, messageData.IotData.humidity, messageData.IotData.pressure);
// add device to the UI list
const node = document.createElement('option');
const nodeText = document.createTextNode(messageData.DeviceId);
node.appendChild(nodeText);
listOfDevices.appendChild(node);
// if this is the first device being discovered, auto-select it
if (needsAutoSelect) {
needsAutoSelect = false;
listOfDevices.selectedIndex = 0;
OnSelectionChange();
}
}
myLineChart.update();
} catch (err) {
console.error(err);
}
};
});
ここまで準備ができたら実行する。
npm install
npm start
Using IoT Hub connection string [HostName=************************************************************;SharedAccessKey=********************************************]
consumer-group
Using event hub consumer group [consumer-group]
Listening on 3000.
Successfully created the EventHubConsumerClient from IoT Hub event hub-compatible connection string.
The partition ids are: [ '0', '1' ]
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":5,"temperature":24.26,"humidity":33.62,"pressure":1026.43},"MessageDate":"2021-01-03T16:05:09.582Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":6,"temperature":24.26,"humidity":33.66,"pressure":1026.49},"MessageDate":"2021-01-03T16:05:19.723Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":7,"temperature":24.25,"humidity":33.71,"pressure":1026.49},"MessageDate":"2021-01-03T16:05:29.874Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":8,"temperature":24.23,"humidity":33.69,"pressure":1026.51},"MessageDate":"2021-01-03T16:05:40.022Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":9,"temperature":24.21,"humidity":33.73,"pressure":1026.5},"MessageDate":"2021-01-03T16:05:50.178Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":10,"temperature":24.23,"humidity":33.7,"pressure":1026.51},"MessageDate":"2021-01-03T16:06:00.334Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":11,"temperature":24.21,"humidity":33.74,"pressure":1026.53},"MessageDate":"2021-01-03T16:06:10.475Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":12,"temperature":24.22,"humidity":33.73,"pressure":1026.51},"MessageDate":"2021-01-03T16:06:20.617Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":13,"temperature":24.21,"humidity":33.74,"pressure":1026.53},"MessageDate":"2021-01-03T16:06:30.784Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":14,"temperature":24.22,"humidity":33.76,"pressure":1026.55},"MessageDate":"2021-01-03T16:06:40.940Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":15,"temperature":24.23,"humidity":33.73,"pressure":1026.47},"MessageDate":"2021-01-03T16:06:51.083Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":16,"temperature":24.23,"humidity":33.71,"pressure":1026.52},"MessageDate":"2021-01-03T16:07:01.227Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":17,"temperature":24.22,"humidity":33.72,"pressure":1026.5},"MessageDate":"2021-01-03T16:07:11.386Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":18,"temperature":24.23,"humidity":33.73,"pressure":1026.46},"MessageDate":"2021-01-03T16:07:21.534Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":19,"temperature":24.23,"humidity":33.71,"pressure":1026.48},"MessageDate":"2021-01-03T16:07:31.676Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":20,"temperature":24.22,"humidity":33.73,"pressure":1026.51},"MessageDate":"2021-01-03T16:07:41.832Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":21,"temperature":24.23,"humidity":33.76,"pressure":1026.47},"MessageDate":"2021-01-03T16:07:51.981Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":22,"temperature":24.22,"humidity":33.74,"pressure":1026.46},"MessageDate":"2021-01-03T16:08:02.137Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":23,"temperature":24.24,"humidity":33.75,"pressure":1026.45},"MessageDate":"2021-01-03T16:08:12.277Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":24,"temperature":24.21,"humidity":33.74,"pressure":1026.47},"MessageDate":"2021-01-03T16:08:22.434Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":25,"temperature":24.2,"humidity":33.75,"pressure":1026.44},"MessageDate":"2021-01-03T16:08:32.582Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":26,"temperature":24.16,"humidity":33.84,"pressure":1026.44},"MessageDate":"2021-01-03T16:08:42.739Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":27,"temperature":24.17,"humidity":33.81,"pressure":1026.4},"MessageDate":"2021-01-03T16:08:52.897Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":28,"temperature":24.16,"humidity":33.88,"pressure":1026.44},"MessageDate":"2021-01-03T16:09:03.039Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":29,"temperature":24.15,"humidity":33.92,"pressure":1026.47},"MessageDate":"2021-01-03T16:09:13.195Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":30,"temperature":24.16,"humidity":33.91,"pressure":1026.47},"MessageDate":"2021-01-03T16:09:23.344Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":31,"temperature":24.15,"humidity":33.94,"pressure":1026.49},"MessageDate":"2021-01-03T16:09:33.500Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":32,"temperature":24.14,"humidity":33.97,"pressure":1026.42},"MessageDate":"2021-01-03T16:09:43.641Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":33,"temperature":24.14,"humidity":33.96,"pressure":1026.44},"MessageDate":"2021-01-03T16:09:53.797Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":34,"temperature":24.14,"humidity":33.96,"pressure":1026.45},"MessageDate":"2021-01-03T16:10:03.953Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":35,"temperature":24.13,"humidity":33.97,"pressure":1026.44},"MessageDate":"2021-01-03T16:10:14.110Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":36,"temperature":24.13,"humidity":33.99,"pressure":1026.43},"MessageDate":"2021-01-03T16:10:24.251Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":37,"temperature":24.13,"humidity":34,"pressure":1026.47},"MessageDate":"2021-01-03T16:10:34.408Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":38,"temperature":24.14,"humidity":34.03,"pressure":1026.47},"MessageDate":"2021-01-03T16:10:44.564Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":39,"temperature":24.17,"humidity":33.95,"pressure":1026.49},"MessageDate":"2021-01-03T16:10:54.705Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":40,"temperature":24.18,"humidity":33.92,"pressure":1026.46},"MessageDate":"2021-01-03T16:11:04.864Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":41,"temperature":24.22,"humidity":33.86,"pressure":1026.47},"MessageDate":"2021-01-03T16:11:15.004Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":42,"temperature":24.22,"humidity":33.87,"pressure":1026.48},"MessageDate":"2021-01-03T16:11:25.160Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":43,"temperature":24.23,"humidity":33.9,"pressure":1026.46},"MessageDate":"2021-01-03T16:11:35.307Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":44,"temperature":24.24,"humidity":33.85,"pressure":1026.45},"MessageDate":"2021-01-03T16:11:45.463Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":45,"temperature":24.26,"humidity":33.86,"pressure":1026.47},"MessageDate":"2021-01-03T16:11:55.604Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":46,"temperature":24.26,"humidity":33.84,"pressure":1026.45},"MessageDate":"2021-01-03T16:12:05.761Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":47,"temperature":24.27,"humidity":33.82,"pressure":1026.49},"MessageDate":"2021-01-03T16:12:15.911Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":48,"temperature":24.27,"humidity":33.81,"pressure":1026.45},"MessageDate":"2021-01-03T16:12:26.055Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":49,"temperature":24.27,"humidity":33.8,"pressure":1026.5},"MessageDate":"2021-01-03T16:12:36.211Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":50,"temperature":24.25,"humidity":33.83,"pressure":1026.49},"MessageDate":"2021-01-03T16:12:46.368Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":51,"temperature":24.26,"humidity":33.86,"pressure":1026.49},"MessageDate":"2021-01-03T16:12:56.516Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":52,"temperature":24.29,"humidity":33.82,"pressure":1026.49},"MessageDate":"2021-01-03T16:13:06.661Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":53,"temperature":24.27,"humidity":33.81,"pressure":1026.51},"MessageDate":"2021-01-03T16:13:16.817Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":54,"temperature":24.32,"humidity":33.75,"pressure":1026.5},"MessageDate":"2021-01-03T16:13:26.973Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":55,"temperature":24.31,"humidity":33.78,"pressure":1026.51},"MessageDate":"2021-01-03T16:13:37.129Z","DeviceId":"m5stack-bme280-device"}
Broadcasting data {"IotData":{"DeviceId":"M5Stack-BME280-device","messageId":56,"temperature":24.3,"humidity":33.8,"pressure":1026.52},"MessageDate":"2021-01-03T16:13:47.273Z","DeviceId":"m5stack-bme280-device"}
ブラウザからlocalhost:3000にアクセスすると
グラフが激しく波打っているのは, 小数点以下の動きを視覚化しているから。
これだけ出来たから今日は終わり。