Garage Door - NRCHKB/node-red-contrib-homekit-bridged GitHub Wiki

Service

GarageDoorOpener

Characteristics

Characteristic Optional/Required AcceptedValues Description
ObstructionDetected Required true, false Status of obstructions. Default: false
TargetDoorState Required 0, 1 0: open, 1: closed. Default: 0
CurrentDoorState Required 0, 1, 2, 3, 4 0: open, 1: closed, 2: opening, 3: closing, 4: stopped. Default: 0
LockTargetState Optional 0, 1 0: unsecured, 1: secured. Default: 0
LockCurrentState Optional 0, 1, 2, 3 0: unsecured, 1: secured, 2: jammed, 3: unknown. Default: 0
Name Optional String

Synopsis

Garage door is dangerous cause it can lock you inside or damage your car. Thats why it is a good idea to have at least 3 sensors:

  • Door fully opened
  • Door fully closed
  • Obstruction sensor

Motion sensor or button inside to open it manually also is optional.

Examples

Garage door with initial state and simple open/close logics.

[{"id":"5534366a.7ef91","type":"homekit-service","z":"75848247.7201a4","isParent":true,"bridge":"1f4da0a9.4023c7","parentService":"","name":"Garage Door","serviceName":"GarageDoorOpener","topic":"","filter":false,"manufacturer":"ptath","model":"Default Model","serialNo":"0001","characteristicProperties":"{\n    \"CurrentDoorState\":1\n}","x":518,"y":256,"wires":["14d4bf27.4db229","745cd5b8.149d1c","d12ee2b5.67db6"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"14d4bf27.4db229","745cd5b8.149d1c","d12ee2b5.67db6")},{"id":"14d4bf27.4db229","type":"debug","z":"75848247.7201a4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":894,"y":256,"wires":[]},{"id":"f0a87280.f66ea","type":"inject","z":"75848247.7201a4","name":"TargetDoorState 0 To Open","topic":"","payload":"{\"TargetDoorState\": 0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":142,"y":40,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"2f0bb109.cee4ee","type":"inject","z":"75848247.7201a4","name":"TargetDoorState 1 To Close","topic":"","payload":"{\"TargetDoorState\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":152,"y":80,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"26ef612d.04cd86","type":"inject","z":"75848247.7201a4","name":"CurrentDoorState 0 opened","topic":"","payload":"{\"CurrentDoorState\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":152,"y":168,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"1dcedc5c.cc1004","type":"inject","z":"75848247.7201a4","name":"CurrentDoorState 1 closed","topic":"","payload":"{\"CurrentDoorState\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":142,"y":208,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"75402de5.d52d84","type":"inject","z":"75848247.7201a4","name":"ObstructionDetected 1 true","topic":"","payload":"{\"ObstructionDetected\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":152,"y":400,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"70fdf078.8d2b48","type":"inject","z":"75848247.7201a4","name":"ObstructionDetected 0 false","topic":"","payload":"{\"ObstructionDetected\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":152,"y":440,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"ea0e73a2.6eba48","type":"inject","z":"75848247.7201a4","name":"CurrentDoorState 4 stopped in the middle","topic":"","payload":"{\"CurrentDoorState\":4}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":192,"y":328,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"d12ee2b5.67db6","type":"function","z":"75848247.7201a4","name":"Save STATE","func":"var GD1 = global.get(\"GD1\");\n\nif (msg.payload.TargetDoorState !== undefined) {\n    global.set(\"GD1.TargetState\", msg.payload.TargetDoorState);\n    // 0 - want to open, 1 — want to close\n}\n\n//node.warn(GD1);\nreturn msg;","outputs":1,"noerr":0,"x":718,"y":296,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"d9b75532.233b28","type":"function","z":"75848247.7201a4","name":"Set GD1 — initial state (from sensors)","func":"var GD1 = {\n    SensorState: 1, // set real init state according to sensor\n    RunTime: 20, // time in seconds to fully open/close door (not implemented here)\n    ObstructionDetected: false // set real init state according to sensor\n}\n\nglobal.set(\"GD1\", GD1);\n\n//node.warn(GD1);\n\nreturn [GD1];","outputs":1,"noerr":0,"x":686,"y":40,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"a45db63a.eb474","type":"inject","z":"75848247.7201a4","name":"Set initial state","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":432,"y":40,"wires":["d9b75532.233b28"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"d9b75532.233b28")},{"id":"745cd5b8.149d1c","type":"function","z":"75848247.7201a4","name":"Main Logic","func":"var GD1 = global.get(\"GD1\");\n\nif ((msg.payload.TargetDoorState === 1) && \n    (GD1.ObstructionDetected === false) && \n    (GD1.CurrentState === 0)) {\n        // real command to close here\n        return {\"payload\": \"CLOSE COMMAND\"}\n}\n\nif (msg.payload.TargetDoorState === 0) {\n    // real command to open here\n    return {\"payload\": \"OPEN COMMAND\"}\n}","outputs":1,"noerr":0,"x":718,"y":336,"wires":["14d4bf27.4db229"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"14d4bf27.4db229")},{"id":"c53b5c5a.49826","type":"function","z":"75848247.7201a4","name":"Set initial HomeKit state","func":"var GD1 = global.get(\"GD1\");\n\nif (GD1.SensorState === 1) {\n    var newMsg = {\"payload\": {\n        \"TargetDoorState\":1,\n        \"CurrentDoorState\":1 }\n    }\n    //node.warn(newMsg);\n    return newMsg\n}\n\nif (GD1.SensorState === 0) {\n    var newMsg = {\"payload\": {\n        \"TargetDoorState\":0,\n        \"CurrentDoorState\":0 }\n    }\n    //node.warn(newMsg);\n    return newMsg\n}","outputs":1,"noerr":0,"x":726,"y":80,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"38b37223.7302b6","type":"inject","z":"75848247.7201a4","name":"Send initial state to HomeKit","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":"0.5","x":472,"y":80,"wires":["c53b5c5a.49826"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"c53b5c5a.49826")},{"id":"35daf933.b31bae","type":"inject","z":"75848247.7201a4","name":"CurrentDoorState 2 opening","topic":"","payload":"{\"CurrentDoorState\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":152,"y":248,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"ab4940dd.c6e4f","type":"inject","z":"75848247.7201a4","name":"CurrentDoorState 3 closing","topic":"","payload":"{\"CurrentDoorState\":3}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":142,"y":288,"wires":[](/NRCHKB/node-red-contrib-homekit-bridged/wiki/)},{"id":"d3e3a15f.775f","type":"inject","z":"75848247.7201a4","name":"Sensor Closed","topic":"1","payload":"SensorState","payloadType":"global","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":432,"y":432,"wires":["dcae49cf.d24648"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"dcae49cf.d24648")},{"id":"d57c187.234f768","type":"inject","z":"75848247.7201a4","name":"Sensor Opened","topic":"0","payload":"SensorState","payloadType":"global","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":432,"y":472,"wires":["c37a0663.e9b01"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"c37a0663.e9b01")},{"id":"c37a0663.e9b01","type":"function","z":"75848247.7201a4","name":"","func":"// sensor send opened state\n\nvar GD1 = global.get(\"GD1\");\nglobal.set(\"GD1.CurrentState\", 0);\nvar newMsg = {\"payload\": {\"CurrentDoorState\":0 }}\nreturn newMsg;","outputs":1,"noerr":0,"x":586,"y":472,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"dcae49cf.d24648","type":"function","z":"75848247.7201a4","name":"","func":"// sensor send closed state\n\nvar GD1 = global.get(\"GD1\");\nglobal.set(\"GD1.CurrentState\", 1);\nvar newMsg = {\"payload\": {\"CurrentDoorState\":1 }}\nreturn newMsg;","outputs":1,"noerr":0,"x":586,"y":432,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"b49fbf5e.c23e08","type":"inject","z":"75848247.7201a4","name":"Sensor Unknown","topic":"0","payload":"SensorState","payloadType":"global","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":432,"y":512,"wires":["91fbd029.4be268"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"91fbd029.4be268")},{"id":"91fbd029.4be268","type":"function","z":"75848247.7201a4","name":"","func":"// sensor send unknown (not closed and not opened) state\n\nvar GD1 = global.get(\"GD1\");\n\nif (GD1.TargetState === 0) {\n    var newMsg = {\"payload\": {\"CurrentDoorState\":2 }}\n} else if (GD1.TargetState === 1) {\n    var newMsg = {\"payload\": {\"CurrentDoorState\":3 }}\n} else {\n    var newMsg = {\"payload\": {\"CurrentDoorState\":4 }}\n}\n\n// dunno what to do with this info =)\nreturn newMsg;","outputs":1,"noerr":0,"x":586,"y":512,"wires":["5534366a.7ef91"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"5534366a.7ef91")},{"id":"1f4da0a9.4023c7","type":"homekit-bridge","z":"","bridgeName":"villa-test","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"ptath","model":"raspberry pi zeroW","serialNo":"12345678"}]

Advanced Garage door setup

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!

Flow

[{"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\") ](/NRCHKB/node-red-contrib-homekit-bridged/wiki/|-{};-//-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\") ](/NRCHKB/node-red-contrib-homekit-bridged/wiki/|-{};\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\") ](/NRCHKB/node-red-contrib-homekit-bridged/wiki/|-{};-//-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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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"](/NRCHKB/node-red-contrib-homekit-bridged/wiki/"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":""}]