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{}) +}