Integrating KNX+ZWave, v0.01

A hack-ish but fully functional integration of KNX (http://www.knx.org) and ZWave (http://www.z-wavealliance.org/). Uses two new Node-Red nodes for talking to KNX and Zwave, namely:

The integration aims to extend an existing KNX installation with ZWave wireless devices. It's bidirectional so that I can control:

  • ZWave devices from KNX commands sent to a specific groupaddress (eg. 2/2/81 => COMMAND_CLASS_SWITCHBINARY, node 8, instance 1)
  • KNX status groupaddresses sent as a result of a manual ZWave operation (eg. updated switch status is written to 2/2/88 after successful ZWave transmission)
  • It can also respond to KNX Read requests.
[{"id":"591091fd.a6ef7","type":"zwave-controller","port":"/dev/ttyUSB0","driverattempts":"3","pollinterval":"500"},{"id":"d3959f76.600708","type":"eibd-controller","host":"10.12.23.90","port":"6720"},{"id":"ac7ba191.508628","type":"eibd-out","name":"KNX OUT","controller":"d3959f76.600708","x":534,"y":108,"z":"60af26ff.5ae918","wires":[]},{"id":"36991d8e.86799a","type":"inject","name":"2/2/82 ON","topic":"write","payload":"{\"dstgad\":\"2/2/82\", \"dpt\":\"1\", \"value\":1 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":86,"y":88,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"54166d24.0ba284","type":"inject","name":"2/2/51 dimmer at 50%","topic":"write","payload":"{\"dstgad\":\"2/2/51\", \"dpt\":\"5\", \"value\":50 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":251,"y":42,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"3c7715f7.54cad2","type":"eibd-in","name":"KNX IN","controller":"d3959f76.600708","x":84,"y":221,"z":"60af26ff.5ae918","wires":[["cb8d7362.169a08","c80d603d.37f2a","1246164a.a6fcda"]]},{"id":"1246164a.a6fcda","type":"debug","name":"","active":true,"console":"false","complete":"true","x":579.0000305175781,"y":211,"z":"60af26ff.5ae918","wires":[]},{"id":"f925f22.baf9f9","type":"zwave-in","name":"zwave IN","controller":"591091fd.a6ef7","x":98,"y":258,"z":"60af26ff.5ae918","wires":[["1246164a.a6fcda","471cb4e5.ae6e44"]]},{"id":"c5b8e76d.d9dc58","type":"zwave-out","name":"zwave OUT","controller":"591091fd.a6ef7","x":530,"y":384,"z":"60af26ff.5ae918","wires":[]},{"id":"c66e1e1f.9e7248","type":"inject","name":"switch ON ZWave node 9","topic":"switchOn","payload":"{\"nodeid\":9}","payloadType":"string","repeat":"","crontab":"","once":false,"x":168,"y":483,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"3ec24ea6.af858a","type":"inject","name":"switch OFF ZWave node 9","topic":"switchOff","payload":"{\"nodeid\":9}","payloadType":"string","repeat":"","crontab":"","once":false,"x":174,"y":514,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"1c03f4f8.8778d3","type":"inject","name":"switch ON KOUZINA 1","topic":"setValue","payload":"{\"nodeid\":8, \"instance\":1, \"value\":1}","payloadType":"string","repeat":"","crontab":"","once":false,"x":135,"y":324,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"2b4beed9.46c012","type":"inject","name":"switch OFF KOUZINA 1","topic":"setValue","payload":"{\"nodeid\":8, \"instance\":1, \"value\":0}","payloadType":"string","repeat":"","crontab":"","once":false,"x":135,"y":356,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"8dd4a735.59de2","type":"inject","name":"switch ON KOUZINA 2","topic":"setValue","payload":"{\"nodeid\":8, \"instance\":2, \"value\":1}","payloadType":"string","repeat":"","crontab":"","once":false,"x":143,"y":409,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"7b93a8a1.f925a","type":"inject","name":"switch OFF KOUZINA 2","topic":"setValue","payload":"{\"nodeid\":8, \"instance\":2, \"value\":0}","payloadType":"string","repeat":"","crontab":"","once":false,"x":155,"y":439,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"5fa83e7b.24c6f8","type":"inject","name":"zwave dimmer setLevel 0","topic":"setLevel","payload":"{\"nodeid\":5, \"value\":0}","payloadType":"string","repeat":"","crontab":"","once":false,"x":359,"y":468,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"eee7bafc.cc1e28","type":"inject","name":"zwave dimmer at 50% (setValue)","topic":"setValue","payload":"{\"nodeid\":5, \"cmdclass\":38, \"value\":50}","payloadType":"string","repeat":"","crontab":"","once":false,"x":392,"y":489,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"cb8d7362.169a08","type":"function","name":"knx to zwave","func":"var map = {\n\t'2/2/50' : {\"nodeid\": 5, \"value\": msg.payload.value},\n\t'2/2/51' : {\"nodeid\": 5, \"cmdclass\": 38, \"value\": msg.payload.value},\n\t'2/2/81':  {\"nodeid\": 8, \"instance\":1, \"value\": msg.payload.value},\n\t'2/2/82':  {\"nodeid\": 8, \"instance\":2, \"value\": msg.payload.value},\n\t'2/2/90' : {\"nodeid\": 9, \"value\": msg.payload.value}\n}\nswitch (msg.topic) {\n// or forward them to KNX\ncase \"knx: write\":\n\tif (msg.payload.dstgad in map) {\n\t\tvar response = {\"topic\": \"setValue\", \"payload\": map[msg.payload.dstgad] };\n\t\tconsole.log('== knx to zwave: %j', response);\n\t\treturn response;\n\t}\n}\nreturn;\n","outputs":"1","x":305,"y":260,"z":"60af26ff.5ae918","wires":[["1246164a.a6fcda","c5b8e76d.d9dc58"]]},{"id":"d7006497.8a4ed8","type":"inject","name":"2/2/82 OFF","topic":"write","payload":"{\"dstgad\":\"2/2/82\", \"dpt\":\"1\", \"value\":0 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":128,"y":111,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"17605e70.ac36aa","type":"inject","name":"2/2/90 OFF","topic":"write","payload":"{\"dstgad\":\"2/2/90\", \"dpt\":\"1\", \"value\":0 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":171,"y":174,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"60a8a71d.f57f6","type":"inject","name":"2/2/90 ON","topic":"write","payload":"{\"dstgad\":\"2/2/90\", \"dpt\":\"1\", \"value\":1 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":145,"y":149,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"471cb4e5.ae6e44","type":"function","name":"zwave to knx","func":"var map = {\n//zwnode, cmdClass, index, instance\n\t5: {\t\t37: { 0: { 1: \n\t\t\t\t\t{\"dstgad\": '2/2/58', \"dpt\":1, \"value\": msg.payload.currState},\n\t\t}}, \t38: { 0: { 1: \n\t\t\t\t\t{\"dstgad\": '2/2/59', \"dpt\":1, \"value\": msg.payload.currState},\n\t}}}, 8: {\t37: { 0: { \n\t\t\t\t1: {\"dstgad\": '2/2/88', \"dpt\":1, \"value\": msg.payload.currState},\n\t\t\t\t2: {\"dstgad\": '2/2/89', \"dpt\":1, \"value\": msg.payload.currState},\n\t}}}, 9: {\t37: { 0: { 1: \n\t\t\t{\"dstgad\": '2/2/99', \"dpt\":1, \"value\": msg.payload.currState},\n\t}}}\n}\nswitch (msg.topic) {\ncase \"zwave: value changed\":\n\tif ((msg.payload !== null) &&\n\t\t(msg.payload.nodeid in map) &&\n\t\t(msg.payload.cmdclass in map[msg.payload.nodeid]) &&\n\t\t(msg.payload.cmdidx in map[msg.payload.nodeid][msg.payload.cmdclass]) &&\n\t\t(msg.payload.instance in map[msg.payload.nodeid][msg.payload.cmdclass][msg.payload.cmdidx])) \n\t{\n\t\tconsole.log('=== zwave to knx: %j', msg);\n\t\treturn({\n\t\t\t\"topic\": \"write\", \n\t\t\t\"payload\": map[msg.payload.nodeid][msg.payload.cmdclass][msg.payload.cmdidx][msg.payload.instance] \n\t\t});\n\t}\n}","outputs":1,"x":330,"y":299,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"3023c218.e8815e","type":"inject","name":"zwave node 9 OFF (setValue)","topic":"setValue","payload":"{\"nodeid\":9, \"value\":0}","payloadType":"string","repeat":"","crontab":"","once":false,"x":187,"y":546,"z":"60af26ff.5ae918","wires":[["c5b8e76d.d9dc58"]]},{"id":"a0ec8a75.fc97f8","type":"inject","name":"2/2/51 dimmer at 0%","topic":"write","payload":"{\"dstgad\":\"2/2/51\", \"dpt\":\"5\", \"value\":0 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":289,"y":67,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"866ffe6d.454c68","type":"inject","name":"2/2/50 Dimmer ON","topic":"write","payload":"{\"dstgad\":\"2/2/50\", \"dpt\":\"1\", \"value\":1 }","payloadType":"string","repeat":"","crontab":"","once":false,"x":97,"y":22,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]},{"id":"c80d603d.37f2a","type":"function","name":"knx groupcache","func":"if (!context.cache) context.cache = {};\n//\nswitch (msg.topic) {\n// cache KNX group writes\ncase \"knx: write\":\n\tcontext.cache[msg.payload.dstgad] = msg.payload.value;\n\tbreak;\n// respond to KNX read requests\ncase \"knx: read\":\n\tif (msg.payload.dstgad in context.cache) {\n\t\tvar cachedval = context.cache[msg.payload.dstgad];\n\t\tvar response = {\n\t\t\t\"topic\": \"knx: response\", \n\t\t\t\"payload\": {\n\t\t\t\t\"dstgad\": msg.payload.dstgad,\n\t\t\t\t\"dpt\": msg.payload.dpt,\n\t\t\t\t\"value\": cachedval}\n\t\t\t}; \n\t\tconsole.log('== knx groupcache response: %j', response);\n\t\treturn response;\n\t}\n}\nreturn null;","outputs":1,"x":318.8888854980469,"y":206.88888549804688,"z":"60af26ff.5ae918","wires":[["ac7ba191.508628"]]}]
ekarak

Flow Info

created 2 years, 8 months ago

Node Types

Core
  • debug (x1)
  • function (x3)
  • inject (x16)
Other

Tags

  • knx
  • zwave
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option