My node-red + HomeKit + OpenHAB setup

I know others have connected their devices and everyone has their own twist on how to do this. My preferred method is to use function nodes wherever possible. This keeps things from getting too messy with all of the switch and change nodes that come up in similar setups.

It came up today when I started showing @rkrisi how to use MQTT+Node-Red to send command line codes to other computers. So here goes.

A couple of prerequisites:
-Install node-red (obviously)
-Add the flow “node-red-contrib-homekit-bridged” from the “Manage Pallets” item in the node-red hamburger menu (top right)

A couple of important comments to avoid problems:
The HomeKit node has a problem when ever it is deployed. If you have to deploy it more than once (hint: you will have to) then you’ll want to restart node-red for HomeKit to keep working. Easiest restart:

sudo systemctl restart nodered.service

Once you’ve got the HomeKit items pretty well set you can go ahead and just set node-red to only deploy modified nodes. Then you’ll only have to restart node-red if your homekit items show the little blue dot (means they’re going to be updated).

Main takeaway here: if homekit is being weird, restart node-red.

Edit: December 18, 2020- this is and has been fixed for a while.

I’ll put screenshots of the whole flow then paste in my functions. In comment #2 on this thread I’ll put my flows that you can just copy and paste into node-red to see everything for yourself.

Switch Item
HomeKit service: “Switch”


OpenHAB to HomeKit function:

if (msg.payload == "ON") {
    msg.payload = {
        "On": true
    };
} else {
    msg.payload = {
        "On": false
    };
}
return msg;

OpenHAB to HomeKit function:

if (msg.hap.context !== undefined )
{
if(msg.payload.On === false){
    msg.payload = "OFF";
}
else {
    if(msg.payload.On === true){
    msg.payload = "ON";
}
}
return msg;
}

These functions “translate” the commands to/from OpenHAB/HomeKit. Pretty straightforward I think except the msg.hap.context which is only “undefined” if the message didn’t come from HomeKit (if you use your phone or siri to control an item then hap.context is NOT undefined - so the first line returns “true”). This prevents loops since the HomeKit node passes everything through. This if statement is used in all of my outgoing functions.

Outlet Item
HomeKit service: “Outlet”


I use this for my MQTT relays. Functions are exactly the same as the switch item above. The “outlet” item has extra items that the switch doesn’t have. For outlet this includes:

"InUse": true //switch using power
"InUse": false //switch not using power

I would use this if I had any power-monitoring outlets - I would set a rule in tasmota to send a message through openhab or just MQTT so that I could trigger whether the outlet is drawing power. Special note if you do this is you’ll want to add “Characteristic Properties” in the HomeKit node so that HomeKit actually shows that “In Use” is an option. There is an example of this below for my dimmers. I haven’t used this characteristic properties for anything but dimmers.

Feel free to show me if you add this.

Fan Item
HomeKit service: “Fan”


Again - same functions as above.

Additional “Characteristic Properties” for this one are (as far as I know):
-fan speed
-oscillating on/off
I have a pretty good idea of how to add this - but I only have on/off bathroom fans in my system so I haven’t actually done it.

Dimmer Item
HomeKit service: “Lightbulb”


Now we need to get more interesting with the functions. First step is put the following in “Characteristic Properties” in the Chandelier HomeKit node:

{"Brightness":true}

This will make it always show as a dimmer in HomeKit instead of an on/off lightbulb.

Dimmer to HK function:

var input = msg.payload;
if (input < 101){
    if (input < 1) {
        msg.payload = {
        "On": false
    }
    }
    else {
        msg.payload = {
        "Brightness": input,
        "On": true
    }
    }
    return msg;
}

I had to be a little careful here with my OpenHAB rules for dimmers. OpenHAB can send “ON”, “OFF”, “NULL”, or a brightness level 0-100. I’ve set my rules so that they only send numerical updates. If I was sending “ON” and “OFF” messages through dimmers I would have to add if statements for those commands.

Dimmer to OH function:

var b = context.get('b')||0;
if(msg.payload.Brightness){
    b = msg.payload.Brightness;
    context.set('b',b);
    msg.payload=b
}
if (msg.hap.context !== undefined) {
    if(msg.payload.Brightness === 0){
        msg.payload = 0
    }
    if(msg.payload.On === false){
        msg.payload = 0
    }
    if(msg.payload.On === true){
        msg.payload = b
    }
    return msg
}

