Monthly Archives: December 2017

Hooking up Harmony Hub and generic ZigBee Lights to HomeKit

Home automation seems to be the rage this christmas, with gadgets to control lights, heating and entertainment systems wirelessly, maybe even with only your voice.

I’ve been using Logitech’s Harmony Hub for many years now, and are very happy being able to switch on all devices needed and set them to the right channels: the TV, the surround receiver, the TV and an Apple TV, Fire TV or Bluray player, with single button press on a single remote.

Harmony Hub isn’t supported by Apple’s HomeKit, but so far, that wasn’t really a concern, since I wasn’t using anything else that would be able to be controlled by HomeKit. But in December, I broke down and got a bunch of Philips Hue lights. Naturally, tying Hue and Harmony together became a challenge.

I also have a number of light fixtures that Philips has no bulbs for; I decided to get an Osram Lightify Smart Plug to be able to at least turn the light off and on through the system. While it’s simple to connect the Smart Plug to the Hue controller, Philips somehow fails to offer up 3rd-party devices to either HomeKit or Hub. (Ikea Tradfri components seem to suffer the same fate.)

So I started looking around, to find a way to control everything through a single interface. It seems that HomeKit together with homebridge manages to do exactly what I want: offer all devices connected to the Hue hub to HomeKit (through homebridge-hue), and allow me to control the Harmony Hub (through homebridge-harmonyhub).

Here’s how I got this all working in FreeBSD.

Installing homebridge on FreeBSD

Creating a user

homebridge is a daemon process that mediates between HomeKit, Hue and Harmony. As such, it needs to run permanently. For security reasons, we do not want to run homebridge as root, but as a less privileged user homebridge. To create the user, I used vipw and consulted /usr/ports/GIDs to look for an id in the range below 1000 that is not yet used by any port. Instead of vipw, you can use adduser(1). I gave the user /usr/sbin/nologin as a shell since we’re never going to log in directly as a user.

Installing packages

There is no FreeBSD port for homebridge, but the installation is relatively straightforward. The installation instructions for homebridge insist that the NPM must be installed globally; I briefly tried to install locally, but couldn’t get it work.

Let’s start with the prerequisites, and a hack:

# pkg install npm-node8 avahi-libdns
# ln -s /usr/local/include/avahi-compat-libdns_sd/dns_sd.h /usr/local/include

The FreeBSD port for avahi-libdns puts the include file into its own subdirectory (so it won’t conflict with mDNSResponder), but the NPM packages expect it to be in /usr/local/include. The easiest way to fix this is to create the symlink. Since I’m running avahi, I have not investigated how to run homebridge with mDNSResponder.

After this, we can starting installing the NPM packages:

# npm install -g mdns
# npm install -g --unsafe-perm homebridge
# npm install -g homebridge-hue homebridge-harmonyhub

As of homebridge-harmonyhub 0.2.1, you’ll need to hack the broadcast address that it uses to find the Harmony Hub. Edit /usr/local/lib/node_modules/homebridge-harmonyhub/node_modules/harmonyhubjs-discover/lib/ping.js and change the address in line 9 to the appropriate broadcast address for the network that your Hub is connected to. For example:

this.address = '192.168.1.255';

Configuring Homebridge

Create a config file in the homebridge users’ home directory, as .homebridge/config.json. I created the initial file like this:

{
    "bridge": {
        "name": "Homebridge",
        "username": "CC:22:3D:E3:CE:30",
        "port": 51826,
        "pin": "031-45-154"
    },
    
    "description": "My Homebridge",

    "accessories": [
    ],

    "platforms": [
        {
            "platform" : "Hue",
            "name" : "Hue",
            "users": {
            },
            "lights": true,
            "nativeHomeKit": false,
            "sensors": true,
            "excludeSensorTypes": ["CLIPPresence", "Geofence"]
        },
        {
            "platform": "HarmonyHub",
            "name": "Hub",
        }
    ]
}

Then, start homebridge for the first time:

sudo -u homebridge homebridge

The output from this is important in two ways: homebridge-hue will connect to the Hue bridge, wait for you to press the button to authorise the pairing, and then display the username and token for this connection. You’ll need to copy the output and add it to the users key for the Hue platform entry in the configuration. You will need to restart homebridge for this config change to become effective.

Also, the terminal output will show a QR code you can use to connect homebridge as a bridge to HomeKit, using the Home app on your phone or iPad. You can also enter the code manually, in this example the code is 031-45-154.

Running homebridge as a daemon

There’s (at least) two ways to run homebridge in the background: using tmux(1) or daemon(8)

WIth tmux(1) (or screen(1)), you can run a terminal session independent of the current login. You can detach from that session at any time, and it will continue to run; you can also re-attach at a later time. This allows you to start homebridge, observe all the log output, and then detach from the session, keeping it running. If you need to look at the log output, you can reattach. This is most useful while you’re optimising the configuration, or trying out additional plugins.

For a more production-oriented setup, you can use daemon(8) and an rc(8) script. The following script /usr/local/etc/rc.d/homebridge creates a service homebridge that you can enable and disable from rc.conf(5):

#!/bin/sh
#
# PROVIDE: homebridge
# REQUIRE: NETWORKING SYSLOG
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf to enable homebridge:
#
#homebridge_enable="YES"

. /etc/rc.subr

name="homebridge"
rcvar="homebridge_enable"

load_rc_config $name

: ${homebridge_user:="homebridge"}
: ${homebridge_enable:="NO"}
: ${homebridge_facility:="daemon"}
: ${homebridge_priority:="debug"}

command="/usr/local/bin/${name}"
procname="/usr/local/bin/${name}"
home="$(eval echo ~${homebridge_user})"

pidfile="/var/run/${name}.pid"

start_cmd="${name}_start"

homebridge_start() {
	/usr/sbin/daemon -S -l ${homebridge_facility} -s ${homebridge_priority} \
		-u ${homebridge_user} -p ${pidfile} \
		/usr/bin/env -i \
		"HOME=${home}" \
		"PATH=/usr/local/bin:${PATH}" \
		$command
}

run_rc_command "$1"

Now the last thing I need to figure out is which Siri commands to use to activate a scene. Then I can switch on the entertainment center and dim the lights with a single voice command!