1.はじめに
今回は おんどとり Web Storage API (以降、公開API と表記) と Google Apps Script (以降、GAS と表記) (※1) を使ってスプレッドシートにおんどとり Web Storageのデータを自動入力する方法をご紹介します。また、温湿度データから算出できる簡易的な WBGT も一緒に算出してみようと思います。
WBGT は湿球黒体温度 (Wet Bulb Globe Temperature) の略で、熱中症を予防する目的でアメリカで提案された指数です。日本では暑さ指数とも呼ばれています。熱中症予防の指針として有用とされ、日射の無い室内に限っては温度と湿度から簡易的に推定できるとのことから、本記事では TR72A が記録した温度・湿度の値を元にして室内の簡易的な WBGT を算出します。WBGT の推定は日本生気象学会様の「日常生活における熱中症予防指針 Ver.4」の「室内用の WBGT 簡易推定図 Ver.4」を参考にしています。
上記サンプルデータの詳細はこちらからご確認ください。
サンプルデータのE列は、「室内用の WBGT 簡易推定図 Ver.4」を参考に [表1] のような色分けをして表示しています。
表1
WBGT(暑さ指数)
|
基準
|
スクリプトで定義した値
(WBGT()関数の返り値)
|
25未満
|
注意
|
0
|
25~28未満
|
警戒
|
1
|
28~31未満
|
厳重警戒
|
2
|
31以上
|
危険
|
3
|
-
・「室内用のWBGT簡易推定図 Ver.4」で求めた WBGT は「日射のない室内専用」です。室外では使用できません。また、室内でも日射や発熱体のある場合は使用できません。
-
・危険、厳重警報等の分類は、日常生活の上での基準であって、労働の場における熱中症予防の基準には当てはまらないことに注意してください。
-
・室外、日射のある室内、発熱体のある室内の場合は黒球付きのWBGT測定器等を用いて評価して下さい。
(※1) Google Apps Script は JavaScript をベースとした Google のサービスを連携・自動化させるためのスクリプトです。
2.動作概要
公開API を GAS と連携させて、おんどとり Web Storage に登録した機器のシリアルナンバーを指定するとアップロードされたデータをスプレッドシート に自動入力します。
3.事前に用意するもの
-
・おんどとり Web Storage のアカウント
-
・おんどとり Web Storage に対応した T&D の製品
-
・Google アカウント
おんどとり Web Storage のアカウントは以下のリンクから作成してください。
https://ondotori.webstorage.jp/
4.公開 API の発行について
おんどとり Web Storage にログインし、メニューから [アカウント管理] - [開発者向けAPI管理] の順に選択してください。
開発者向け API 管理画面から下記の手順で API KEY を発行します。
1. [API KEY を発行する] を選択
2. [API KEY] を発行しましたと表示
3. [アカウント管理へ戻る] を選択
4. [開発者向けAPI管理] を選択
5. 利用可能なAPI KEY:xxxxxxxxxxxxxxxxxxxxxx が表示
API KEY は 後で GAS を記述する際に使用します。
5.スプレッドシートの準備
事前に用意した Google アカウントからスプレッドシートを開きます。今回は例として TR72A と RTR502B が おんどとり Web Storage にアップロードしたデータをスプレッドシートへ自動入力していくための準備をします。スプレッドシートには予め見出しとなる項目名を入力しておきます。例えば、TR72A のチャンネル1は「温度」、チャンネル2は「湿度」となりますので、それぞれ以下のように項目名を入力します。
-
・「A」列には測定日時を入力していくので「A1」のセルに「日時」と入力
-
・「B」列には機器名称を入力していくので「B1」のセルに「機器名称」と入力
-
・「C」列にはチャンネル1のデータを入力していくので「C1」のセルに「温度」と入力
-
・「D」列にはチャンネル2のデータを入力していくので「D1」のセルに「湿度」と入力
-
・室内 WBGT を自動入力する場合、「E1」に「室内 WBGT」と入力
RTR502B の場合、温度チャンネル1つのみなので、以下のように項目名を入力します。
-
・「G」列には測定日時を入力していくので「G1」のセルに「日時」と入力
-
・「H」列には機器名称を入力していくので「H1」のセルに「機器名称」と入力
-
・「I」列にはチャンネル1のデータを入力していくので「I1」のセルに「温度」と入力
上記の項目名は例として挙げていますので、わかりやすい名称を入力していただいても構いません。
項目名の入力が完了したらスプレッドシートのメニューにある「拡張機能」の「Apps Script」を選択してコード入力画面を表示します。この画面に次の章の GAS を入力していきます。
6.GAS の入力
以下のソースコードを基に GAS を入力します。公開 API KEY、おんどとり Web Storage アカウントID・パスワード、機器のシリアル番号の項目はご自身の情報に置き換えて入力してください。室内 WBGT が不要の場合、サンプルソースコード内の59~61行目、81~265行目を削除してください。
リスト1
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
function myFunction() {
//===== 書き込み先スプレッドシートの用意(このGASを埋め込んだシートで動作します) =====
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//===== T&D Web Storage Web APIのアクセス先 =====
var api_url = "https://api.webstorage.jp/v1/devices/current"; //現在値取得のAPIです。
//===== T&D Web Storage アカウント(ご自身のアカウント情報・機器情報をxxxxxxの部分に入力) =====
var api_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //おんどとり Web Storageで発行された APIKEY
var login_id = "XXXXXXXX"; //おんどとり Web Storage のアカウントID
var login_pass = "XXXXXXXX"; //おんどとり Web Storage のパスワード
//===== 設定する HTTPヘッダフィールド =====
var headers = {
"X-HTTP-Method-Override": "GET",
"Content-Type": "application/json"
};
//===== POSTで送信するデータを配列で一時作成 =====
var payload = {
"api-key": api_key,
"login-id": login_id,
"login-pass": login_pass,
};
//===== 送信するデータを配列で作成 =====
var options = {
"method": "post",
"headers": headers,
"payload": JSON.stringify(payload) // 用意したデータ配列をJSON文字列に変換
};
var response = UrlFetchApp.fetch(api_url, options);
var data = JSON.parse(response.getContentText());
if(response.getResponseCode() == 200){ //正常にデータを受信出来ていた場合に、データ処理する
var devices = data.devices; //受信データから機器の情報を抽出
for (var i = 0; i < devices.length; i++) { //受信データに含まれる機器の台数分ループ。(この例では1台分を指定しているので、ループは1回です)
var device = devices[i]; // 機器1台分を抽出
if(device.serial == "XXXXXXXX"){ //TR72A のシリアルナンバーを入力
var lastRow = sheet.getRange(sheet.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow()+1;
var unixtime = device.unixtime; // 機器(子機)の最新測定値の時刻(unixtime)
// スプレッドシートに書き込むデータ配列を作成
sheet.getRange(lastRow, 1).setValue(Utilities.formatDate(new Date( unixtime * 1000 ), "JST", "yyyy/MM/dd HH:mm:ss")); //unixtimeを日本時間に変更
sheet.getRange(lastRow, 2).setValue(device.name);
for (var i2 = 0; i2 < device.channel.length; i2++) {
if(device.channel[i2].num == 1){
var temp = device.channel[i2].value;
sheet.getRange(lastRow, 3).setValue(temp);
} else if(device.channel[i2].num == 2){
var humi = device.channel[i2].value;
sheet.getRange(lastRow, 4).setValue(humi);
}
}
//温度と湿度からWBGTの判定してスプレッドシートに入力
var wbgt_data = WBGT(temp,humi);
sheet.getRange(lastRow, 5).setValue(wbgt_data);
} else if(device.serial == "XXXXXXXX"){ //RTR502B のシリアルナンバーを入力
var lastRow = sheet.getRange(sheet.getMaxRows(), 7).getNextDataCell(SpreadsheetApp.Direction.UP).getRow()+1;
var unixtime = device.unixtime; // 機器(子機)の最新測定値の時刻(unixtime)
// スプレッドシートに書き込むデータ配列を作成
sheet.getRange(lastRow, 7).setValue(Utilities.formatDate(new Date( unixtime * 1000 ), "JST", "yyyy/MM/dd HH:mm:ss")); //unixtimeを日本時間に変更
sheet.getRange(lastRow, 8).setValue(device.name);
for (var i2 = 0; i2 < device.channel.length; i2++) {
if(device.channel[i2].num == 1){
sheet.getRange(lastRow, 9).setValue(device.channel[i2].value);
}
}
}
}
}
}
function WBGT(temp,humi){
if(humi < 20 ){
if(temp <= 35){
return 0;
} else if(temp > 35 && temp <= 39){
return 1;
} else if(temp > 39 && temp <= 42){
return 2;
} else if(temp > 42 ){
return 3;
}
} else if(humi >= 20 && humi < 25){
if(temp <= 33){
return 0;
} else if(temp > 33 && temp <= 37){
return 1;
} else if(temp > 37 && temp <= 41){
return 2;
} else if(temp > 41 ){
return 3;
}
} else if(humi >= 25 && humi < 30){
if(temp <= 32){
return 0;
} else if(temp > 32 && temp <= 36){
return 1;
} else if(temp > 36 && temp <= 40){
return 2;
} else if(temp > 40 ){
return 3;
}
} else if(humi >= 30 && humi < 35){
if(temp <= 32){
return 0;
} else if(temp > 32 && temp <= 36){
return 1;
} else if(temp > 36 && temp <= 40){
return 2;
} else if(temp > 40 ){
return 3;
}
} else if(humi >= 35 && humi < 40){
if(temp <= 32){
return 0;
} else if(temp > 32 && temp <= 35){
return 1;
} else if(temp > 35 && temp <= 39){
return 2;
} else if(temp > 39 ){
return 3;
}
} else if(humi >= 40 && humi < 45){
if(temp <= 31){
return 0;
} else if(temp > 31 && temp <= 34){
return 1;
} else if(temp > 34 && temp <= 38){
return 2;
} else if(temp > 38 ){
return 3;
}
} else if(humi >= 45 && humi < 50){
if(temp <= 30){
return 0;
} else if(temp > 30 && temp <= 33){
return 1;
} else if(temp > 33 && temp <= 37){
return 2;
} else if(temp > 37 ){
return 3;
}
} else if(humi >= 50 && humi < 55){
if(temp <= 29){
return 0;
} else if(temp > 29 && temp <= 33){
return 1;
} else if(temp > 33 && temp <= 36){
return 2;
} else if(temp > 36 ){
return 3;
}
} else if(humi >= 55 && humi < 60){
if(temp <= 29){
return 0;
} else if(temp > 29 && temp <= 32){
return 1;
} else if(temp > 32 && temp <= 35){
return 2;
} else if(temp > 35 ){
return 3;
}
} else if(humi >= 60 && humi < 65){
if(temp <= 28){
return 0;
} else if(temp > 28 && temp <= 31){
return 1;
} else if(temp > 31 && temp <= 35){
return 2;
} else if(temp > 35 ){
return 3;
}
} else if(humi >= 65 && humi < 70){
if(temp <= 27){
return 0;
} else if(temp > 27 && temp <= 31){
return 1;
} else if(temp > 31 && temp <= 34){
return 2;
} else if(temp > 34 ){
return 3;
}
} else if(humi >= 70 && humi < 75){
if(temp <= 27){
return 0;
} else if(temp > 27 && temp <= 30){
return 1;
} else if(temp > 30 && temp <= 33){
return 2;
} else if(temp > 33 ){
return 3;
}
} else if(humi >= 75 && humi < 80){
if(temp <= 26){
return 0;
} else if(temp > 26 && temp <= 29){
return 1;
} else if(temp > 29 && temp <= 33){
return 2;
} else if(temp > 33 ){
return 3;
}
} else if(humi >= 80 && humi < 85){
if(temp <= 26){
return 0;
} else if(temp > 26 && temp <= 29){
return 1;
} else if(temp > 29 && temp <= 32){
return 2;
} else if(temp > 32 ){
return 3;
}
} else if(humi >= 85 && humi < 90){
if(temp <= 25){
return 0;
} else if(temp > 25 && temp <= 28){
return 1;
} else if(temp > 28 && temp <= 31){
return 2;
} else if(temp > 31 ){
return 3;
}
} else if(humi >= 90 && humi < 95){
if(temp <= 25){
return 0;
} else if(temp > 25 && temp <= 28){
return 1;
} else if(temp > 28 && temp <= 31){
return 2;
} else if(temp > 31 ){
return 3;
}
} else if(humi >= 95 && humi < 100){
if(temp <= 24){
return 0;
} else if(temp > 24 && temp <= 27){
return 1;
} else if(temp > 27 && temp <= 30){
return 2;
} else if(temp > 30 ){
return 3;
}
} else if(humi > 100){
if(temp <= 24){
return 0;
} else if(temp > 24 && temp <= 27){
return 1;
} else if(temp > 27 && temp <= 30){
return 2;
} else if(temp > 30 ){
return 3;
}
}
}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
入力が完了したら「プロジェクトを保存」を選択します。
続いて画面左側の「トリガー」を選択し、トリガーの設定画面を表示します。
画面右下の「トリガーを追加」を選択します。
トリガーの設定を行い、最後に画面右下の「保存」を選択します。TR72A の自動送信間隔と RTR502B の親機 (今回は RTR500BW) の現在値送信間隔を10分に設定しているので、それに合わせて 「10分おき(※2)」に設定しました。
保存すると設定したトリガーの情報が反映されます。
スプレッドシートへ戻ると、データが反映 (※3) されていきます。
7.カラースケールの設定について
サンプルのような色付けを行う場合、以下の手順で設定します。
1. 色を付ける列を選択
2. 「右クリック」して「条件付き書式」を選択
3. 画面右側の [条件付き書式設定ルール] から「カラースケール」を選択
4. 「最小値」「最大値」それぞれ任意の色を設定
5. 設定ができたら「完了」を選択
6. [+条件を追加] を選択し、同じ手順で他の値の色を設定
8.室内 WBGT のカラー設定について
サンプルデータのような色分けは以下の手順で行います。GAS で定義した値が「1」の場合の塗り潰し例を紹介します。
1. 室内 WBGT が自動入力される列を選択
2. 「右クリック」して「条件付き書式」を選択
3. 画面右側の [条件付き書式設定ルール] から「単一色」を選択
4. [書式ルール] の [セルの書式設定の条件...] から「次を含むテキスト」選択し、「1」を入力
5. [書式のスタイル] から色を選択
6. 全ての設定が完了したら「完了」を選択
7. [+条件を追加] を選択し、同じ手順で他の値の色を設定
9.データの共有について
スプレッドシートを共有する際、相手に GAS が見えないよう権限を設定する必要があります。データの共有に関する詳細は Google 社が公開しているこちらのヘルプページをご参照ください。
10.最後に
今回は おんどとり Web Storage に登録した任意の機器を指定して、スプレッドシートへ自動入力する方法を紹介しました。この方法は 2、3台程度であれば画面から見切れることはありませんが、指定する機器が増えてくると画面から見切れて確認しにくくなります。その場合、例えばシート1 には TR72A のデータを自動入力、シート2 には RTR503B のデータを自動入力するといったように、シート毎に機器を分けてデータを自動入力することも可能です。この方法については「スプレッドシートの複数のシートに指定した機器のデータを自動入力する方法」の記事で紹介していますので、是非そちらの記事もご覧ください。