Node-REDでECHONET LiteのエアコンON/OFF操作と状態確認Getリクエストを自動送信する方法

日本発のスマートホーム通信規格「ECHONET Lite」はUDPで住宅内にある機器の操作や状態取得ができます。今回は、Node-REDからエアコンをON/OFFしたら、その後にGetリクエストを自動送信して実際の状態を確認するというフローを作成します。

ECHONET Liteのデバイスについては、「ECHONET Lite Emulator」を利用します。

フローの流れ

  • Injectノードで true/、falseを送信
  • FunctionノードでSetリクエスト作成
  • UDP送信 (Set)
  • UDP-Inノードで全受信第一線
  • Functionノードで受信パケットを分類
    • SetC後は自動でGetリクエスト送信
    • Get後は実際に解析
  • Get後形式を分析しON/OFFを表示

フローはこのような流れで作成します。。

Node-REDのフロー

[{"id":"function_create_set_packet","type":"function","z":"af2181cd6b94e0c2","name":"Setリクエスト作成","func":"// Setリクエスト作成\nconst buffer = Buffer.alloc(15);\nbuffer[0] = 0x10; buffer[1] = 0x81;\nbuffer[2] = 0x00; buffer[3] = 0x02;\nbuffer[4] = 0x05; buffer[5] = 0xFF; buffer[6] = 0x01;\nbuffer[7] = 0x01; buffer[8] = 0x30; buffer[9] = 0x01;\nbuffer[10] = 0x61;\nbuffer[11] = 0x01;\nbuffer[12] = 0x80;\nbuffer[13] = 0x01;\n\nif (msg.payload === true) {\n    buffer[14] = 0x30;\n    flow.set('lastCommand', true);\n} else {\n    buffer[14] = 0x31;\n    flow.set('lastCommand', false);\n}\n\nmsg.payload = buffer;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":280,"wires":[["udp_out_set"]]},{"id":"udp_out_set","type":"udp out","z":"af2181cd6b94e0c2","name":"UDP送信(Set)","addr":"192.168.1.14","iface":"","port":"3610","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":760,"y":280,"wires":[]},{"id":"udp_in_common","type":"udp in","z":"af2181cd6b94e0c2","name":"UDP受信(共通)","iface":"","port":"3610","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":260,"y":380,"wires":[["function_classify_response"]]},{"id":"function_classify_response","type":"function","z":"af2181cd6b94e0c2","name":"受信パケット分類","func":"// UDP-Inから受信したパケットを分類する\nconst buf = Buffer.from(msg.payload);\n\nif (buf.length < 14) {\n    return null;\n}\n\nconst esv = buf[10];\n\nif (esv === 0x72) {\n    // Get応答\n    msg.topic = \"get_response\";\n    return [msg, null];\n} else if (esv === 0x71) {\n    // SetC応答(成功時)\n    // Getリクエストを自動で発行\n    const buffer = Buffer.alloc(14);\n    buffer[0] = 0x10; buffer[1] = 0x81;\n    buffer[2] = 0x00; buffer[3] = 0x03;\n    buffer[4] = 0x05; buffer[5] = 0xFF; buffer[6] = 0x01;\n    buffer[7] = 0x01; buffer[8] = 0x30; buffer[9] = 0x01;\n    buffer[10] = 0x62;\n    buffer[11] = 0x01;\n    buffer[12] = 0x80;\n    buffer[13] = 0x00;\n\n    msg.payload = buffer;\n    return [null, msg];\n}\n\nreturn null;","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":380,"wires":[["function_parse_get_response"],["udp_out_get"]]},{"id":"udp_out_get","type":"udp out","z":"af2181cd6b94e0c2","name":"UDP送信(Get)","addr":"192.168.1.14","iface":"","port":"3610","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":760,"y":440,"wires":[]},{"id":"function_parse_get_response","type":"function","z":"af2181cd6b94e0c2","name":"Get応答解析","func":"// Get応答解析\nconst buf = Buffer.from(msg.payload);\n\nconst epc = buf[12];\nconst edt = buf[14];\n\nif (epc === 0x80) {\n    if (edt === 0x30) {\n        msg.payload = \"【状態確認】エアコンは ON です\";\n    } else if (edt === 0x31) {\n        msg.payload = \"【状態確認】エアコンは OFF です\";\n    } else {\n        msg.payload = \"【状態確認】未知の値 (0x\" + edt.toString(16).toUpperCase() + \")\";\n    }\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":360,"wires":[["debug_result"]]},{"id":"debug_result","type":"debug","z":"af2181cd6b94e0c2","name":"状態表示","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","statusVal":"","statusType":"auto","x":1010,"y":360,"wires":[]},{"id":"5611bd4b70772e2b","type":"inject","z":"af2181cd6b94e0c2","name":"ON","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":250,"y":240,"wires":[["function_create_set_packet"]]},{"id":"092626da080407d6","type":"inject","z":"af2181cd6b94e0c2","name":"OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":250,"y":300,"wires":[["function_create_set_packet"]]}]

フローの解説

1. Injectノード (ON/OFF指示)

  • true:エアコンをON
  • false:エアコンをOFF

2. Setリクエスト作成

  • ECHONET LiteのSetパケットを作成
  • その時flowコンテキストに最後のON/OFF指示を保存

3. UDP-Out (Set)

  • IPアドレス:192.168.1.14(ECHONET Lite Emulatorを動かしているPC)
  • ポート:3610

4. UDP-In (共通)

  • 全ての返信を受けるノード

5. 受信分類Function

  • ESV=0x72(Get後):Get後分岐
  • ESV=0x71(SetC後):すぐGetリクエストを送信

6. UDP-Out (Get)

  • Getリクエストを送信

7. Get後分析Function

  • EPC=0x80を分析
  • EDT=0x30:ON / 0x31:OFFで状態を分別
  • Debugノードに結果表示

実行結果

ONを押すとレスポンスが表示され

Emulator側にも反映されました。(再読込が必要です)

まとめ

Node-REDでECHONET LiteのエアコンON/OFF操作と状態確認Getリクエストを自動送信する方法をご紹介しました。

ただし、これはあくまでもNode-RED側からON/OFFの操作をしたときにレスポンスを取得する方法です。

実際のスマートホームでは、実物のリモコンを人が操作してON/OFFしたときの状態もコントローラー側で取得する必要があります。ECHONET Liteではデバイス側で動作状態(例:ON/OFF)が変わったときに、自動で通知(プッシュ)をする仕組みが用意されています。

それが、 インフォメーション送信(INF送信)と呼ばれる機能です。

次回はNode-REDでインフォメーション送信を受信する方法を紹介します。