The special item here is my global variable. It holds on to the previous state when the item is turned off. This is because HomeKit always remembers the previous state of a dimmer and restores that state with a simple {“On”: true} message. Since OpenHAB doesn’t remember the previous state I just keep it saved in a node-red context variable (context stays only within the current flow).

Smoke Detector
HomeKit service type: “SmokeSensor”

This is an easy one. I’ve got a hardwired relay from my smoke detector to my OpenHAB GPIO. “Open” is fire. “Closed” is no fire.


Run function:

if(msg.payload == "OPEN"){
    msg.payload = {
        "SmokeDetected": 1
    };
    return msg
}
if(msg.payload == "CLOSED"){
    msg.payload = {
        "SmokeDetected": 0
    };
    return msg
}

This doesn’t have anything coming out of HomeKit because HomeKit can’t set off the fire alarm. It’s a one-way item.

Curtains
HomeKit service type: “WindowCovering”


My curtains are seen by OpenHAB as a dimmer switch. The functions are very similar to dimmers above - with one addition. The “WindowCovering” item looks for 2 signals one to come after the other. First it sets “Target Position” - or where HomeKit wants the curtain to be. Second it sets “Current Position” - or where the curtain actually is. If “target position” is closed when current position is open HomeKit shows “closing”. If target is open when the current position is closed HomeKit shows “opening”.

My curtains take about 12 seconds to open and close so I send the messages out of the function nodes into HomeKit but with a 12-second delay on the “Current Position” so it shows “opening” and “closing” while it’s in motion. Unnecessary but a nice detail.

Target Position function:

var input = msg.payload;
var delay = {payload:0};
if(input < 101){
    msg.payload = {
        "TargetPosition": input
    };
    delay.payload = {
        "CurrentPosition": input
    };
    return [msg,delay];
}

Curtain out function:

var t = context.get('t')||0;
var delay = {payload:0}
if(msg.payload.TargetPosition){
    t = msg.payload.TargetPosition;
    context.set('t',t);
    msg.payload=t
}
if(msg.payload.TargetPosition === 0){
    t = msg.payload.TargetPosition;
    context.set('t',t);
    msg.payload=t
}
if (msg.hap.context !== undefined){
    delay.payload = {
        "CurrentPosition": t
    };
    return [msg,delay]
}

Extra items are available on this one in HomeKit as well. I believe blinds angle and some things with angles. I don’t have windows or blinds like this so I haven’t explored.

Sprinklers Bonus Item
HomeKit item type: “Valve”


This one is not one that just anyone can copy. I’m happy to share more code (I believe I have posted versions of this before) but I had to do a lot more work for this one. I had to get access to the Skydrop sprinkler developer API, use OAUTH2 authentication with myopenhab.org, and put together some nodes (not shown) to hold my access and refresh tokens. But now I can say “hey Siri, start watering the flowers” - which I think is very cool.

This could be done pretty easily I suppose with a few relays attached to a wemos… I won’t go into that. As everything else, feel free to request more details about how I’m handling the sprinklers in HomeKit.

Final Comments
Another thing I’ve done is add extra “switch” items in HomeKit to send messages back to OpenHAB. I use this for presence detection so I have “Anyone Home” as an item that HomeKit turns on when we arrive and off when we leave. Works pretty well for presence detection.

I went into this setup because I wanted to fix some of my issues with HomeKit that seem to be pitfalls with OpenHAB including the poor handling of dimmers, limited HomeKit object types, and problems with disappearing items when I made changes to my .items files. This setup has been running without issues for 3 or 4 months now in my house.

The best way to find out which items are available is to make yourself an inject node, connect it to a HomeKit node and check the “errors” tab in node red. The inject command needs to be JSON and can be any message, I use:

{"Break":"HomeKit"}

I’ll post the text version of all of this (except sprinklers) in my next comment. Then y’all can go ahead and paste it right into node red (hamburger menu - import for beginners).

Enjoy.

Update December 18, 2020: I don’t hang around here much any more. If anyone has questions, feel free to come find me at this GitHub project

