Post 6: Controlling a Smart Outlet with Kubernetes (Z-Wave + Home Assistant)

Z-Wave logo

Home automation is one of the key focuses of my project, as it's one of the areas where privacy and security matter the most but also an area where many consumer devices skimp on. It's also unusual to see Kubernetes handling this; most k8s demos tend to be a bit more focused on webservers or enterprise software.

For my lab I'll be using a Z-Wave USB dongle to communicate with Z-Wave smart devices. The stick is plugged into a Raspberry Pi, which will talk via MQTT to Home Assistant running on Kubernetes, an application which provides an easy to use web dashboard. The setup is summed up by this diagram:

Setting up the Raspberry pi

  1. Set up the Raspberry Pi with an OS of your choice. In my case I'm using Ubuntu Server for Raspberry Pi. Set the server to use a static IP, and optionally you can also set up a DNS resolver entry for the Pi in your router.
  1. Install Docker on the Pi. You can do so easily with the following script (Ubuntu specific, for other distros see the docker website):
# Remove old docker if it exists
sudo apt-get remove docker docker-engine docker.io containerd runc
# Update dependencies
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg software-properties-common
# Docker repo key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker latest runtime
sudo apt update
sudo apt install -y docker-ce docker-ce-cli docker-compose-plugin
# Add current user to docker group (so you can use docker without sudo)
sudo groupadd docker
sudo usermod -aG docker $USER
  1. Plug in your zwave usb dongle.
  1. Find the id of the serial device you just plugged in. You can list all serial devices using ls /dev/serial/by-id/.
  1. Create a docker-compose file for zwavejs2mqtt:
cat <<EOF > docker-compose.yml
version: '3.7'
services:
  zwavejs2mqtt:
    container_name: zwavejs2mqtt
    image: zwavejs/zwavejs2mqtt:latest
    restart: always
    tty: true
    stop_signal: SIGINT
    environment:
      - SESSION_SECRET=mysupersecretkey
      - ZWAVEJS_EXTERNAL_CONFIG=/usr/src/app/store/.config-db
      # Uncomment if you want logs time and dates to match your timezone instead of UTC
      # Available at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
      # - TZ=America/Los_Angeles
    networks:
      - zwave
    devices:
      # Do not use /dev/ttyUSBX serial devices, as those mappings can change over time.
      # Instead, use the /dev/serial/by-id/X serial device for your Z-Wave stick.
      - '/dev/serial/by-id/insert_stick_reference_here:/dev/zwave'
    volumes:
      - zwave-config:/usr/src/app/store
    ports:
      - '8091:8091' # port for web interface
      - '3000:3000' # port for Z-Wave JS websocket server
      - '1883:1883' # mqtt
networks:
  zwave:
volumes:
  zwave-config:
    name: zwave-config
EOF
Replace mysupersecretkey with a key of your choice. You can generate one easily using openssl: openssl rand -hex 15. Replace insert_stick_reference_here with the id from step 4. 
  1. Start the container:
docker compose up

Deploying home assistant

Over on the jumpbox machine, add the k8s-at-home helm repository (if you haven't done so already).

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

Create a values file:

cat <<EOF > home-assistant-values.yaml
env:
  TZ: America/Los Angeles
service:
  main:
    type: LoadBalancer
persistence:
  config:
    enabled: true
EOF
Replace TZ with the timezone of your choice. A full list can be found here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Then install:

helm install home-assistant k8s-at-home/home-assistant -f home-assistant-values.yaml

Installing Mosquitto MQTT

Create a values file:

cat <<EOF > mqtt-values.yaml
env:
  TZ: America/Los Angeles
service:
  main:
    type: LoadBalancer
Replace TZ with the timezone of your choice.

Install the helm chart.

helm install mosquitto k8s-at-home/mosquitto

Now get the external IP address of the LoadBalancer service:

kubectl get svc mosquitto
NAME        TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
mosquitto   LoadBalancer   100.69.203.75   192.168.30.213   1883:30582/TCP   62d

The mqtt broker will be running at externalIP:1883.

Setting up zwavejstomqtt

Open the web ui at <raspberrypi ip>:8091. Configure the following:

  1. Set serial port to /dev/zwave under Settings → Zwave → Serial Port (this is where docker mounts the USB stick).
  2. Create network security keys under Settings → Zwave → Security Keys (S0 Legacy, S2 Unauthenticated, S2 Authenticated, and S2 Access Control). You can use the generate button (two arrows in each text box) to generate them for you.
  3. Under Settings → MQTT, add the MQTT information from earlier. For Host url use the LoadBalancer external IP, and for port use 1883.
  4. Under Settings → Home Assistant, enable MQTT Discovery.

Adding a device to zwavejstomqtt

Under the "Smart Start" tab, click on the + icon in the bottom right. If your Zwave device has a QR code on the side you can use the add using QR code option. Click on the option, grant the website camera access, and scan the QR code with your computer's webcam (or scan the info with your phones webcam and type it in manually). If your device does not have a QR code you can also add it manually using the DSK.

On the Control Panel page you should see a second device (with the first being the USB stick itself). If you click the device you should be able to control it, as well as query its data if it presents any. For example, for the smart outlet I have configured I can look at the historical power usage.

Adding MQTT to Home Assistant

Under Settings → Devices and Services → Add Integration (bottom right button), search for MQTT. Add the integration. Configure with the IP and port of the MQTT broker. Finally, go back to the dashboard. The added device should be visible.

Conclusion

Bit of a long article, but we configured a number services across different machines. Hopefully this helps you on your Kubernetes edge journey!