1
0

気象情報(例 石川県金沢市)を取得し、Node-REDでDashboard表示してみました。(Insights Hub上で作成したFlowを移植&修正&追加)

Last updated at Posted at 2024-03-13

はじめに

前回Siemens社オープンクラウドプラットフォーム "Insights Hub(旧名称 Mindsphere)" 上で、石川県金沢市の気象情報(気圧、気温、湿度、風速、日照時間)を定期的に取得しデータ保存およびDashboard(折れ線グラフなど)表示に挑戦してみましたが、その際、作成したFlowをNode-REDに移植してのDashboard表示に挑戦してみました。今回は手動処理といたしました。取得したデータはテキストファイルに保存する方針です。
(Node-REDのVer3.0.2を使用しております。)

今回のグラフ表示目標

 Insights Hub時と同様、以下のようなグラフ表示を目指します。
「気圧、気温、湿度、風速、日照時間」の前日分の折れ線グラフ表示と最大値or平均値等の表示です

データ取得対象 前回と同様となります。

 〇対象:「石川県 金沢市」の「過去の気象データ検索」、「10分ごとの値」
     項目は気圧(現地)、気温、湿度、風速(最大)、日照時間の5項目とします。
    「10分ごとの値」ですので1日に144件あります。

 以下、少々長くなりますが、設定について説明させていただきます。
 「Insights Hub側でのExport」、「Node-REDでのデータ取得処理の構築」、「Node-REDでのDashboard設定」と進んでまいります。

Insights Hub側でのFlowのExport

手順としては以下となります。
 【1】右上のボタンを押し、Exportを選択
Kanazawa_Weather_NodeRED_VFC_export.png

 【2】右下の Download ボタンを押します。
Kanazawa_Weather_NodeRED_VFC_export_2.png

すると flow.json ファイルが出力されます

Node-REDでの処理の構築 フローの全体図

まず、上記のファイルをImport(読み込み)します。
unknownになっているNode(Write Timeseries)はInsights Hub専用のNodeですので削除します。
Kanazawa_Weather_NodeRED_Importl.png

最終系のフローの全体像は以下となります。
 データ取得はunknownになっていたNode(Write Timeseries)をWrite fileノードに置き換え。
 ダッシュボード表示のNodeは新たに追加。
Kanazawa_Weather_NodeRED_Flow_all.png

この後、細かな修正点を見ていきたいと思います。

Node-REDでのデータ取得処理の構築

 VisualFlowCreatorで作成したFLOWの流用となります。
Kanazawa_Weather_NodeRED_Flow_1.png

【1】「Inject処理」

Kanazawa_Weather_NodeRED_inject-1.png

VisualFlowCreatorからの変更点は以下となります(新規の場合の設定箇所に同じ)
・msg.dirにディレクトリ名称をセットしております。
 例 c:\Users\xxxx\csv
・Repeat(繰り返し) に をなし に変更しております。

【2】「日付とURLの編集」

Kanazawa_Weather_NodeRED_function-1.png

以下の処理をしております。
VisualFlowCreatorからの変更点は10行目(ファイル名称)を追記している点です

var urls = [];
const today = new Date();
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
var yy = yesterday.getFullYear();
var mm = ("00" + String(yesterday.getMonth() + 1)).slice(-2);
var dd = ("00" + String(yesterday.getDate())).slice(-2);
urls = "https://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?prec_no=56&block_no=47605&year=" + yy + "&month=" + mm + "&day=" + dd +"&view=";
msg.url = urls;
msg.filenamejson = msg.dir + "kanazawaWeather" + yy + mm + dd + ".json";
return msg;

・2行目 todayを取得
・3ー4行目 yesterdayを計算 (todayから1日マイナス)
・5行目 yesterdayのyy(年)を編集しています
・6行目 yesterdayのmm(月)を編集しています
・7行目 yesterdayのdd(日)を編集しています
・8行目 Urlsに「石川県金沢市ー過去の気象データ検索ー10分ごとの値」の固定値
     上記で計算したyy,mm,dd をセットしています。
     ※金沢の場合、prec_no=56&block_no=47605 となっています。
   東京の場合は、prec_no=44&block_no=47662 で取得できると思います。

・9行目 msg.urlにUrlsをセットしています。
・10行目 保存するファイル名称をセットしています(Json形式)

【3】「HttpRequest」
Kanazawa_Weather_NodeRED_Http_request-1.png

VisualFlowCreatorからの変更点はございません。
・Method に 「Get」を指定
・Return に 「UTF-8 string」を設定

【4】「Html編集」
Kanazawa_Weather_NodeRED_Html-1.png

VisualFlowCreatorからの変更点はございません。
・Selectorには .data2_s と tr と tdを設定
・outputは only the text・・・ 要素のテキストのみ
     as a message・・・  配列化した1つのメッセージ

