Thursday 18 November 2021

Homekit: Replacing the Ikea TRÅDFRI Gateway

For a couple of years I've been running a small automated homekit setup with the Ikea TRÅDFRI gateway.  It's been a bit of a rollercoaster ride, with everything working fine to start with, a few hiccups a bit later,  then getting better, and now just being almost unusable;  I can't connect to the gateway from the Ikea app, even though I'm only 10 feet away from the gateway, until I power cycle it, and then it only works for about a day before I need to do it all again.  Needless to say, at this point, none of the HomeKit automations work either.  An exercise in frustration.

A positive point of all the Ikea stuff I have bought (actually only bulbs and 2 power adapters) is that they are all Zigbee compliant, and so any Zigbee controller could be used.

One of my colleagues at work is a bit of a home automation expert, so I asked about his setup, and decided to bit the bullet and migrate to an all new setup using the Ikea devices.  It also means that I don't need to stick to Ikea in future in case I wanted to experiment with other vendors as well.  I had a spare Raspberry PI 3 lying around not doing much ( well, just running Pi-Hole for ad blocker and DHCP, but mostly idle) which I could use so decided to go this route.

I used the Zigbee2MQTT page as a starting point as to what adapter to get.  This was no mainly about what was available at the time, but I decided to go with the "Electrolama zig-a-zig-ah! (zzh!)" from the Zigbee2MQTT recommended devices, use a docker container on the Rasperry Pi to setup and run the Zigbee devices and use Home Assistant to act as a bridge between the devices and HomeKit on the Apple Ecosystem.

Zigbee Stick

The stick supplied doesn't come with any firmware on it at all, just code to flash the LEF when it is plugged in, so I needed first to flash the firmware.  There are instructions on the Electrolama web page for this for Windows and using a python program.  Also, when I ordered the stick, I didn't bother with the debug module.

Not having a windows machine around, I decided to go with the Python program which was remarkably easy on my Macbook Pro.  There are instructions on the page, specifically for Macintosh:


To run cc2538-bsl.py you need to install some extra python dependencies, python3 should already be shipped with macOS (Catalina onwards?). 

Download and extract cc2538-bsl: curl --output cc2538-bsl.zip https://codeload.github.com/JelmerT/cc2538-bsl/zip/master && unzip cc2538-bsl.zip 