16 Likes
[
    {
        "id": "1da38bd6.d719f4",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "Openhab to HomeKit",
        "func": "if (msg.payload == \"ON\") { \n    msg.payload = {\n        \"On\": true\n    };\n} else { \n    msg.payload = {\n        \"On\": false\n    };\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "x": 400,
        "y": 240,
        "wires": [
            [
                "195899c5.6e05ee"
            ]
        ]
    },
    {
        "id": "3276e10c.b5e296",
        "type": "openhab2-in",
        "z": "deb4fe66.cc6b48",
        "name": "Garage 1",
        "controller": "9d8afcef.f3d04",
        "itemname": "Garage1",
        "x": 200,
        "y": 240,
        "wires": [
            [
                "1da38bd6.d719f4"
            ],
            []
        ],
        "outputLabels": [
            "msg.payload",
            ""
        ]
    },
    {
        "id": "195899c5.6e05ee",
        "type": "homekit-service",
        "z": "deb4fe66.cc6b48",
        "bridge": "4b4fbb6e.6cfaec",
        "name": "Workbench",
        "serviceName": "Outlet",
        "manufacturer": "Hayley",
        "model": "Outlet",
        "serialNo": "1",
        "characteristicProperties": "{}",
        "x": 610,
        "y": 240,
        "wires": [
            [
                "676252a6.449654"
            ]
        ]
    },
    {
        "id": "676252a6.449654",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "HomeKit to OpenHAB",
        "func": "if (msg.hap.context !== undefined )\n{\nif(msg.payload.On === false){\n    msg.payload = \"OFF\";\n}\nelse {\n    if(msg.payload.On === true){\n    msg.payload = \"ON\";\n}\n}\nreturn msg;\n}\n",
        "outputs": 1,
        "noerr": 0,
        "x": 820,
        "y": 240,
        "wires": [
            [
                "301157a1.e795d8"
            ]
        ]
    },
    {
        "id": "301157a1.e795d8",
        "type": "openhab2-out",
        "z": "deb4fe66.cc6b48",
        "name": "Garage 1",
        "controller": "9d8afcef.f3d04",
        "itemname": "Garage1",
        "topic": "ItemCommand",
        "payload": "",
        "x": 1020,
        "y": 240,
        "wires": [
            []
        ],
        "inputLabels": [
            "msg.payload"
        ]
    },
    {
        "id": "51dd0c5.4fcc674",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "OpenHAB to HomeKit",
        "func": "if (msg.payload == \"ON\") {\n    msg.payload = {\n        \"On\": true\n    };\n} else {\n    msg.payload = {\n        \"On\": false\n    };\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "x": 420,
        "y": 320,
        "wires": [
            [
                "c4e3e8b.df26218"
            ]
        ]
    },
    {
        "id": "8e1ec8f1.44c07",
        "type": "openhab2-in",
        "z": "deb4fe66.cc6b48",
        "name": "Back Porch",
        "controller": "9d8afcef.f3d04",
        "itemname": "BackPorch",
        "x": 210,
        "y": 320,
        "wires": [
            [
                "51dd0c5.4fcc674"
            ],
            []
        ],
        "outputLabels": [
            "msg.payload",
            ""
        ]
    },
    {
        "id": "c4e3e8b.df26218",
        "type": "homekit-service",
        "z": "deb4fe66.cc6b48",
        "bridge": "4b4fbb6e.6cfaec",
        "name": "Back Porch",
        "serviceName": "Switch",
        "manufacturer": "Hayley",
        "model": "Outlet",
        "serialNo": "1",
        "characteristicProperties": "{}",
        "x": 630,
        "y": 320,
        "wires": [
            [
                "ee62c6fc.3331d8"
            ]
        ]
    },
    {
        "id": "ee62c6fc.3331d8",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "HomeKit to OpenHAB",
        "func": "if (msg.hap.context !== undefined )\n{\nif(msg.payload.On === false){\n    msg.payload = \"OFF\";\n}\nelse {\n    if(msg.payload.On === true){\n    msg.payload = \"ON\";\n}\n}\nreturn msg;\n}\n",
        "outputs": 1,
        "noerr": 0,
        "x": 840,
        "y": 320,
        "wires": [
            [
                "bca2afa7.bdee18"
            ]
        ]
    },
    {
        "id": "bca2afa7.bdee18",
        "type": "openhab2-out",
        "z": "deb4fe66.cc6b48",
        "name": "Back Porch",
        "controller": "9d8afcef.f3d04",
        "itemname": "BackPorch",
        "topic": "ItemCommand",
        "payload": "",
        "x": 1050,
        "y": 320,
        "wires": [
            []
        ],
        "inputLabels": [
            "msg.payload"
        ]
    },
    {
        "id": "395c093f.c3249e",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "OpenHAB to HomeKit",
        "func": "if (msg.payload == \"ON\") {\n    msg.payload = {\n        \"On\": true\n    };\n} else {\n    msg.payload = {\n        \"On\": false\n    };\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 420,
        "y": 400,
        "wires": [
            [
                "d4ff4ed7.c649e"
            ]
        ]
    },
    {
        "id": "2ff93c34.3245ec",
        "type": "openhab2-in",
        "z": "deb4fe66.cc6b48",
        "name": "Small Fan",
        "controller": "9d8afcef.f3d04",
        "itemname": "SmallFan",
        "x": 200,
        "y": 400,
        "wires": [
            [
                "395c093f.c3249e"
            ],
            []
        ],
        "outputLabels": [
            "msg.payload",
            ""
        ]
    },
    {
        "id": "d4ff4ed7.c649e",
        "type": "homekit-service",
        "z": "deb4fe66.cc6b48",
        "bridge": "4b4fbb6e.6cfaec",
        "name": "Small Fan",
        "serviceName": "Fan",
        "manufacturer": "Hayley",
        "model": "Outlet",
        "serialNo": "1",
        "characteristicProperties": "{}",
        "x": 620,
        "y": 400,
        "wires": [
            [
                "be53ff29.c90968"
            ]
        ]
    },
    {
        "id": "be53ff29.c90968",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "HomeKit to OpenHAB",
        "func": "if (msg.hap.context !== undefined )\n{\nif(msg.payload.On === false){\n    msg.payload = \"OFF\";\n}\nelse {\n    if(msg.payload.On === true){\n    msg.payload = \"ON\";\n}\n}\nreturn msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "x": 820,
        "y": 400,
        "wires": [
            [
                "2352f791.edc3c"
            ]
        ]
    },
    {
        "id": "2352f791.edc3c",
        "type": "openhab2-out",
        "z": "deb4fe66.cc6b48",
        "name": "Small Fan",
        "controller": "9d8afcef.f3d04",
        "itemname": "SmallFan",
        "topic": "ItemCommand",
        "payload": "",
        "x": 1020,
        "y": 400,
        "wires": [
            []
        ],
        "inputLabels": [
            "msg.payload"
        ]
    },
    {
        "id": "d4efdbd7.2044d",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "Dimmer to HK",
        "func": "var input = msg.payload;\nif (input < 101){\n    if (input < 1) {\n        msg.payload = {\n        \"On\": false\n    }\n    }\n    else {\n        msg.payload = {\n        \"Brightness\": input,\n        \"On\": true\n    }\n    }\n    return msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "x": 400,
        "y": 480,
        "wires": [
            [
                "6c61fa96.818874"
            ]
        ]
    },
    {
        "id": "6c61fa96.818874",
        "type": "homekit-service",
        "z": "deb4fe66.cc6b48",
        "bridge": "4b4fbb6e.6cfaec",
        "name": "Chandelier",
        "serviceName": "Lightbulb",
        "manufacturer": "Zoey",
        "model": "Lamp",
        "serialNo": "2",
        "characteristicProperties": "{\"Brightness\":true}",
        "x": 590,
        "y": 480,
        "wires": [
            [
                "ccab9de6.b51f"
            ]
        ]
    },
    {
        "id": "38b89325.e5202c",
        "type": "openhab2-in",
        "z": "deb4fe66.cc6b48",
        "name": "Chandelier",
        "controller": "9d8afcef.f3d04",
        "itemname": "ChandelierION",
        "x": 200,
        "y": 480,
        "wires": [
            [
                "d4efdbd7.2044d"
            ],
            []
        ]
    },
    {
        "id": "ccab9de6.b51f",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "Dimmer to OH",
        "func": "var b = context.get('b')||0;\nif(msg.payload.Brightness){\n    b = msg.payload.Brightness;\n    context.set('b',b);\n    msg.payload=b\n}\nif (msg.hap.context !== undefined) {\n    if(msg.payload.Brightness === 0){\n        msg.payload = 0\n    }\n    if(msg.payload.On === false){\n        msg.payload = 0\n    }\n    if(msg.payload.On === true){\n        msg.payload = b\n    }\n    return msg\n}",
        "outputs": 1,
        "noerr": 0,
        "x": 820,
        "y": 480,
        "wires": [
            [
                "2200a119.5ef656"
            ]
        ]
    },
    {
        "id": "2200a119.5ef656",
        "type": "openhab2-out",
        "z": "deb4fe66.cc6b48",
        "name": "Chandelier",
        "controller": "9d8afcef.f3d04",
        "itemname": "ChandelierION",
        "topic": "ItemCommand",
        "payload": "",
        "x": 1010,
        "y": 480,
        "wires": [
            []
        ]
    },
    {
        "id": "5c4ad162.06fea",
        "type": "homekit-service",
        "z": "deb4fe66.cc6b48",
        "bridge": "4b4fbb6e.6cfaec",
        "name": "Smoke Detector",
        "serviceName": "SmokeSensor",
        "manufacturer": "Default Manufacturer",
        "model": "Default Model",
        "serialNo": "Default Serial Number",
        "characteristicProperties": "{}",
        "x": 520,
        "y": 560,
        "wires": [
            []
        ]
    },
    {
        "id": "8162b795.1e6108",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "Run",
        "func": "if(msg.payload == \"OPEN\"){\n    msg.payload = {\n        \"SmokeDetected\": 1\n    };\n    return msg\n}\nif(msg.payload == \"CLOSED\"){\n    msg.payload = {\n        \"SmokeDetected\": 0\n    };\n    return msg\n}\n",
        "outputs": 1,
        "noerr": 0,
        "x": 350,
        "y": 560,
        "wires": [
            [
                "5c4ad162.06fea"
            ]
        ]
    },
    {
        "id": "2b3d44c5.3d8124",
        "type": "openhab2-in",
        "z": "deb4fe66.cc6b48",
        "name": "Smoke",
        "controller": "9d8afcef.f3d04",
        "itemname": "FireWire",
        "x": 190,
        "y": 560,
        "wires": [
            [
                "8162b795.1e6108"
            ],
            []
        ]
    },
    {
        "id": "433f420b.c92304",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "Target Position",
        "func": "var input = msg.payload;\nvar delay = {payload:0};\nif(input < 101){\n    msg.payload = {\n        \"TargetPosition\": input\n    };\n    delay.payload = {\n        \"CurrentPosition\": input\n    };\n    return [msg,delay];\n}",
        "outputs": 2,
        "noerr": 0,
        "x": 360,
        "y": 640,
        "wires": [
            [
                "26948c69.da9654"
            ],
            [
                "4190205b.85e85"
            ]
        ]
    },
    {
        "id": "26948c69.da9654",
        "type": "homekit-service",
        "z": "deb4fe66.cc6b48",
        "bridge": "4b4fbb6e.6cfaec",
        "name": "Window",
        "serviceName": "WindowCovering",
        "manufacturer": "Zoey",
        "model": "Lamp",
        "serialNo": "2",
        "characteristicProperties": "{\"Brightness\":true}",
        "x": 700,
        "y": 640,
        "wires": [
            [
                "b01cbb7.2508dc8"
            ]
        ]
    },
    {
        "id": "4190205b.85e85",
        "type": "delay",
        "z": "deb4fe66.cc6b48",
        "name": "",
        "pauseType": "delay",
        "timeout": "12",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 540,
        "y": 680,
        "wires": [
            [
                "26948c69.da9654"
            ]
        ]
    },
    {
        "id": "e7f3ebec.d2eb5",
        "type": "openhab2-in",
        "z": "deb4fe66.cc6b48",
        "name": "Window",
        "controller": "9d8afcef.f3d04",
        "itemname": "Window",
        "x": 200,
        "y": 660,
        "wires": [
            [
                "433f420b.c92304"
            ],
            []
        ]
    },
    {
        "id": "b01cbb7.2508dc8",
        "type": "function",
        "z": "deb4fe66.cc6b48",
        "name": "Curtain Out",
        "func": "var t = context.get('t')||0;\nvar delay = {payload:0}\nif(msg.payload.TargetPosition){\n    t = msg.payload.TargetPosition;\n    context.set('t',t);\n    msg.payload=t\n}\nif(msg.payload.TargetPosition === 0){\n    t = msg.payload.TargetPosition;\n    context.set('t',t);\n    msg.payload=t\n}\nif (msg.hap.context !== undefined){\n    delay.payload = {\n        \"CurrentPosition\": t\n    };\n    return [msg,delay]\n}",
        "outputs": 2,
        "noerr": 0,
        "x": 850,
        "y": 640,
        "wires": [
            [
                "ebb13afe.87f8a"
            ],
            [
                "3719fd8c.11aed2"
            ]
        ]
    },
    {
        "id": "7c104855.17e5f8",
        "type": "link in",
        "z": "deb4fe66.cc6b48",
        "name": "",
        "links": [
            "3719fd8c.11aed2"
        ],
        "x": 435,
        "y": 700,
        "wires": [
            [
                "4190205b.85e85"
            ]
        ]
    },
    {
        "id": "ebb13afe.87f8a",
        "type": "openhab2-out",
        "z": "deb4fe66.cc6b48",
        "name": "Window",
        "controller": "9d8afcef.f3d04",
        "itemname": "Window",
        "topic": "ItemCommand",
        "payload": "",
        "x": 1020,
        "y": 640,
        "wires": [
            []
        ]
    },
    {
        "id": "3719fd8c.11aed2",
        "type": "link out",
        "z": "deb4fe66.cc6b48",
        "name": "",
        "links": [
            "7c104855.17e5f8"
        ],
        "x": 995,
        "y": 700,
        "wires": []
    },
    {
        "id": "9d8afcef.f3d04",
        "type": "openhab2-controller",
        "z": "",
        "name": "Openhab",
        "protocol": "http",
        "host": "localhost",
        "port": "8080",
        "path": "",
        "username": "",
        "password": ""
    },
    {
        "id": "4b4fbb6e.6cfaec",
        "type": "homekit-bridge",
        "z": "",
        "bridgeName": "Node Red",
        "pinCode": "514-02-658",
        "port": "",
        "manufacturer": "Garrett Porter",
        "model": "Pi3",
        "serialNo": "Rev.1"
    }
]
1 Like

