My Quest for Home Automation, Part 2

It’s been entirely too long since I last wrote about my home automation setup and a number of other things have started cropping up, so this is a more pragmatic update to point out some of the pitfalls and outline what else I’ve been doing with my HomeKit setup.

Node-RED May Save You, Or Make You Mad

I’m running a Node-RED instance on my ODROID alongside HomeBridge, and as it turns out it too can talk directly to HomeKit and publish virtual accessories, buttons or sensors. It has some pretty nifty features (I can, for instance, build up live dashboards of input data, bridge web services with HomeKit or MQTT, and even run my own automation), but it can be a right mess to “program” and debug, leading to some situatious that would give Rube Goldberg pause.

Grabbing multicast packets and updating virtual HomeKit sensors.

Besides requiring a fair amount of hidden code inside those bubbles (and a few specific plugins), these things aren’t versionable (so no source control), and debugging requires sticking little green boxes all over the place and figuring out how to filter the relevant logs on the web UI, which just doesn’t scale.

The thing is, there aren’t many options out there right now–I would be happy as a clam if I could simply run everything as a set of tiny Python daemons exchanging messages via MQTT, but there aren’t that many HomeKit implementations out there, and right now Node-RED is OK for quick and dirty experimentation1.

Naming Things Is Hard

Getting voice control to work through the Apple Watch turned out to be a fun little game of charade, since Siri figures out what you want to do largely through the names you give accessories, and Apple has lobotomized it to the point where it cannot fathom context at all, so any mention of “play”, “pause” or “start” is invariably tied to built-in iOS apps.

“TV” is somewhere in an unfathomable limbo, because “Start TV” or “Play TV” can’t be made to work, but I was able to assign “Pause TV” to a fake accessory and wire that up to my IPTV set-top box:

Faking the virtual 'rose' button for the MEO MediaRoom setup.

Proper English, however, seems to be beyond Siri’s ken, so after some experimentation “Heater by the Sofa” was shortened to “Sofa Heater”. Setting scenes works fine (as does “turn off everything in the living room” or “all the outlets”), but be prepared for naming things in awkward and inconsistent ways in order to get voice control to work.

Sonoff-Tasmota Firmware Is Still a Work In Progress

I now have ten S20 ITEAD sockets flashed with Sonoff-Tasmota, three of which are spares (they are that cheap).

They’re all running version 5.11.1, but two of them keep hanging, requiring them to be reset to factory defaults (four quick button presses) and re-configured.

Among the many suspects (cleaning lady unplugging them to power the vacuum, Wi-Fi signal variations and firmware instability), I haven’t yet been able to pinpoint the actual issue, but the end effect is disconcerting: the sockets reboot every minute or so, toggling the relay due to the way ITEAD wired it to the GPIO pins (which are cycled on reset by the base firmware).

Number Four, crashing suspiciously near the time the corridor was vaccuumed.

To mitigate/debug this, I’ve been doing a few things:

  • The devices report telemetry data since day one (including RSSI and Wi-Fi BSSID) on the tele/# MQTT topic.
  • I’ve (manually) set all of them to use WifiConfig 4, which means they will keep retrying to connect to Wi-Fi rather than fall back into configuration mode (bewilderingly, this is not the default, which took me a while to realize).
  • I’ve also set all of them to PowerOnState 0, which means they default to be powered off when plugged back in.
  • The two problematic sockets now have syslog enabled as well, which so far has yielded no new insights.

Setting the parameters above requires you to use the web console or MQTT commands, and (maddeningly) neither are part of the web interface. I’m still fascinated by WifiConfig defaulting to re-entering configuration mode upon signal loss and not retrying the connection and filed an issue accordingly, but I don’t think it will get fixed without some serious refactoring of Wi-Fi settings.

Dumb Appliances are Another Challenge

In order to control my air conditioner and other appliances, I got my hands on a Broadlink RM Mini 3, which is nothing more than a glorified IR blaster–but one that looks nice and is relatively unobtrusive.

The very first thing I did was build a simple MQTT proxy for it, so that I could control any IR device by publishing hex codes to a topic:

#!/usr/bin/python -u
import os, pwd
import paho.mqtt.client as mqtt
import broadlink

def on_connect(client, userdata, flags, rc):
    print "connected"

def on_message(client, userdata, msg):
    print msg.topic, msg.payload

