Colored lights controlled by Kubernetes

In my apartment I control my lights using Zigbee2MQTT, Mosquitto (MQTT), and openHAB all running on Kubernetes. Here’s the how and why for this over-engineered nonsense.

But why?

You could probably get similar features with various smart home hubs. Philosophically, I am opposed to my lights relying on services outside of my control. My goals are:

  • Everything can run locally and if the internet is down.
  • No hard dependencies on third party services.
  • Control all properties of the lights programmatically. (On/off, color, etc.)
  • Automate deployment as much as possible.
  • Learn Kubernetes.

When it’s all working I can control my lights from anywhere using a VPN. I can also use other Zigbee devices like smart plugs to turn things on/off when I’m away. OpenHAB plugins open up a world of possibilities for controlling the lights.

Hardware

Tutorial

I run a single-node k3s cluster managed by Flux on Arch Linux. All the Kubernetes configs are defined on GitHub for reference.

Prerequisites

You should know the basics of Kubernetes. You should have a working Kubernetes cluster with a proxy like Traefik.

Set up services

Create zigbee2mqtt-values.yaml, mosquitto-values.yaml, and openhab-values.yaml (or use Flux). You can find my Flux configs in the GitHub repo, but you will need to modify them to fit your environment. You’ll probably also want an ingress so you can connect to openHAB.

At a high level, we have zigbee2mqtt for the Zigbee controller passing messages to mosquitto. OpenHAB subscribes to mosquitto and controls the lights by publishing messages.

Something like this will install the three helm charts and apply the configuration values:

helm repo add k8s-at-home https://k8s-at-home.com/charts/
helm repo add kilip https://charts.itstoni.com/

helm repo update

helm install zigbee2mqtt k8s-at-home/zigbee2mqtt -f zibgee2mqtt-values.yaml
helm install mosquitto k8s-at-home/mosquitto -f mosquitto-values.yaml
helm install openhab kilip/openhab -f openhab-values.yaml

Configure zigbee2mqtt

Start the pod with permit_join: true in /data/configuration.yaml and connect your Zigbee devices. Once paired, set permit_join: false and restart the pod. I did this manually by getting a shell in the zigbee2mqtt pod.

Configure openHAB

Configure openHAB using its web interface.

Configure MQTT Broker

  • Install the MQTT add-on.
  • Create a new Thing of type MQTT Broker and set the Broker Hostname/IP to mosquitto.

Philips Hue configuration

Philips Hue color lights require some custom channel transformations. For each bulb, create a Thing of type Generic MQTT Thing with a Color channel and Switch channel. Find the device IDs in /data/configuration.yaml under devices.

Color channel

You will need to install the JS Scripting add-on. To encode the outgoing color, I wrote the following script to be placed in /data/config/transform/color.js in the openHab container:

(function(i) {
    var pieces = i.split(',')
    var x = pieces[0]
    var y = pieces[1]
    var bri = pieces[2] * (254/100)
    return JSON.stringify({color: {x: x, y: y}, brightness: bri})
})(input)

For the Color channel, select type Color Value (HSB, RGB, or CIE xyY) and set the following values (suppose 0x0123456789012345 is the bulb’s ID):

PropertyValue
Color ModeCIE xyY
MQTT State Topiczigbee2mqtt/0x0123456789012345
MQTT Command Topiczigbee2mqtt/0x0123456789012345/set
Incoming Value TransformationsJINJA:{{value_json["color"]["x"]}},{{value_json["color"]["y"]}},{{value_json["brightness"]}}
Outgoing Value TransformationsJS:color.js
Outgoing Value Format%s

Switch channel

For the Switch channel, select type Switch and set the following values (suppose 0x0123456789012345 is the bulb’s ID):

PropertyValue
MQTT State Topiczigbee2mqtt/0x0123456789012345
MQTT Command Topiczigbee2mqtt/0x0123456789012345/set
Custom On/Open ValueON
Custom Off/Close ValueOFF
Incoming Value TransformationsJSONPATH:$.state
Outgoing Value Transformation(leave blank)
Outgoing Value Format%s

Conclusion & Possible Mistakes

While complicated to set up, this home automation strategy requires minimal maintenance once running. If you’re willing to put in the effort, you get an extremely customizable set up that doesn’t depend on any third-party services for operation.

Some mistakes I ran into:

  • WiFi interferes with Zigbee, so I had to move my WiFi access point away from the Zigbee controller.
  • Using a low power device (Raspberry Pi 4) instead of a desktop PC caused connection issues.

Please feel free to suggest changes to this post if you ran into any issues following this guide!


  1. I tried using Raspberry Pi 4s, but they were not powerful enough and would frequently drop messages causing shenanigans with the lights. Not ideal unless you like debugging in the dark. ↩︎