/zigbee-steward

ZigBee hub

Primary LanguageGo

ZigBee-Steward

DEPRECATED

This was a fork of dyrkin/zigbee-steward, however due to being unable to get into contact with regards to contributions and licenses I have abandoned the work.

If you're interested in Zigbee and Golang, please see my new suite of Zigbee libraries under Shimmering Bee.

Overview

Bla bla bla

Example

In this example, we are going to send toggle command to IKEA TRÅDFRI bulb using Xiaomi Aqara Wireless Remote Switch. To prepare, follow the steps:

  1. Connect ZigBee stick cc2531 to USB;
  2. Flash it using instruction: https://www.zigbee2mqtt.io/getting_started/flashing_the_cc2531.html;
  3. Run the example;
  4. Pair IKEA TRÅDFRI bulb by repeating 6 ONs and 5 OFFs one by one (ON -> OFF, ON -> OFF, ON -> OFF, ON -> OFF, ON -> OFF, ON);
  5. Pair Xiaomi Aqara Wireless Remote Switch by holding the button for ~10 seconds until blue LEDs start blinking.

Now you can toggle the bulb using the remote switch. Just click on it.

import (
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"github.com/dyrkin/zcl-go/cluster"
	"github.com/dyrkin/zigbee-steward"
	"github.com/dyrkin/zigbee-steward/configuration"
	"github.com/dyrkin/zigbee-steward/model"
	"sync"
)

//simple device database
var devices = map[string]*model.Device{}

func main() {

	conf := configuration.Default()
	conf.PermitJoin = true

	stewie := steward.New(conf)

	eventListener := func() {
		for {
			select {
			case device := <-stewie.Channels().OnDeviceRegistered():
				saveDevice(device)
			case device := <-stewie.Channels().OnDeviceUnregistered():
				deleteDevice(device)
			case device := <-stewie.Channels().OnDeviceBecameAvailable():
				saveDevice(device)
			case deviceIncomingMessage := <-stewie.Channels().OnDeviceIncomingMessage():
				fmt.Printf("Device received incoming message:\n%s", spew.Sdump(deviceIncomingMessage))
				toggleIkeaBulb(stewie, deviceIncomingMessage)
			}
		}
	}

	go eventListener()
	stewie.Start()
	infiniteWait()
}

func toggleIkeaBulb(stewie *steward.Steward, message *model.DeviceIncomingMessage) {
	if isXiaomiButtonSingleClick(message) {
		if ikeaBulb, registered := devices["TRADFRI bulb E27 W opal 1000lm"]; registered {
			toggleTarget(stewie, ikeaBulb.NetworkAddress)
		} else {
			fmt.Println("IKEA bulb is not available")
		}
	}
}

func toggleTarget(stewie *steward.Steward, networkAddress string) {
	go func() {
		stewie.Functions().Cluster().Local().OnOff().Toggle(networkAddress, 0xFF)
	}()
}

func isXiaomiButtonSingleClick(message *model.DeviceIncomingMessage) bool {
	command, ok := message.IncomingMessage.Data.Command.(*cluster.ReportAttributesCommand)

	return ok && message.Device.Manufacturer == "LUMI" &&
		message.Device.Model == "lumi.remote.b186acn01\x00\x00\x00" &&
		isSingleClick(command)
}

func isSingleClick(command *cluster.ReportAttributesCommand) bool {
	click, ok := command.AttributeReports[0].Attribute.Value.(uint64)
	return ok && click == uint64(1)
}

func saveDevice(device *model.Device) {
	fmt.Printf("Registering device:\n%s", spew.Sdump(device))
	devices[device.Model] = device
}

func deleteDevice(device *model.Device) {
	fmt.Printf("Unregistering device:\n%s", spew.Sdump(device))
	delete(devices, device.Model)
}

func infiniteWait() {
	wg := &sync.WaitGroup{}
	wg.Add(1)
	wg.Wait()
}

Full examples