def on_send(client, userdata, msg):
    print devices, msg.payload
    try:
        if devices and len(devices):
            devices[0].send_data(msg.payload.decode('hex'))
    except Exception as e:
        print e

def run():
    c = mqtt.Client("mqtt_ir")
    c.on_connect = on_connect
    c.on_message = on_message
    c.connect("localhost")
    c.subscribe([("broadlink/#",0)])
    c.message_callback_add("broadlink/send", on_send)
    c.loop_forever()

if __name__ == '__main__':
    devices = broadlink.discover(timeout=5)
    if devices and len(devices):
        devices[0].auth()
        print devices
    else:
        print "no Broadlink devices"
    run()

However, this only provides part of the solution–in order to control things, you need to be aware of their state, so I ended up spending a good deal of time trying to figure out how to cope with some fairly simple notions, such as detecting whether the TV is on.

As it turned out, that bit was relatively easy, since I have a Chromecast plugged into it:

Messing about with Chromecast SSDP announcements. Yes, there's some XML involved.

However, turning Chromecast state into TV state and tying it to IR commands gets hairy fairly quickly:

Trying to set state sanely

In the end, though, it’s a lot simpler to just ignore current state and do some tricks with the IR codes (avoiding power on/off toggles and sending out, for instance, HDMI input select codes to force power on).

HomeBridge Can Be Unnacountably Slow

Every now and then Siri complains that an accessory isn’t responding, or the Home App on my iPhone effectively locks up with every accessory displaying an “Updating…” message.

At first I thought this was because I had my iPad set as the Home Hub and it had trouble connecting to HomeBridge, since everything would go back to normal after a minute or so. However, after a few months, it was obvious that relying on my iPad for scheduling wasn’t the way to go, so I caved in and got a new Apple TV 4K.

Response times have improved, but the unnacountable pauses are still there, and I’ve noticed that only HomeBridge accessories lock up–the ones I have bridged through Node-RED respond immediately, so I’m starting to think about replacing HomeBridge itself (which isn’t going to be easy).

A Note On Security

One of the hassles about modern home automation is that nobody seems to have designed it with basic security principles in mind, and everyone assumes you’re running everything atop your home Wi-Fi network in the clear (or with otherwise elementary security precautions), or that you’re OK with having a device you don’t really control inside your LAN, exposing control points to the Internet–which is an iffy proposition even if they’re “secured” with SSL or use outbound connections (buffer overflows in embedded devices are a dime a dozen, and can you really trust every manufacturer to have top notch security?).

Google's take on home automation, with devices hooked up to the cloud. Scared yet?

I started out running devices on our family SSID for debugging purposes, but I’m fast reaching the point where it makes sense to move the whole shebang to a dedicated Raspberry Pi 3 that sits on both the wired LAN and a dedicated SSID for IoT. It’ll take a while, though.

Power Measurement

Finally, a FAQ of sorts–everyone who saw the original post asked me if I was looking into power measurements, and the answer is… well, not really, or at least not using these devices.

I’ve been looking into measuring overall wattage, but since all the electricity conduits and breakers are sealed, I can’t use a split-core clamp sensor (there’s no way for me to get at a single wire), and my meters are quite dated–I have two, which seem to be contemporaries, and they are both of the rotary digits/spinning disk variety, so there’s no nice, easy to get to blinking LED or any sort of digital interface).

So I’m doing it the hard way–I stuck a Raspberry Pi Zero in front of the meter, tweaked the camera lens for close range (just rotate the lens carefully with needlenose pliers) and have been playing with OpenCV and Azure Cognitive Services since November or so:

You gotta love OpenCV

It “works”, but not reliably enough due to the rotary digits, and I’ve yet to spend the time to train a dedicated digit recognizer–I gathered a nice, fat training set and started on it, but I ran out of time around Christmas and ended up passing the images to a friend for him to put together a demo, but it’s apparently really hard to get past 80% accuracy on this kind of meter reading, so I’m looking at other options.

And that’s all for this week.

I suspect I’ll eventually churn out another of these behemoth posts in a few months (probably concerning the nitty-gritty details of how I ripped out everything and rebuilt it in a slightly saner fashion), but this will have to do for now.


  1. Perhaps a tad too dirty, since it keeps crashing when I deploy more than one flow with HomeKit accessories–but since I’m running it in a container, it gets restarted automatically. ↩︎


See Also: