今回は、ABLICのPH-Bシリーズで漏水センサーの死活監視を取り入れ、バッテリーが低下してきた際にメールと積層表示灯で知らせるロジックを紹介しようと思います。
今回使うノード
今回は積層表示灯ということで、ablicさんのPH-Bのシリーズに変更をかけていきます。

今回は大きく変更になるため、データをダウンロードしていただき、ポイントと要点を説明していきたいと思います。
ノードの変更
今回、死活監視の動作が加わるため、メールや積層表示灯の動作が新たに1パターン加わります。
そのため、センサー識別の後ろから丸々コピーして新たに1パターン追加します。
まずは、センサー識別の左側についている線を削除します。


この状態でセンサー識別をシフトクリックすると、繋がっているものがすべて選択されますので、下側にコピー&ペーストします。


次に中身を変えます。メール本文は、センサー番号の後を死活監視用(自由に決めてください)にします。自分は交換を促すメールにします。


メールの件名は、漏水検知メールから死活監視メールにします。


次に、パトランプ光&音声をクリックし、「漏水を検知しました。」から「死活監視エラーを検知しました。交換してください」に変更します。


次に、LED点灯設定を開きredを9、yellowを1、greenを9にしてください。


最後に、メール送信ノードなのですが、コピーすると中の「ユーザーIDとパスワード」が消えてしまいます。こちらを再度記入してください。(gmailの場合こちらを下記URLを参照)
なおわからない場合は、既存のメールノードに繋げてください。(わからない場合は下図参照)
追加したメールノードを消します。


メール件名から上のメール送信に線を繋ぎます。


これでメール、積層表示灯の追加は完了になります。
フローの追加と接続
今回はデータが多いため、フローを2つに分けたいと思います。
下記のデータをコピーして、Node-REDに追加してください。追加方法は、右上のメニューバーを開き読み込みを選択


