Advanced Garage Door setup in NRCHKB

Based on #33. Using Sonoff-Tasmota and mqtt in real case: NodeMCU with two magnetic sensors (to check open/close position) and one relay (to control Garage door). In this case relay should blink (Power 3 in sonoff-tasmota) once to send signal to the door, please check this before running IRL!

See more at https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki/Garage-Door

[{"id":"69226b8c.22ab04","type":"homekit-service","z":"3e0d11cf.29e996","isParent":true,"bridge":"56f83ee1.f0bbd","parentService":"","name":"Ptath","serviceName":"GarageDoorOpener","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{}","x":890,"y":1000,"wires":[["81e26608.9dcf1"]]},{"id":"7ba4d5eb.9d83ec","type":"mqtt in","z":"3e0d11cf.29e996","name":"TELE Sensors","topic":"tele/garage/SENSOR","qos":"1","datatype":"json","broker":"8de2bd93.86c898","x":210,"y":1060,"wires":[["564864bb.b1601c","1a3938a1.19889f"]]},{"id":"15ff5e5a.1ac742","type":"mqtt out","z":"3e0d11cf.29e996","name":"cmnd/garage/Power 3","topic":"cmnd/garage/Power","qos":"1","retain":"","broker":"8de2bd93.86c898","x":1300,"y":960,"wires":[]},{"id":"81e26608.9dcf1","type":"function","z":"3e0d11cf.29e996","name":"Main Logic","func":"if (msg.hap !== undefined && msg.hap.context !== undefined) {\n    var GarageDoor = global.get(\"GarageDoor\");\n    var command;\n    \n    if (msg.payload.TargetDoorState === 1) {\n        if (GarageDoor.CurrentState === \"OPENED\") {\n            // Normal close command\n            if (GarageDoor.Obstruction !== \"TRUE\") {\n                // Close if no obstruction\n                command = {\"payload\": \"3\"};\n                node.warn (\"CLOSING...\");\n                GarageDoor.CurrentState = \"CLOSING\";\n            } else {\n                // Do not close if obstruction detected\n                node.warn (\"Obstruction! Clear the door area!\");\n                command = null;\n            }\n        } else if (GarageDoor.CurrentState === \"OPENING\") {\n            // Stop door while opening\n            command = {\"payload\": \"3\"};\n            node.warn (\"STOPPING...\");\n            GarageDoor.LastState = \"STOPPED\";\n            GarageDoor.CurrentState = \"STOPPED\";\n        } else if (GarageDoor.CurrentState === \"STOPPED\") {\n            // Restart door from stopped\n            if (GarageDoor.Obstruction !== \"TRUE\") {\n                // Close if no obstruction\n                command = {\"payload\": \"3\"};\n                node.warn (\"CLOSING...\");\n                GarageDoor.LastState = \"OPENED\"\n                GarageDoor.CurrentState = \"CLOSING\";\n            } else {\n                // Do not close if obstruction detected\n                node.warn (\"Obstruction! Clear the door area!\");\n                command = null;\n            }\n        }\n    } else if (msg.payload.TargetDoorState === 0) {\n        if (GarageDoor.CurrentState === \"CLOSED\") {\n            // Normal open command\n            command = {\"payload\": \"3\"};\n            node.warn (\"OPENING...\");\n            // GarageDoor.LastState = \"CLOSED\";\n            GarageDoor.CurrentState = \"OPENING\";\n        } else if (GarageDoor.CurrentState === \"CLOSING\") {\n            // Stop door while closing\n            command = {\"payload\": \"3\"};\n            node.warn (\"STOPPING...\");\n            GarageDoor.LastState = \"STOPPED\";\n            GarageDoor.CurrentState = \"STOPPED\";\n        } else if (GarageDoor.CurrentState === \"STOPPED\") {\n            // Restart door from stopped, assume it's going to close.\n            if (GarageDoor.Obstruction !== \"TRUE\") {\n                // Close if no obstruction\n                command = {\"payload\": \"3\"};\n                node.warn (\"CLOSING...\");\n                GarageDoor.LastState = \"OPENED\"\n                GarageDoor.CurrentState = \"CLOSING\";\n            } else {\n                // Do not close if obstruction detected\n                node.warn (\"Obstruction! Clear the door area!\");\n                command = null;\n            }\n        }\n    }\n    return [command, {\"payload\": GarageDoor.CurrentState}]\n}","outputs":2,"noerr":0,"x":1070,"y":1000,"wires":[["15ff5e5a.1ac742"],["76c85a60.bd0004"]]},{"id":"564864bb.b1601c","type":"function","z":"3e0d11cf.29e996","name":"State Handler","func":"var GarageDoor = global.get(\"GarageDoor\") || {}; // load \"GarageDoor\" or set to empty\n\nif (msg.payload.Switch1 == \"ON\" && msg.payload.Switch2 == \"OFF\") {\n    // The door is fully opened\n    GarageDoor.LastState = \"OPENED\";\n    GarageDoor.CurrentState = \"OPENED\";\n}\n\nif (msg.payload.Switch1 == \"OFF\" && msg.payload.Switch2 == \"ON\") {\n    // The door is fully closed\n    GarageDoor.LastState = \"CLOSED\";\n    GarageDoor.CurrentState = \"CLOSED\";\n}\n\nif (msg.payload.Switch1 == \"OFF\" && msg.payload.Switch2 == \"OFF\") {\n    // The door is in the middle\n    if (GarageDoor.LastState == \"OPENED\") GarageDoor.CurrentState = \"CLOSING\";\n    if (GarageDoor.LastState == \"CLOSED\") GarageDoor.CurrentState = \"OPENING\";\n    if (GarageDoor.LastState == \"STOPPED\") GarageDoor.CurrentState = \"STOPPED\";\n}\n\nvar moving = false;\nif (GarageDoor.CurrentState == \"OPENING\" || GarageDoor.CurrentState == \"CLOSING\") moving = true;\n\nglobal.set(\"GarageDoor\", GarageDoor);\n\nif (moving){\n    return [{\"payload\": GarageDoor.CurrentState}, {\"payload\": 1}]\n} else {\n    return [{\"payload\": GarageDoor.CurrentState}, {\"payload\": \"RESET\"}]\n}\n","outputs":2,"noerr":0,"x":500,"y":1060,"wires":[["fb761eae.a5ef8"],["d1438336.ad7238"]]},{"id":"d1438336.ad7238","type":"trigger","z":"3e0d11cf.29e996","op1":"","op2":"","op1type":"nul","op2type":"date","duration":"30","extend":false,"units":"s","reset":"RESET","bytopic":"all","name":"Trigger","x":730,"y":1220,"wires":[["97dd7cf5.c6075"]]},{"id":"97dd7cf5.c6075","type":"function","z":"3e0d11cf.29e996","name":"Set stopped","func":"var GarageDoor = global.get(\"GarageDoor\") || {};\nGarageDoor.CurrentState = \"STOPPED\";\nGarageDoor.LastState = \"STOPPED\";\nglobal.set(\"GarageDoor\", GarageDoor);","outputs":0,"noerr":0,"x":910,"y":1220,"wires":[]},{"id":"81d3c123.834598","type":"inject","z":"3e0d11cf.29e996","name":"Neither","topic":"","payload":"{\"Switch1\":\"OFF\",\"Switch2\":\"OFF\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":840,"wires":[["c18468e.fdde518"]]},{"id":"ef6c6ca4.618ae","type":"inject","z":"3e0d11cf.29e996","name":"Opened","topic":"","payload":"{\"Switch1\":\"ON\",\"Switch2\":\"OFF\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":880,"wires":[["c18468e.fdde518"]]},{"id":"1ed91362.10f605","type":"inject","z":"3e0d11cf.29e996","name":"Closed","topic":"","payload":"{\"Switch1\":\"OFF\",\"Switch2\":\"ON\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":920,"wires":[["c18468e.fdde518"]]},{"id":"fb761eae.a5ef8","type":"function","z":"3e0d11cf.29e996","name":"To HomeKit","func":"var GarageDoor = global.get(\"GarageDoor\");\nvar output = {};\n\nif (GarageDoor.CurrentState == \"OPENED\") {\n    output = {\n        \"payload\": {\n            \"TargetDoorState\": 0,\n            \"CurrentDoorState\": 0\n        }\n    }\n}\nelse if (GarageDoor.CurrentState == \"CLOSED\") {\n    output = {\n        \"payload\": {\n            \"TargetDoorState\": 1,\n            \"CurrentDoorState\": 1\n        }\n    }\n}\nelse if (GarageDoor.CurrentState == \"OPENING\") {\n    output = {\n        \"payload\": {\n            \"TargetDoorState\": 0,\n            \"CurrentDoorState\": 3\n        }\n    }\n}\nelse if (GarageDoor.CurrentState == \"CLOSING\") {\n    output = {\n        \"payload\": {\n            \"TargetDoorState\": 1,\n            \"CurrentDoorState\": 2\n        }\n    }\n}\nelse if (GarageDoor.CurrentState == \"STOPPED\") {\n    output = {\n        \"payload\": {\n            \"TargetDoorState\": 0,\n            \"CurrentDoorState\": 4\n        }\n    }\n}\n\nreturn output;","outputs":1,"noerr":0,"x":710,"y":1020,"wires":[["69226b8c.22ab04"]]},{"id":"c18468e.fdde518","type":"mqtt out","z":"3e0d11cf.29e996","name":"Simulator","topic":"tele/garage/SENSOR","qos":"1","retain":"","broker":"8de2bd93.86c898","x":500,"y":720,"wires":[]},{"id":"1450ca78.249d8e","type":"function","z":"3e0d11cf.29e996","name":"Simulator","func":"var Newmsg = {};\nNewmsg.hap = {\"context\":\"defined\"};\nNewmsg.payload = {\"TargetDoorState\":msg.payload};\nreturn Newmsg;\n","outputs":1,"noerr":0,"x":860,"y":720,"wires":[["81e26608.9dcf1"]]},{"id":"4eb7eeb2.56b25","type":"inject","z":"3e0d11cf.29e996","name":"Close","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":710,"y":720,"wires":[["1450ca78.249d8e"]]},{"id":"3d998491.e2daac","type":"inject","z":"3e0d11cf.29e996","name":"Open","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":710,"y":760,"wires":[["1450ca78.249d8e"]]},{"id":"152449f6.bcaece","type":"inject","z":"3e0d11cf.29e996","name":"OBSTRUCTION","topic":"","payload":"{\"Switch3\":\"ON\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":720,"wires":[["c18468e.fdde518"]]},{"id":"e359a895.408258","type":"inject","z":"3e0d11cf.29e996","name":"All clear","topic":"","payload":"{\"Switch3\":\"OFF\"}","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":760,"wires":[["c18468e.fdde518"]]},{"id":"d2add466.b69c98","type":"function","z":"3e0d11cf.29e996","name":"Obstruction Handler","func":"GarageDoor = global.get(\"GarageDoor\");\nvar output = {};\n\nif (msg.payload.Switch3 === \"ON\") {\n    if (GarageDoor.CurrentState !== \"CLOSED\"){\n        output = {\n            \"payload\": {\n                \"ObstructionDetected\": true\n            }\n        }\n        GarageDoor.Obstruction = \"TRUE\"\n    } else {\n        output = {\n            \"payload\": {\n                \"ObstructionDetected\": false\n            }\n        }\n    }\n} else {\n    output = {\n        \"payload\": {\n            \"ObstructionDetected\": false\n        }\n    }\n    GarageDoor.Obstruction = \"FALSE\"\n}\nglobal.set(\"GarageDoor\", GarageDoor);\n\nreturn output;\n","outputs":1,"noerr":0,"x":680,"y":960,"wires":[["69226b8c.22ab04"]]},{"id":"a09fe844.ef8af","type":"comment","z":"3e0d11cf.29e996","name":"Obstruction simulator","info":"","x":260,"y":680,"wires":[]},{"id":"1a3938a1.19889f","type":"delay","z":"3e0d11cf.29e996","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":490,"y":960,"wires":[["d2add466.b69c98"]]},{"id":"7e1c4b.927f33b4","type":"comment","z":"3e0d11cf.29e996","name":"Teleperiod simulator","info":"","x":250,"y":800,"wires":[]},{"id":"97e48d59.73d608","type":"comment","z":"3e0d11cf.29e996","name":"HomeKit simulator","info":"","x":730,"y":680,"wires":[]},{"id":"b67bb3a5.19e1f8","type":"link in","z":"3e0d11cf.29e996","name":"","links":["76c85a60.bd0004"],"x":555,"y":1000,"wires":[["fb761eae.a5ef8"]]},{"id":"76c85a60.bd0004","type":"link out","z":"3e0d11cf.29e996","name":"","links":["b67bb3a5.19e1f8"],"x":1215,"y":1040,"wires":[]},{"id":"b7e5025d.e11e58","type":"mqtt in","z":"3e0d11cf.29e996","name":"SwitchTopic (on=opened off=closing)","topic":"cmnd/SwitchTopic/POWER1","qos":"1","datatype":"auto","broker":"8de2bd93.86c898","x":230,"y":1180,"wires":[["81eb9be3.c25088"]]},{"id":"6c47141f.43b344","type":"mqtt in","z":"3e0d11cf.29e996","name":"SwitchTopic (on=closed off=opening)","topic":"cmnd/SwitchTopic/POWER2","qos":"1","datatype":"auto","broker":"8de2bd93.86c898","x":230,"y":1240,"wires":[["5d350244.59bd4c"]]},{"id":"81eb9be3.c25088","type":"function","z":"3e0d11cf.29e996","name":"Opened Handler","func":"var GarageDoor = global.get(\"GarageDoor\") || {}; // load \"GarageDoor\" or set to empty\n\nif (msg.payload == \"ON\") {\n    // Sensor just turned on = door is fully opened\n    GarageDoor.LastState = \"OPENED\";\n    GarageDoor.CurrentState = \"OPENED\";\n} else if (msg.payload == \"OFF\" && GarageDoor.LastState == \"OPENED\") {\n    // Sensor just turned off == door is starting to close\n    GarageDoor.CurrentState = \"CLOSING\";\n}\n\nvar moving = false;\nif (GarageDoor.CurrentState == \"OPENING\" || GarageDoor.CurrentState == \"CLOSING\") moving = true;\n\nglobal.set(\"GarageDoor\", GarageDoor);\n\nif (moving){\n    return [{\"payload\": GarageDoor.CurrentState}, {\"payload\": 1}]\n} else {\n    return [{\"payload\": GarageDoor.CurrentState}, {\"payload\": \"RESET\"}]\n}","outputs":2,"noerr":0,"x":480,"y":1180,"wires":[["fb761eae.a5ef8"],["d1438336.ad7238"]]},{"id":"5d350244.59bd4c","type":"function","z":"3e0d11cf.29e996","name":"Closed Handler","func":"var GarageDoor = global.get(\"GarageDoor\") || {}; // load \"GarageDoor\" or set to empty\n\nif (msg.payload == \"ON\") {\n    // Sensor just turned on = door is fully opened\n    GarageDoor.LastState = \"CLOSED\";\n    GarageDoor.CurrentState = \"CLOSED\";\n} else if (msg.payload == \"OFF\" && GarageDoor.LastState == \"CLOSED\") {\n    // Sensor just turned off == door is starting to close\n    GarageDoor.CurrentState = \"OPENING\";\n}\n\nvar moving = false;\nif (GarageDoor.CurrentState == \"OPENING\" || GarageDoor.CurrentState == \"CLOSING\") moving = true;\n\nglobal.set(\"GarageDoor\", GarageDoor);\n\nif (moving){\n    return [{\"payload\": GarageDoor.CurrentState}, {\"payload\": 1}]\n} else {\n    return [{\"payload\": GarageDoor.CurrentState}, {\"payload\": \"RESET\"}]\n}","outputs":2,"noerr":0,"x":480,"y":1240,"wires":[["fb761eae.a5ef8"],["d1438336.ad7238"]]},{"id":"37c95a46.9afdb6","type":"inject","z":"3e0d11cf.29e996","name":"opened = ON","topic":"cmnd/SwitchTopic/POWER1","payload":"ON","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1070,"y":720,"wires":[["77d679b2.662be"]]},{"id":"f8407fd2.2cef88","type":"inject","z":"3e0d11cf.29e996","name":"Closing = OFF","topic":"cmnd/SwitchTopic/POWER1","payload":"OFF","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1070,"y":760,"wires":[["77d679b2.662be"]]},{"id":"1fd925ac.3d202a","type":"inject","z":"3e0d11cf.29e996","name":"Closed = ON","topic":"cmnd/SwitchTopic/POWER2","payload":"ON","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1070,"y":820,"wires":[["77d679b2.662be"]]},{"id":"4894bcad.103fec","type":"inject","z":"3e0d11cf.29e996","name":"Opening = OFF","topic":"cmnd/SwitchTopic/POWER2","payload":"OFF","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1080,"y":860,"wires":[["77d679b2.662be"]]},{"id":"77d679b2.662be","type":"mqtt out","z":"3e0d11cf.29e996","name":"state change","topic":"","qos":"1","retain":"false","broker":"8de2bd93.86c898","x":1310,"y":720,"wires":[]},{"id":"facbd911.62551","type":"comment","z":"3e0d11cf.29e996","name":"Instant feedback simulator","info":"","x":1090,"y":680,"wires":[]},{"id":"c2c8c131.b76c48","type":"inject","z":"3e0d11cf.29e996","name":"Obstruction","topic":"cmnd/SwitchTopic/POWER3","payload":"ON","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1310,"y":820,"wires":[["77d679b2.662be"]]},{"id":"38ae5250.c50d16","type":"inject","z":"3e0d11cf.29e996","name":"Clear","topic":"cmnd/SwitchTopic/POWER3","payload":"OFF","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1290,"y":860,"wires":[["77d679b2.662be"]]},{"id":"56f83ee1.f0bbd","type":"homekit-bridge","z":"","bridgeName":"villa-test","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"ptath","model":"raspberry pi zeroW","serialNo":"12345678","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true},{"id":"8de2bd93.86c898","type":"mqtt-broker","z":"","name":"villa","broker":"192.168.100.10","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""}]

Flow Info

Created 6 years ago
Rating: 5 1

Owner

Actions

Rate:

Node Types

Core
  • comment (x4)
  • delay (x1)
  • function (x8)
  • inject (x13)
  • link in (x1)
  • link out (x1)
  • mqtt in (x3)
  • mqtt out (x3)
  • mqtt-broker (x1)
  • trigger (x1)
Other
  • homekit-bridge (x1)
  • homekit-service (x1)

Tags

  • nrchkb
  • node-red-contrib-homekit-bridged
  • homekit
  • homeautomation
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option