Joseph Halfmoon
前回から引き続き自前ノード data-check に機能追加をしております。コード書いていたら避けられない?のがコーディングミスであります。今回はいろいろやらかしたときの反応をいくつか掲げます。ちゃんとチェックしてからupdateかければ良いのに、コーディング終了即アップデートするからそんなことになるのだわな。
※「ブロックを積みながら」投稿順 index はこちら
※動作確認にはRaspberry Pi 3 model B+のRaspberry Pi OS(32bit)上にインストールした以下を使用しています。
-
- Node-RED v2.0.5
- node-red-dashboard 3.2.0
自前ノードへの機能追加の目論見
自前ノードは 流れいるmsgに載ってくるデータを吟味?し、過去最大とか、過去最少とかを検出してその旨プロパティに追加するノードです。今回追加変更いたしますのは以下の点です。
-
- 変更:前回まで、過去最大(DATAMAX)、過去最小(DATAMIN)はレコード更新したときのみプロパティに載せていたが、全てのパケットに載せるようにした。1パケット見れば全部分かるように。
- 追加:セッティングにUlimit(上限)、Dlimit(下限)フィールドを追加。上限越え、下限を下回るときにはTopicプロパティにその旨を追記する。
エラーなコードに対する2つの反応
追加変更で「やっちまったとき」のNodeRedの反応は大きく以下に分かれます。
-
- ノードそのものが消えてなくなる(Unknown)
- ノードは存在、フローも動くけれども下流へ送出されるmsg にエラーが載っている
どうも html 部分でエラーを起こすとノードそのものが消えてなくなることが多いようです。コマケー所の記号一つでも消えます。そのようなときにNodeRedエディタ画面を開いたときの様子が以下に。

いや~、「npm update モジュールパス」したら、先ほどまで動いていた筈の 自前ノード、data-checkが不明ノードになってます。
フローはどうなっているの?とみると以下のようにノードがunknownです。
このunknownノードの設定画面を開くこともできて、こんな感じです。

上記は、html ファイル内で “,” 一個忘れただけなんだけれどもキビシ~です。
一方、jsファイル内でのエラーに対しては反応がチト異なるようです。以下のケースでは、”isNaN”と綴るべきJavaScriptの関数名を”isNan”と書いてしまったときのエラーです。特にノードが消えるようなこともなく、フローを動かすこともできるのですが、流れてきた結果をみると msg: error が載ってます。こんな感じ。

