前回の反省
- ステータス反映時にESVをチェックしていなかったためEDTがない場合(ESV0x71など)に挙動がおかしかった
ESV0x72(プロパティ値読み出し応答)0x73(プロパティ値通知)をチェック
- 設定値の確認をしていなった
tidをflowコンストラクタで設定して戻りのESV0x71で同一tidであることを確認(本来はGet0x62で確認推奨)
同一tidとなるまでwait0.2secをかけてループ(本来は20sec空ける必要あり)
- 並列処理ができないことを考慮せず
さらなる反省点・感想
最初から規格書(pdf)を読んでいればおかしな挙動はなかった。panasonic謹製アプリでもエラーとなることから無線アダプタでの処理には時間がかかる模様。
フロー図
flow.json
[{"id":"b85c21964717f67c","type":"tab","label":"sample","disabled":false,"info":"","env":[]},{"id":"107c117ed3e88b49","type":"function","z":"b85c21964717f67c","name":"Parse EL1","func":"// Parse ECHONET Lite packet\n// Assumption: OPC = 1\n\n// OUTPUT:\n// msg.elr.ip // ip address (String)\n// msg.elr.ehd // EHD (Int)\n// msg.elr.tid // TID (Int)\n// msg.elr.seoj // SEOJ ([Int:device, Int:instance])\n// msg.elr.deoj // DEOJ ([Int:device, Int:instance])\n// msg.elr.esv // ESV (Int)\n// msg.elr.opc // OPC (Int)\n// msg.elr.epc // EPC (Int)\n// msg.elr.pdc // PDC (Int)\n// msg.elr.edt // EDT ([Int]) or [](no EDT data)\n\nconst buffer = msg.payload;\nmsg.elr = null;\n\nif (buffer.length >= 14) {\n const ehd_buffer = buffer.slice(0, 2);\n const tid_buffer = buffer.slice(2, 4);\n const seoj_device_buffer = buffer.slice(4, 6);\n const seoj_instance_buffer = buffer.slice(6, 7);\n const deoj_device_buffer = buffer.slice(7, 9);\n const deoj_instance_buffer = buffer.slice(9, 10);\n const esv_buffer = buffer.slice(10, 11);\n const opc_buffer = buffer.slice(11, 12);\n const epc_buffer = buffer.slice(12, 13);\n const pdc_buffer = buffer.slice(13, 14);\n\n const ehd = ehd_buffer.readUInt16BE(0);\n const tid = tid_buffer.readUInt16BE(0);\n const seoj_device = seoj_device_buffer.readUInt16BE(0);\n const seoj_instance = seoj_instance_buffer.readUInt8(0);\n const seoj = [seoj_device, seoj_instance];\n const deoj_device = deoj_device_buffer.readUInt16BE(0);\n const deoj_instance = deoj_instance_buffer.readUInt8(0);\n const deoj = [deoj_device, deoj_instance];\n const esv = esv_buffer.readUInt8(0);\n const opc = opc_buffer.readUInt8(0);\n const epc = epc_buffer.readUInt8(0);\n const pdc = pdc_buffer.readUInt8(0);\n let edt = [];\n \n if (buffer.length >= 15) {\n const edt_buffer = buffer.slice(14);\n for (var i = 0; i < edt_buffer.length; i++) {\n edt[i] = edt_buffer.readUInt8(i);\n }\n }\n\n // ECHONET Lite header check\n if (ehd == 0x1081) {\n msg.elr = {\n \"ip\" : msg.ip,\n \"ehd\" : ehd,\n \"tid\" : tid,\n \"seoj\" : seoj,\n \"deoj\" : deoj,\n \"esv\" : esv,\n \"opc\" : opc,\n \"epc\" : epc,\n \"pdc\" : pdc,\n \"edt\" : edt\n };\n }\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":480,"wires":[["625ebf051f146439"]]},{"id":"3f9cf3c7fce15c9a","type":"udp in","z":"b85c21964717f67c","name":"EL receive","iface":"","port":"3610","ipv":"udp4","multicast":"true","group":"224.0.23.0","datatype":"buffer","x":80,"y":480,"wires":[["107c117ed3e88b49"]]},{"id":"5d2c38d0e47d2d88","type":"function","z":"b85c21964717f67c","name":"EL set","func":"// msg.els.ip_string // ip address (String)\n// msg.els.tid // TID (Int)\n// msg.els.seoj // SEOJ ([Int:device, Int:instance])\n// msg.els.deoj // DEOJ ([Int:device, Int:instance])\n// msg.els.esv // ESV (Int)\n// msg.els.epc // EPC (Int)\n// msg.els.edt_int // EDT ([Int])\n\nmsg.els = {\n \"ip\" : flow.get(\"ip\"),\n \"tid\" : flow.get(\"tid\"),\n \"seoj\" : [0x05ff,1],\n \"deoj\" : [0x0291,flow.get(\"num\")],\n \"esv\" : 0x61,\n \"epc\" : 0x80,\n \"edt\" : [msg.payload]\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":250,"y":340,"wires":[["60024e3da3add6fc","ade4ebce158594b1"]]},{"id":"60024e3da3add6fc","type":"function","z":"b85c21964717f67c","name":"Send EL1","func":"// Send ECHONET Lite packet\n// Assumption: OPC = 1\n//\n// Usage:\n// Input following data\n//\n// msg.els.ip // ip address (String)\n// msg.els.tid // TID (Int)\n// msg.els.seoj // SEOJ ([Int:device, Int:instance])\n// msg.els.deoj // DEOJ ([Int:device, Int:instance])\n// msg.els.esv // ESV (Int)\n// msg.els.epc // EPC (Int)\n// msg.els.edt // EDT ([Int])\n// // in case of no EDT data, no edt or []\n\nconst tid_buffer = Buffer.allocUnsafe(2);\nlet seoj_buffer = Buffer.allocUnsafe(3);\nconst seoj = msg.els.seoj;\nlet deoj_buffer = Buffer.allocUnsafe(3);\nconst deoj = msg.els.deoj;\nconst esv_buffer = Buffer.allocUnsafe(1);\nconst opc_buffer = Buffer.from([1]);\nconst epc_buffer = Buffer.allocUnsafe(1);\nconst pdc_buffer = Buffer.allocUnsafe(1);\nlet edt = msg.els.edt;\n\ntid_buffer.writeUInt16BE(msg.els.tid, 0);\nesv_buffer.writeUInt8(msg.els.esv, 0);\nepc_buffer.writeUInt8(msg.els.epc, 0);\n\nseoj_buffer.writeUInt16BE(seoj[0], 0);\nseoj_buffer.writeUInt8(seoj[1], 2);\ndeoj_buffer.writeUInt16BE(deoj[0], 0);\ndeoj_buffer.writeUInt8(deoj[1], 2);\n\n// edt[]からedt_bufferを作成\nif ((typeof edt) == \"undefined\") {\n edt = [];\n}\n\nconst edt_buffer = Buffer.allocUnsafe(edt.length);\nfor (var i = 0; i < edt.length; i++) {\n edt_buffer.writeUInt8(edt[i], i);\n}\n\npdc_buffer.writeUInt8(edt_buffer.length, 0);\n\n// Create ECHONET Lite packet\nconst el_buffer = Buffer.from([\n\t0x10, 0x81,\n\ttid_buffer[0], tid_buffer[1],\n\tseoj_buffer[0], seoj_buffer[1], seoj_buffer[2],\n\tdeoj_buffer[0], deoj_buffer[1], deoj_buffer[2],\n\tesv_buffer[0], opc_buffer[0], epc_buffer[0], pdc_buffer[0]]);\n\n// add EDT data\nif (edt_buffer.length !== 0) {\n msg.payload = Buffer.concat([el_buffer, edt_buffer], \n (el_buffer.length + edt_buffer.length));\n} else {\n msg.payload = el_buffer;\n}\n\nmsg.ip = msg.els.ip;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":400,"y":340,"wires":[["086e9c37aeaeb73f"]]},{"id":"086e9c37aeaeb73f","type":"udp out","z":"b85c21964717f67c","name":"","addr":"","iface":"","port":"3610","ipv":"udp4","outport":"","base64":false,"multicast":"multi","x":560,"y":340,"wires":[]},{"id":"1bcfe5e32bfb7ee8","type":"inject","z":"b85c21964717f67c","name":"init.","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":90,"y":40,"wires":[["477f97c0baea1ab2"]]},{"id":"477f97c0baea1ab2","type":"change","z":"b85c21964717f67c","name":"set const","rules":[{"t":"set","p":"tid","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"rtntid","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"ip","pt":"flow","to":"xxx.xxx.xxx.xxx","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":260,"y":40,"wires":[["38f51eccb6f2d466"]]},{"id":"a3a6770475bca34a","type":"change","z":"b85c21964717f67c","name":"tid up","rules":[{"t":"set","p":"tid","pt":"flow","to":"$flowContext(\"tid\") > 254 ? 1 :$flowContext(\"tid\")+1\t","tot":"jsonata"},{"t":"set","p":"num","pt":"flow","to":"num","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":90,"y":340,"wires":[["5d2c38d0e47d2d88"]]},{"id":"dcbb3d3bd2864920","type":"change","z":"b85c21964717f67c","name":"trigger","rules":[{"t":"set","p":"trigger","pt":"msg","to":"1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":420,"wires":[["717bdb12c53fca9f"]]},{"id":"ade4ebce158594b1","type":"delay","z":"b85c21964717f67c","name":"","pauseType":"delay","timeout":"200","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":110,"y":420,"wires":[["3e68f05414f9ae49"]]},{"id":"3e68f05414f9ae49","type":"switch","z":"b85c21964717f67c","name":"loop?","property":"tid","propertyType":"flow","rules":[{"t":"eq","v":"rtntid","vt":"flow"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":270,"y":420,"wires":[["dcbb3d3bd2864920"],["5d2c38d0e47d2d88"]]},{"id":"625ebf051f146439","type":"switch","z":"b85c21964717f67c","name":"filter light","property":"elr.seoj[0]","propertyType":"msg","rules":[{"t":"eq","v":"0x0291","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":380,"y":480,"wires":[["0f40e70fdff1d4ac"],[]]},{"id":"0f40e70fdff1d4ac","type":"switch","z":"b85c21964717f67c","name":"ESV","property":"elr.esv","propertyType":"msg","rules":[{"t":"eq","v":"0x71","vt":"num"},{"t":"eq","v":"0x72","vt":"num"},{"t":"eq","v":"0x73","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":510,"y":480,"wires":[["e9bd206124b655b2"],["eeeebc86a9fcfd46"],["eeeebc86a9fcfd46"]]},{"id":"e9bd206124b655b2","type":"change","z":"b85c21964717f67c","name":"set rtntid","rules":[{"t":"set","p":"rtntid","pt":"flow","to":"elr.tid","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":640,"y":440,"wires":[[]]},{"id":"1e174b2edd341b8c","type":"ui_switch","z":"b85c21964717f67c","name":"","label":"switch","tooltip":"","group":"f13025dc.ef0068","order":4,"width":0,"height":0,"passthru":false,"decouple":"true","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":130,"y":100,"wires":[["7d40b967aae0c187"]]},{"id":"7d40b967aae0c187","type":"change","z":"b85c21964717f67c","name":"set var","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"0x30","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"0x31","tot":"str"},{"t":"set","p":"num","pt":"msg","to":"1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":100,"wires":[["717bdb12c53fca9f"]]},{"id":"eeeebc86a9fcfd46","type":"switch","z":"b85c21964717f67c","name":"EPC","property":"elr.epc","propertyType":"msg","rules":[{"t":"eq","v":"0x80","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":630,"y":480,"wires":[["f942085872416cdb"]]},{"id":"f942085872416cdb","type":"change","z":"b85c21964717f67c","name":"set sw","rules":[{"t":"set","p":"payload","pt":"msg","to":"elr.edt[0]","tot":"msg"},{"t":"change","p":"payload","pt":"msg","from":"0x30","fromt":"num","to":"true","tot":"bool"},{"t":"change","p":"payload","pt":"msg","from":"0x31","fromt":"num","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":70,"y":560,"wires":[["0c3fafda21ad5275"]]},{"id":"0c3fafda21ad5275","type":"switch","z":"b85c21964717f67c","name":"sw sort","property":"elr.seoj[1]","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"2","vt":"num"},{"t":"eq","v":"3","vt":"num"},{"t":"eq","v":"4","vt":"num"}],"checkall":"true","repair":false,"outputs":4,"x":220,"y":560,"wires":[["1e174b2edd341b8c"],["355136b001189a5e"],["95feeb20a4b43e0c"],["f6ae3629061dc573"]]},{"id":"717bdb12c53fca9f","type":"simple-queue","z":"b85c21964717f67c","name":"","firstMessageBypass":true,"bypassInterval":"0","x":460,"y":180,"wires":[["a3a6770475bca34a"]]},{"id":"355136b001189a5e","type":"ui_switch","z":"b85c21964717f67c","name":"","label":"switch","tooltip":"","group":"f13025dc.ef0068","order":4,"width":0,"height":0,"passthru":false,"decouple":"true","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":130,"y":160,"wires":[["47fbee85f4135747"]]},{"id":"47fbee85f4135747","type":"change","z":"b85c21964717f67c","name":"set var","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"0x30","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"0x31","tot":"str"},{"t":"set","p":"num","pt":"msg","to":"2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":160,"wires":[["717bdb12c53fca9f"]]},{"id":"38f51eccb6f2d466","type":"function","z":"b85c21964717f67c","name":"status","func":"// msg.els.ip_string // ip address (String)\n// msg.els.tid // TID (Int)\n// msg.els.seoj // SEOJ ([Int:device, Int:instance])\n// msg.els.deoj // DEOJ ([Int:device, Int:instance])\n// msg.els.esv // ESV (Int)\n// msg.els.epc // EPC (Int)\n// msg.els.edt_int // EDT ([Int])\n\nmsg.els = {\n \"ip\" : flow.get(\"ip\"),\n \"tid\" : 0,\n \"seoj\" : [0x05ff,1],\n \"deoj\" : [0x0291,0],\n \"esv\" : 0x62,\n \"epc\" : 0x80,\n \"edt\" : [0x30]\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":40,"wires":[["60024e3da3add6fc"]]},{"id":"95feeb20a4b43e0c","type":"ui_switch","z":"b85c21964717f67c","name":"","label":"switch","tooltip":"","group":"f13025dc.ef0068","order":4,"width":0,"height":0,"passthru":false,"decouple":"true","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":130,"y":220,"wires":[["b94d8e1d738f9cb9"]]},{"id":"b94d8e1d738f9cb9","type":"change","z":"b85c21964717f67c","name":"set var","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"0x30","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"0x31","tot":"str"},{"t":"set","p":"num","pt":"msg","to":"3","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":220,"wires":[["717bdb12c53fca9f"]]},{"id":"f6ae3629061dc573","type":"ui_switch","z":"b85c21964717f67c","name":"","label":"switch","tooltip":"","group":"f13025dc.ef0068","order":4,"width":0,"height":0,"passthru":false,"decouple":"true","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":130,"y":280,"wires":[["c0f226aa7e24935c"]]},{"id":"c0f226aa7e24935c","type":"change","z":"b85c21964717f67c","name":"set var","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"0x30","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"0x31","tot":"str"},{"t":"set","p":"num","pt":"msg","to":"4","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":280,"wires":[["717bdb12c53fca9f"]]},{"id":"f13025dc.ef0068","type":"ui_group","name":"buttons","tab":"67ec7f3f.c65bb8","order":6,"disp":false,"width":1,"collapse":false},{"id":"67ec7f3f.c65bb8","type":"ui_tab","name":"ホーム","icon":"dashboard","disabled":false,"hidden":false}]