really nice! Thanks for sharing!

Could you please talk more about stability?

  • how about remote controlling? does it always reports the status smoothly when using 4g?
  • does it often reports “updating” or “unresponsive” even when LAN control?

Thanks!

this is really cool! Thanks for sharing. Now I will have almost every oh item available in HomeKit as well!

Stability is fantastic. It’s been more stable than most of my native HomeKit items actually - I have an ecobee, chamberlain garage door hub, and a few iHome plugs. Each of those native items has been “updating” or “no response” 2 or 3 times over the last few months. The node-red setup has not had any problems.

These problems are not happening. Any time I have a connection to HomeKit I am able to control all of my items as expected. I think once or twice our power went out and the Apple TVs didn’t reconnect properly so I had to go home to restart them but that was a HomeKit issue and not an issue with this setup (ALL of my devices including native HomeKit were offline).

The “updating” is only ever for 1-2 seconds while it updates. “no response” doesn’t happen.

I’m trying to think of any other issues I’ve had but after the original setup there really have been no problems. One thing I’ll probably add is a little delay buffer between my HomeKit dimmers and OpenHAB - when I slide the little slider HomeKit will send 3-4 updates depending how “slowly” I’m sliding it. I think it will smooth out my system if I put a half-second delay on those and only send the last one so that my light (Insteon) only gets one update…