このエラーメッセージは分かりやすくて良いな。
機能追加後のjsファイルとhtmlファイル
ダラダラ書いているdatacheck.jsファイルが以下に。
module.exports = function(RED) {
function DataCheckNode(config) {
RED.nodes.createNode(this, config);
this.ulimit = config.ulimit;
this.dlimit = config.dlimit;
node.on('input', function(msg) {
var nodeContext = this.context();
var nData = nodeContext.get('nData')||0;
var minData = nodeContext.get('minData')||Number.MAX_VALUE;
var maxData = nodeContext.get('maxData')||-Number.MAX_VALUE;
var inputData = Number(msg.payload);
var ulim = Number(this.ulimit);
var dlim = Number(this.dlimit);
if (inputData > maxData) {
nodeContext.set('maxData', maxData);
if (inputData < minData) {
nodeContext.set('minData', minData);
nodeContext.set('nData', nData);
if (!isNaN(ulim) && (inputData > ulim)) {
msg.topic = "Higher than the ulimit";
if (!isNaN(dlim) && (inputData < dlim)) {
msg.topic = "Lower then the dlimit";
RED.nodes.registerType("data-check", DataCheckNode);
module.exports = function(RED) {
function DataCheckNode(config) {
RED.nodes.createNode(this, config);
var node = this;
this.name = config.name;
this.ulimit = config.ulimit;
this.dlimit = config.dlimit;
node.on('input', function(msg) {
var nodeContext = this.context();
var nData = nodeContext.get('nData')||0;
var minData = nodeContext.get('minData')||Number.MAX_VALUE;
var maxData = nodeContext.get('maxData')||-Number.MAX_VALUE;
var inputData = Number(msg.payload);
var ulim = Number(this.ulimit);
var dlim = Number(this.dlimit);
if (!isNaN(inputData)) {
nData++;
if (inputData > maxData) {
maxData = inputData;
nodeContext.set('maxData', maxData);
}
if (inputData < minData) {
minData = inputData;
nodeContext.set('minData', minData);
}
msg.NDATA = nData;
msg.DATAMAX = maxData;
msg.DATAMIN = minData;
msg.NAME = this.name;
nodeContext.set('nData', nData);
if (!isNaN(ulim) && (inputData > ulim)) {
msg.topic = "Higher than the ulimit";
}
if (!isNaN(dlim) && (inputData < dlim)) {
msg.topic = "Lower then the dlimit";
}
}
node.send(msg);
});
}
RED.nodes.registerType("data-check", DataCheckNode);
}
module.exports = function(RED) {
function DataCheckNode(config) {
RED.nodes.createNode(this, config);
var node = this;
this.name = config.name;
this.ulimit = config.ulimit;
this.dlimit = config.dlimit;
node.on('input', function(msg) {
var nodeContext = this.context();
var nData = nodeContext.get('nData')||0;
var minData = nodeContext.get('minData')||Number.MAX_VALUE;
var maxData = nodeContext.get('maxData')||-Number.MAX_VALUE;
var inputData = Number(msg.payload);
var ulim = Number(this.ulimit);
var dlim = Number(this.dlimit);
if (!isNaN(inputData)) {
nData++;
if (inputData > maxData) {
maxData = inputData;
nodeContext.set('maxData', maxData);
}
if (inputData < minData) {
minData = inputData;
nodeContext.set('minData', minData);
}
msg.NDATA = nData;
msg.DATAMAX = maxData;
msg.DATAMIN = minData;
msg.NAME = this.name;
nodeContext.set('nData', nData);
if (!isNaN(ulim) && (inputData > ulim)) {
msg.topic = "Higher than the ulimit";
}
if (!isNaN(dlim) && (inputData < dlim)) {
msg.topic = "Lower then the dlimit";
}
}
node.send(msg);
});
}
RED.nodes.registerType("data-check", DataCheckNode);
}
設定項目を増やしたので水ぶくれ気味のdata-check.htmlが以下に。
<script type="text/javascript">
RED.nodes.registerType('data-check', {
return this.name||"data-check";
oneditprepare: function() {
if (this.name === undefined) {
$("#node-input-name").val("NO-NAME");
<script type="text/html" data-template-name="data-check">
<label for="node-input-ulimit"><i class="fa fa-level-up"></i> Ulimit</label>
<input type="text" id="node-input-ulimit" placeholder="Ulimit">
<label for="node-input-dlimit"><i class="fa fa-level-down"></i> Dlimit</label>
<input type="text" id="node-input-dlimit" placeholder="Dlimit">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
<script type="text/html" data-help-name="data-check">
<p>Checking MIN/MAX values in the data flow.</p>
<script type="text/javascript">
RED.nodes.registerType('data-check', {
category: 'function',
color: "#fdebd0",
defaults: {
name: {value:""},
ulimit: {value:""},
dlimit: {value:""}
},
inputs:1,
outputs:1,
icon: "debug.svg",
label: function() {
return this.name||"data-check";
},
oneditprepare: function() {
if (this.name === undefined) {
$("#node-input-name").val("NO-NAME");
}
}
});
</script>
<script type="text/html" data-template-name="data-check">
<div class="form-row">
<label for="node-input-ulimit"><i class="fa fa-level-up"></i> Ulimit</label>
<input type="text" id="node-input-ulimit" placeholder="Ulimit">
</div>
<div class="form-row">
<label for="node-input-dlimit"><i class="fa fa-level-down"></i> Dlimit</label>
<input type="text" id="node-input-dlimit" placeholder="Dlimit">
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="data-check">
<p>Checking MIN/MAX values in the data flow.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('data-check', {
category: 'function',
color: "#fdebd0",
defaults: {
name: {value:""},
ulimit: {value:""},
dlimit: {value:""}
},
inputs:1,
outputs:1,
icon: "debug.svg",
label: function() {
return this.name||"data-check";
},
oneditprepare: function() {
if (this.name === undefined) {
$("#node-input-name").val("NO-NAME");
}
}
});
</script>
<script type="text/html" data-template-name="data-check">
<div class="form-row">
<label for="node-input-ulimit"><i class="fa fa-level-up"></i> Ulimit</label>
<input type="text" id="node-input-ulimit" placeholder="Ulimit">
</div>
<div class="form-row">
<label for="node-input-dlimit"><i class="fa fa-level-down"></i> Dlimit</label>
<input type="text" id="node-input-dlimit" placeholder="Dlimit">
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="data-check">
<p>Checking MIN/MAX values in the data flow.</p>
</script>
実行結果
フローそのものは前回、前々回とまったく同じです。上流から流れてくる乱数値を処理して追記したパケットを下流に流し出すもの。
上限、下限を設定できるようになった(数値を与えないとチェックは無効)ので以下のように数値を設定しておきます。

data-checkノード通過後、Dlimitを下回ったときのmsg内容の様子が以下です。

今度はUlimitを上回ったとき。

おっちょこちょいなことをするとノードが消えてしまうの怖いな。それにしても npm update は今のところどんなときもノーエラー。内容は関知していない?
ブロックを積みながら(117) Node-RED、自前ノード、Iconとプロパティ読み取り へ戻る
ブロックを積みながら(119) Node-RED、自前ノードにWelform算法追加 へ進む