はじめに
やりたいこと
- Node-REDでどんなことがどこまでできるのかを調べる
- part2(応用編)では、Node-REDの設定ファイルや小技などをまとめました
Node-REDのまとめ記事
動作環境
- OS : CentOS Linux release 7.5.1804 (Core)
- Node-RED : v0.19.5
- docker : 18.09.1
- Node-REDイメージ : nodere/node-red-docker (IMAGE ID/d4f07b39b24d)
- Dockerを使いますが、ホストに立てても大丈夫かと思います。
免責事項
- 検証をして確実と思われる情報を載せておりますが、誤っている可能性もゼロではないので、参考程度にご利用ください
- 本来はコードと実行結果のコンソールログも載せるべきなのですが、数と量が多いので、一旦は画面イメージまでとさせてください。
調査結果
変数共有
調べたこと
- 各ノード、フロー間の情報のやりとりをどのように行うのか確認する
- contextオブジェクトの中にデータを保持しておくことができ、別の個所でその値を参照できる仕組みがある
- ローカルノードコンテキスト変数:単一のノードで共有できる変数
- フローコンテキスト変数:フローで共有できる変数
- グローバル変数:全体で共有できる変数
- コンソールのコンテキストタブでも値を確認できる
ソースコードイメージ
// ローカルノードコンテキスト変数
// 同じノードが再度利用されるときに、前の値を引き継げる
var con_count = context.get('con_count')||0;
con_count += 1;
context.set('con_count',con_count);
// フローコンテキスト変数
// 同じフロー内にいるノードで情報を引き継げる。再利用時も引き継がれる
var flow_count = flow.get('flow_count')||0;
flow_count += 1;
flow.set('flow_count',flow_count);
// グローバル変数
// すべての場所から参照可能
var global_count = global.get('global_count')||0;
global_count += 1;
global.set('global_count',global_count);
時間測定
調べたこと
- 性能を測定する際には、処理時間を測定したいケースが度々発生するので、測定方法を確認する
- 前述の変数とJSの基本機能であるDate関数を使えば簡単に実現できる
- functionノードAで今の時間を記録し、処理終了後にfunctionノードBでも今の時間を記録する。両者の差分を取って経過時間を測定する
ソースコードイメージ
// functionノードA
global.set('global_count',new Date().getTime());
// functionノードB
var start = global.get('global_count');
var diff = new Date().getTime() - start;
msg.payload = diff + "ミリ秒"
定期実行
調べたこと
- 単にInjectノードの設定で指定した時間間隔を設定するだけ
- 指定した時間間隔、日時などある程度細かく設定できる
複数入力の時間内判定
調べたこと
- 複数の入力が一定時間内に送られたらtrueを返すロジックが必要になったので、実現性を確認する
- フローコンテキストに時間とイベントを紐づけて記録し、チェック機能で両者を取り出して時間を測るだけ
// Input1側(Input2側もInput1をInput2にするだけ)
var time_table = flow.get("time_table") || {}
var user_data = time_table[msg.payload] || {}
user_data["Input1"] = new Date().getTime()
time_table[msg.payload] = user_data
flow.set("time_table",time_table)
return msg;
// 取り出し&比較ロジック
var time_table = flow.get("time_table") || {}
var user_data = time_table[msg.payload] || {}
var in1_time = user_data["Input1"]
var in2_time = user_data["Input2"]
try{
var diff = (in1_time - in2_time) / 1000
msg.diff = time_table
if(Math.abs(diff) < 5){
msg.payload = "5秒未満"
msg.flag = true
}else{
msg.payload = "5秒以上"
msg.flag = false
}
}catch(e){
msg.flag = false
}
return msg;
functionノードのログ出力
調べたこと
- functionノード内からログに出力する機能を確認する
- 警告以上のログは、コンソールに出力される
- ログファイルには指定されたログレベル以上のものが記録される
- ログファイルに記述されるlevelについては、以下の通り定義されている模様
- off:1, fatal:10, error:20, warn:30, info:40, debug:50, trace:60, audit:98, metric:99
- ログファイルに記述されるlevelについては、以下の通り定義されている模様
// functionノードでの記述
node.trace("トレースレベルのログ")
node.debug("デバッグレベルのログ")
node.log("インフォレベルのログ");
node.warn("警告レベルのログ");
node.error("エラーレベルのログ");
functionノードの状態設定
調べたこと
- node.statusを使えば、状態を変えられるらしいので、確認する
- fill,shape,textの3つを指定できる
- statusノードにも伝播される
// 緑の〇でOKをステータスとして表示させる
node.status({fill:"green",shape:"dot",text:"OK"});
JSのrequire
調べたこと
- functionノードにモジュールを直接requireすることはできないので、実現方法を確認する
- settings.jsに記述し、functionノードから参照する
- settings.jsへの修正が必要なため、Node-REDの再起動が必要?
// settings.js内の設定
// axiosをfunctionノードで使いたい
functionGlobalContext: {
axios:require('axios')
},
// functionノードの中
const axios = global.get('axios');
SSL化
調べたこと
- Node-REDへのアクセスおよび、http/wsをhttps/wssにする方法を確認する
- 鍵を作成して特定の場所に置けばよい
- http/ws と https/wssの共存はできない模様
// settings.js
// XXXには、認証に必要な鍵と認証書のパスを記述する
var fs = require("fs");
https: {
key: fs.readFileSync('XXX'),
cert: fs.readFileSync('XXX')
},
ユーザ認証
調べたこと
- Node-REDのフローを特定の人だけに変更できるようにするため、認証をする方法がないか確認する
- いくつかの手段があるが、ひとまずbasic認証で可とする
// settings.js
// XXXには、ユーザ名とパスワードのMD5のハッシュ値をいれる
httpAdminAuth: {
user:"XXX",
pass:"XXX"
},
ログファイル出力
調べたこと
- Node-REDはデフォルトではコンソールにしか出力できないらしいので、ログファイル出力の方法を確認する
- logstashに送る方法もあるらしいが、うまくいかなかった
// settings.js
// XXXにはログファイルのパスを入れる
var fs = require("fs");
fs.writeFile('XXX',''); // 初期化
logging: {
file:{
level: 'debug',
metrics: false,
audit: false,
handler : function(settings){
return function (msg){
fs.appendFile('XXX',(new Date(msg.timestamp)).toISOString() + " : " + JSON.stringify(msg) + '\n');
}
}
}
},
デスクトップ版
調べたこと
- Serverを立てずに利用できると、利用できる人が増えるのではないかという発想で探したら、electronを使ったデスクトップアプリ版が存在していた
- デスクトップアプリ版の差異を確認する
- 2つのバージョンがあり、組み込まれているノードの数が異なる
- Node.jsを入れない影響か、作業環境の影響か、ノードの追加インストールとフローの書き出しができなかった