Homebridge and HEOS
I love voice assistants, I really do. While I have some privacy concerns with Google and certainly Amazon, if I'm going to compromise for convenience, I'm at least doing it with Apple. That means I've gone all in on HomeKit. Every "smart device" I have in my house is HomeKit-compatible. Except when it isn't.
HEOS by Denon
I have three HEOS 1 speakers by Denon all around my house. This model is discontinued, but is replaced by the Denon Home 150 which supports AirPlay 2 natively, which is amazing. When I upgrade, I'll likely go this route.
Only thing is, I can't necessarily control these with voice. And even if I get the new ones, they have Alexa built in, and I feel like I would disable that.
The only thing I really wished I had voice for was to group all the speakers (whole home audio) vs. when I want to ungroup them (and control them individually). For example, when we're cleaning the house, I like to have the music everywhere. But, when I put the kids to bed at night, I only want to play their StoryNory on the upstairs speaker.
Boy, I sure wish I had a way to group and ungroup the speakers with Siri.
Homebridge to the Rescue?
I had heard about Homebridge, a project which describes itself as "HomeKit support for the impatient":
Homebridge allows you to integrate with smart home devices that do not natively support HomeKit. There are over 2,000 Homebridge plugins supporting thousands of different smart accessories.
One thing I love about Homebridge is that it's all based on Node and NPM, so it was already in my wheelhouse in terms of setting it up, and even potentially writing plugins.
How does this help HEOS?
Well, the good news is that the HEOS speakers actually have a telnet API!
Even as I write this, I see more tools and packages for controlling HEOS devices than I did originally, but I certainly took note of a heos-api NPM package. But, I decided to keep things simple.
Controlling the HEOS
First, to see if I could control the heos at all, I used the HEOSpy package. This gives you a command-line tool called
heos_player that you can use to interact with your HEOS speakers using the API. You can then parse responses coming back from HEOS in JSON using the jq utility.
The glue that holds this all together is the
homebridge-script2 plugin. There are TONS of homebridge plugins out there to control any number of devices, but among the most simple and powerful is being able to execute Bash scripts by controlling a virtual "lightswitch" in HomeKit. To do this, you can use three scripts:
- one that turns the switch on
- one that turns the switch off
- one that returns the current state of the switch
According to the homebridge-script2 documentation:
The state.sh script in this case would be executed to check current state. Insure that this script outputs to stdout the matching on value as configured by the on_value config parameter. If the on_value matches the on value output of this script then the accessory will be determined to be on.
Here are my scripts, maybe they'll help you!
#!/bin/bash heos_player system/heart_beat heos_player player/set_volume -p pname="Upstairs" -p level="28" heos_player player/set_volume -p pname="Kitchen" -p level="28" heos_player player/set_volume -p pname="Living Room" -p level="28" heos_player group/set_group -p pid="-1415880048,1693331228,78765959" heos_player group/set_volume -p pid="-1415880048" -p level="28"
The pids are ones I had to discover by poking around in using heos_player and issuing some commands, but they're the unique "player IDs" of speakers on my network.
It recommends you wake up the system by doing a heart_beat first, then I set all the volumes to the same number, then I build the group, then I set the group volume.
#!/bin/bash heos_player group/set_group -p pname="Kitchen"
#!/bin/bash heos_player group/get_groups -lERROR | jq '.payload | length'