この中に、コピーした下記データを貼り付けてください。
[
{
"id": "54675ca6c0bc75a3",
"type": "tab",
"label": "フロー 6",
"disabled": false,
"info": "",
"env": []
},
{
"id": "02054ca0f1615857",
"type": "switch",
"z": "54675ca6c0bc75a3",
"name": "死活監視/漏水 判定",
"property": "len",
"propertyType": "global",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1160,
"y": 260,
"wires": [
[
"49ed710265381fc3"
],
[
"b4bf573c53813d18"
]
]
},
{
"id": "602c96cb92dafee7",
"type": "debug",
"z": "54675ca6c0bc75a3",
"name": "debug 131",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "state",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1630,
"y": 300,
"wires": []
},
{
"id": "b4bf573c53813d18",
"type": "change",
"z": "54675ca6c0bc75a3",
"name": "",
"rules": [
{
"t": "set",
"p": "state",
"pt": "msg",
"to": "正常",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1390,
"y": 300,
"wires": [
[
"602c96cb92dafee7",
"4850cfe6dcb7252e"
]
]
},
{
"id": "49ed710265381fc3",
"type": "change",
"z": "54675ca6c0bc75a3",
"name": "",
"rules": [
{
"t": "set",
"p": "state",
"pt": "msg",
"to": "漏水",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1390,
"y": 240,
"wires": [
[
"aa43e584d7e4bc10",
"7b291f32a629b5d3"
]
]
},
{
"id": "aa43e584d7e4bc10",
"type": "debug",
"z": "54675ca6c0bc75a3",
"name": "debug 132",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "state",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1610,
"y": 140,
"wires": []
},
{
"id": "cefaa361ab43a2a8",
"type": "change",
"z": "54675ca6c0bc75a3",
"name": "",
"rules": [
{
"t": "set",
"p": "len",
"pt": "global",
"to": "false",
"tot": "bool"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 930,
"y": 280,
"wires": [
[
"02054ca0f1615857"
]
]
},
{
"id": "c0a3d4c6b42da288",
"type": "function",
"z": "54675ca6c0bc75a3",
"name": "データ蓄積(デバイスごと)",
"func": "const triggerStockData = flow.get(\"triggerStockData\");\n\n// デバイス ID\nconst deviceID = msg.topic;\n// 1つ前のカウント数\nvar counter = triggerStockData[deviceID] || 0;\n\n// データ蓄積\ntriggerStockData[deviceID] = counter + 1;\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 420,
"y": 260,
"wires": [
[
"21c3e60c34e4af77",
"1090bab4bde4c1d5",
"1df3ce111ea39c71"
]
]
},
{
"id": "b6f57c72542be6bd",
"type": "switch",
"z": "54675ca6c0bc75a3",
"name": "信号回数",
"property": "triggerStockData[msg.topic]",
"propertyType": "flow",
"rules": [
{
"t": "gte",
"v": "4",
"vt": "str"
},
{
"t": "lt",
"v": "4",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 780,
"y": 260,
"wires": [
[
"ec26ce57a37f8dd8"
],
[
"cefaa361ab43a2a8"
]
]
},
{
"id": "ec26ce57a37f8dd8",
"type": "change",
"z": "54675ca6c0bc75a3",
"name": "",
"rules": [
{
"t": "set",
"p": "len",
"pt": "global",
"to": "true",
"tot": "bool"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 930,
"y": 240,
"wires": [
[
"02054ca0f1615857"
]
]
},
{
"id": "1df3ce111ea39c71",
"type": "trigger",
"z": "54675ca6c0bc75a3",
"name": "",
"op1": "",
"op2": "",
"op1type": "pay",
"op2type": "pay",
"duration": "5",
"extend": true,
"overrideDelay": false,
"units": "min",
"reset": "",
"bytopic": "topic",
"topic": "topic",
"outputs": 2,
"x": 630,
"y": 160,
"wires": [
[],
[
"152264cc7c8d0b0e"
]
]
},
{
"id": "152264cc7c8d0b0e",
"type": "function",
"z": "54675ca6c0bc75a3",
"name": "初期化&連絡",
"func": "const triggerStockData = flow.get(\"triggerStockData\");\nconst deviceID = msg.topic;\n// 上記配列の初期化\ntriggerStockData[deviceID] = 0;\nflow.set(\"triggerStockData\", triggerStockData);\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 840,
"y": 160,
"wires": [
[]
]
},
{
"id": "4e25e0f927247eae",
"type": "inject",
"z": "54675ca6c0bc75a3",
"name": "初期化",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "5",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 200,
"y": 60,
"wires": [
[
"133ff58871f44000"
]
]
},
{
"id": "133ff58871f44000",
"type": "change",
"z": "54675ca6c0bc75a3",
"name": "triggerStockData 初期化",
"rules": [
{
"t": "set",
"p": "triggerStockData",
"pt": "flow",
"to": "{}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 410,
"y": 60,
"wires": [
[
"1597025f1dbed1f4"
]
]
},
{
"id": "1597025f1dbed1f4",
"type": "function",
"z": "54675ca6c0bc75a3",
"d": true,
"name": "初期化",
"func": "const triggerStockData = flow.get(\"triggerStockData\");\nconst sen_num1 =global.get(\"sen_num1\");\nconst sen_num2 =global.get(\"sen_num2\");\nconst sen_num3 =global.get(\"sen_num3\");\nconst sen_num4 =global.get(\"sen_num4\");\nconst sen_num5 =global.get(\"sen_num5\");\nconst sen_num6 =global.get(\"sen_num6\");\n// 上記配列の初期化\ntriggerStockData[sen_num1] = 0;\ntriggerStockData[sen_num2] = 0;\ntriggerStockData[sen_num3] = 0;\ntriggerStockData[sen_num4] = 0;\ntriggerStockData[sen_num5] = 0;\ntriggerStockData[sen_num6] = 0;\nflow.set(\"triggerStockData\", triggerStockData);\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 610,
"y": 60,
"wires": [
[]
]
},
{
"id": "2f9c7ba0019def2b",
"type": "trigger",
"z": "54675ca6c0bc75a3",
"name": "",
"op1": "1",
"op2": "",
"op1type": "str",
"op2type": "pay",
"duration": "24",
"extend": true,
"overrideDelay": false,
"units": "hr",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 2,
"x": 1510,
"y": 480,
"wires": [
[],
[
"1b41ad0650b3ba88",
"130ae6f718eb300b"
]
]
},
{
"id": "76597d47895e549e",
"type": "trigger",
"z": "54675ca6c0bc75a3",
"name": "",
"op1": "1",
"op2": "",
"op1type": "str",
"op2type": "pay",
"duration": "24",
"extend": true,
"overrideDelay": false,
"units": "hr",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 2,
"x": 1510,
"y": 520,
"wires": [
[],
[
"1b41ad0650b3ba88"
]
]
},
{
"id": "899794d63266b670",
"type": "trigger",
"z": "54675ca6c0bc75a3",
"name": "",
"op1": "1",
"op2": "",
"op1type": "str",
"op2type": "pay",
"duration": "24",
"extend": true,
"overrideDelay": false,
"units": "hr",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 2,
"x": 1510,
"y": 560,
"wires": [
[],
[
"1b41ad0650b3ba88"
]
]
},
{
"id": "e99369d9985d8031",
"type": "trigger",
"z": "54675ca6c0bc75a3",
"name": "",
"op1": "1",
"op2": "",
"op1type": "str",
"op2type": "pay",
"duration": "24",
"extend": true,
"overrideDelay": false,
"units": "hr",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 2,
"x": 1510,
"y": 600,
"wires": [
[],
[
"1b41ad0650b3ba88"
]
]
},
{
"id": "aef6f656f724b41f",
"type": "debug",
"z": "54675ca6c0bc75a3",
"name": "debug 136",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1450,
"y": 400,
"wires": []
},
{
"id": "130ae6f718eb300b",
"type": "debug",
"z": "54675ca6c0bc75a3",
"name": "debug 138",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1810,
"y": 380,
"wires": []
},
{
"id": "7880e3d17e6e4737",
"type": "link in",
"z": "54675ca6c0bc75a3",
"name": "センサー識別",
"links": [
"88a86d909df6d2d7"
],
"x": 125,
"y": 180,
"wires": [
[
"acaebec405e547a3",
"c9013eef25ded4a9"
]
]
},
{
"id": "7b291f32a629b5d3",
"type": "link out",
"z": "54675ca6c0bc75a3",
"name": "漏水",
"mode": "link",
"links": [
"52664be563d95b68",
"4bf140ca2fc8a2ca",
"73bdb9b29b4306d4"
],
"x": 1625,
"y": 240,
"wires": []
},
{
"id": "1b41ad0650b3ba88",
"type": "link out",
"z": "54675ca6c0bc75a3",
"name": "死活監視",
"mode": "link",
"links": [
"334c04c9a779e7f9",
"99f546abad6a7ed8"
],
"x": 1855,
"y": 540,
"wires": []
},
{
"id": "699a97c6c5abc1a1",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "信号の回数が4回を超えると漏水、漏水の時はTrue 正常の時はFalse",
"info": "エラーの時はTrue\n正常の時はFalse",
"x": 1020,
"y": 320,
"wires": []
},
{
"id": "58512b4aa531818d",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "漏水のメールに繋がっている",
"info": "",
"x": 1680,
"y": 200,
"wires": []
},
{
"id": "385369d6fe96faf2",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "正常の時は24時間以内にセンサーから死活監視信号が来る",
"info": "",
"x": 1510,
"y": 640,
"wires": []
},
{
"id": "de4f3d6ba5c1b308",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "死活監視メールに繋がっている",
"info": "",
"x": 1930,
"y": 440,
"wires": []
},
{
"id": "8ad289fd847f5698",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "検証用で24秒のため、確認取れたら24時間に戻す",
"info": "",
"x": 1530,
"y": 440,
"wires": []
},
{
"id": "9bf6bda06b705151",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "信号をセンサー番号ごとにカウント",
"info": "",
"x": 440,
"y": 320,
"wires": []
},
{
"id": "b674d4b1bb79f8b5",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "センサー番号をtopicに移す",
"info": "",
"x": 170,
"y": 320,
"wires": []
},
{
"id": "36e28f2b394740a1",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "格納する配列を作る",
"info": "",
"x": 430,
"y": 20,
"wires": []
},
{
"id": "4b04fd819acdb4aa",
"type": "comment",
"z": "54675ca6c0bc75a3",
"name": "信号を受けてから5分間信号の受け取り猶予を設定し、5分後にカウントをリセットする",
"info": "",
"x": 740,
"y": 120,
"wires": []
},
{
"id": "acaebec405e547a3",
"type": "debug",
"z": "54675ca6c0bc75a3",
"name": "debug 141",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload.data_Dec",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 310,
"y": 160,
"wires": []
},
{
"id": "21c3e60c34e4af77",
"type": "debug",
"z": "54675ca6c0bc75a3",
"name": "debug 142",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "triggerStockData[msg.topic]",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 670,
"y": 320,
"wires": []
},
{
"id": "1090bab4bde4c1d5",
"type": "function",
"z": "54675ca6c0bc75a3",
"name": "連絡",
"func": "const payload = msg.payload;\n\nconst triggerStockData = flow.get(\"triggerStockData\");\n\nconst deviceID = msg.topic;\n\n// 今回のデバイスの配列取り出し\nconst currentDeviceData = triggerStockData[deviceID];\nmsg.payload = {\n \"count\":currentDeviceData,\n \"data_Dec\":msg.topic\n}\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 630,
"y": 260,
"wires": [
[
"b6f57c72542be6bd"
]
]
},
{
"id": "c9013eef25ded4a9",
"type": "change",
"z": "54675ca6c0bc75a3",
"name": "センサー番号を移す",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "payload.data_Dec",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 160,
"y": 260,
"wires": [
[
"c0a3d4c6b42da288"
]
]
},
{
"id": "4850cfe6dcb7252e",
"type": "switch",
"z": "54675ca6c0bc75a3",
"name": "センサー識別",
"property": "payload.data_Dec",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2458",
"vt": "str"
},
{
"t": "eq",
"v": "",
"vt": "str"
},
{
"t": "eq",
"v": "",
"vt": "str"
},
{
"t": "eq",
"v": "",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 4,
"x": 1220,
"y": 540,
"wires": [
[
"2f9c7ba0019def2b",
"aef6f656f724b41f"
],
[
"76597d47895e549e"
],
[
"899794d63266b670"
],
[
"e99369d9985d8031"
]
],
"outputLabels": [
"センサ1",
"センサ2",
"センサ3",
"センサ4"
]
}
]
すると下図のようなデータが入ります。

動作はある程度コメントで書いているのですが、大まかに説明します。
まずは、どのようにパトランプのデータとつながっているかですが、小さい矢印のノードでつながっています。

これはlink inノードといい、ノードが遠かったり新しいフローで作成する際の紐づけ役になります。
現状は何も繋がっていませんので、パトランプのデータにlink outを追加して繋げます。
パトランプデータの音声繰り返し回数設定(切り離した部分)の後ろに追加します。


中身を開くと、先ほどのフロー名にセンサー識別と出てきます。名前をmainデータにし、センサー識別にチェックを入れるとノードが繋がりデータのやり取りができます。


これは1対1ではないため、追加すればするだけ表示されます。そのため、必ず名前を付けてください。
次に、1番上の初期化というところで配列を作成します。ポイントは、線で繋がっていない孤立したデータのため、flow、もしくはglobalで設定してください。


作成したら、信号の受けた回数をカウントします。コードは下図のようになっています。

ここではmsg.topicでカウントしますので、1つ前にセンサー番号をtopicに移しています。
ここで、受けた回数で漏水か死活監視の信号かを判定し、2つに分けます。漏水の場合はこのまま元のパトランプデータに戻るのですが、この際にもlink outを使います。
パトランプデータに行き、漏水検知側のセンサー識別にlink inを追加します。


中身を開いて、名前を変更し漏水にチェックを入れます。

正常だった場合、24時間以内にもう一度死活監視の信号を受け取るかカウントを開始します。
受け取らなかった場合、バッテリーが少なくなってるとし、死活監視エラーが送られます。

センサーごとに振り分け、triggerノードで24時間待機します。この際追加で信号を受け取ると24時間リセットされます。
この時、ポイントは再送信データを元のmsgオブジェクトにしないとデータが消えてしまいます。

ここでもポイントがあり、triggerノードの右側に2つ繋ぐところが出てきます。こちらの下の部分に接続してください。上は24時間待たずにそのままデータが流れてしまいます。そのため、下の部分に接続する必要があります。


今回、センサー識別は中身がない状態で追加されているので、センサー番号も追加してください。

最後にlink outノードでパトランプに返します。
パトランプ側では、死活監視エラー側のセンサー識別の前にlink inを追加し、名前を変え、死活監視にチェックを入れます。


こちらで設定が終わりになります。
右上のデプロイを押し、設定ができているか確認してみてください。
なお、確認しやすいようデバック用に死活監視の時間を24秒に設定しています。確認が終わりましたら、24時間に変更してください。

中を開き、秒を時間に変更します。

死活監視のON/OFF切り替えの導入
上記で追加した死活監視は、常にONの状態で死活監視か漏水かを判断してます。
これを、簡単に前の状況に戻すスイッチを作りたいと思います。
まずは新しいページを追加します。

この中に、injectノードとchangeノードを2つずつ入れてください。



これを1対1で繋げ、injectノードの名前を「死活監視ON/死活監視OFF」にします。
上の死活監視ONのinjectノードのみ変更を加えます。中身を開き、Node-RED起動の0.1秒後、以下を行うにチェックを入れます。


次に、死活監視ONのchangeノードを開き、値の代入を「global.」に変更し名前を「surveillance」にします。(名前は小文字ならお好きに決められます)代入する値はtrueにしてください。ノードの名前も死活監視ONに変更します。

下のchangeノードも同様に変更し、代入する値をfalseにしてください。
falseにした方は、追加でmsg.resetを作り、0を代入してください。
名前は死活監視OFFにします。

次に、死活監視OFFの後ろにlink outノードを追加し、名前を死活監視リセットにします。


死活監視のフローに行き、下図の赤い部分にline inノードを追加します。


中身を開き、名前を死活監視リセットに変更して、同じ名前にチェックを付けます。

追加したLink inをすべてのtriggerノードに接続します。


最後にパトランプのデータに行き、link outノードの手前にスイッチノードを追加します。


中身を開き、プロパティーをglobalにし、死活監視ON/OFFで決めた名前にします。

条件で、「==」の部分をクリックし、tuerであるを選択します。1つ追加して、追加分はfalseであるを選択してください。


戻ると、switchノードの右側に接続できる点が2つに増えます。
上の部分(条件の1番目、tuer)をline outノードに接続し、下の部分(条件の2番目、false)をメールのセンサー識別に接続してください。(下図参照)

こちらで設定完了です。
フロー2の部分をダブルクリックすると、設定が開けるので、「死活監視ON/OFFボタン」など名前を変えてください。



デプロイを押し、ボタンのページを開きます。
injectノードの右側の■をクリックすると死活監視のON/OFFが切り替えられます。
現在がどちらか確認したい場合は、下図の部分をクリックしコンテキストデータを選択します。

右側にグローバルと出てきますので、そちらのリロードをすると現在のON/OFFが確認できます。