【5】「データの退避」
Kanazawa_Weather_CahgeData.png

VisualFlowCreatorからの変更点はございません。
・msg.payloadのデータをmsg.dataに退避します

【6】「数値セット」
Kanazawa_Weather_NodeRED_Function_2.png

VisualFlowCreatorからの変更点は4か所のみです。
(1行目のコメント化、項目設定tokyoなどを追加、18行目 tokyoへの540分の加算へ変更、24行目のValues.pushの内容変更)

//msg.topic = "XXXXXXXXX/Datapoint01_05";//asset id/aspect名	
	
var ix1=0; 	
var ix2=0;	
var values = []; 	
let date = new Date(); 	
let unixTime = new Date();	
var hh = []; var mm = []; 	
let tokyo = new Date();	
const today = new Date();	
const yesterday = new Date(today);	
yesterday.setDate(yesterday.getDate() - 1);	
	
for (ix1 = 0; ix1 < msg.data.length;) {	
    hh = msg.data[ix1].substring(0,2);	
    mm = msg.data[ix1].slice(-2);	
    date = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate(), hh, mm,0);	
    tokyo = new Date(date.getTime() + (540 * 60 * 1000));	
    unixTime = Math.floor(date.getTime() / 1000);	
    	
    if( isNaN(msg.data[ix1 + 10]) == true){ msg.data[ix1 + 10] = 0;}	
    if( isNaN(msg.data[ix1 + 8]) == true){ msg.data[ix1 + 8] = 0;}	
    if( msg.data[ix1 + 10] == ""){ msg.data[ix1 + 10] = 0;}	
//    values.push({ _time: utc, Datapoint01: msg.data[ix1 + 1], Datapoint02: msg.data[ix1 + 4], Datapoint03: msg.data[ix1 + 5],   Datapoint04: msg.data[ix1 + 8], Datapoint05: msg.data[ix1 + 10]});	
    values.push({ "時分": tokyo, "気圧現地": msg.data[ix1 + 1], "気圧海面": msg.data[ix1 + 2], "降水量": msg.data[ix1 + 3], "気温": msg.data[ix1 + 4], "相対湿度": msg.data[ix1 + 5], "風向風速平均": msg.data[ix1 + 6], "風向風速風向": msg.data[ix1 + 7], "風向風速最大瞬間": msg.data[ix1 + 8], "風向風速風向 ": msg.data[ix1 + 9], "日照時間": msg.data[ix1 + 10] });	
	
    ix1=ix1+11;	
    ix2=ix2+1;	
}	
msg.payload = values;	
	
return msg;	


・10行目 todayを取得
・11ー12行目 yesterdayを計算 (todayから1日マイナス)

・14行目 For文 1544個のメッセージについて以下処理を実施
・15行目 時刻をhhにセット
・16行目 分をmmにセット
・17行目 dateに yesterday と hh と mm を統合した時刻情報をセット
・18行目 tokyo情報を計算 日本時間から世界時間へ変換(9時間(540分)プラス)

・21行目 ・8項目目 風速 が Nan のとき 0をセット
・22行目 ・10項目目  日照時間 が Nanのとき 0をセット
・23行目 ・10項目目  日照時間 が ""のとき 0をセット
・24行目 Valuesに以下をセット
  "時分": tokyo,  18行目で計算した時刻情報
  "気圧現地": msg.data[ix1 + 1], 1項目目 気圧現地
  "気圧海面": msg.data[ix1 + 2], 2項目目 気圧海面
  "降水量": msg.data[ix1 + 3],  3項目目 降水量
  "気温": msg.data[ix1 + 4],   4項目目 気温
  "相対湿度": msg.data[ix1 + 5], 5項目目 湿度
  "風向風速平均": msg.data[ix1 + 6],  6項目目 風速平均
  "風向風速風向": msg.data[ix1 + 7],  7項目目 風向
  "風向風速最大瞬間": msg.data[ix1 + 8],  8項目目 風速最大瞬間
  "風向風速風向 ": msg.data[ix1 + 9],   9項目目  風向
  "日照時間": msg.data[ix1 + 10]  10項目目 日照時間
・28行目 indexに  ix1に 11を加算
・29行目 indexに  ix2に 1を加算

・31行目 msg.payload に valuesをセット;

【7】「ファイル保存」
VisualFlowCreatorからのノードをファイル保存に変更しております。
Kanazawa_Weather_NodeRED_Wite_file1.png

・ファイル名に msg.filenamejsonをセット
。動作 ファイル上書き

【8】「保存したファイル」 以下となります。
Kanazawa_Weather_NodeRED_jsonfile.png

Node-REDでのDashboard表示

 新規に作成した部分となります。
Kanazawa_Weather_NodeRED_Flow_2.png