Install required dependencies: $ /usr/bin/python3 -m pip install --user pyserial intelhex (As we cannot write to the system's location we need to install the dependencies with in the user location.)

After this, I put my stick in BSL mode by pressing the small button on the top and plugging into my USB port at the same time.  The device appeared as /dev/tty.usbserial*

I needed to download the firmware for co-ordinator usage as I was wanting to use this stand alone.  The link was on the main Zigbee2MQTT page, so I downloaded directly from there.  At this point, it was a simple case of running:

python3 cc2538-bsl.py -p /dev/tty.usbserial* -evw CC2652R_coordinator_20210708.hex

And the firmware.

Raspberry Pi

Docker.

As mentioned, earlier, I wanted to run the Automation in a container, so it would be way to start/stop and migrate to a new machine if necessary.

The Raspberry Pi, does not come with docker or docker-compose installed by default, but they are easy to install. https://dev.to/elalemanyo/how-to-install-docker-and-docker-compose-on-raspberry-pi-1mo gives a simple tutorial on installing docker and docker-compose.  It also has the benefit of restarting the containers, and hence the Homekit stuff if, for any reason, the Pi reboots.  I followed steps 1-6 and made sure everything was working successfully.

Next step was to create a directory for all of the zigbee/home automation code and config.

pi@bluepi:~ $ mkdir ~/zigbee

pi@bluepi:~ $ cd ~/zigbee

pi@bluepi:~/zigbee $ 

Hardware

The following are modifed from https://www.zigbee2mqtt.io/guide/getting-started/ with my local changes.


First, I plugged the stick into my Raspberry Pi. I then needed to determine the device that it was assigned to.


pi@bluepi:~/zigbee $ sudo dmesg

  [ deleted ]

usbcore: registered new interface driver ch341

usbserial: USB Serial support registered for ch341-uart

ch341 1-1.3:1.0: ch341-uart converter detected

usb 1-1.3: ch341-uart converter now attached to ttyUSB0

  [ deleted ]

pi@bluepi:~/zigbee $ ls -lL /dev/serial/by-id/

total 0

crw-rw---- 1 root dialout 188, 0 Nov 17 17:05 usb-1a86_USB_Serial-if00-port0

pi@bluepi:~/zigbee $ ls -l /dev/ttyUSB0

crw-rw---- 1 root dialout 188, 0 Nov 17 17:05 /dev/ttyUSB0

pi@bluepi:~/zigbee $ 




First I created a configuration file for docker-compose, using the device above.


pi@bluepi:~/zigbee $ cat docker-compose.yaml

version: '3.8'

services:

  mqtt:

    image: eclipse-mosquitto:2.0

    restart: unless-stopped

    volumes:

      - "./mosquitto-data:/mosquitto"

    ports:

      - "1883:1883"

      - "9001:9001"

    command: "mosquitto -c /mosquitto-no-auth.conf"


  zigbee2mqtt:

    container_name: zigbee2mqtt

    restart: unless-stopped

    image: koenkk/zigbee2mqtt

    volumes:

      - ./zigbee2mqtt-data:/app/data

      - /run/udev:/run/udev:ro

    ports:

      - 8080:8080

    environment:

      - TZ=Europe/London

    devices:

      - /dev/ttyUSB0:/dev/ttyUSB0

pi@bluepi:~/zigbee $ 

Since I'm running as the 'pi' users, and the permissions on the USB device above don't allow me to read/write to it, and I also had to run the usermod command to add 'pi' to the dialout group:

pi@bluepi:~/zigbee $ sudo usermod -aG dialout pi
pi@bluepi:~/zigbee $

Then a configuration file is needed. Yhis should be created under zigbee2mqtt-data/configuration.yaml after creating the zigbee2mqtt-data directory.  I added the homeassistant support in this file ready for later as well.

pi@bluepi:~/zigbee $ cat zigbee2mqtt-data/configuration.yaml

permit_join: true

mqtt:

  base_topic: zigbee2mqtt

  server: mqtt://mqtt

serial:

  port: /dev/ttyUSB0

frontend:

  port: 8080

homeassistant: true

advanced:

  network_key: GENERATE

pi@bluepi:~/zigbee $



Connect to the devices

Now it's time to start the docker images, and pair all the devices.  This is a simple case of running docker-compose.

The first time round, this may take some time as it will have to download images.  Subsequent calls to the command will be much faster.  The '-d' option to to disassociate from the terminal, so one they have started the shell prompt will appear.  After that we can run a 'tail -f' on the logs.  This can be interrupted with ^C at any time without stopping the docker image.

pi@bluepi:~/zigbee $ docker-compose up -d
    [ deleted ]
# Check the logs
pi@bluepi:~/zigbee $ docker-compose logs -f

Connect to the Zigbee web

The next stage was to connect to the Raspberry-Pi on port 8080 to ensure everything was working.  At this point it will be pretty much an empty page.

RePair all devices

At this point, I needed to re-pair all of the devices.  For the power adapters, it's a matter of pressing a small pin into the bottom for about 5 seconds until the LED flashes.  No problem.  The lights needed to be turned off and on 6 times at just the right amount of time between each on/off interval.  For some of the lights, this took about 5 or 6 attempts, but they all eventually went into pair mode and each appeared on the Zibgee web page.

As each was being paired, I changed the name of the device to something more reasonable.  At the end, the screen looked like this:


Set up Home Assistant and Homekit

I already added the homeassistant tag to the configuration file, above, so all this is needed is to add the Home Assitant information to the docker-compose file.  First, I created a directory "HA" in the zigbee directory for all of the Home Assistant configuration and storage.

Create a directory under zigbee and then add the following to the docker-compose file for HomeAssistant:

pi@bluepi:~/zigbee $ mkdir HA

pi@bluepi:~/zigbee $ cat docker-compose.yaml

  [deleted]

 homeassistant:

    container_name: homeassistant

    image: "ghcr.io/home-assistant/raspberrypi3-homeassistant:stable"

    volumes:

      - /home/pi/zigbee/HA:/config

      - /etc/localtime:/etc/localtime:ro

    restart: unless-stopped

# Example for HomeKit setup

    privileged: true

    network_mode: host

pi@bluepi:~/zigbee $


  1. Start up the docker images again and log on to Home assistant on the default port of 8123
  2. Set up account for the first time.

Now, back on the Raspberry-pi close all docker images down.

pi@bluepi:~/zigbee $ docker-compose down

Stopping homeassistant ... done

Stopping zigbee_mqtt_1 ... done

Stopping zigbee2mqtt   ... done

Removing homeassistant ... done

Removing zigbee_mqtt_1 ... done

Removing zigbee2mqtt   ... done

Removing network zigbee_default

pi@bluepi:~/zigbee $

Add 'homekit: and mqtt broker' information to homekit configuration.yaml file.

To edit this sudo will need to be used, as it will have been created by the root user.  i.e. sudo vi HA/configuration.yaml

pi@bluepi:~/zigbee $ cat HA/configuration.yaml 


# Configure a default setup of Home Assistant (frontend, api, etc)

default_config:


# Text to speech

tts:

  - platform: google_translate


group: !include groups.yaml

automation: !include automations.yaml

script: !include scripts.yaml

scene: !include scenes.yaml

homekit:

mqtt:

  broker: localhost

pi@bluepi:~/zigbee $ 

Start all the docker images again and then login to Home Assistant.

pi@bluepi:~/zigbee $ docker-compose up -d

Creating network "zigbee_default" with the default driver

Creating zigbee_mqtt_1 ... done

Creating homeassistant ... done

Creating zigbee2mqtt   ... done

pi@bluepi:~/zigbee $

Note: Notification about new devices with barcode will appear

Note: Scan in barcode on Phone Homekit app

Note: New devices will appear automatically.

Note: Move the devices to the correct rooms and carry on as normal, but just much faster now.

Conclusion

Take Aways:
  • Response from the new setup is much faster than with the original IKEA gateway.    Siri integration is more responsive as well.
  • A Raspberry PI 3 model B with 1G of memory is sufficient to run the Zigbee and Home Assistant software in a docker image, even with running Pi-Hole along side it.
  • It did take longer that it seems above; a few false starts trying to use the native Zigbee support in Home Assistant didn't work as expected, so moving to use MQTT messages was the better option.
  • Zigbee2MQTT has a net map feature that shows which devices are active and the string s of the signal between each one.
  • Home Assistant has a lot of scripting and reporting which can be used on the web page and there is an associated  iOS and Android app that can be used to control the devices as well as using HomeKit.

Summary for adding docker-compose.


In case the link forestalling docker-compose if offline, these are the steps.

Prerequisites

Raspberry Pi with a running Raspbian OS
  • SSH connection enabled


1. Update and Upgrade

First of all make sure that the system runs the latest version of the software.
Run the command:

sudo apt-get update && sudo apt-get upgrade

2. Install Docker

Now is time to install Docker! Fortunately, Docker provides a handy install script for that, just run:

curl -sSL https://get.docker.com | sh

3. Add a Non-Root User to the Docker Group

By default, only users who have administrative privileges (root users) can run containers. If you are not logged in as the root, one option is to use the sudo prefix.
However, you could also add your non-root user to the Docker group which will allow it to execute docker commands.

The syntax for adding users to the Docker group is:

sudo usermod -aG docker [user_name]

To add the permissions to the current user run:

sudo usermod -aG docker ${USER}

Check it running:

groups ${USER}

Reboot the Raspberry Pi to let the changes take effect.


4. Install Docker-Compose

Docker-Compose usually gets installed using pip3. For that, we need to have python3 and pip3 installed. If you don't have it installed, you can run the following commands:

sudo apt-get install libffi-dev libssl-dev
sudo apt install python3-dev
sudo apt-get install -y python3 python3-pip

Once python3 and pip3 are installed, we can install Docker-Compose using the following command:

sudo pip3 install docker-compose

5. Enable the Docker system service to start your containers on boot

This is a very nice and important addition. With the following command you can configure your Raspberry Pi to automatically run the Docker system service, whenever it boots up.

sudo systemctl enable docker

With this in place, containers with a restart policy set to always or unless-stopped will be re-started automatically after a reboot.