Z-Wave Control Panel with node-red-dashboard

Custom implementation of Open-Zwave-Control-Panel (https://github.com/OpenZWave/open-zwave-control-panel) using node-contrib-openzwave (https://github.com/OpenZWave/node-red-contrib-openzwave) and node-red-dashboard.

Buy Me A Coffee

[{"id":"c8fe91b8.daa3","type":"tab","label":"Flow 2"},{"id":"5b1e3f38.50856","type":"zwave-in","z":"c8fe91b8.daa3","name":"read_zwave","controller":"93bf10ea.1c4c3","x":194,"y":180,"wires":[["ee5ce307.9c417","c46bb234.40dcc"]]},{"id":"c46bb234.40dcc","type":"debug","z":"c8fe91b8.daa3","name":"","active":false,"console":"false","complete":"false","x":416,"y":74,"wires":[]},{"id":"ee5ce307.9c417","type":"switch","z":"c8fe91b8.daa3","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"zwave: driver ready","vt":"str"},{"t":"eq","v":"zwave: node added","vt":"str"},{"t":"eq","v":"zwave: value added","vt":"str"},{"t":"eq","v":"zwave: notification","vt":"str"},{"t":"eq","v":"zwave: value changed","vt":"str"},{"t":"eq","v":"zwave: node ready","vt":"str"},{"t":"eq","v":"zwave: scan complete","vt":"str"}],"checkall":"true","outputs":7,"x":455,"y":180,"wires":[["2bbed007.b1598"],["f439bf74.64e93"],["5dd0df27.0fddb"],["c1c7ad30.1fe2"],["1000fdaf.d177e2"],["592813f3.15708c"],["b9cbd4d9.694eb8"]]},{"id":"2bbed007.b1598","type":"function","z":"c8fe91b8.daa3","name":"init nodes","func":"flow.set(\"nodes\", []);\nflow.set(\"scanComplete\", false);\n\n","outputs":"0","noerr":0,"x":698,"y":77,"wires":[]},{"id":"f439bf74.64e93","type":"function","z":"c8fe91b8.daa3","name":"add node","func":"var nodes = flow.get(\"nodes\");\nmsg.payload.values = [];\nmsg.payload.ready = false;\n\nnodes.push(msg.payload);\n\n","outputs":"0","noerr":0,"x":697,"y":111,"wires":[]},{"id":"5dd0df27.0fddb","type":"function","z":"c8fe91b8.daa3","name":"add value to node","func":"var nodes = flow.get(\"nodes\");\n\nvar n = nodes.find(n => n.nodeid == msg.payload.nodeid);\n\nvar value = msg.payload.value;\n\nn.values.push(value);\n\n//optionally send enablepool \nif(value.label == \"Temperature\"){\n    node.send({topic: \"enablePool\", payload: {\"args\": [value.nodeid, value.cmdclass]}});\n}\n\n\n","outputs":"1","noerr":0,"x":727,"y":147,"wires":[[]]},{"id":"c1c7ad30.1fe2","type":"function","z":"c8fe91b8.daa3","name":"notification","func":"var nodes = flow.get(\"nodes\");\nvar nodeid = msg.payload.nodeid;\nvar n = nodes.find(n => n.nodeid == nodeid);\n\nswitch (msg.payload.notification) {\n    case 0:\n      console.log('node%d: message complete', nodeid);\n      break;\n    case 1:\n      console.log('node%d: timeout', nodeid);\n      break;\n    case 2:\n      console.log('node%d: nop', nodeid);\n      break;\n    case 3:\n      console.log('node%d: node awake', nodeid);\n      break;\n    case 4:\n      console.log('node%d: node sleep', nodeid);\n      break;\n    case 5:\n      console.log('node%d: node dead', nodeid);\n      n.ready = false;\n      node.send({topic: \"node_status\", nodeid: nodeid, payload: false});\n      break;\n    case 6:\n      console.log('node%d: node alive', nodeid);\n      n.ready = true;\n      node.send({topic: \"node_status\", nodeid: nodeid, payload: true});\n      break;\n }\n","outputs":1,"noerr":0,"x":705,"y":186,"wires":[[]]},{"id":"1000fdaf.d177e2","type":"function","z":"c8fe91b8.daa3","name":"value changed","func":"var nodes = flow.get(\"nodes\");\n\nvar node = nodes.find(n => n.nodeid == msg.payload.nodeid);\n\nvar value = node.values.find(v => v.value_id == msg.payload.value.value_id);\n\nvalue.value = msg.payload.value.value;\n\n\nmsg.payload = value;\nmsg.topic = \"value_changed\";\n\nreturn msg;","outputs":"1","noerr":0,"x":713,"y":227,"wires":[["3c7afb39.71dd74"]]},{"id":"592813f3.15708c","type":"function","z":"c8fe91b8.daa3","name":"node ready","func":"var nodes = flow.get(\"nodes\");\n\nvar n = nodes.find(n => n.nodeid == msg.payload.nodeid);\n\nn.ready = true;\nn.type = msg.payload.nodeinfo.type;\n\n/* NODEINFO\n{\"manufacturer\":\"Qubino\",\"manufacturerid\":\"0x0159\",\"product\":\"ZMNHKDx Flush Heat and Cool thermostat\",\"producttype\":\"0x0005\",\"productid\":\"0x0052\",\"type\":\"Thermostat HVAC\",\"name\":\"\",\"loc\":\"\"}\n*/","outputs":"0","noerr":0,"x":705,"y":266,"wires":[]},{"id":"b9cbd4d9.694eb8","type":"function","z":"c8fe91b8.daa3","name":"scan complete","func":"var nodes = flow.get(\"nodes\");\n\nflow.set(\"scanComplete\", true);\n\nreturn [{payload:{}, topic: \"writeConfig\"}, {payload: nodes, topic: \"init\"}];","outputs":"2","noerr":0,"x":714,"y":304,"wires":[[],[]]},{"id":"cd817b4e.3f49b8","type":"link in","z":"c8fe91b8.daa3","name":"zwaveWrite","links":["59251ba3.b3c2b4","bea6132.04aacf","177b2fe1.737a1"],"x":975,"y":480,"wires":[["47d342b5.7563cc"]]},{"id":"47d342b5.7563cc","type":"zwave-out","z":"c8fe91b8.daa3","name":"write","controller":"93bf10ea.1c4c3","x":1090,"y":480,"wires":[[]]},{"id":"d2183a6d.1b43e8","type":"ui_dropdown","z":"c8fe91b8.daa3","name":"","label":"Nodes","place":"Select a node","group":"91eff83b.4842a8","order":0,"width":0,"height":0,"passthru":false,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"","x":340,"y":480,"wires":[["84c3d05.479453"]]},{"id":"59fc0fa2.398dc","type":"function","z":"c8fe91b8.daa3","name":"parse options","func":"var nodes = msg.payload;\nvar options = [];\n\nfor(var i=0;i<nodes.length; i++){\n    var n = nodes[i];\n    var tmp = {};\n    var title = n.nodeid +\": \"+n.type;\n    tmp[title] = n.nodeid;\n    options.push(tmp);\n}\n\nmsg.options = options;\n\nreturn msg;","outputs":1,"noerr":0,"x":160,"y":480,"wires":[["d2183a6d.1b43e8"]]},{"id":"84c3d05.479453","type":"function","z":"c8fe91b8.daa3","name":"","func":"var n = flow.get(\"nodes\").find(n => n.nodeid == msg.payload);\n\nmsg.payload = n.values;\n\nmsg.topic = \"init\";\n\nreturn msg;","outputs":1,"noerr":0,"x":485,"y":480,"wires":[["a9ba8c06.0593c"]]},{"id":"a9ba8c06.0593c","type":"ui_template","z":"c8fe91b8.daa3","group":"d8a503ba.8c0ad","name":"config","order":0,"width":"20","height":"20","format":"<style>\nmd-tooltip .md-content {\n    height: auto !important;\n    max-width: 200px !important;\n    font-size: 13px !important;\n}\n\nmd-tooltip {\n    height: auto !important;\n    max-width: 200px !important;\n    font-size: 13px !important;\n    overflow: visible !important;\n    white-space: normal !important;\n}\n\nmd-tooltip ._md-content {\n    height: auto !important;\n    max-width: 200px !important;\n    font-size: 13px !important;\n}\n</style>\n\n<div ng-repeat=\"v in values\">\n    <label>\n        {{v.label}}\n    <md-tooltip ng-if=\"v.help\" md-direction=\"right\">{{v.help}}</md-tooltip>\n    <select ng-if=\"v.values\" id=\"{{v.value_id}}\" ng-model=\"v.value\" ng-change=\"updateValue(v)\" ng-options=\"value as value for (key , value) in v.values\">\n    </select>\n    <div ng-if=\"!v.values\">\n        <input type=\"text\" id=\"{{v.value_id}}\" ng-model=\"v.value\" ng-disabled=\"v.read_only\">\n        <button ng-if=\"!v.read_only\" ng-click=\"updateValue(v)\">Submit</button>\n    </div>\n    </label>\n</div>\n\n<script>\n(function(scope) {\n    \n scope.values = [];\n scope.send({topic:\"load\"});\n \n scope.updateValue = function(v){\n    var newValue = $('#'+v.value_id).val();\n    if(v.values) newValue = newValue.split(':')[1];\n    var cmd = {};\n    cmd.nodeid = v.node_id;\n    cmd.cmdclass = v.class_id;\n    cmd.instance = v.instance;\n    cmd.cmdidx = v.index;\n    cmd.value = newValue;\n    v.value = \"\"; //to check updating\n    scope.send({payload: cmd, topic: \"setValue\"});\n }\n    \n scope.$watch('msg', function (msg) { \n    if(msg){\n        switch(msg.topic){\n            case \"init\":\n                if(scope.values.length == 0)\n                    scope.values = msg.payload;\n                break;\n            case \"value_changed\":\n                var value = scope.values.find(n => n.value_id == msg.payload.value_id);\n                if(value)\n                    value.value = msg.payload.value;\n                break;\n        }\n    }\n }); \n\n})(scope);\n\n\n</script>\n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":625,"y":480,"wires":[["30212724.e08828"]]},{"id":"30212724.e08828","type":"switch","z":"c8fe91b8.daa3","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"setValue","vt":"str"},{"t":"eq","v":"load","vt":"str"}],"checkall":"true","outputs":2,"x":767,"y":480,"wires":[["59251ba3.b3c2b4"],["85f1bb2a.ed8278"]]},{"id":"59251ba3.b3c2b4","type":"link out","z":"c8fe91b8.daa3","name":"writeConfig","links":["cd817b4e.3f49b8"],"x":876,"y":480,"wires":[]},{"id":"a7c360ff.c8e3","type":"link in","z":"c8fe91b8.daa3","name":"configs","links":["3c7afb39.71dd74"],"x":565,"y":420,"wires":[["a9ba8c06.0593c"]]},{"id":"85f1bb2a.ed8278","type":"change","z":"c8fe91b8.daa3","name":"load","rules":[{"t":"set","p":"payload","pt":"msg","to":"nodes","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":560,"wires":[["59fc0fa2.398dc"]]},{"id":"3c7afb39.71dd74","type":"link out","z":"c8fe91b8.daa3","name":"value_changed","links":["a7c360ff.c8e3"],"x":857,"y":227,"wires":[]},{"id":"185c5e39.6f0d12","type":"inject","z":"c8fe91b8.daa3","name":"","topic":"","payload":"nodes","payloadType":"flow","repeat":"","crontab":"","once":false,"x":120,"y":280,"wires":[["589071d.12e7d9"]]},{"id":"589071d.12e7d9","type":"debug","z":"c8fe91b8.daa3","name":"","active":true,"console":"false","complete":"false","x":305,"y":280,"wires":[]},{"id":"8afcb2c1.c6946","type":"inject","z":"c8fe91b8.daa3","name":"healNetwork","topic":"healNetwork","payload":"{}","payloadType":"json","repeat":"","crontab":"","once":false,"x":132,"y":327,"wires":[["bea6132.04aacf"]]},{"id":"bea6132.04aacf","type":"link out","z":"c8fe91b8.daa3","name":"healNetwork","links":["cd817b4e.3f49b8"],"x":282,"y":327,"wires":[]},{"id":"171a9cd4.bb6a53","type":"inject","z":"c8fe91b8.daa3","name":"softReset","topic":"softReset","payload":"{}","payloadType":"json","repeat":"","crontab":"","once":false,"x":120,"y":371,"wires":[["177b2fe1.737a1"]]},{"id":"177b2fe1.737a1","type":"link out","z":"c8fe91b8.daa3","name":"softReset","links":["cd817b4e.3f49b8"],"x":281,"y":371,"wires":[]},{"id":"93bf10ea.1c4c3","type":"zwave-controller","z":"","port":"/dev/ttyACM0","driverattempts":"3","pollinterval":"10000","allowunreadyupdates":false,"logging":"full"},{"id":"91eff83b.4842a8","type":"ui_group","z":"","name":"Seleziona nodo","tab":"f990693c.63b0e8","disp":true,"width":"6"},{"id":"d8a503ba.8c0ad","type":"ui_group","z":"","name":"Config","tab":"f990693c.63b0e8","disp":true,"width":"20"},{"id":"f990693c.63b0e8","type":"ui_tab","z":"","name":"Configurazione","icon":"dashboard"}]

Flow Info

Created 6 years, 11 months ago
Updated 3 years, 11 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • change (x1)
  • debug (x2)
  • function (x9)
  • inject (x3)
  • link in (x2)
  • link out (x4)
  • switch (x2)
Other
  • tab (x1)
  • ui_dropdown (x1)
  • ui_group (x2)
  • ui_tab (x1)
  • ui_template (x1)
  • zwave-controller (x1)
  • zwave-in (x1)
  • zwave-out (x1)

Tags

  • z-wave
  • openzwave
  • openzwaveshared
  • dashboard
  • ui-template
  • roberts-lando
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option