こんにちは、ENGかぴです。
Webソケットを実装するとESP32-WROOM-32Eが取得したデータをクライアントのHTMLで使用することができます。温湿度データからJSON形式のデータを生成してWebソケットでHTMLに送信して履歴をグラフ表示する方法をまとめました。
ESP32-WROOM-32E開発ボード(秋月電子)を使用しArduino IDEで開発を行います。温湿度センサーはAE-SHT35(秋月電子)を使用しています。
ESP32-WROOM-32Eで温湿度データをグラフで表示する
上記記事で紹介している方法をHTMLファイルとJSファイルを分けて管理し、グラフ表示する方法を説明しています。ESP32-WROOM-32E(以下ではESP32とする)を使って動作確認したことをまとめています。
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
WebサーバーとWebソケットの関係

スマホなどのクライアントから接続要求を受けるとWebサーバーが応答してHTMLファイルで応答します。HTMLでJavaスクリプトを参照するように指定した場合はJavaスクリプト専用のJSファイルを呼び出します。
JSファイルはグラフを表示するためのChart.jsライブラリの設定やWebソケットの接続イベントの処理をまとめたファイルです。
ESP32が温湿度センサーから取得したデータをJSONデータに変換し、Webソケットでクライアントに返信することでクライアント側のHTMLは温湿度データを表示することができます。
Webソケット及びJSONデータを生成するためにArduino IDEにライブラリを追加して使用します。
WebSocketsライブラリを追加する

Arduino IDEのライブラリマネージャの検索欄にWebsocketsを入力するとライブラリの候補が表示されます。候補の中からWebSockets by Markus Sattlerをインストールします。Webソケットの初期化の例は以下の通りです。
#include <WebSocketsServer.h>
WebSocketsServer webSocket = WebSocketsServer(81);
void setup() {
webSocket.begin(); //Webソケットの初期化
webSocket.onEvent(webSocketEvent); //イベント登録
}
void loop() {
webSocket.loop(); //接続の待機
}
WebSocketをサーバーとして使用するためWebSocketsServer.hをインクルードします。WebSocketsServerクラスの変数としてwebSocketをインスタンス化して、WebSocketsServer(81)で81番のポートを使用する設定を行います。
WebSocketsServerクラスのbegin()関数でWebソケットの初期化を行います。onEvent()関数でWebソケットのイベントが発生した時に遷移させる関数を指定します。例ではイベント発生時にwebSoketEvent()関数に遷移します。
loop()関数でクライアントからの接続要求を待機します。
/* WebSocketパケット処理*/
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_CONNECTED:
webSocket.sendTXT(num, jsonXString); //クライアントへの応答
break;
}
}
クライアントから接続要求を受けるとwebSocketEvent()関数に遷移します。引数にパケットのタイプが格納されているので接続要求(WStype_CONNECTED)の場合にsendTXT()関数でクライアントへの応答を送信します。
sendTXT()関数の第1引数は、クライアントの受付番号、第2引数はペイロードのアドレスを指定します。例ではペイロードのアドレスは生成したJSONデータを指定しています。
Arduino_JSONライブラリを追加する