【1】Inject処理(Json)
Kanazawa_Weather_NodeRED_inject-d1.png

・msg.dir データ取得処理で保存したファイルのあるフォルダを指定します

【1】’ Inject処理(日付指定)
Kanazawa_Weather_NodeRED_inject-d2.png

・msg.dir データ取得処理で保存したファイルのあるフォルダを指定します
・msg.yy 取得したいファイルの年を指定します
・msg.mm 取得したいファイルの月を指定します
・msg.dd 取得したいファイルの日を指定します

【2】昨日指定処理
Kanazawa_Weather_NodeRED_function-d1.png

const today = new Date();
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
var yy = yesterday.getFullYear();
var mm = ("00" + String(yesterday.getMonth() + 1)).slice(-2);
var dd = ("00" + String(yesterday.getDate())).slice(-2);

msg.filenamejson = msg.dir + "kanazawaWeather" + yy + mm + dd + ".json";
return msg;

・2行目 todayを取得
・3ー4行目 yesterdayを計算 (todayから1日マイナス)
・5-7行目 inkectノードでセットされたmsg.yy、msg.mm、msg.ddをyy、mm、ddにセットします
・9行目 msg.filenamejsonに msg.dir ファイル名称と 日付を連結したファイル名称をセットします

【2】’日付指定処理
Kanazawa_Weather_NodeRED_function-d2.png

var yy = msg.yy;
var mm = msg.mm;
var dd = msg.dd;

msg.filenamejson = msg.dir + "kanazawaWeather" + yy + mm + dd + ".json";
return msg;

・2-4行目 inkectノードでセットされたmsg.yy、msg.mm、msg.ddをyy、mm、ddにセットします
・6行目 msg.filenamejsonに msg.dir ファイル名称と 日付を連結したファイル名称をセットします

【3】read File処理
Kanazawa_Weather_NodeRED_read_file.png

・ファイル名 msg.filenamejson を設定します
・出力形式 文字列 を設定します

【4】Json処理
Kanazawa_Weather_NodeRED_json_node.png

 ・動作 「Json文字列とオブジェクト間の相互変換」を選択

【5】「データの退避」 Changeノード
Kanazawa_Weather_NodeRED_Change_data_taihi.png

msg.payloadの内容をmsg.dataに退避します
。ルール 
 ・値の代入 msg.data
 ・対象の値  msg.payload

【6】「function_5 数値セット」 
Kanazawa_Weather_NodeRED_function_5.png

var ix; var x = []; var y = []; var z = []; var u = []; var v = []; var w = [];
var file_old = msg.payload;
var file_new_x = []; var file_new_y = []; var file_new_z = []; 
var file_new_u = [];var file_new_v = []; var file_new_w = [];

for (ix = 0; ix < file_old.length; ix++) {
    x[ix] = file_old[ix].時分;
    y[ix] = parseFloat(file_old[ix].気圧現地);
    z[ix] = parseFloat(file_old[ix].気温);
    u[ix] = parseFloat(file_old[ix].相対湿度);
    v[ix] = parseFloat(file_old[ix].風向風速最大瞬間);
    w[ix] = parseFloat(file_old[ix].日照時間);

    file_new_x[ix] = { "時分": x[ix], "気圧現地": y[ix], "気温": z[ix], "相対湿度": u[ix], "風速": v[ix], "日照時間": w[ix] };
    file_new_y[ix] = { "x": x[ix], "y": y[ix] };
    file_new_z[ix] = { "x": x[ix], "y": z[ix] };
    file_new_u[ix] = { "x": x[ix], "y": u[ix] };
    file_new_v[ix] = { "x": x[ix], "y": v[ix] };
    file_new_w[ix] = { "x": x[ix], "y": w[ix] };
}
msg.file_new_x = file_new_x;
msg.file_new_y = [{ "series": ["csv"], "labels": ["気圧"], "data": [file_new_y] }];
msg.file_new_z = [{ "series": ["csv"], "labels": ["気温"], "data": [file_new_z] }];
msg.file_new_u = [{ "series": ["csv"], "labels": ["湿度"], "data": [file_new_u] }];
msg.file_new_v = [{ "series": ["csv"], "labels": ["風速"], "data": [file_new_v] }];
msg.file_new_w = [{ "series": ["csv"], "labels": ["日照時間"], "data": [file_new_w] }];
msg.col_y = y;
msg.col_z = z;
msg.col_u = u;
msg.col_v = v;
msg.col_w = w;
return msg;

・1-4行目 変数の設定
・6行目 For文で繰り返し処理 1日分のデータ144件分の 処理を実行
・7-12行目 時分、気圧、気温。湿度、最大瞬間風速、日照時間を個別配列にセット
 (気圧、気温。湿度、最大瞬間風速、日照時間はゲージ用)