Thank you for the details, really awesome job!
May I also ask you how many devices(including none-homekit wifi devices) in your local network? Which router are you using?

I am having very deep troubles about “updating” and become “unresponsive”, when I in LAN, everything working very well, no delay at all! Then I disconnect the wifi and go to 4g, the remote homekit is also working very well, however if I stay 4g and wait around 20-30 minutes then reopen the home app, everything becomes “updating”, and need to wait 2-3min(during the wait time all devices report “updating” and finally report “unresponsive”), then after 2-3 minutes, I reopen the home app, everything back to normal(I can watch real time streaming without any issue).

In this case, if I leave wifi and wait long enough(20-30min), the problem happen. But if I wait within 20min(say 17min, then I reopen the home app in 4g remote mode), everything still working smoothly. no “updating” at all…
So I am facing this problem like half year and still don’t have any clue of how this strange thing happen.

I am guessing it’s the router’s problem, I am running openwrt router with dnsmasq, somehow it may cause this strange problem, something related to dnsmasq(still guessing). No idea at all!

Do you have any idea of what cause this problem? Thanks!

I can think of 20 wireless devices connected in my house. Of those, 2 are actual “genuine HomeKit” devices, 2 are HomePods, 7 are phone/watch/tablet/computer, 1 is a sprinkler controller, and the others are various ESP8266 or Raspberry Pi devices. Router is a TP-Link C5400 running default firmware. I’ve been thinking of switching to openwrt - but you’re making me reconsider that a bit…