JSONデータはJavaScriptのオブジェクトの書き方に対応したデータのフォーマットであり、C++などの言語でサポートされています。また文字列、数値、配列、bool(true,false)、オブジェクトに対応しているため幅広く使用されています。
Arduino環境ではB版(2023年12月下旬)としてArduino_JSON by Arduinoが公開されています。本記事ではArduino_JSONライブラリを追加して温湿度データをJSONデータに変換します。
Arduino IDEのライブラリマネージャの検索欄にjsonを入力するとライブラリの候補が表示されます。候補の中からArduino_JSON by Arduinoをインストールします。使用例は以下の通りです。
#include <Arduino_JSON.h>
String jsonString;//JSONの文字列
void charDataSet(void){
JSONVar json;
uint16_t i;
char temp_s[7];
for(i=0; i < CHART_SZ; i++ ){
json["X"][i] = i;
}
for(i=0; i < CHART_SZ; i++ ){
sprintf(&temp_s[0], "%6.2f",tempdat[i]);
json["Temp"][i] = temp_s;
}
jsonString = JSON.stringify(json);//JSONファイル生成
}
Arduino_JSON.hをインクルードします。生成したJSONデータの文字列を格納して使用する場合はString型の変数を準備して格納します。
JSONVarクラスの変数としてjsonをインスタンス化してJSONデータの生成要素を指定します。例ではid:”X”の配列とid:”Temp”の配列を生成するように指定しています。
Tempの配列は数値を指定するとfloatの型の数値が文字列として変換されるため、文字列が大きくなってしまいます。そのためsprintf()で小数点2桁に変換して文字列を削減しています。
JSONオブジェクトのstringify()関数でJSONデータに変換します。今回の例では以下のようなJSONデータの文字列が生成されます。変換後の文字列はString型の変数に格納して使用します。
{“X”:[0,1,2,・・・・,599],”Temp”:[“23.16″,”23.16″,・・・・,”0.00”]}
“”で囲まれているのは文字列で、囲まれていないものは数値になります。HTMLで表示する場合はテキストデータになるため数値と文字列はどちらで生成しても特に問題になりません。
JSONデータをWebソケットで送信することでJavaScriptがJSONデータを展開して使用できるためクライアントで温湿度データを表示することができます。
Webサーバーで表示するページを作成する。
Webサーバーの設定は以下の通りとします。WebサーバーでHTMLファイルとJSファイルを読み込んで使用します。
WebServer Wserver(80);
Wserver.on("/",HTTP_GET,HtmlSet2);
Wserver.serveStatic("/", SPIFFS, "/"); //SPIFFSでアクセス
ポートを80番としon()関数で指定した関数であるHtmlSet2()関数に遷移させます。serveStatic()関数はSPIFFSを使用してファイルにアクセスするための設定です。
void HtmlSet2(void){
File file = SPIFFS.open("/textHtml3.html", "r");
Wserver.streamFile(file, "text/html"); //ファイルを読み込む
file.close();
}
SPIFFSオブジェクトのopen()関数でtextHtml3.htmlのファイルを開きます。WebサーバークラスのstreamFile()関数でファイルの内容をtext/htmlとして送信して応答します。ファイルの内容をすべて送信するとclose()関数でファイルを閉じます。
HTMLファイルを作成する
Webサーバーで読み込むファイルを作成します。HTMLデータはテキストドキュメントの拡張子をhtmlに変更すると作成できます。HTML形式でソースコードを記述してページを作成します。
<!DOCTYPE html>
<html lang = "ja">
<head>
<meta charset = "UTF-8">
<title>Sensor SHT35</title>
<link rel="icon" href="myfavicon.ico">
<script src ="chart.umd.js"></script>
<script src ="chartText.js" defer ></script>
</head>
<body>
<h2>温度:
<code id="latest-temp">--.--</code>
<code>℃</code>
</h2>
<div class="height: 900px; width: 800px; margin: auto;">
<canvas id="temp-humid-chart" class="chart"></canvas>
</div>
</body>
</html>
<head></head>の間にタイトル、ファビコンのリンク設定、スクリプトファイル(JSファイル)のアドレスの指定を行います。
Webサーバーが指定しているアドレスにそれぞれのファイル参照できるようにアドレスパスを指定します。例では同一の場所に配置しているためファイル名を指定しています。
<body></body>の間はコンテンツを追加します。温度情報はJSファイルで関連付けしたid=”latest-temp”で指定した温度データが表示します。
<canvas></canvas>はJSファイルで関連付けしたid=”temp-humid-chart”で指定したグラフをキャンパスで描写します。
広告
マイベスト3年連続1位を獲得した実績を持つ実践型のプログラミングスクール
JSファイルを作成する
JSファイルはJavaScriptを記述します。JSファイルにはWebソケットで取得したJSONデータの展開とidの関連付けやグラフ表示の設定などを行います。
var xval;
var tempval;
/* Chartのグラフを生成 */
window.onload = () => {
let ctx = document.getElementById("temp-humid-chart").getContext("2d");
window.tempHumidChart = new Chart(ctx, chartConfig);
};
/* SebSocketイベントのインスタンスを生成 */
var ws = new WebSocket('ws://' + window.location.hostname + ':81/');
/* WebSocketがメッセージを受信 */
ws.onmessage = function(evt){
var i;
obj = JSON.parse(evt.data);//JSONファイルを展開
xval = obj["X"];
tempval = obj["Temp"];
document.getElementById("latest-temp").innerHTML = tempval[0];
for(i=0; i<600;i++){
window.tempHumidChart.data.labels.push(xval[i]);
window.tempHumidChart.data.datasets[0].data.push(tempval[i]);
}
window.tempHumidChart.update();
};
/* WebSocketの廃棄 */
ws.onclose = function(evt) {
ws.close();
};
フォームが読み込まれるとonLoad()プロパティでイベントを検出します。グラフ表示のためChartの設定を行いtempHumidChartでインスタンス化します。
Chart()の第1引数にキャンパスのid(“temp-humid-chart”)を指定します。第2引数にグラフの設定(configデータ)を指定します。id及びグラフの設定が間違えていなければグラフが表示されます。
WebSocket()でポートを指定してWebソケットを設定しwsでインスタンス化します。ESP32のWebソケットとポート番号を同一にするため81番と指定します。wsを操作してWebソケットのイベントを管理します。
Webソケットがデータを受信しイベントを検出するとonmessage()プロパティでイベントを検出します。ESP32が送信したJSONデータをJSONオブジェクトのparse()メソッドで展開します。
展開したデータからidが”X”の配列をxvalに格納し、idが”Temp”の配列をtempvalに格納します。
document.getElementById()メソッドで指定したidの配列の0番目の値をセットすると最新のデータがidを介して引き渡させるため、HTMLでidを指定すると最新のデータを表示することができます。
グラフの設定(chartConfig)でlabelsは横軸なのでxvalの配列の値を順にpushしてセットします。グラフの設定でdata.datasets[0]は縦軸なのでtempvalの配列の値を順にpushしてセットします。履歴のサイズ分の600回繰り返すことでグラフの値がセットできます。
update()関数でグラフを更新するとセットした値でグラフが表示できます。
FLASHにファイルを格納する