・14行目 テーブル表示用の配列 File_new_x
・15-19行目 折線グラフ用の気圧、気温。湿度、最大瞬間風速、日照時間の個別の配列
・21ー26行目 繰り返し処理終了後に msg.file_new_* に 各配列をセット(テーブル、折れ線グラフ用)
・27ー32行目 繰り返し処理終了後に msg_col_*に 各配列をセット(ゲージ用)

【7】グラフ表示準備
Kanazawa_Weather_NodeRED_Change_file_new_y.png

 上記は file_new_y 気圧 の設定例となります。
 
 file_new_Z、file_new_u、file_new_v、file_new_w も下記の通り設定します。
 (file_new_y 気圧 のNode をcopyしてオレンジ枠部分を変更)
Kanazawa_Weather_NodeRED_Change_file_new_z.png

【8】グラフ表示
 Payloadにセットされたデータを折れ線グラフで表示します。
Kanazawa_Weather_NodeRED_Chart_file_new_y.png

・グループ 下記で作成してある 【金沢】金沢気象 を指定
・サイズ 10×5を入力
。ラベル 金沢 気圧 を入力
他はデフォルトのままとします

なお、Dashboard group設定は以下となります。名前、タブを設定、幅は30にします。
Kanazawa_Weather_NodeRED_Dashboard_group.png

気温、湿度、風速。日照時間も上記と同様に設定します。
(気圧で設定したノードをコピーして、ラベル部分のみ変更)

【9】ゲージ表示準備
Kanazawa_Weather_NodeRED_Dashboard_change_Gauge_pressure.png

気圧
・名前 Col_y avr を入力
。ルール 
 ・値の代入 msg.payload
 ・対象の値 JSONata式 $average(col_y)

気圧で作成した上記GhangeノードをCopyして以下を作成します、変更点はオレンジ枠の2箇所です。
(以下は風速と日照時間の場合)
Kanazawa_Weather_NodeRED_Dashboard_change_Gauge_temp_hud_vw.png

気温
・名前 Col_z max を入力
・対象の値 JSONata式 $max(col_z)

湿度
・名前 Col_u Avr を入力
・対象の値 JSONata式 $average(col_u)

風速
・名前 Col_v Avr を入力
・対象の値 JSONata式 $average(col_v)

日照時間
・名前 Col_w Sum を入力
・対象の値 JSONata式 $sum(col_w)

【10】ゲージ表示
Kanazawa_Weather_NodeRED_Dashboard_Gauge_pressure.png

・グループ 下記で作成してある 【金沢】金沢気象 を指定
・サイズ 5×5を入力
・タイプ Gaugeのままとします 他にDonutなども選択できます
・ラベル 金沢 気圧(平均) を入力
・値フォーマット  {{value | number:2}} と設定し、小数2桁まで表示します。
・範囲 0から1200にします

他はデフォルトのままとします

気圧で作成したGaugeをCopyして以下を作成します、変更点はオレンジ枠の2箇所です。
Kanazawa_Weather_NodeRED_Dashboard_Gauge_temp_hud_zu.png

Kanazawa_Weather_NodeRED_Dashboard_Gauge_temp_hud_vw.png

気温
・ラベル 金沢 気温(最大) を入力
・範囲 0から30にします

湿度
・ラベル 金沢 湿度(平均) を入力
・範囲 0から80にします

風速
・ラベル 金沢 風速(平均) を入力
・範囲 0から10にします

日照時間
・ラベル 金沢 日照時間(平均) を入力
・範囲 0から800にします

【11】テーブル表示準備
 file_new_x テーブル表示用の の設定例となります。
Kanazawa_Weather_NodeRED_Dashboard_change_table.png

【12】テーブル表示
Kanazawa_Weather_NodeRED_Dashboard_table.png

・グループ 【金沢】金沢気象 を指定
・サイズ 15×5を入力
・名前 テーブル を入力
他はデフォルトのままとします

【13】ダッシュボードレイアウト調整
Kanazawa_Weather_NodeRED_Dashboard_reiaut.png

各パネルの位置を上記のように調整します。

おわりに 

 今後、深堀したい点は以下です。
 ・Dashboard設定部分について GrafanaとNode-REDでの設定生産性の比較
  (例 Grafanaが数倍設定は楽な印象ですが、初期設定と変更設定で設定作業時間にどのくらいの差があるのかを調査)

 今後の課題は以下となります。
  ・データ取得
   前日分取得のみ可能な設定ですので、日付指定で取れるようにする
  ・過去日付指定機能
    デプロイせずとも、データ取得&ダッシュボード表示をできるようにする

 留意点としては、気象情報のレイアウトが変更されてしまうと変更作業(Node-REDでのデータ取得処理の構築【6】「数値セット」など)を実施する必要があるところです。

参考資料

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0