I’ve made it a point to keep things off wifi as much as possible. We have 6 or 7 things connected with ethernet - including my OpenHAB pi. I use Insteon light switches so there’s no wifi involved there.

When I open up the home app and scroll through my rooms there’s maybe a 1-2 second time where everything says “updating” then boom - all of the accurate states of everything.

Are all of your homekit devices openhab devices? Or do you have some native ones? Do any update more reliably than others? I find there are times when my garage doors (native homekit) is a little behind my node-red devices but not by much. For some reason my ecobee thermostat (native homekit) is the most spotty, it will drop out for 5-10 minutes at times and the only way to kick it back is restart the home app on my phone.

Try setting up a “dummy device” in node-red and adding it to your homekit then watch if it goes offline with the others. This could help pinpoint where the issues are coming from.

The only other problems I’ve had is in spotty signal areas but that’s to be expected right? Nobody expects these things to work in the middle of nowhere when cell service is lackluster at best.

Here are some of the other threads and comments that helped me get everything put together.

For anyone wanting colored homekit lights - start here. My brightness function was based on this post.


For a thermostat, see this post (copy and paste the line of code into your node-red)

For those with oscillating / multi-speed fans see this post for an example of sending speed and oscillation commands to HomeKit:


If anyone has interesting in building out a relay-based sprinkler flow, let me know. I think it would be fun to help put that code together!

