I think an update on my HomeKit setup is in order, especially given that the last time I wrote about it at length was back in March, and a lot has happened since then.
My primary goal was to automate heating, and once I got an Apple TV 4K to act as a home hub and set up some basic automation everyone was pretty happy with the results, since we could step into a warm kitchen and office in the mornings, with heaters turned on (and off) around the house to match our typical schedules.
I still don’t have any decent way of monitoring power consumption (I’ve been pushing that back because it requires spending too much time fiddling with ways to point LEDs at the ancient rotating disk meters we have). But the results were worth it, with only three caveats:
- Some initial instability that appeared to go away once I upgraded to newer Sonoff-Tasmota firmware and changed the default settings to
WifiConfig 4
. - One socket tended to lose connectivity now and then (which I ascribed to coverage and later to the default firmware config, but never really figured out).
- Our cleaning lady tended to unplug things at random (both sockets and my Apple TV), which played havoc with some of the scheduling (you should always account for human factors).
As the cold season waned I disconnected most of the Sonoff S20 sockets and put them in storage for next year, but two are still in operation (one to switch on a foot lamp a little before sunset and another as a Wi-Fi canary/testing device in my office). I’ve had zero real issues with them for over six months1.
Beyond Heating
Besides that one lamp, I didn’t tackle any lighting automation (which apparently surprises a lot of people). We have enough natural light that it just isn’t something interesting to do, even though I did wire up a WS2812 RGB LED ring to a WeMos D1 clone2 to build a prototype mood light–which was fun, just not that interesting or useful.
My next stated target was dealing with the air conditioners, but over Summer I didn’t find a good way to completely automate them, partly because it’s trickier than I thought from an IR perspective (the devices sit under windowsills, and the IR blaster I have relies in ceiling reflections and simply can’t pump out enough power to compensate for the outside lighting), and partly because Summer is effectively still on, but not to the point where they were needed.
We did, however, set up timed shutdown via their arcane remotes for the few times we used them, and I captured some of the IR hex codes for later use.
The Tech
I’m running everything as Docker containers on my trusty old ODROID U2, which is around five years old but still better than a Raspberry Pi 3 (it has twice the RAM and EMMC storage, which makes it extremely reliable): I have an MQTT broker, HomeBridge and Node-RED containers talking to each other, and my own device shims running as user-level daemons using Piku:
A lot of people keep asking me if I tried HomeAssistant, and I did. But since I want to stick to managing things from iOS devices and don’t really need the added complexity I find it largely redundant.
I would probably have ditched Node-RED in the meantime (since I simply cannot get its HomeKit accessory support to work reliably), but it’s turned out to be useful for testing MQTT-related stuff and desigining simple dashboards (although to be fair it’s a pain to do anything data-related on it).
One of its saving graces is that I can actually edit flows and dashboards from my iPad (it pops up radial menus if you use a touch-enable device to access the Web UI), so I intend to keep using it as a front-end. I’d just like to have better ways to deal with data and nicer charts, since the default ones are somewhat utilitarian:
However, the thing that I would very much like to replace is HomeBridge. I’m not overly fond of it and its Node underpinnings, so I’ve been investigating Python (HAP-Python) and Go (HomeControl) alternatives with some degree of success–a few weeks back I built a Python accessory that is much better at dealing with my dumb TV/set-top-box combo via IR, and included a presence sensor shim that notifies me whenever the kids arrive home and turn on the TV (by detecting the Chromecast plugged into it3).
Hey Siri, is the kitchen on fire yet?
Once configured as part of a second HomeKit bridge, those shim accessories work well enough with Siri and the IR blaster to switch inputs, pause live TV and turn everything off (which are the things I most need to do), and I suspect I will be expanding them with Siri Shortcuts on iOS 12.
So, in a nutshell, I’m effectively running two HomeKit bridges: HomeBridge (with a plugin that talks MQTT directly to the Sonoff sockets), and my own Python bridge, which deals with all the UPNP and IR stuff required to control the media center.
And the base experience was just fine with iOS 11: even without Shortcuts, as long as you give proper names to your devices and rooms, Siri is perfectly capable of dealing with “switch off everything in the living room”, or answer queries like “is the office window open?”.
I keep leaving the window open and letting in mosquitoes, so a notification to go back and shut it after dinner is forthcoming–since Shortcuts can’t schedule things and the HomeKit app can’t do conditional alerts, I’m going to build another shim that will alert me and trigger a notification if the window is left open before bedtime.
Adding Zigbee Sensors
Although automation hasn’t yielded significant benefits during the warm season, I decided to start taking a serious look at adding more sensors. The main reason is that my ESP8266 temperature sensor works OK but is hardly nice to look at, with the added annoyance that battery life is still on the short side (I’m tracking this GitHub issue in the ESP8266/Arduino project, which will eventually provide a fix, but it’s taking too long).
Thanks to a friend’s recommendation (hi Paulo!) I decided to start looking at the Xiaomi Aqara product range, which uses Zigbee–something I’d shied away from due to compatibility hassles but that is perfect for low-power, long-lasting sensors.
A bit more digging led me to the zigbee2mqtt
project, which has a rather impressive compatibility list and allowed me to build my own gateway by using an USB dongle with the CC2531 chipset (currently €5), which has the nice bonus of isolating IoT devices from my Wi-Fi network.
The Xiaomi gateway is HomeKit compatible, but I wasn’t interested in that–the sensors, though, were another matter, since they are rather nicely turned out pieces of hardware and some of them can be gotten off AliExpress by around €10 including shipping:
So I ordered some Aqara gear (a couple of contact sensors, a couple of temperature sensors and a couple of vibration sensors) along with the dongle and TI flashing cables, and spent this weekend setting things up. I started by flashing the dongle and figuring out a way to encase the naked circuit board, since it is not something I want to leave unprotected. Fortunately, there is a readily available 3D printable cover for it (which has a decorative hole that lets in dust, but that’s fixable with a sticky label):
While that was printing, I built my own Docker image for the gateway (there is an official zigbee2mqtt
container image for ARM and Intel, but I like having more control), mapped /dev/ttyACM0
into the running container (which required some fiddling, but nothing special), and set up the devices using this nice Node-RED web dashboard:
Integration
The contact sensors were trivial to add to my Python gateway, and I’m currently in the process of doing the same for the temperature ones. But to have immediate feedback and a better feel for when they reported link and battery status (which isn’t done on every update) I simply whipped up a temporary MQTT logger in Node-RED:
This feeds into the nice little dashboard shown at the top of this piece, which is mobile-ready and did the trick until I finished wiring up the devices to HomeKit.
Caveats
Software-wise, everything is peachy. I have less than 500 lines of my own code to do everything I want, but even then I’m keen to find the time to rip out HomeBridge and my Python shims and redo the whole thing in Go, because even though things work and are quite easy to code, I would like to make it all more efficient and eventually move all the gateways to a Raspberry Pi Zero.
As to why code at all, I actually prefer writing code for sensor correlations rather than try to wire things up in Node-RED, where any kind of complex logic invariably deteriorates into my swearing at Undefined
values and trying to debug stuff in a browser.
Hardware-wise, so far only the vibration sensor has given me trouble–partly because it’s harder to pair with the Zigbee gateway for some reason, and partly because it’s not fully supported yet. Moving it around and even walking past it generates some interesting debug log entries in the gateway, but I’m happy to wait until it’s fully debugged and merged.
But most importantly, I’m still figuring out Zigbee radio coverage and range limitations.
The farthest sensor updates less frequently than the nearest, and even though it is amazing that it even works at all (our walls are a mix of brick and concrete, and the flat partially wraps around an elevator shaft and adjoining pillars), it does work.
But I don’t like the signal levels in more extreme locations around the house and don’t want to relocate the current gateway, so I’m currently considering ordering a couple more CC2531 dongles (which can be reflashed as Zigbee routers and stuck in vacant USB ports) and seeing if I can get a mesh going.
I’ll also obviously be adding a few more contact and temperature sensors, and possibly experimenting with other Zigbee gadgetry.
Opportunities for Extra Fun
What I’m still looking for, though, are two simple things: The first is a doorbell sensor–I don’t want to wire anything up to the actual doorbell, but since it’s a metal chime I was expecting the contact sensor (which is essentially magnetic) or the vibration sensor to be able to detect when it rings. Alas, partially disassembling the doorbell to squeeze the sensors in closer to the chime didn’t yield any useful results.
I suspect I’ll have to build my own, or hack a contact sensor to get the magnetic reed deeper inside the doorbell mechanism.
The second is an MQTT-triggered buzzer/alert light to act as a doorbell extender, but that’s almost trivial, and I intend to re-purpose my RGB LED gadget for that once I can actually detect doorbell rings. Or, if I’m feeling lazy, I’ll just pop down to IKEA and grab some TRÅDFRI gear.
I just have to remember to not go there during one of their discount weekends (I value my sanity too much to be caught in one of those rushes).
-
Whenever the foot lamp fails to turn on, for instance, it almost invariably is due to something wrong with HomeBridge or my Apple TV having been unplugged during dusting. ↩︎
-
You can do it with Tasmota firmware and map it to HomeKit just fine, and I will probably build a bigger one once I find a decent frosted glass enclosure. ↩︎
-
I’ve put up the code for both Chromecast and Mediaroom detection on this gist in case anyone is interested. I decided against using
asyncio
this time because UDP handling is… just weird. ↩︎