package decode_test import ( "fmt" "testing" can "github.com/fiskerinc/cloud-services/pkg/can-go" "github.com/fiskerinc/cloud-services/pkg/can-go/internal/generate" "github.com/fiskerinc/cloud-services/pkg/can-go/pkg/descriptor" ) type signal struct { name string value float64 description string unit string } func getTestDatabase() descriptor.Database { dbc := []byte(` VERSION "" NS_ : BS_: BU_: DBG DRIVER IO MOTOR SENSOR BO_ 1 EmptyMessage: 0 DBG BO_ 100 DriverHeartbeat: 1 DRIVER SG_ Command : 0|8@1+ (1,0) [0|0] "" SENSOR,MOTOR BO_ 101 MotorCommand: 1 DRIVER SG_ Steer : 0|4@1- (1,-5) [-5|5] "" MOTOR SG_ Drive : 4|4@1+ (1,0) [0|9] "" MOTOR BO_ 400 MotorStatus: 3 MOTOR SG_ WheelError : 0|1@1+ (1,0) [0|0] "" DRIVER,IO SG_ SpeedKph : 8|16@1+ (0.001,0) [0|0] "km/h" DRIVER,IO BO_ 200 SensorSonars: 8 SENSOR SG_ Mux M : 0|4@1+ (1,0) [0|0] "" DRIVER,IO SG_ ErrCount : 4|12@1+ (1,0) [0|0] "" DRIVER,IO SG_ Left m0 : 16|12@1+ (0.1,0) [0|0] "" DRIVER,IO SG_ Middle m0 : 28|12@1+ (0.1,0) [0|0] "" DRIVER,IO SG_ Right m0 : 40|12@1+ (0.1,0) [0|0] "" DRIVER,IO SG_ Rear m0 : 52|12@1+ (0.1,0) [0|0] "" DRIVER,IO SG_ NoFiltLeft m1 : 16|12@1+ (0.1,0) [0|0] "" DBG SG_ NoFiltMiddle m1 : 28|12@1+ (0.1,0) [0|0] "" DBG SG_ NoFiltRight m1 : 40|12@1+ (0.1,0) [0|0] "" DBG SG_ NoFiltRear m1 : 52|12@1+ (0.1,0) [0|0] "" DBG BO_ 500 IODebug: 6 IO SG_ TestUnsigned : 0|8@1+ (1,0) [0|0] "" DBG SG_ TestEnum : 8|6@1+ (1,0) [0|0] "" DBG SG_ TestSigned : 16|8@1- (1,0) [0|0] "" DBG SG_ TestFloat : 24|8@1+ (0.5,0) [0|0] "" DBG SG_ TestBoolEnum : 32|1@1+ (1,0) [0|0] "" DBG SG_ TestScaledEnum : 40|2@1+ (2,0) [0|6] "" DBG BO_ 1530 DisconnectState: 14 MOTOR SG_ LockCountRearRight : 91|20@0+ (1,0) [0|1048575] "" IO SG_ DisconnectStateRearRight : 95|4@0+ (1,0) [0|5] "" IO SG_ CurrentRearRight : 79|16@0+ (1,0) [0|65535] "" IO SG_ DisconnectStateRearRightTarget : 64|1@0+ (1,0) [0|1] "" IO SG_ TargetSpeedRearRight : 63|15@0+ (0.125,-2048) [-2048|2047.875] "rad/s" IO SG_ LockCountRearLeft : 35|20@0+ (1,0) [0|1048575] "" IO SG_ DisconnectStateRearLeft : 39|4@0+ (1,0) [0|5] "" IO SG_ CurrentRearLeft : 23|16@0+ (1,0) [0|65535] "" IO SG_ DisconnectStateRearLeftTarget : 8|1@0+ (1,0) [0|1] "" IO SG_ TargetSpeedRearLeft : 7|15@0+ (0.125,-2048) [-2048|2047.875] "rad/s" IO BO_ 1927 EvaporatorVariables: 14 SENSOR SG_ EvaporatorAirTempIn : 96|8@0+ (0.4,-20) [-19.6|82.4] "degC" IO SG_ CompressorSpeedActual : 80|16@0+ (1,-1) [0|8600] "RPM" IO SG_ FBTargetCompressorSpeed : 64|16@0+ (1,-8600) [-8599|8600] "RPM" IO SG_ FFTargetCompressorSpeed : 48|16@0+ (1,-1) [0|8600] "RPM" IO SG_ FBTargetSuctionPressure : 32|16@0+ (0.05,0) [0.05|3276.8] "kPa" IO SG_ FFTargetSuctionPressure : 16|16@0+ (0.05,0) [0.05|3276.8] "kPa" IO SG_ ChillerCoolantOutTempTarget : 8|8@0+ (0.4,-20) [-19.6|82.4] "degC" IO SG_ EvaporatorAirOutTempTarget : 0|8@0+ (0.4,-20) [-19.6|82.4] "degC" IO EV_ BrakeEngaged: 0 [0|1] "" 0 10 DUMMY_NODE_VECTOR0 Vector__XXX; EV_ Torque: 1 [0|30000] "mNm" 500 16 DUMMY_NODE_VECTOR0 Vector__XXX; CM_ EV_ BrakeEngaged "Brake fully engaged"; CM_ BU_ DRIVER "The driver controller driving the car"; CM_ BU_ MOTOR "The motor controller of the car"; CM_ BU_ SENSOR "The sensor controller of the car"; CM_ BO_ 100 "Sync message used to synchronize the controllers"; BA_DEF_ "BusType" STRING ; BA_DEF_ BO_ "GenMsgSendType" ENUM "None","Cyclic","OnEvent"; BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0; BA_DEF_ SG_ "FieldType" STRING ; BA_DEF_ SG_ "GenSigStartValue" INT 0 10000; BA_DEF_DEF_ "BusType" "CAN"; BA_DEF_DEF_ "FieldType" ""; BA_DEF_DEF_ "GenMsgCycleTime" 0; BA_DEF_DEF_ "GenSigStartValue" 0; BA_ "GenMsgSendType" BO_ 1 0; BA_ "GenMsgSendType" BO_ 100 1; BA_ "GenMsgCycleTime" BO_ 100 1000; BA_ "GenMsgSendType" BO_ 101 1; BA_ "GenMsgCycleTime" BO_ 101 100; BA_ "GenMsgSendType" BO_ 200 1; BA_ "GenMsgCycleTime" BO_ 200 100; BA_ "GenMsgSendType" BO_ 400 1; BA_ "GenMsgCycleTime" BO_ 400 100; BA_ "GenMsgSendType" BO_ 500 2; BA_ "FieldType" SG_ 100 Command "Command"; BA_ "FieldType" SG_ 500 TestEnum "TestEnum"; BA_ "GenSigStartValue" SG_ 500 TestEnum 2; VAL_ 100 Command 2 "Reboot" 1 "Sync" 0 "None" ; VAL_ 500 TestEnum 2 "Two" 1 "One" ; VAL_ 500 TestScaledEnum 3 "Six" 2 "Four" 1 "Two" 0 "Zero" ; VAL_ 500 TestBoolEnum 1 "One" 0 "Zero" ; VAL_ 1530 DisconnectStateRearRight 0 "Undefined" 1 "Locked" 2 "Unlocked" 3 "Locking" 4 "Unlocking" 5 "Faulted" ; VAL_ 1530 DisconnectStateRearLeft 0 "Undefined" 1 "Locked" 2 "Unlocked" 3 "Locking" 4 "Unlocking" 5 "Faulted" ; `) c, _ := generate.Compile("test.dbc", dbc) db := *c.Database return db } func TestDecodeEvaporatorVariables(t *testing.T) { db := getTestDatabase() message, _ := db.Message(uint32(1927)) canDataHexString := "008232204e027600ca4b0007d296" payload, err := can.PayloadFromHex(canDataHexString) if err != nil { t.Errorf("err = %v; want nil", err) } expected := []signal{ { name: "EvaporatorAirOutTempTarget", value: 6.0, description: "", unit: "degC", }, { name: "ChillerCoolantOutTempTarget", value: -10.0, description: "", unit: "degC", }, { name: "FFTargetSuctionPressure", value: 206.75, description: "", unit: "kPa", }, { name: "FBTargetSuctionPressure", value: 15.75, description: "", unit: "kPa", }, { name: "FFTargetCompressorSpeed", value: 100, description: "", unit: "RPM", }, { name: "FBTargetCompressorSpeed", value: 1000, description: "", unit: "RPM", }, { name: "CompressorSpeedActual", value: 1000, description: "", unit: "RPM", }, { name: "EvaporatorAirTempIn", value: 10.0, description: "", unit: "degC", }, } expectedMap := make(map[string]signal) for _, s := range expected { expectedMap[s.name] = s } for _, signal := range message.Signals { value := signal.UnmarshalPhysicalPayload(&payload) valueDesc, _ := signal.UnmarshalValueDescriptionPayload(&payload) unit := signal.Unit name := signal.Name if value != expectedMap[name].value { t.Errorf("signal[%s] value = %f ; expected: %f", name, value, expectedMap[name].value) } if valueDesc != expectedMap[name].description { t.Errorf("signal[%s] value = %s ; expected: %s", name, valueDesc, expectedMap[name].description) } if unit != expectedMap[name].unit { t.Errorf("signal[%s] value = %s ; expected: %s", name, unit, expectedMap[name].unit) } } for _, signal := range message.Decode(&payload) { value := signal.Value valueDesc := signal.Description name := signal.Signal.Name if value != expectedMap[name].value { t.Errorf("signal[%s] value = %f ; expected: %f", name, value, expectedMap[name].value) } if valueDesc != expectedMap[name].description { t.Errorf("signal[%s] value = %s ; expected: %s", name, valueDesc, expectedMap[name].description) } } } func TestDecodeDisconnectState(t *testing.T) { byteStringHex := "8000000420061880000005200600" p, err := can.PayloadFromHex(byteStringHex) if err != nil { fmt.Println(err) } expected := []signal{ { name: "TargetSpeedRearLeft", value: 0.0, description: "", unit: "rad/s", }, { name: "DisconnectStateRearLeftTarget", value: 0, description: "", unit: "", }, { name: "CurrentRearLeft", value: 4, description: "", unit: "", }, { name: "DisconnectStateRearLeft", value: 2, description: "Unlocked", unit: "", }, { name: "LockCountRearLeft", value: 1560, description: "", unit: "", }, { name: "TargetSpeedRearRight", value: 0, description: "", unit: "rad/s", }, { name: "DisconnectStateRearRightTarget", value: 0, description: "", unit: "", }, { name: "CurrentRearRight", value: 5, description: "", unit: "", }, { name: "DisconnectStateRearRight", value: 2, description: "Unlocked", unit: "", }, { name: "LockCountRearRight", value: 1536, description: "", unit: "", }, } expectedMap := make(map[string]signal) for _, s := range expected { expectedMap[s.name] = s } db := getTestDatabase() message, _ := db.Message(uint32(1530)) for _, signal := range message.Signals { value := signal.UnmarshalPhysicalPayload(&p) valueDesc, _ := signal.UnmarshalValueDescriptionPayload(&p) unit := signal.Unit name := signal.Name if value != expectedMap[name].value { t.Errorf("signal[%s] value = %f ; expected: %f", name, value, expectedMap[name].value) } if valueDesc != expectedMap[name].description { t.Errorf("signal[%s] value = %s ; expected: %s", name, valueDesc, expectedMap[name].description) } if unit != expectedMap[name].unit { t.Errorf("signal[%s] value = %s ; expected: %s", name, unit, expectedMap[name].unit) } } } func TestDecodeSensorSonarsData(t *testing.T) { data := can.Data{0x01, 0x01, 0x01, 0x02, 0x01, 0x00} payload := can.Payload{Data: data[:]} db := getTestDatabase() message, _ := db.Message(uint32(500)) fmt.Println(message.Length) for _, signal := range message.Signals { value := signal.UnmarshalPhysicalPayload(&payload) valueDesc, _ := signal.UnmarshalValueDescriptionPayload(&payload) valueFromData := signal.UnmarshalPhysical(data) descFromData, _ := signal.UnmarshalValueDescription(data) name := signal.Name if value != valueFromData { t.Errorf("signal[%s] value = %f ; expected: %f", name, value, valueFromData) } if valueDesc != descFromData { t.Errorf("signal[%s] value = %s ; expected: %s", name, valueDesc, descFromData) } } } func TestMessageDecodeSensorSonarsData(t *testing.T) { data := can.Data{0x01, 0x01, 0x01, 0x02, 0x01, 0x00} payload := can.Payload{Data: data[:]} db := getTestDatabase() message, _ := db.Message(uint32(500)) fmt.Println(message.Length) decodedSignals := message.Decode(&payload) for _, signal := range decodedSignals { value := signal.Value valueDesc := signal.Description name := signal.Signal.Name valueFromData := signal.Signal.UnmarshalPhysical(data) descFromData, _ := signal.Signal.UnmarshalValueDescription(data) if value != valueFromData { t.Errorf("signal[%s] value = %f ; expected: %f", name, value, valueFromData) } if valueDesc != descFromData { t.Errorf("signal[%s] value = %s ; expected: %s", name, valueDesc, descFromData) } } } func BenchmarkDecodeData(b *testing.B) { db := getTestDatabase() message, _ := db.Message(uint32(500)) decodeSignal := func() { data := can.Data{0x01, 0x01, 0x01, 0x02, 0x01, 0x00} for _, signal := range message.Signals { _ = signal.UnmarshalPhysical(data) _, _ = signal.UnmarshalValueDescription(data) } } for i := 0; i < b.N; i++ { decodeSignal() } } func BenchmarkDecodePayload(b *testing.B) { // {0x01, 0x01, 0x01, 0x02, 0x01, 0x00} db := getTestDatabase() message, _ := db.Message(uint32(500)) decodeSignal := func() { data := can.Payload{Data: []byte{0x01, 0x01, 0x01, 0x02, 0x01, 0x00}} for _, signal := range message.Signals { _ = signal.UnmarshalPhysicalPayload(&data) _, _ = signal.UnmarshalValueDescriptionPayload(&data) } } for i := 0; i < b.N; i++ { decodeSignal() } }