Thanks everyone who’s posted things that I’ve copied and modified. There’s so much potential here. For my house we use HomeKit for everything - to the point my 4 year old controls our window, music, lights, and more with our HomePod. I need to not teach her about the sprinkler option - she’d be all over that one to go jump on the trampoline with sprinklers on!

NOTE
Many of these examples use an older version of the node-red homekit plugin which does NOT add as a bridge. Each item adds individually. I just thought it would be cool to put together a nice starting point for people wanting to do homekit+node-red.

One more question.
Do you have a ‘real server’ for your server or you run OH + Node-RED on RPi?

It all runs together on a Pi 3 B+. My MQTT broker is on that same Pi.

I considered splitting it up when I added my node red stuff - but monitoring the ram and cpu everything runs very comfortably. 3-4 weeks uptime shows 85-90% memory usage and low cpu usage (always under 5% when I run “uptime”)

Thanks, same setup, so I’ll install it on that as well :slight_smile: Now I’m just playing on it in a VM.

Just checked again. I’ve got 14% free ram and my 15-minute cpu load is 1%.

I keep a pi running at work so I can try stuff before putting it in my house. Have to keep my family happy!

So I have started implementing my HomeKit with Node-RED.
I have a few questions, maybe you know the answer to some of them.

  • I wanted to implement my Air Quality Sensor. I always get this response, I don’t know where should I specify setValue (tried outside payload, in payload…)
"TypeError: Cannot read property 'setValue' of undefined"
  • I went for a different approach for dimmers, because I have a lamp for example which has ColorTemp as well. So I read all values in, HomeKit accepts multiple jsons with only one value in it. For example: Lamp_Power sends ON for the HomeKit item, Lamp_Bright sends the Brightness… Now I want to do this for setting the values through HomeKit. I wanted to check if the output has the attribute and if yes, just pass back to the power or brightness item.
