1.はじめに
弊社の「おんどとり Web Storage」は、データロガーが測定したデータを保存し、スマホやPCを使ってどこからでもデータを確認することができる無料のクラウドサービスです。
今回、M5StickC Plus (以下、M5Stickと記述) というマイコンボードを用いて「おんどとり Web Storage」から測定値を取得し、M5StickのLCDに表示させてみました。
おんどとり Web Storageのデータとカスタム機器を連携させることにより、下記のような応用が可能となります。
・大型のLCDなどに複数機器のデータを一覧表示する。
・あらかじめ設定した上下限値を超えた場合に警報通知したり、他の機器を制御する。
(回転灯を点ける、ファンを回す、LINEで通知する、など...)
これらの例を見ると、IoTの実現は意外と簡単だと感じるのではないでしょうか。
それでは、どうやって「おんどとり Web Storage」から測定値を取得するかを以下で説明していきましょう。
2.動作概要
おんどとり Web Storageは、おんどとり Web Storage API(以下、公開APIと記述)を公開してしており、これを利用することで外部からインターネット経由でデータを取得することができます。今回はM5Stickから公開APIを使って測定値を取得します。
M5Stickは無線LANアクセスポイント経由でインターネットに接続し、[図1]のように公開APIを用いて測定値取得のリクエストを送信し、おんどとり Web Storageからのレスポンスによりデータを受信します。
3.必要な物
3-1. M5StickC Plus
M5StickC Plusは親指程度の大きさのコンパクトなケースの中に、CPU、Bluetooth機能、カラーLCD、無線LAN機能などが搭載されているマイコンボードです。
2023年4月時点で3,542円で購入が可能です。
詳細は下記サイトを参照ください。
https://docs.m5stack.com/ja/core/m5stickc_plus
3-2. Arduino IDE
M5StickのプログラムはArduino IDEを使って作成します。
(Arduino IDEではプログラムのことをスケッチと呼ぶため、以後この記事の中ではプログラムをスケッチと記述します。)
Arduino IDEは、スケッチを書くエディタ、スケッチをM5Stickに書き込むツール、シリアルモニタなどが含まれる総合開発環境(Integrated Development Environment)です。
Arduino IDEのインストールについては下記サイトを参照してください。
https://docs.m5stack.com/ja/quick_start/m5stickc_plus/arduino
インストール直後のArduino IDEのメニューは英語表示となっていますが、下記の設定をすることで日本語表示に変更できます。
メニューから[File]→[Preferences]を選択し、表示された設定画面の Language: の選択肢から[日本語]を選択して[OK]ボタンを押す。
以降の説明は全て 日本語表示として説明します。
また、今回のスケッチでは『ArduinoJson』というライブラリを使います。
ライブラリとは、よく使われる処理を簡単に呼び出せる部品としてまとめたものです。
ArduinoJsonを使えばJSONデータの生成とJSONデータを分解してデータを取り出すことが簡単にできます。
メニューから[ツール]→[ライブラリ]を選択すると、画面左側にライブラリマネージャが開きます。
一番上の検索欄に「ArduinoJson」と入力し、検索されたArduinoJsonをインストールしてください。
ArduinoJsonの詳細については下記のサイトを参照してください。
https://arduinojson.org/
他にも「M5StickC plus Arduino」などで検索すると参考になる情報が得られると思います。
本記事を執筆時のArduino IDE の動作環境は以下の通りです。
・Arduino IDE バージョン:2.1.0
・ボードマネージャ M5Stack バージョン:2.0.6
・Arduino IDEのメニューで右記を選択:[ツール]→[ボード]→[M5Stick-C-Plus]
・ArduinoJson バージョン:6.21.2
・OS:Windows 11 Home
その他、PCとM5Stickを接続するUSBケーブルが必要です。M5StickはUSB-Cコネクタなので必要に応じて用意してください。
3-3. 無線LANアクセスポイント
今回作成するスケッチでは、M5Stickは無線LAN経由でインターネットに接続して公開APIにアクセスするため、無線LANのアクセスポイントが必要になります。
無線LANの規格IEEE 802.11b/g/n(2.4GHz)に対応しているものをご用意ください。
また、スケッチ内にSSIDとパスワードを記載するので、予め控えておいてください。
3-4. おんどとり Web Storageアカウント
今回の記事では、おんどとり Web Storageからデータを取得するため、そのアカウント情報が必要です。
また、おんどとり Web Storageにデータが保存されていることが前提となります。
おんどとり Web Storageについては、次章で詳しく説明します。
4.おんどとり Web Storage
4-1. おんどとり Web Storageとは
おんどとり Web Storageは、T&Dのデータロガー「おんどとり」シリーズの測定データを保存し、グラフ表示によるデータの閲覧、機器の設定、アラート通知、データのダウンロードなどの機能を提供するサービスです。
更に、公開APIにより現在値やグラフデータを取得することが可能です。
おんどとり Web Storageは、おんどとりシリーズのデータロガーをお使いの方には、無料でご利用いただけます。
このサービスに対応しているデータロガーについてはhttps://ondotori.webstorage.jp の「シリーズ別 対応機器一覧」に記載されています。
4-2. アカウント作成
おんどとり Web Storage(https://ondotori.webstorage.jp)にアクセスし、[新規ユーザ登録する]を押してください。(既にアカウントを取得済みの方は[ログインする]ボタンを押してログインし、「4-3. 公開APIの使い方」へ進んでください)
メールアドレス、パスワードを設定し、[送信する]ボタンを押すと、入力したメールアドレスにおんどとり Web Storageから確認メールが届きます。メール文中に記載されているURLをクリックすることでユーザ登録が完了します。
ここで決まったユーザID(txxx####: xは小文字アルファベット、#は数字)とパスワードはスケッチの中に記述するので控えておいてください。
4-3. 公開APIの使い方
おんどとり Web Storageにログインし、メニューから[アカウント管理]を選択し、[開発者向けAPI管理]ボタンを押してください。
開発者向けAPI管理画面から下記の手順でAPI KEYが発行されます。
1.[API KEYを発行する]ボタンを押す。
2.[API KEY]を発行しましたと表示される。
3.[アカウント管理へ戻る]ボタンを押す。
4.[開発者向けAPI管理]ボタンを押す。
5.利用可能なAPI KEY: xxxxxxxxxxxxxxxxxxxxxx と表示される。
API KEYは、スケッチの中に記述するので控えておいてください。
公開APIには、おんどとり Web Storageに登録されている機器の最新の現在値を一括して取得する「現在値の取得」と、1台の機器を指定し直近300件のデータや指定期間のグラフデータを取得するコマンドがあります。
今回のスケッチでは「現在値の取得」の公開APIを使用します。
https://ondotori.webstorage.jp/docs/api/reference/devices_device.html
公開API全般については下記を参照してください。
https://ondotori.webstorage.jp/docs/api/index.html
5.スケッチの説明
5-1. 概要
Arduinoのスケッチは、setup() と loop() という2つの関数で構成されます。
setup() は、M5Stickの電源が入ってから最初に1回だけ実行され、loop() は、setup() 実行後に繰り返し実行されます。
今回作成するスケッチのフローチャートは[図2]を、スケッチは[リスト1]を参照してください。
スケッチの中で「//」が記載されている場合、その行の「//」以降の文字はコメントとなります。
[リスト1]のコメントのカッコ内の数字は、フローチャートの数字の該当箇所を示しています。
Arduino IDEのメニューから、[ファイル]→[新規スケッチ] を選択すると中身の無い setup() と loop() が作成されます。スケッチを書き始める時はそれを利用して書いていきます。
初心者の方はスケッチの動作がよくわからなくても気にせず、とりあえず[リスト1]を参考に、アルファベットの大文字と小文字の違いに注意してスケッチを書いてみましょう。
リスト1
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
#include <M5StickCPlus.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
//===== 無線LANアクセスポイント設定(各自の環境を入力) =====
const char* ssid = "xxxxxxxx"; //(※変更)APのSSID
const char* password = "yyyyyyyy"; //(※変更)APのパスワード
//===== T&D Web Storage アカウント(各自のアカウントを入力) =====
const char* login_id = "txxxxxxx"; //(※変更)
const char* login_pass = "yyyyyyyy"; //(※変更)
const char* api_key = "xxxxxyyyyyzzzzzxxxxxyyyyyzzzzz";//(※変更)
//===== T&D Web Storage Web APIのアクセス先 =====
const char* api = "https://api.webstorage.jp/v1/devices/current"; //現在値WEB API
void setup() {
M5.begin();
Serial.begin(115200); // (1)シリアル通信初期設定
M5.Lcd.setRotation(3); // (2)LCD表示初期設定
M5.Lcd.setCursor(0, 0, 4); // (2)表示位置とフォントを指定
M5.Lcd.print("Connecting.."); // (2)最初にConnecting..と表示する
WiFi.begin(ssid, password); // (3)無線LANアクセスポイント接続開始
while (WiFi.status() != WL_CONNECTED) { // (3)接続完了を確認
M5.Lcd.print("."); // (3)接続途中の表示
delay(200); // (3)200msec間隔で接続完了を確認
}
M5.Lcd.println("¥nConnected to"); // (4)DHCPで得られたIPアドレスを表示
M5.Lcd.println(WiFi.localIP()); // (4)DHCPで得られたIPアドレスを表示
delay(500);
}
void loop() {
StaticJsonDocument<200> root;
char buffer[256];
uint8_t i,cnt,t_cnt;
HTTPClient http;
String txt;
const char* j_model;
const char* j_name;
const char* j_valu_1;
const char* j_unit_1;
const char* j_valu_2;
const char* j_unit_2;
if (WiFi.status() == WL_CONNECTED) { // (5)無線LAN接続中ならば以下を実行
http.begin(api); // (6)HTTP通信を開始する
root["api-key"] = api_key; // (6)WebAPIに送信するapi_key
root["login-id"] = login_id; // (6)WebAPIに送信するlogin-id
root["login-pass"] = login_pass; // (6)WebAPIに送信するlogin-pass
serializeJson(root, buffer); // (6)WebStorage APIにリクエストするボディ作成
Serial.println(buffer); // (dbg)WSSに送信するデータ
http.addHeader("X-HTTP-Method-Override" , "GET"); // (6)HTTPヘッダ指定
http.addHeader("Content-Type", "application/json"); // (6)HTTPヘッダ指定
int httpCode = http.POST(buffer); // (6)HTTP通信でPOST
if (httpCode > 0) { // (7)http通信が成功したかの判断
String payload = http.getString(); // (8)WebStorage API のレスポンスを取得する
http.end();
Serial.println(payload); // (dbg)WSSから取得した全データ
DynamicJsonDocument doc(65536); // (8)レスポンスをJSONをパースする為の変数を準備
deserializeJson(doc, payload); // (8)レスポンスを上記変数に設定
t_cnt = 30; // WSSとの通信間隔は最低30秒は空ける
while(t_cnt > 0){ // (9)WebAPIアクセスから30秒以上経過を確認
for(cnt = 0 ; cnt < 60 ; cnt++){ // (10)最大60台の機器まで表示する
JsonObject obj = doc["devices"][cnt]; // (11)JSONデータから機器1台分を抽出
j_model = obj["model"]; // (11)j_model = 機種型番
if(j_model){ // (11)j_modelの有無でJsonデータが空か否か判断
j_name = obj["name"]; // (12)j_name = 機器名称
j_valu_1 = obj["channel"][0]["value"]; // (12)j_valu_1 = ch1測定値
j_unit_1 = obj["channel"][0]["unit"]; // (12)j_unit_1 = ch1単位
txt = j_valu_1;
if(txt.indexOf(" Error") != -1){ // (12)測定値にError文字がある場合
j_valu_1 = "----"; // (12)表示を「----」にする
j_unit_1 = " ";
}
j_valu_2 = obj["channel"][1]["value"]; // (12)j_valu_2 = ch2測定値
if(j_valu_2){
j_unit_2 = obj["channel"][1]["unit"]; // (12)j_unit_2 = ch2単位
txt = j_valu_2;
if(txt.indexOf(" Error") != -1){ // (12)測定値にError文字がある場合
j_valu_2 = "----"; // (12)表示を「----」にする
j_unit_2 = " ";
}
}
else{
j_valu_2 = j_unit_2 = " ";
}
//(dbg)WSSから取得した1台分のデータ出力
Serial.printf("%s / %s : %s / %s ¥n", j_model,j_name,j_valu_1,j_valu_2);
M5.Lcd.fillScreen(BLACK); // (13)画面を黒く塗りつぶす(画面クリア)
M5.Lcd.fillRect(0,0,240,21,0x9129); // (13)タイトル背景色をワインレッドに
M5.Lcd.setTextColor(WHITE,0x9129); // (13)文字色(白)、背景色(ワインレッド)指定
M5.Lcd.drawString(j_model,3,1,4); // (13)機種型番表示(x,y位置,font指定)
M5.Lcd.drawString(j_name,115,6,2); // (13)機器名称表示(x,y位置,font指定)
M5.Lcd.fillRect(0,21,240,6,BLACK); // (13)はみ出たワインレッドを黒で塗りつぶす
M5.Lcd.setTextColor(WHITE,BLACK); // (13)文字色(白)、背景色(黒)指定
M5.Lcd.drawString(j_valu_1,28,28,7); // (13)ch1測定値表示(x,y位置,font指定)
M5.Lcd.drawString(j_unit_1,165,48,4); // (13)ch1単位表示(x,y位置,font指定)
M5.Lcd.drawString(j_valu_2,28,82,7); // (13)ch2測定値表示(x,y位置,font指定)
M5.Lcd.drawString(j_unit_2,165,102,4);// (13)ch2単位表示(x,y位置,font指定)
delay(2000); // (14)2秒間Wait
if(t_cnt > 0)t_cnt = t_cnt - 2;
}
}
}
}
else { // WSSからレスポンスが得られなかった場合の処理
M5.Lcd.println("error");
http.end();
}
}
}
5-2. 初期設定値
スケッチの中に個別設定が必要な項目が5箇所あります。
下記[表1]の全ての内容を各自の環境に合わせて入力して下さい。
表1 : 初期設定の入力が必要な項目
7行
|
ssid=
|
無線LANアクセスポイントのSSID
(3-3. 無線LANアクセスポイント 参照)
|
8行
|
password=
|
無線LANアクセスポイントのパスワード
(3-3. 無線LANアクセスポイント 参照)
|
11行
|
login_id=
|
おんどとり Web StorageのログインID
(4-2. アカウント作成 参照)
|
12行
|
login_pass=
|
おんどとり Web Storageのログインパスワード
(4-2. アカウント作成 参照)
|
13行
|
api_key=
|
おんどとり Web StorageのAPI KEY
(4-3. 公開APIの使い方 参照)
|
16行は、公開APIのアクセス先を指定しています。
今回は、「現在値の取得」という公開APIのアクセス先を指定しています。
※「現在値の取得」では、リクエストに親機や子機のシリアル番号を指定することで取得するデータを絞り込むことも可能です。
詳しくは下記サイトを参照してください。
https://ondotori.webstorage.jp/docs/api/reference/devices_device.html
5-3. setup()
setup() では、M5Stickで無線LANやカラーLCDなどを動作させるための初期設定を行っています。
更に、無線LANのアクセスポイントとの接続を行い、接続完了後にIPアドレスを表示しています。
今回のスケッチでは、IPアドレスはDHCPにより取得する前提です。
(1)の Serial.bigin(115200) は115200bpsでシリアル通信する為の初期設定です。シリアル通信はスケッチの動作確認の為に使用し、Arduino IDEのメニューから [ツール]→[シリアルモニタ]で開いた画面に動作状況を出力させることができます。
スケッチの途中に Serial.println("xxxxxx")と記述するとシリアルモニタに「xxxxxx」と表示され、スケッチが実行されている状況を確認することができる仕組みです。
(2)の M5.Lcd.xxxxxxx という部分はM5StickのLCD表示関連のコマンドで、LCDの初期設定と「Connecting..」と表示させる処理を行っています。
(3)の WiFi.bigin(ssid, password) は無線LANの接続を開始し、次の行の while(WiFi.status() != WL_CONNECTED) は接続完了をチェックしています。
無線LANの接続が完了すると、(4)でDHCPで取得したIPアドレスを表示します。
5-4. loop()
loop()の先頭の37~47行はスケッチ内で使用する変数を宣言しています。
(5)の if (WiFi.status() == WL_CONNECTED) では無線LANの接続状態を確認しています。
無線LANの接続が維持されている場合に以降の処理を実行します。
(6)ではいよいよ公開APIにアクセスします。
公開APIは、リクエスト、レスポンス共にJSONデータを使用し、その処理の中でArduinoJsonライブラリを使用しています。
51~58行で公開APIのHTTPサーバにリクエストする為のパラメータとヘッダを設定し、60行でHTTP通信を実行します。
JSONについて
JSONとは、各種デバイス間でのデータの受け渡しに使用されるフォーマットの仕様です。
例えば、key1の値は「山」でkey2の値は「海」というようなデータを伝えたい時は下記のようになります。
{“key1”:“山”, “key2”:“海”}
公開APIでは、リクエストもレスポンスもJSONを使用します。
例えば、M5Stickからサーバへのリクエストは下記のJSONをサーバに送信しています。
{"api-key":"(API KEY)" , "login-id":"(ログインID)" , "login-pass":"(ログインパスワード)"}
API KEY、ログインID、ログインパスワード は、5-2. 初期設定値、[表1]で指定した値となります。
(7)は、公開APIからレスポンスが得られたか判断し、得られた場合は以降の処理を実行していきます。
(8)は、レスポンスを、そこからJSONの値を取得する為の専用の変数(payload)に格納しています。
ArduinoJsonライブラリを使うと、(11)以降で値を取り出す処理が簡単に行えます。
(9)は非常に重要な部分です。公開APIは2分間に10回までという実行回数の制限があります。
その為、最短でも30秒の時間をおいて公開APIを実行するためのカウンタ(t_cnt)を設け、30秒未満の間は公開APIのリクエストはせず、前回取得したデータを繰り返して表示します。
(10)では公開APIで得られた機器の台数を60台に制限しています。
JSONデータの処理で必要なM5Stickのメモリは機器台数により増えるため、実際に動作確認した台数に制限しました。
もし、機器の台数を増やしたい場合は70行の[60]を増やすと共に、65行の[65536]も増やしてお試しください。
(11)では、JSONデータから機器1台分のJSONデータを抜き出し、項目名”model”の有無を確認しています。”model”が見つからない場合は、機器1台分のJSONデータが存在しないことになります。
(12)では、機器1台分のJSONデータから、機器名称、測定値、測定値の単位を抜き出します。
通常測定値には数値が入りますが、センサエラーなどにより「.... Error」というような文字列が入る場合があり、その場合は「----」と表示させるような変換も行っています。
(13)では、(11)、(12)で抜き出した、機器型番、機器名称、測定値、測定単位をM5StickのLCDに表示します。
(14)では、機器1台あたり測定値を2秒間表示させる為に2秒間Waitさせる処理をしています。
6.実行
6-1. コンパイルと書き込み
スケッチの入力が終わったら、PCとM5StickをUSBケーブルで接続し、Arduino IDEのメニューから [スケッチ]→[書き込み] を実行します。(又は上部の丸い右矢印(→)のスイッチを押下)
実行するとPCの画面右下に「スケッチをコンパイル中...」→「書き込み中」→「書き込み完了」と処理状態を示すメッセージが変化していきます。
「書き込み完了」と表示された場合、自動的にM5Stickはスケッチ通りの動作を開始します。
ただし、途中でエラーが発生した場合、「書き込み完了」に至らないこともあります。
その場合、よくある例として[表2]の状況が考えられるので確認してみてください。
表2 Arduino IDEエラー例
Arduino IDE
画面下部の出力の表示
|
対処内容
|
exit status 1 ・・・
|
プログラムの記述が間違っている。
「exit status 1」以下の記述やリストの色が変わっている箇所を確認。
メニューの [ツール]→[ボード] でM5Stick-C-Plus が選択されているか確認。
M5Stick-C-Plusが選択肢にない場合、下記を参考にM5Stackライブラリをインストールする。
https://docs.m5stack.com/en/quick_start/m5stickc_plus/arduino
|
exit status 1
Compilation error: ArduinoJson.h: No such file or directory
|
ArduinoJsonライブラリがインストールされていません。
3-2.章を確認してインストールしてください。
|
Failed uploading: no upload port provided
|
M5StickがPCとUSBケーブルで接続されているか確認。
[ツール]→[ポート]: M5Stickが接続されているCOMポートの選択を確認。
|
6-2. 動作確認
M5Stickでスケッチが動作し始めると、まず setup() が実行され、
M5StickのLCDに「Connecting..」と表示されます。
この状態で無線LANアクセスポイントの接続が完了すると、DHCPで得られたIPアドレスを表示します。
続いて loop() が実行され、
公開APIにリクエストし、レスポンスが得られるとLCDは測定値を表示します。
複数のデータがある場合は、2秒ごとに切り替えて表示します。
M5StickをPCに接続した状態で、Arduino IDEのメニューから [ツール]→[シリアルモニタ] を実行し、シリアルモニタ画面右上の設定を「115200 baud」に変更してみてください。
スケッチの中で Serial.print… と記述している内容がシリアルモニタに表示され、スケッチの実行状況を確認することができます。
6-3. 課題
今回のスケッチには下記のような制限があります。
・測定値の桁数が4桁以上は表示できない
・測定単位の文字数が4文字以上は表示できない
・機器名称の日本語は表示できない
測定値や測定単位の表示は、リスト1の97行~108行を修正することで変更が可能です。使用する測定値や測定単位に合わせて表示位置や表示フォントを変更して試してみてください。
M5Stickに日本語の表示をさせる為には、別途ライブラリが必要なようです。
「m5stick 日本語表示」等で検索していただき、挑戦してみて下さい。
7.最後に
いかがでしたか?
M5StickのLCDに、公開APIで得られた測定値を表示させることができたでしょうか。
今回ご紹介したのは「現在値を表示する」というシンプルな内容ですが、冒頭でも少し触れたように、様々な応用が可能です。
この記事が、自由な発想で「おんどとり Web Storage」の公開APIを活用していただくきっかけになることを望みます。