dataフォルダにHTMLファイル、JSファイル、ファビコン、グラフ表示用のChart.jsライブラリを配置します。
dataフォルダのファイルをFLASH領域に格納することでSPIFFSでそれぞれのファイルを読み出せるようになります。
下記記事ではSDカードを使用してファイルを書き込む方法やESP32 Sketch Data Uploadプラグインを使用してFLASHにファイルを書き込む方法をまとめています。
ESP32-WROOM-32EにSDカードのファイルをアップロードする
ESP32 Sketch Data Uploadプラグインを使用する場合は、Arduino IDEのバージョンが2.00未満のものを使用する必要があります。
動作確認

ESP32-WROOM-32EとSHT35-DISの配線例を示しています。回路図の番号はESP32 -WROOM-32Eの左上を1ピンとした時反時計回りにピンを数えた場合の番号としています。ピン番号横の()内の番号はシルク印刷されているピンの名称です。
WiFiのアクセスポイント「EngKapi1」を選択しパスワードに「22223333」を入力してアクセスポイントに接続します。

スマホのGoogle ChromeでIPアドレス「192.168.11.2」を入力しリクエストを送るとESP32-WROOM-32Eからスマホに返信し温湿度データと時間経過による温湿度情報がグラフ表示されました。
IPアドレス「192.168.11.2/ti」と存在しないURLを指定するとFile Not Foundが表示されることも確認しています。
アクセスポイント、パスワード、IPアドレスはソースコードで変更している場合は指定したものと置き換えて接続してください。
ソースコード全体
ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。
リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。
本ソースコードでグラフが表示する場合、FLASHにファイルを格納するで説明しているように各種ファイルをFLASHに書き込む必要があります。
関連リンク
Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
最後まで、読んでいただきありがとうございました。
HTMLファイルとJSファイルの記述で表示するページが作成できるためStringで文字を追加してHTMLデータを生成する方法よりもページの作り込みができるようになります。CSSファイルを追加してページの見栄えを良くしたりできます。