msg.payload.hasOwnProperty("Brightness")

It should work, because HomeKit puts just one value to the output, however Node-RED ignores that check and passes all values to the OH item. Why? Node-RED doesn’t have this hasOwnProperty function?

I’m really new to Node-RED and Javascript as well… Some items can be easily implementable (like TempSensor, MotionSensor, LightSwitch) but some of them is harder…

Thanks!

Hi i am also using node red + OH + homekit

but i am using homekit binding from OH, items are defined on OH
and rules will set Home items ,just on and will bring them back to off

i find homekit to be unstalbe so i dont like the cntorl from there , i just use it for siri and nothing else
or maybe backup when cloud is down

Are you doing this as an “air quality” sensor or as an “air purifier” type? What is the “setValue”? Is this from OpenHAB? Best recommendation I can say is watch what’s coming from OpenHAB into Node-red with a “debug” node then see below for formatting on how to write your function to change the openhab information on to homekit.

Air purifier nodes can take input/output of the following types (found by sending a nonsense JSON input and watching debug):

  • Name, Active, CurrentAirPurifierState, TargetAirPurifierState, LockPhysicalControls, Name, SwingMode, RotationSpeed

Air quality sensors can take these:

  • Name, AirQuality, StatusActive, StatusFault, StatusTampered, StatusLowBattery, Name, OzoneDensity, NitrogenDioxideDensity, SulphurDioxideDensity, PM2.5Density, PM10Density, VOCDensity, CarbonMonoxideLevel, CarbonDioxideLevel

The input/output for the HomeKit node would look like:

{"Active":true}
{"TargetAirPurifierState":1} //0 means off, 1 means idle, 2 means purifying air
{"CurrentAirPurifierState":} //0 means off, 1 means idle, 2 means purifying air
{"OzoneDensity":240}//range is 0 to 1000

Note for things with Target and Current state options you need to send both to/from homekit if you want homekit to show properly.

A great resource for seeing what can go in and out of HomeKit is the “HomeKit Accessory Protocol” document available through Apple developer program (free, have to register). If you’d like some help getting this hit me up with a private message I might be able to help. :wink:

The whole purpose of the functions is to change openhab terminology and format to homekit terminology and format.

I think that statement might help you figure out your next question as well:

“hasOwnProperty” is from openhab, right? You’ll need to “translate” that in node-red before sending it to homekit. Then if you get a brightness 45 from OH you send to homekit:

{"Brightness":45}

You can definitely do this but to watch for the output from HomeKit into the node-red system (msg.payload), you’ll be looking for:

msg.payload.Brightness != undefined

That would mean HomeKit is sending a brightness number and you can take it and send it back to OpenHAB to do with as you please.

It took me 2 or 3 days fiddling with my functions, watching input/output between openhab and homekit and node-red before I got comfortable with everything. I think that homekit protocol document would be helpful for you to find which items take which inputs.

Hopefully something here sends you in the right direction to make some progress. You can also export your flows and paste them here - then I (or someone else) could see and comment on which adjustments could be made.

I’m doing with Air Quality Sensor type. Injecting something only returns values like this:

Try one of these: Name, AirQuality, StatusActive, StatusFault, StatusTampered, StatusLowBattery, Name, OzoneDensity, NitrogenDioxideDensity, SulphurDioxideDensity, PM2.5Density, PM10Density, VOCDensity, CarbonMonoxideLevel, CarbonDioxideLevel

The data is from openHab, it is just a plain number. If I setup a node, after transforming for HomeKit, I can see something like this:

payload : {
                PM2.5Density : "4"
}

Well. I just tried to make a dummy Air Quality sensor on my node-red test system and I get the same error:

"TypeError: Cannot read property 'setValue' of undefined"

…I’m restarting node-red…standby…

I have added items which is almost the same as Air Quality Sensor, like Humidity sensor, it works as it should. Only this one has this problem! Maybe a bug?

Thanks for your help!

I think it might have something to do with the “.” in the “PM2.5” - I’m trying with PM10Density