package device import ( "os" "testing" "time" "github.com/stretchr/testify/require" "src.dualinventive.com/go/cp3000-interface/internal/testenv" "src.dualinventive.com/go/dinet/rpc" "src.dualinventive.com/go/lib/cp3000" ) const ( Zkl3000RcPayloadNoShort = `0028/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782` Zkl3000RcPayloadExternalShort = `002A/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782` Zkl3000RcPayloadSelfShort = `002A/9000/8F0F,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782` ) func TestMain(m *testing.M) { // During the test we don't care how much the wait time is for the measurement to arrive // the default value slows down the test significantly so we speed it up. It doesn't change // the functional behaviour but the test runtime. zkl3000RcMaximumWaitForMeasurement = time.Nanosecond os.Exit(m.Run()) } func testZkl3000RequestSwitchInfoAssertReqRep(td *testenv.TestData) { td.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "F0"}, }, nil) } func TestZkl3000RcGetToken(t *testing.T) { testData := testenv.CreateTestData(t) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.Nil(t, response.Error) var configItem []rpc.ResultConfigValueItem err := response.Result.Unmarshal(&configItem) require.Nil(t, err) require.Len(t, configItem, 1) require.Equal(t, float64(0), configItem[0].Value) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,14"}}) response = testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.Nil(t, response.Error) err = response.Result.Unmarshal(&configItem) require.Nil(t, err) require.Len(t, configItem, 1) require.Equal(t, float64(14), configItem[0].Value) } func TestZkl3000RcGetTokenRetriesFail(t *testing.T) { testData := testenv.CreateTestData(t) testZkl3000RequestSwitchInfoAssertReqRep(testData) // Switch not valid testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"00008F14"}}) // Switch malfunction testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"80008F14"}}) // Switch malfunction second and last try testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"80008F14"}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.NotNil(t, response.Error) require.Equal(t, rpc.EBackendCp3000CommError, response.Error.Code) } func TestZkl3000RcGetTokenRetries(t *testing.T) { testData := testenv.CreateTestData(t) testZkl3000RequestSwitchInfoAssertReqRep(testData) // Switch malfunction testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"80008F14"}}) // Switch valid (malfunction gone) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.Nil(t, response.Error) // Switch valid with token 1337 testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,1337"}}) response = testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.Nil(t, response.Error) var configItem []rpc.ResultConfigValueItem err := response.Result.Unmarshal(&configItem) require.Nil(t, err) require.Len(t, configItem, 1) require.Equal(t, float64(1337), configItem[0].Value) } func TestZkl3000RcGetActive(t *testing.T) { testData := testenv.CreateTestData(t) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigActive.UID()}) require.Nil(t, response.Error) var configItem []rpc.ResultConfigValueItem err := response.Result.Unmarshal(&configItem) require.Nil(t, err) require.Len(t, configItem, 1) require.Equal(t, false, configItem[0].Value) // Let the ZKL send a device token so the ZKL is armed testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // Request token to get the ZKL in the armed state response = testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.Nil(t, response.Error) // Turn the switch on testData.Cp3000Connection.Send(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStatus, Params: []string{"16391", `0028/9000/8F0F,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`}}) testData.WaitForMessage() // Even if the switch is on, active is still false, because it is a project state response = testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigActive.UID()}) require.Nil(t, response.Error) err = response.Result.Unmarshal(&configItem) require.Nil(t, err) require.Len(t, configItem, 1) require.Equal(t, false, configItem[0].Value) // Expect activate commands // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{`0028/9000/8F0F,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // part of 'turnMeasurementOn' turn measurement on testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "B4,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // part of 'turnMeasurementOn' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'turnSwitchOn' turn switch on testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "D2,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // part of 'turnSwitchOn' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadSelfShort}}) // Activate the switch response = testData.ReqRep(rpc.ClassMethodConfigSet, rpc.ConfigParam{UID: rpc.ConfigActive.UID(), Value: true}) require.Nil(t, response.Error) // The project state should now be active response = testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigActive.UID()}) require.Nil(t, response.Error) err = response.Result.Unmarshal(&configItem) require.Nil(t, err) require.Len(t, configItem, 1) require.Equal(t, true, configItem[0].Value) } func TestZkl3000RcDontUpdateProjectID(t *testing.T) { testCases := []struct { classMethod rpc.ClassMethod requestPayload string cp3000Command string updatedPayload string }{ { classMethod: rpc.ClassMethodConfigSet, requestPayload: "01008F14", cp3000Command: "96,10", updatedPayload: "01008F14,11", }, { classMethod: rpc.ClassMethodConfigReset, requestPayload: "01008F14,10", cp3000Command: "A5,10", updatedPayload: "01008F14,10", }, } for _, tc := range testCases { // Transfer tc to local variable for fixing schope tc := tc t.Run(string(tc.classMethod), func(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{`0028/9000/8F0F,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.requestPayload}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", tc.cp3000Command}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.updatedPayload}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(tc.classMethod, rpc.ConfigToken.Data(10)) require.NotNil(t, response.Error) require.Equal(t, rpc.EBackendCp3000CommError, response.Error.Code) }) } } func TestZkl3000RcReleaseActivateDeactivateButHasError(t *testing.T) { testCases := []struct { name string payload string classmethod rpc.ClassMethod requestData interface{} expectedErrorCode rpc.ErrorCode }{ { name: "keyswitch/release", payload: `0028/9004/8F00,F020,0020880D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, classmethod: rpc.ClassMethodConfigSet, requestData: rpc.ConfigToken.Data(10), expectedErrorCode: rpc.EFirmwareKeyswitchNotOperational, }, { name: "keyswitch/activate", payload: `0028/9004/8F00,F020,0020880D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, classmethod: rpc.ClassMethodConfigSet, requestData: rpc.ConfigActive.Data(true), expectedErrorCode: rpc.EFirmwareKeyswitchNotOperational, }, { name: "keyswitch/deactivate", payload: `0028/9004/8F00,F020,0020880D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, classmethod: rpc.ClassMethodConfigReset, requestData: rpc.ConfigActive.Data(false), expectedErrorCode: rpc.EFirmwareKeyswitchNotOperational, }, } for _, tc := range testCases { // Transfer tc to local variable for fixing schope tc := tc t.Run(tc.name, func(t *testing.T) { testData := testenv.CreateTestData(t) registerCP3000Device(t, testData, newZkl3000Rc) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.payload}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // Copy of 618-658 //nolint dupl if tc.expectedErrorCode == rpc.Ok { // part of 'turnSwitchOff' turn switch off on testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "E1,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // part of 'turnSwitchOff' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'turnMeasurementOff' turn measurement off testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "C3,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // part of 'turnMeasurementOff' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) } response := testData.ReqRep(rpc.ClassMethodConfigSet, tc.requestData) if tc.expectedErrorCode == rpc.Ok { require.Nil(t, response.Error) } else { require.NotNil(t, response.Error) require.Equal(t, tc.expectedErrorCode, response.Error.Code) } }) } } func TestZkl3000RcActivateDectivateWithShort(t *testing.T) { testCases := []struct { name string payloadBetween string payloadAfter string activate bool expectedError rpc.ErrorCode }{ { "activateWithInternalShort", Zkl3000RcPayloadSelfShort, Zkl3000RcPayloadSelfShort, true, rpc.Ok, }, { "activateWithExternalShort", Zkl3000RcPayloadExternalShort, Zkl3000RcPayloadSelfShort, true, rpc.EWrnFirmwareActivateShortPresent, }, { "deactivateWithShort", Zkl3000RcPayloadExternalShort, Zkl3000RcPayloadNoShort, false, rpc.EWrnFirmwareDeactivateShortPresent, }, { "activateWithoutShort", Zkl3000RcPayloadNoShort, Zkl3000RcPayloadSelfShort, true, rpc.Ok, }, { "deactivateWithoutShort", Zkl3000RcPayloadNoShort, Zkl3000RcPayloadNoShort, false, rpc.Ok, }, } for _, tc := range testCases { // Transfer tc to local variable for fixing schope tc := tc t.Run(tc.name, func(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) var command string if tc.activate { command = "B4,10" } else { command = "E1,10" } testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", command}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.payloadBetween}}) if tc.activate { command = "D2,10" } else { command = "C3,10" } testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", command}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.payloadAfter}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigSet, rpc.ConfigActive.Data(tc.activate)) if tc.expectedError == rpc.Ok { require.Nil(t, response.Error) } else { require.NotNil(t, response.Error) require.Equal(t, tc.expectedError, response.Error.Code) } }) } } func TestZkl3000RcReleaseActivateBatteryErrors(t *testing.T) { testCases := []struct { name string payload string releaseError rpc.ErrorCode activateError rpc.ErrorCode }{ { name: "bat1_full_bat2_full", payload: `0000/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.Ok, activateError: rpc.Ok, }, { name: "bat1_critical_bat2_full", payload: `0100/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.Ok, activateError: rpc.Ok, }, { name: "bat1_empty_bat2_full", payload: `0300/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.Ok, activateError: rpc.Ok, }, { name: "bat1_removed_bat2_full", payload: `0700/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.Ok, activateError: rpc.Ok, }, { name: "bat1_unknown_bat2_full", payload: `0200/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.Ok, activateError: rpc.Ok, }, { name: "bat1_full_bat2_critical", payload: `1000/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.EWrnFirmwareBattery2Critical, activateError: rpc.EWrnFirmwareBattery2Critical, }, { name: "bat1_full_bat2_empty", payload: `3000/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.EFirmwareBattery2Empty, activateError: rpc.EWrnFirmwareBattery2Empty, }, { name: "bat1_full_bat2_removed", payload: `7000/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.EFirmwareBattery2Removed, activateError: rpc.EWrnFirmwareBattery2Removed, }, { name: "bat1_full_bat2_unknown", payload: `2000/9000/8F00,F020,0020888D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,6.489,10.4,` + `-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`, releaseError: rpc.EOpdenied, activateError: rpc.EOpdenied, }, } for _, tc := range testCases { // Transfer tc to local variable for fixing schope tc := tc t.Run(tc.name, func(t *testing.T) { testData := testenv.CreateTestData(t) registerCP3000Device(t, testData, newZkl3000Rc) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.payload}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) // release test case if !tc.releaseError.IsError() { // Set token testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "96,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) // part of 'writeSwitchToken' testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.payload}}) } response := testData.ReqRep(rpc.ClassMethodConfigSet, rpc.ConfigToken.Data(10)) if tc.releaseError == rpc.Ok { require.Nil(t, response.Error) } else { require.NotNil(t, response.Error) require.Equal(t, tc.releaseError, response.Error.Code) } // end release test case testData.Cp3000Connection.WaitForEmptyQueue() // activate test case // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{tc.payload}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,13"}}) // Copy of 302-346 //nolint dupl if !tc.activateError.IsError() { // Send B4 to the switch testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "B4,13"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,13"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // Send D2 to the switch testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "D2,13"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,13"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadSelfShort}}) } response = testData.ReqRep(rpc.ClassMethodConfigSet, rpc.ConfigActive.Data(true)) if tc.activateError == rpc.Ok { require.Nil(t, response.Error) } else { require.NotNil(t, response.Error) require.Equal(t, tc.activateError, response.Error.Code) } testData.Cp3000Connection.WaitForEmptyQueue() }) } } func TestZkl3000RcRelease(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "96,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigSet, rpc.ConfigToken.Data(10)) require.Nil(t, response.Error) // if we do another config:set for config token we should get an error (op denied) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) response = testData.ReqRep(rpc.ClassMethodConfigSet, rpc.ConfigToken.Data(11)) require.NotNil(t, response.Error) require.Equal(t, rpc.EFirmwareMismatchToken, response.Error.Code) } func TestZkl3000RcReturnButHasNoProjectID(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigReset, rpc.ConfigToken.Data(10)) require.Nil(t, response.Error) } func TestZkl3000RcReturnButTokenIsNotRemoved(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "A5,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigReset, rpc.ConfigToken.Data(10)) require.NotNil(t, response.Error) require.Equal(t, rpc.EBackendCp3000CommError, response.Error.Code) } func TestZkl3000RcReturn(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", "A5,10"}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(rpc.ClassMethodConfigReset, rpc.ConfigToken.Data(10)) require.Nil(t, response.Error) } func TestZkl3000RcActivateDeactivateButIsNotOnProject(t *testing.T) { testCases := []struct { classMethod rpc.ClassMethod expectedError rpc.ErrorCode }{ {classMethod: rpc.ClassMethodConfigSet, expectedError: rpc.EFirmwareDeviceIdle}, {classMethod: rpc.ClassMethodConfigReset, expectedError: rpc.EFirmwareDeviceIdle}, } for _, tc := range testCases { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(tc.classMethod, rpc.ConfigActive.Data(true)) require.NotNil(t, response.Error) require.Equal(t, tc.expectedError, response.Error.Code) } } func TestZkl3000RcActivateDeactivate(t *testing.T) { testCases := []struct { name string classMethod rpc.ClassMethod requestData interface{} cp3000Command []string expectError rpc.ErrorCode }{ { name: "activate", classMethod: rpc.ClassMethodConfigSet, requestData: rpc.ConfigParam{UID: rpc.ConfigActive.UID(), Value: true}, cp3000Command: []string{"B4,10", "D2,10"}, expectError: rpc.Ok, }, { name: "deactivate/configset", classMethod: rpc.ClassMethodConfigSet, requestData: rpc.ConfigParam{UID: rpc.ConfigActive.UID(), Value: false}, cp3000Command: []string{"E1,10", "C3,10"}, expectError: rpc.Ok, }, { name: "deactivate/configreset", classMethod: rpc.ClassMethodConfigReset, requestData: rpc.ConfigParam{UID: rpc.ConfigActive.UID(), Value: false}, cp3000Command: []string{"E1,10", "C3,10"}, expectError: rpc.Ok, }, { name: "invalid value", classMethod: rpc.ClassMethodConfigSet, requestData: rpc.ConfigParam{UID: rpc.ConfigActive.UID(), Value: "boem"}, cp3000Command: []string{}, expectError: rpc.EParam, }, } for _, tc := range testCases { // Transfer tc to local variable for fixing schope tc := tc t.Run(tc.name, func(t *testing.T) { testData := testenv.CreateTestData(t) // part of 'preflightChecks' request STAT testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) // part of 'preflightChecks' request SWITCH testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,10"}}) if len(tc.cp3000Command) > 0 { testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", tc.cp3000Command[0]}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}}) // Sensor data testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadNoShort}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStore, Params: []string{"SWITCH", tc.cp3000Command[1]}, }, nil) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"001008F14"}}) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"STAT"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{Zkl3000RcPayloadSelfShort}}) } registerCP3000Device(t, testData, newZkl3000Rc) response := testData.ReqRep(tc.classMethod, tc.requestData) if tc.expectError != rpc.Ok { require.NotNil(t, response.Error) require.Equal(t, tc.expectError, response.Error.Code) } }) } } func TestZkl3000RcHeartbeat(t *testing.T) { testData := testenv.CreateTestData(t) registerCP3000Device(t, testData, newZkl3000Rc) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandWatchdog, Params: []string{}, }, nil) testData.Cp3000Connection.Send(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandWatchdog, Params: []string{}, }) msg := testData.WaitForMessage() var res interface{} err := msg.Result.Unmarshal(&res) require.Nil(t, err) // Make the device armed... (let the device publish a token) testZkl3000RequestSwitchInfoAssertReqRep(testData) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandRetrieve, Params: []string{"SWITCH"}, }, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14,11"}}) response := testData.ReqRep(rpc.ClassMethodConfigGet, rpc.ConfigParam{UID: rpc.ConfigToken.UID()}) require.Nil(t, response.Error) testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandWatchdog, Params: []string{}, }, nil) testData.Cp3000Connection.Send(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandWatchdog, Params: []string{}, }) msg = testData.WaitForMessage() err = msg.Result.Unmarshal(&res) require.Nil(t, err) // Make the device active... (turn on the sections) testData.Cp3000Connection.Send(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandStatus, Params: []string{"16391", `0028/9004/8F0F,F020,0020880D/29/0,43043F00,0.451,8081,0,0.000,2,6.618,` + `6.489,10.4,-128.0,-65,0,51.5464032,4.4679200,44.0,0.9N,0.0,0.00,3471724782`}}) testData.WaitForMessage() testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandWatchdog, Params: []string{}, }, nil) testData.Cp3000Connection.Send(&cp3000.Msg{ Type: cp3000.TypeCommand, Command: cp3000.CommandWatchdog, Params: []string{}, }) msg = testData.WaitForMessage() err = msg.Result.Unmarshal(&res) require.Nil(t, err) }