From 817a66d91348de8dc151966551ea41e5b8a8f78c Mon Sep 17 00:00:00 2001 From: Melair Date: Thu, 9 May 2024 22:06:44 +0100 Subject: [PATCH] Add identify ZCL cluster. --- commands/local/identify/identify.go | 30 ++++++ commands/local/identify/identify_test.go | 116 +++++++++++++++++++++++ commands/local/identify/register.go | 14 +++ 3 files changed, 160 insertions(+) create mode 100644 commands/local/identify/identify.go create mode 100644 commands/local/identify/identify_test.go create mode 100644 commands/local/identify/register.go diff --git a/commands/local/identify/identify.go b/commands/local/identify/identify.go new file mode 100644 index 0000000..78f99fa --- /dev/null +++ b/commands/local/identify/identify.go @@ -0,0 +1,30 @@ +package identify + +import "github.com/shimmeringbee/zcl" + +const ( + IdentifyTime = zcl.AttributeID(0x0000) +) + +const ( + IdentifyId = zcl.CommandIdentifier(0x00) + IdentifyQueryId = zcl.CommandIdentifier(0x01) + TriggerEffectId = zcl.CommandIdentifier(0x02) + + IdentifyQueryResponseId = zcl.CommandIdentifier(0x00) +) + +type Identify struct { + IdentifyTime uint16 +} + +type IdentifyQuery struct{} + +type TriggerEffect struct { + EffectIdentifier uint8 + EffectVariant uint8 +} + +type IdentifyQueryResponse struct { + Timeout uint16 +} diff --git a/commands/local/identify/identify_test.go b/commands/local/identify/identify_test.go new file mode 100644 index 0000000..6e5913a --- /dev/null +++ b/commands/local/identify/identify_test.go @@ -0,0 +1,116 @@ +package identify + +import ( + "github.com/shimmeringbee/bytecodec" + "github.com/shimmeringbee/zcl" + "github.com/shimmeringbee/zigbee" + "github.com/stretchr/testify/assert" + "testing" +) + +func Test_Identify(t *testing.T) { + t.Run("marshals and unmarshalls correctly", func(t *testing.T) { + expectedCommand := Identify{ + IdentifyTime: 0x1122, + } + actualCommand := Identify{} + expectedBytes := []byte{0x22, 0x11} + + actualBytes, err := bytecodec.Marshal(&expectedCommand) + assert.NoError(t, err) + assert.Equal(t, expectedBytes, actualBytes) + + err = bytecodec.Unmarshal(expectedBytes, &actualCommand) + assert.NoError(t, err) + assert.Equal(t, expectedCommand, actualCommand) + }) + + t.Run("the message is registered in the command registry", func(t *testing.T) { + cr := zcl.NewCommandRegistry() + Register(cr) + + id, err := cr.GetLocalCommandIdentifier(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ClientToServer, &Identify{}) + assert.NoError(t, err) + assert.Equal(t, IdentifyId, id) + }) +} + +func Test_IdentifyQuery(t *testing.T) { + t.Run("marshals and unmarshalls correctly", func(t *testing.T) { + expectedCommand := IdentifyQuery{} + actualCommand := IdentifyQuery{} + expectedBytes := []byte(nil) + + actualBytes, err := bytecodec.Marshal(&expectedCommand) + assert.NoError(t, err) + assert.Equal(t, expectedBytes, actualBytes) + + err = bytecodec.Unmarshal(expectedBytes, &actualCommand) + assert.NoError(t, err) + assert.Equal(t, expectedCommand, actualCommand) + }) + + t.Run("the message is registered in the command registry", func(t *testing.T) { + cr := zcl.NewCommandRegistry() + Register(cr) + + id, err := cr.GetLocalCommandIdentifier(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ClientToServer, &IdentifyQuery{}) + assert.NoError(t, err) + assert.Equal(t, IdentifyQueryId, id) + }) +} + +func Test_TriggerEffect(t *testing.T) { + t.Run("marshals and unmarshalls correctly", func(t *testing.T) { + expectedCommand := TriggerEffect{ + EffectIdentifier: 0x11, + EffectVariant: 0x22, + } + actualCommand := TriggerEffect{} + expectedBytes := []byte{0x11, 0x22} + + actualBytes, err := bytecodec.Marshal(&expectedCommand) + assert.NoError(t, err) + assert.Equal(t, expectedBytes, actualBytes) + + err = bytecodec.Unmarshal(expectedBytes, &actualCommand) + assert.NoError(t, err) + assert.Equal(t, expectedCommand, actualCommand) + }) + + t.Run("the message is registered in the command registry", func(t *testing.T) { + cr := zcl.NewCommandRegistry() + Register(cr) + + id, err := cr.GetLocalCommandIdentifier(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ClientToServer, &TriggerEffect{}) + assert.NoError(t, err) + assert.Equal(t, TriggerEffectId, id) + }) +} + +func Test_IdentifyQueryResponse(t *testing.T) { + t.Run("marshals and unmarshalls correctly", func(t *testing.T) { + expectedCommand := IdentifyQueryResponse{ + Timeout: 0x1122, + } + actualCommand := IdentifyQueryResponse{} + expectedBytes := []byte{0x22, 0x11} + + actualBytes, err := bytecodec.Marshal(&expectedCommand) + assert.NoError(t, err) + assert.Equal(t, expectedBytes, actualBytes) + + err = bytecodec.Unmarshal(expectedBytes, &actualCommand) + assert.NoError(t, err) + assert.Equal(t, expectedCommand, actualCommand) + }) + + t.Run("the message is registered in the command registry", func(t *testing.T) { + cr := zcl.NewCommandRegistry() + Register(cr) + + id, err := cr.GetLocalCommandIdentifier(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ServerToClient, &IdentifyQueryResponse{}) + assert.NoError(t, err) + assert.Equal(t, IdentifyQueryResponseId, id) + }) +} diff --git a/commands/local/identify/register.go b/commands/local/identify/register.go new file mode 100644 index 0000000..4542c40 --- /dev/null +++ b/commands/local/identify/register.go @@ -0,0 +1,14 @@ +package identify + +import ( + "github.com/shimmeringbee/zcl" + "github.com/shimmeringbee/zigbee" +) + +func Register(cr *zcl.CommandRegistry) { + cr.RegisterLocal(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ClientToServer, IdentifyId, &Identify{}) + cr.RegisterLocal(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ClientToServer, IdentifyQueryId, &IdentifyQuery{}) + cr.RegisterLocal(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ClientToServer, TriggerEffectId, &TriggerEffect{}) + + cr.RegisterLocal(zcl.IdentifyId, zigbee.NoManufacturer, zcl.ServerToClient, IdentifyQueryResponseId, &IdentifyQueryResponse{}) +}