cover image
IoT

Control ZigBee LED Lights with Go Web App

Normally, when buying a home light that you want to control electronically, you need to install custom software. But with the ZigBee protocol and the RaspBee II gateway, you can use compatible devices and open source software. In this article I will show you how to add a custom Go API service to the stack.

In the following diagram, you can see the software stack that I use for the project:

Software stack

ZigBee

ZigBee is an IEEE 802.15.4-based specification for a suite of high-level communication protocols used to create personal area networks with small, low-power digital radios. It is often used in home automation, but also in other contexts like industrial production or medical devices. Its key feature is that it does not use much power. Therefore, it can often run on battery for a long time. The flip-side of this coin is that its data rate is also low. But for turning on and off lights this is enough.

When you buy a ZigBee enables device, like a LED light strip, you need a gateway to control the device.

RaspBee II Gateway

One such ZigBee gateway is the Raspbee II gateway that I use for this article. RaspBee II is developed by Dresden Elektronik in Germany and is an extension card that fits on a standard Raspberry Pi. RaspBee II comes with a software application called "deCONZ" that interfaces with the hardware.

The great thing about deCONZ is that you can integrate it easily with Home Assistant, thereby allowing you to control the ZigBee gateway directly within Home Assistant.

Home Assistant

Home Assistant is a widely used open source home automation application. It was originally developed by Paulus Schoutsen and initially released in 2013. It is written in Python and has a web interface but also releases mobile apps.

In Home Assistant you can add deCONZ as an integration. Thereby, your ZigBee devices that are recognized by deCONZ are also available in Home Assistant. Then, you can configure simple automation routines. For example, if you have a motion detector device, you could add an automation routine that whenever a movement is detected, the lights turn on.

But for our purpose, we want to integrate MQTT and control the lights via MQTT.

Mosquitto

MQTT is a light-weight publish-subscribe protocol that is often used in home automation scenarios. Applications can communicate with each other with a publish-subscribe messaging mechanism. In our case I use it to control the state of the LED lights.

But first, we need to install a MQTT broker. One popular open source MQTT broker is Eclipse Mosquitto. It is easy to install and configure. In my case I installed it together on the same machine where Home Assistant runs.

Then, you configure an automation in Home Assistant that reacts to messages received on a MQTT channel and turns the LED lights on or off.

You can see my configuration in the follwing screenshot:

Home Assistant MQTT

As MQTT topic I chose "/homeassistant/sleep-light", but the naming is up to you. It just needs to be consistent with the Go web application we program later that publishes a MQTT message.

Once Home Assistant is configured, it listens for incoming MQTT messages on the topic "/homeassistant/sleep-light" and toggles the LED light accordingly.

Now we need to create a REST API and a simple web application to control the lights.

Go App

For writing the REST API and the simple web application, I chose Go as the programming language. With Go it is easy to compile to ARM architecture processors. Also, deployment is straightforward on the Raspberry Pi.

This is the source code of the Go application:

package main

import (
	"fmt"
	"os"

	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/gofiber/fiber/v2"
)

func main() {
	broker := "tcp://your-server:1883"
	clientID := "go-mqtt-publisher"
	topic := "/homeassistant/sleep-light"
	message := "TOGGLE"

	opts := mqtt.NewClientOptions().AddBroker(broker).SetClientID(clientID)
	client := mqtt.NewClient(opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		fmt.Println(token.Error())
		os.Exit(1)
	}

	app := fiber.New()

	app.Get("/", func(c *fiber.Ctx) error {
		return c.SendFile("./public/index.html")
	})

	app.Get("/v1/lights", func(c *fiber.Ctx) error {
		token := client.Publish(topic, 0, false, message)
		token.Wait()

		if token.Error() != nil {
			return c.SendString(token.Error().Error())
		} else {
			return c.SendString("Toggled lights!")
		}
	})

	app.Listen(":3005")
}

As a REST API framework I use Fiber. The MQTT library is Paho MQTT. Before you run this Go app, you need to adapt the "broker" endpoint to your server. This application listens on the GET "/v1/lights" endpoint and sends out a MQTT message to the Mosquitto MQTT broker. Since Home Assistant listens for these kind of MQTT messages, once you invoke the REST endpoint, the LED lights toggle.

One missing piece is the web application. It is a simple button that invokes the "/v1/lights" GET endpoint. Thus, the lights are toggled when the button is pressed.

Here is the web application:

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Lights Toggler</title>
  </head>
  <body>
    <button id="myButton" style="font-size: 60px; padding: 10px 20px;">Toggle Lights</button>

    <script>
      document
        .getElementById("myButton")
        .addEventListener("click", function () {
          var xhr = new XMLHttpRequest();
          xhr.open("GET", "http://your-server:3005/v1/lights", true);
          xhr.send();
        });
    </script>
  </body>
</html>

This web page gets delivered to the browser via the "/" endpoint as configured in the Go Fiber application.

In the web page I used XMLHttpRequest() instead of the now standard fetch() because the website has to work on legacy browsers for me. If this is not the case for you, then you can substitute these lines with fetch().

Now you can control the ZigBee lights with a web application and an API.

This brings to an end our story of how to control ZigBee LED lights with a web application. I hope you enjoyed the ride.

Conclusion

As you could see from this article, integrating a LED ZigBee light into the word of web standard like HTTP and web applications requires quite some pieces. But luckily, many parts are open source and freely available. I am sure there are other ways to reach the same goal, and I would love the hear your story. You can contact me by pressing the contact button below.

References

Cover photo by Dejan Nasteski on Unsplash

Published 14 Mar 2024
Thomas Derflinger

Written by Thomas Derflinger

I am a visionary entrepreneur and software developer. In this blog I mainly write about web programming and related topics like IoT.