In this article I will explain how I created a simple wake-up light from an IKEA smartbulb that relies on Zigbee2MQTT running on a Raspberry Pi
Instead of doing the Azure project I had planned, I've been studying for the AZ-204 certificate on my free time. I decided to use my first vacation day to start and surprisingly finish a project that has been on my mind ever since I bought the Raspberry Pi. We have an IKEA Trådfri lamp in our bedroom and I wanted to turn it into a make shift wake-up light.
Not knowing at all what I was doing I started googling and found Zigbee2MQTT, which supports IKEA lightbulbs and remote control out of the box. As the name suggests, it also provides an MQTT setup which can be used to publish messages to the control topics. I will be using moquitto_pub to send control messages.
I then needed a Zigbee stick to connect the Raspberry Pi to the IKEA devices, and basically bought the first thing that I found in stock. It was a SONOFF Zigbee 3.0 USB dongle.
And of course I needed my trusty Raspberry Pi model 3 b+ and something to control with it. Supported devices can be found from here.
First thing I did was start from the Getting started page of the Zigbee2MQTT. I already had docker installed on my Raspberry so I could jump straight in. Finding the device location after plugging in my dongle was easy, as it printed the whole name of the device:
mituuz@raspberrypi:~ sudo dmesg | grep -A 5 -B 5 'Zigbee' [764059.436555] usb 1-1.2: new full-speed USB device number 5 using dwc_otg [764059.592285] usb 1-1.2: Product: SONOFF Zigbee 3.0 USB Dongle Plus V2 [764059.592298] usb 1-1.2: Manufacturer: ITEAD [764060.112726] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device [764060.113028] usbcore: registered new interface driver cdc_acm [764060.113047] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters mituuz@raspberrypi:~ $ ls -ltr /dev/ttyACM0 crw-rw---- 1 root dialout 166, 0 Jun 26 20:16 /dev/ttyACM0
Instead of worrying about the Zigbee networking adapters I could just get the container running. Replacing the device location in the docker-compose file and using a different port for the Zigbee2MQTT frontend as I already had something running on the 8080 port.
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: - 8088:8088 environment: - TZ=Europe/Helsinki devices: - /dev/ttyACM0:/dev/ttyACM0
The port and serial had to be changed to match on the configuration.yaml.
permit_join: true mqtt: base_topic: zigbee2mqtt server: mqtt://mqtt keepalive: 60 reject_unauthorized: true version: 4 serial: port: /dev/ttyACM0 frontend: port: 8088
Then I could start the docker containers and access the Zigbee2MQTT frontend from the port 8088 of the Raspberry Pi and connect the devices as instructed on the supported devices page.
To manually insert messages to the MQTT topic I installed mosquitto and mosquitto-clients.
sudo apt-get update sudo apt-get install mosquitto mosquitto-clients
When testing the initial setup I noticed that you can't have the light connecting to the remote and the Raspberry at the same time. To overcome this limitation I had to connect the remote to the Raspberry too. Using the bind functionality the remote could be used to control the light normally. This functionality was covered on the remote's page itself.
I spent some time playing with the frontend and mosquitto messages and found out that I could control the transition time of the light. This would make creating a wake-up light effect extremely easy. Instead of updating the values incrementally I could change the transition timer and update the brightness value of the light once.
I had some issues getting the messages to work, but after some digging and asking ChatGPT for help it pointed out that I was sending the messages to localhost instead of the docker container. To solve this, I populate an env variable at the beginning of the script.
MQTT_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' zigbeelights-mqtt-1)
With this I could create a script that:
Replace the {friendly_name} with the actual device name set on the frontend (or id).
echo 'Wakey wakey' $(date +"%Y-%m-%d %H:%M") # Get the IP address of the docker container MQTT_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' zigbeelights-mqtt-1) # Reset the light parameters mosquitto_pub -h $MQTT_IP -t zigbee2mqtt/{friendly_name}/set -m '{"color_temp": 250, "brightness": 2, "color":{"x": 0.3804, "y": 0.3767}}' # Turn on the light mosquitto_pub -h $MQTT_IP -t zigbee2mqtt/{friendly_name}/set -m '{"state": "ON"}' # Change transition time (30min) mosquitto_pub -h $MQTT_IP -t zigbee2mqtt/bridge/request/device/options -m '{"id": "{friendly_name}", "options":{"transition":1800}}' # Set brightness to max mosquitto_pub -h $MQTT_IP -t zigbee2mqtt/{friendly_name}/set -m '{"brightness": 254}' # Set a bash timer and log progress sleep 450 echo 'Quarter of the way there' $(date +"%Y-%m-%d %H:%M") sleep 450 echo 'Halfway point' $(date +"%Y-%m-%d %H:%M") sleep 450 echo 'Almost there' $(date +"%Y-%m-%d %H:%M") sleep 450 # Change the transition time back to instant mosquitto_pub -h $MQTT_IP -t zigbee2mqtt/bridge/request/device/options -m '{"id": "{friendly_name}", "options":{"transition":0}}' echo 'Wake up complete' $(date +"%Y-%m-%d %H:%M")
I wanted to have some logging so I included the echo commands and setup my cronjob to output to a log file. I setup three cronjobs for different days of the week.
30 4 * * 1,3-5 /home/mituuz/Projects/ZigbeeLights/morning-light.sh > /home/mituuz/Projects/ZigbeeLights/morning.log 2>&1 40 6 * * 2 /home/mituuz/Projects/ZigbeeLights/morning-light.sh > /home/mituuz/Projects/ZigbeeLights/morning.log 2>&1 40 7 * * 6-7 /home/mituuz/Projects/ZigbeeLights/morning-light.sh > /home/mituuz/Projects/ZigbeeLights/morning.log 2>&1
This is just one application for the Zigbee2MQTT that could be used and the supported devices list seemed to be quite long. I will definitely be coming back and seeing what else I could do with this setup.