Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
158
pkg/dbc/dbc.go
Normal file
158
pkg/dbc/dbc.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/dbc/diagnostics"
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
"fiskerinc.com/modules/grpc/kafka_grpc"
|
||||
|
||||
can "github.com/Fisker-Inc/project-ai-can-go"
|
||||
"github.com/Fisker-Inc/project-ai-can-go/pkg/descriptor"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NewDBC(d *descriptor.Database, f diagnostics.Flags, s map[int]state.StateFunc) DBCInterface {
|
||||
return &DBC{database: d, diagnosticFlags: f, stateFuncs: s}
|
||||
}
|
||||
|
||||
type DBCInterface interface {
|
||||
GetActiveDiagnosticFlags(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, bool, error)
|
||||
GetStateFunc(id int) (state.StateFunc, bool)
|
||||
GenerateCANSignals(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, error)
|
||||
GenerateCANSignalsMap(vin string, msg *kafka_grpc.GRPC_CANFrame) (map[string]common.CANSignal, error)
|
||||
DecodeMessage(msg *kafka_grpc.GRPC_CANFrame) ([]descriptor.DecodedSignal, error)
|
||||
GetDBCHash() string
|
||||
SetDBCHash(string)
|
||||
GetDatabase() *descriptor.Database
|
||||
}
|
||||
|
||||
type DBC struct {
|
||||
database *descriptor.Database
|
||||
hash string
|
||||
diagnosticFlags diagnostics.Flags
|
||||
stateFuncs map[int]state.StateFunc
|
||||
}
|
||||
|
||||
func (d *DBC) GetStateFunc(id int) (state.StateFunc, bool) {
|
||||
f, ok := d.stateFuncs[id]
|
||||
return f, ok
|
||||
}
|
||||
|
||||
// GenerateCANSignals parses raw can bus message (encoded in base64) to ECU data
|
||||
func (d *DBC) GenerateCANSignals(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, error) {
|
||||
decodedSignals, err := d.DecodeMessage(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signals := make([]common.CANSignal, 0, len(decodedSignals))
|
||||
for _, signal := range decodedSignals {
|
||||
signals = append(signals, common.CANSignal{
|
||||
VIN: vin,
|
||||
Timestamp: float64(msg.Epoch) * math.Pow(10, -6),
|
||||
ID: int(msg.ID),
|
||||
Name: signal.Signal.Name,
|
||||
Value: signal.Value,
|
||||
})
|
||||
}
|
||||
|
||||
return signals, nil
|
||||
}
|
||||
|
||||
// GenerateCANSignalSets parses raw can bus message (encoded in base64) to ECU
|
||||
func (d *DBC) GenerateCANSignalsMap(vin string, msg *kafka_grpc.GRPC_CANFrame) (map[string]common.CANSignal, error) {
|
||||
var signals map[string]common.CANSignal
|
||||
|
||||
decodedSignals, err := d.DecodeMessage(msg)
|
||||
if err != nil {
|
||||
return signals, err
|
||||
}
|
||||
signals = make(map[string]common.CANSignal, len(decodedSignals))
|
||||
for _, signal := range decodedSignals {
|
||||
signals[signal.Signal.Name] = common.CANSignal{
|
||||
VIN: vin,
|
||||
Timestamp: float64(msg.Epoch) * math.Pow(10, -6),
|
||||
ID: int(msg.ID),
|
||||
Name: signal.Signal.Name,
|
||||
Value: signal.Value,
|
||||
}
|
||||
}
|
||||
|
||||
return signals, nil
|
||||
}
|
||||
|
||||
func (d *DBC) GetActiveDiagnosticFlags(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, bool, error) {
|
||||
var flags []common.CANSignal
|
||||
|
||||
diagnosticSignals, ok := d.diagnosticFlags[int(msg.ID)]
|
||||
if !ok {
|
||||
return flags, false, nil
|
||||
}
|
||||
|
||||
decodedSignals, err := d.DecodeMessage(msg)
|
||||
if err != nil {
|
||||
return flags, false, err
|
||||
}
|
||||
|
||||
flags = make([]common.CANSignal, 0)
|
||||
for _, signal := range decodedSignals {
|
||||
faultVal, ok := diagnosticSignals[signal.Signal.Name]
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
} else if signal.Value != faultVal {
|
||||
continue
|
||||
}
|
||||
|
||||
flags = append(flags, common.CANSignal{
|
||||
VIN: vin,
|
||||
Timestamp: float64(msg.Epoch) * math.Pow(10, -6),
|
||||
ID: int(msg.ID),
|
||||
Name: signal.Signal.Name,
|
||||
Value: signal.Value,
|
||||
})
|
||||
}
|
||||
|
||||
return flags, len(flags) != 0, nil
|
||||
}
|
||||
|
||||
func (d *DBC) DecodeMessage(msg *kafka_grpc.GRPC_CANFrame) ([]descriptor.DecodedSignal, error) {
|
||||
var decodedSignals []descriptor.DecodedSignal
|
||||
|
||||
if msg.ID >= 2048 || msg.ID < 0 {
|
||||
return decodedSignals, errors.Errorf("message id %v out of bounds", msg.ID)
|
||||
}
|
||||
message, ok := d.database.Message(uint32(msg.ID))
|
||||
if !ok {
|
||||
return decodedSignals, errors.Errorf(
|
||||
"message id %v not found in %s, version: %s",
|
||||
msg.ID, d.database.SourceFile, d.database.Version)
|
||||
}
|
||||
|
||||
strippedData := strings.TrimRight(string(msg.Value), "=")
|
||||
data, err := base64.RawStdEncoding.DecodeString(strippedData)
|
||||
if err != nil {
|
||||
return decodedSignals, errors.WithStack(err)
|
||||
}
|
||||
|
||||
p := can.Payload{Data: data}
|
||||
decodedSignals = message.Decode(&p)
|
||||
return decodedSignals, nil
|
||||
}
|
||||
|
||||
func (d *DBC) GetDBCHash() string {
|
||||
return d.hash
|
||||
}
|
||||
|
||||
func (d *DBC) GetDatabase() *descriptor.Database {
|
||||
return d.database
|
||||
}
|
||||
|
||||
func (d *DBC) SetDBCHash(hash string) {
|
||||
d.hash = hash
|
||||
}
|
||||
111
pkg/dbc/dbc_fm29_frs90.go
Normal file
111
pkg/dbc/dbc_fm29_frs90.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/dbc/diagnostics"
|
||||
fm29_frs90 "fiskerinc.com/modules/dbc/fm29_frs90"
|
||||
"fiskerinc.com/modules/dbc/models"
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
)
|
||||
|
||||
func NewFM29_FRS90_DBC() models.DBCVersionInterface {
|
||||
fm29_frs90md := &fm29_frs90.MessagesDescriptor{}
|
||||
fm29_frs90db := fm29_frs90md.Database()
|
||||
|
||||
dbc := models.NewDBCVersion(fm29_frs90db, fm29_frs90.Hash)
|
||||
FM29_FRS90_AddState(dbc)
|
||||
|
||||
return dbc
|
||||
}
|
||||
|
||||
func FM29_FRS90_AddState(dbc models.DBCVersionInterface) models.DBCVersionInterface {
|
||||
return dbc.
|
||||
// bbus.go
|
||||
AddMsg(models.NewCANMessage(608, 11).
|
||||
Signal(1, state.VCU_VehChrgDchgMod, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial_value",
|
||||
1: "DC_charging",
|
||||
2: "VTOL_discharging",
|
||||
3: "VTOV_discharging",
|
||||
4: "AC_charging",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(757, 3).
|
||||
Signal(0, state.BMS_Bat_SoC_usable, state.IntFloor).
|
||||
Signal(2, state.BMS_Bat_SOH, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(801, 6).
|
||||
Signal(0, state.BCM_AP_FL_LeFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_FL_RiFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_FL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(3, state.BCM_AP_FL_RiReWinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(816, 14).
|
||||
Signal(4, state.BMS_PwrBattRmngCpSOC, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(821, 37).
|
||||
Signal(21, state.BCM_ReDefrstHeatgCmd, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(835, 34).
|
||||
Signal(4, state.BCM_FrntHoodLidSts, state.FloatToBool).
|
||||
Signal(6, state.BCM_FrntDrDoorLockSts, state.FloatToBool).
|
||||
Signal(9, state.BCM_DrFrntDoorSts, state.FloatToBool).
|
||||
Signal(10, state.BCM_PasFrntDoorSts, state.FloatToBool).
|
||||
Signal(12, state.BCM_CenLockSwtSts, state.IntFloor).
|
||||
Signal(14, state.BCM_RiReDoorSts, state.FloatToBool).
|
||||
Signal(15, state.BCM_LeReDoorSts, state.FloatToBool).
|
||||
Signal(29, state.BCM_SunroofPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(873, 12).
|
||||
Signal(0, state.BCM_AP_TL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_TL_RiReWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_RW_WinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(882, 13).
|
||||
Signal(5, state.BMS_BattAvrgT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(883, 24).
|
||||
Signal(15, state.ECC_OutdT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(902, 8).
|
||||
Signal(0, state.BCM_HeatedSteerWhlSt, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(1284, 16).
|
||||
Signal(12, state.VCU_DrvgMilg, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1298, 4).
|
||||
Signal(0, state.PSM_PassSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1304, 14).
|
||||
Signal(0, state.DSMC_DrvrSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1329, 7).
|
||||
Signal(1, state.ICC_TotMilg_ODO, nil)).
|
||||
AddMsg(models.NewCANMessage(1410, 7).
|
||||
Signal(0, state.ECC_InsdT, state.IntFloor).
|
||||
Signal(2, state.ECC_RemTSetSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1408, 4).
|
||||
Signal(2, state.VCU_DCChrgRmngTi, state.Int)).
|
||||
// ibus2.go
|
||||
AddMsg(models.NewCANMessage(1317, 5).
|
||||
Signal(2, state.TBOX_GPSHei, state.RoundMilli).
|
||||
Signal(3, state.TBOX_GPSLongi, state.RoundGPS).
|
||||
Signal(4, state.TBOX_GPSLati, state.RoundGPS)).
|
||||
AddMsg(models.NewCANMessage(345, 10).
|
||||
Signal(5, state.ACU_Drvr_Occpt_St, state.Int)).
|
||||
AddMsg(models.NewCANMessage(819, 12).
|
||||
Signal(4, state.BCM_PwrMod, state.Int)).
|
||||
AddMsg(models.NewCANMessage(1316, 4).
|
||||
Signal(0, state.PWC_ChrgSts, state.Int)).
|
||||
AddMsg(models.NewCANMessage(532, 23).
|
||||
Signal(2, state.VCU_RdyLamp, state.FloatToBool)).
|
||||
// Alexander Andrews Immobilization status possible signals
|
||||
AddMsg(models.NewCANMessage(54, 99).
|
||||
Signal(15, state.TBOX_RemCtrlCmdFb, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Void",
|
||||
1: "Successful",
|
||||
2: "Failed",
|
||||
3: "Reserved",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(537, 23).
|
||||
Signal(3, state.VCU_IMMO_Sts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Immo_Active",
|
||||
1: "Immo_Inactive",
|
||||
2: "Reserved",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(817, 15).
|
||||
Signal(6, state.PKC_IMMO_AuthSts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial",
|
||||
1: "Auth_Valid",
|
||||
2: "Auth_Invalid",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
SetDiagnosticFlags(diagnostics.FM29FRS90DiagnosticFlags)
|
||||
}
|
||||
106
pkg/dbc/dbc_fm29_frsd0.go
Normal file
106
pkg/dbc/dbc_fm29_frsd0.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/dbc/diagnostics"
|
||||
fm29_frsd0 "fiskerinc.com/modules/dbc/fm29_frsd0"
|
||||
"fiskerinc.com/modules/dbc/models"
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
)
|
||||
|
||||
func NewFM29_FRSD0_DBC() models.DBCVersionInterface {
|
||||
fm29_frsd0md := &fm29_frsd0.MessagesDescriptor{}
|
||||
fm29_frsd0db := fm29_frsd0md.Database()
|
||||
|
||||
return models.NewDBCVersion(fm29_frsd0db, fm29_frsd0.Hash).
|
||||
// bbus.go
|
||||
AddMsg(models.NewCANMessage(608, 12).
|
||||
Signal(4, state.VCU_VehChrgDchgMod, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial_value",
|
||||
1: "DC_charging",
|
||||
2: "VTOL_discharging",
|
||||
3: "VTOV_discharging",
|
||||
4: "AC_charging",
|
||||
5: "V2L_trunk_active",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(757, 4).
|
||||
Signal(0, state.BMS_Bat_SoC_usable, state.IntFloor).
|
||||
Signal(2, state.BMS_Bat_SOH, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(801, 6).
|
||||
Signal(0, state.BCM_AP_FL_LeFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_FL_RiFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_FL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(3, state.BCM_AP_FL_RiReWinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(816, 14).
|
||||
Signal(4, state.BMS_PwrBattRmngCpSOC, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(821, 37).
|
||||
Signal(21, state.BCM_ReDefrstHeatgCmd, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(835, 34).
|
||||
Signal(4, state.BCM_FrntHoodLidSts, state.FloatToBool).
|
||||
Signal(6, state.BCM_FrntDrDoorLockSts, state.FloatToBool).
|
||||
Signal(9, state.BCM_DrFrntDoorSts, state.FloatToBool).
|
||||
Signal(10, state.BCM_PasFrntDoorSts, state.FloatToBool).
|
||||
Signal(12, state.BCM_CenLockSwtSts, state.IntFloor).
|
||||
Signal(14, state.BCM_RiReDoorSts, state.FloatToBool).
|
||||
Signal(15, state.BCM_LeReDoorSts, state.FloatToBool).
|
||||
Signal(29, state.BCM_SunroofPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(873, 12).
|
||||
Signal(0, state.BCM_AP_TL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_TL_RiReWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_RW_WinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(882, 14).
|
||||
Signal(6, state.BMS_BattAvrgT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(883, 24).
|
||||
Signal(15, state.ECC_OutdT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(902, 8).
|
||||
Signal(0, state.BCM_HeatedSteerWhlSt, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(1284, 16).
|
||||
Signal(12, state.VCU_DrvgMilg, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1298, 5).
|
||||
Signal(0, state.PSM_PassSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1304, 6).
|
||||
Signal(0, state.DSMC_DrvrSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1329, 7).
|
||||
Signal(1, state.ICC_TotMilg_ODO, nil)).
|
||||
AddMsg(models.NewCANMessage(1408, 4).
|
||||
Signal(2, state.VCU_DCChrgRmngTi, state.Int)).
|
||||
AddMsg(models.NewCANMessage(1410, 7).
|
||||
Signal(0, state.ECC_InsdT, state.IntFloor).
|
||||
Signal(2, state.ECC_RemTSetSts, state.IntFloor)).
|
||||
// ibus2.go
|
||||
AddMsg(models.NewCANMessage(1317, 3).
|
||||
Signal(2, state.TBOX_GPSHei, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(1318, 2).
|
||||
Signal(0, state.TBOX_GPSLongi, state.RoundGPS).
|
||||
Signal(1, state.TBOX_GPSLati, state.RoundGPS)).
|
||||
AddMsg(models.NewCANMessage(345, 10).
|
||||
Signal(5, state.ACU_Drvr_Occpt_St, state.Int)).
|
||||
AddMsg(models.NewCANMessage(819, 12).
|
||||
Signal(4, state.BCM_PwrMod, state.Int)).
|
||||
AddMsg(models.NewCANMessage(1316, 4).
|
||||
Signal(0, state.PWC_ChrgSts, state.Int)).
|
||||
AddMsg(models.NewCANMessage(532, 23).
|
||||
Signal(2, state.VCU_RdyLamp, state.FloatToBool)).
|
||||
// Alexander Andrews Immobilization status possible signals
|
||||
AddMsg(models.NewCANMessage(54, 99).
|
||||
Signal(15, state.TBOX_RemCtrlCmdFb, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Void",
|
||||
1: "Successful",
|
||||
2: "Failed",
|
||||
3: "Reserved",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(537, 23).
|
||||
Signal(3, state.VCU_IMMO_Sts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Immo_Active",
|
||||
1: "Immo_Inactive",
|
||||
2: "Reserved",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(817, 15).
|
||||
Signal(6, state.PKC_IMMO_AuthSts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial",
|
||||
1: "Auth_Valid",
|
||||
2: "Auth_Invalid",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
SetDiagnosticFlags(diagnostics.FM29FRSD0DiagnosticFlags)
|
||||
}
|
||||
113
pkg/dbc/dbc_fm29_frsd21.go
Normal file
113
pkg/dbc/dbc_fm29_frsd21.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/dbc/diagnostics"
|
||||
fm29_frsd21 "fiskerinc.com/modules/dbc/fm29_frsd21"
|
||||
"fiskerinc.com/modules/dbc/models"
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
)
|
||||
|
||||
func NewFM29_FRSD21_DBC() models.DBCVersionInterface {
|
||||
fm29_frsd0md := &fm29_frsd21.MessagesDescriptor{}
|
||||
fm29_frsd0db := fm29_frsd0md.Database()
|
||||
|
||||
return models.NewDBCVersion(fm29_frsd0db, fm29_frsd21.Hash).
|
||||
// bbus.go
|
||||
AddMsg(models.NewCANMessage(532, 23).
|
||||
Signal(2, state.VCU_RdyLamp, state.FloatToBool).
|
||||
Signal(8, state.VCU_GearSig, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(792, 17).
|
||||
Signal(10, state.ESP_VehSpd, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(608, 12).
|
||||
Signal(4, state.VCU_VehChrgDchgMod, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial_value",
|
||||
1: "DC_charging",
|
||||
2: "VTOL_discharging",
|
||||
3: "VTOV_discharging",
|
||||
4: "AC_charging",
|
||||
5: "V2L_trunk_active",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(681, 5).
|
||||
Signal(1, state.IBS_BatteryVoltage, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(757, 4).
|
||||
Signal(0, state.BMS_Bat_SoC_usable, state.IntFloor).
|
||||
Signal(2, state.BMS_Bat_SOH, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(801, 6).
|
||||
Signal(0, state.BCM_AP_FL_LeFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_FL_RiFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_FL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(3, state.BCM_AP_FL_RiReWinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(816, 14).
|
||||
Signal(4, state.BMS_PwrBattRmngCpSOC, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(821, 37).
|
||||
Signal(21, state.BCM_ReDefrstHeatgCmd, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(835, 34).
|
||||
Signal(4, state.BCM_FrntHoodLidSts, state.FloatToBool).
|
||||
Signal(6, state.BCM_FrntDrDoorLockSts, state.FloatToBool).
|
||||
Signal(9, state.BCM_DrFrntDoorSts, state.FloatToBool).
|
||||
Signal(10, state.BCM_PasFrntDoorSts, state.FloatToBool).
|
||||
Signal(12, state.BCM_CenLockSwtSts, state.IntFloor).
|
||||
Signal(14, state.BCM_RiReDoorSts, state.FloatToBool).
|
||||
Signal(15, state.BCM_LeReDoorSts, state.FloatToBool).
|
||||
Signal(29, state.BCM_SunroofPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(873, 12).
|
||||
Signal(0, state.BCM_AP_TL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_TL_RiReWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_RW_WinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(882, 14).
|
||||
Signal(6, state.BMS_BattAvrgT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(883, 24).
|
||||
Signal(15, state.ECC_OutdT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(902, 8).
|
||||
Signal(0, state.BCM_HeatedSteerWhlSt, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(1284, 16).
|
||||
Signal(12, state.VCU_DrvgMilg, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1298, 5).
|
||||
Signal(0, state.PSM_PassSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1304, 6).
|
||||
Signal(0, state.DSMC_DrvrSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1329, 7).
|
||||
Signal(1, state.ICC_TotMilg_ODO, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1408, 4).
|
||||
Signal(2, state.VCU_DCChrgRmngTi, state.Int)).
|
||||
AddMsg(models.NewCANMessage(1410, 7).
|
||||
Signal(0, state.ECC_InsdT, state.IntFloor).
|
||||
Signal(2, state.ECC_RemTSetSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1137, 21).
|
||||
Signal(17, state.PLGM_TrSts, state.FloatToBool)).
|
||||
// ibus2.go
|
||||
AddMsg(models.NewCANMessage(1317, 3).
|
||||
Signal(2, state.TBOX_GPSHei, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(1318, 2).
|
||||
Signal(0, state.TBOX_GPSLongi, state.RoundGPS).
|
||||
Signal(1, state.TBOX_GPSLati, state.RoundGPS)).
|
||||
AddMsg(models.NewCANMessage(345, 10).
|
||||
Signal(5, state.ACU_Drvr_Occpt_St, state.Int)).
|
||||
AddMsg(models.NewCANMessage(819, 12).
|
||||
Signal(4, state.BCM_PwrMod, state.Int)).
|
||||
AddMsg(models.NewCANMessage(1316, 4).
|
||||
Signal(0, state.PWC_ChrgSts, state.Int)).
|
||||
// Alexander Andrews Immobilization status possible signals
|
||||
AddMsg(models.NewCANMessage(54, 99).
|
||||
Signal(15, state.TBOX_RemCtrlCmdFb, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Void",
|
||||
1: "Successful",
|
||||
2: "Failed",
|
||||
3: "Reserved",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(537, 23).
|
||||
Signal(3, state.VCU_IMMO_Sts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Immo_Active",
|
||||
1: "Immo_Inactive",
|
||||
2: "Reserved",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(817, 15).
|
||||
Signal(7, state.PKC_IMMO_AuthSts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial",
|
||||
1: "Auth_Valid",
|
||||
2: "Auth_Invalid",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
SetDiagnosticFlags(diagnostics.FM29FRSD0DiagnosticFlags)
|
||||
}
|
||||
173
pkg/dbc/dbc_fm29_frsd390.go
Normal file
173
pkg/dbc/dbc_fm29_frsd390.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/dbc/diagnostics"
|
||||
fm29_frsd390 "fiskerinc.com/modules/dbc/fm29_frsd390"
|
||||
"fiskerinc.com/modules/dbc/models"
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
)
|
||||
|
||||
func NewFM29_FRSD390_DBC() models.DBCVersionInterface {
|
||||
fm29_frsd0md := &fm29_frsd390.MessagesDescriptor{}
|
||||
fm29_frsd0db := fm29_frsd0md.Database()
|
||||
|
||||
return models.NewDBCVersion(fm29_frsd0db, fm29_frsd390.Hash).
|
||||
// bbus.go
|
||||
AddMsg(models.NewCANMessage(336, 12).
|
||||
Signal(7, state.MCU_F_CrtMod, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(337, 13).
|
||||
Signal(7, state.MCU_R_CrtMod, state.IntFloor).
|
||||
Signal(8, state.MCU_R_Decoup_State, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(532, 23).
|
||||
Signal(2, state.VCU_RdyLamp, state.FloatToBool).
|
||||
Signal(8, state.VCU_GearSig, state.IntFloor).
|
||||
Signal(12, state.VCU_VehSt, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(552, 9).
|
||||
Signal(7, state.MCU_F_ActSafeSt, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(553, 9).
|
||||
Signal(7, state.MCU_R_ActSafeSt, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(566, 10).
|
||||
Signal(8, state.VCU_VcuState, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(792, 17).
|
||||
Signal(10, state.ESP_VehSpd, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(608, 12).
|
||||
Signal(4, state.VCU_VehChrgDchgMod, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial_value",
|
||||
1: "DC_charging",
|
||||
2: "VTOL_discharging",
|
||||
3: "VTOV_discharging",
|
||||
4: "AC_charging",
|
||||
5: "V2L_trunk_active",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(681, 5).
|
||||
Signal(1, state.IBS_BatteryVoltage, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(757, 4).
|
||||
Signal(0, state.BMS_Bat_SoC_usable, state.IntFloor).
|
||||
Signal(2, state.BMS_Bat_SOH, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(801, 6).
|
||||
Signal(0, state.BCM_AP_FL_LeFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_FL_RiFrntWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_FL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(3, state.BCM_AP_FL_RiReWinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(816, 14).
|
||||
Signal(4, state.BMS_PwrBattRmngCpSOC, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(821, 37).
|
||||
Signal(21, state.BCM_ReDefrstHeatgCmd, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(835, 34).
|
||||
Signal(4, state.BCM_FrntHoodLidSts, state.FloatToBool).
|
||||
Signal(6, state.BCM_FrntDrDoorLockSts, state.FloatToBool).
|
||||
Signal(9, state.BCM_DrFrntDoorSts, state.FloatToBool).
|
||||
Signal(10, state.BCM_PasFrntDoorSts, state.FloatToBool).
|
||||
Signal(12, state.BCM_CenLockSwtSts, state.IntFloor).
|
||||
Signal(14, state.BCM_RiReDoorSts, state.FloatToBool).
|
||||
Signal(15, state.BCM_LeReDoorSts, state.FloatToBool).
|
||||
Signal(29, state.BCM_SunroofPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(873, 12).
|
||||
Signal(0, state.BCM_AP_TL_LeReWinPosnInfo, state.IntCeil).
|
||||
Signal(1, state.BCM_AP_TL_RiReWinPosnInfo, state.IntCeil).
|
||||
Signal(2, state.BCM_AP_RW_WinPosnInfo, state.IntCeil)).
|
||||
AddMsg(models.NewCANMessage(882, 14).
|
||||
Signal(6, state.BMS_BattAvrgT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(883, 24).
|
||||
Signal(15, state.ECC_OutdT, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(902, 8).
|
||||
Signal(0, state.BCM_HeatedSteerWhlSt, state.FloatToBool)).
|
||||
AddMsg(models.NewCANMessage(1284, 16).
|
||||
Signal(12, state.VCU_DrvgMilg, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1298, 5).
|
||||
Signal(0, state.PSM_PassSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1304, 6).
|
||||
Signal(0, state.DSMC_DrvrSeatHeatgSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1329, 7).
|
||||
Signal(1, state.ICC_TotMilg_ODO, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1429, 2).
|
||||
Signal(0, state.BMS_RmChrgTi_FullChrg, state.Int).
|
||||
Signal(1, state.BMS_RmChrgTi_TrgtSoC, state.Int)).
|
||||
/*
|
||||
AddMsg(models.NewCANMessage(1408, 4).
|
||||
Signal(2, state.VCU_DCChrgRmngTi, state.Int)).
|
||||
*/
|
||||
AddMsg(models.NewCANMessage(1410, 7).
|
||||
Signal(0, state.ECC_InsdT, state.IntFloor).
|
||||
Signal(2, state.ECC_RemTSetSts, state.IntFloor)).
|
||||
AddMsg(models.NewCANMessage(1137, 21).
|
||||
Signal(17, state.PLGM_TrSts, state.FloatToBool)).
|
||||
// ibus2.go
|
||||
AddMsg(models.NewCANMessage(1317, 3).
|
||||
Signal(2, state.TBOX_GPSHei, state.RoundMilli)).
|
||||
AddMsg(models.NewCANMessage(1318, 2).
|
||||
Signal(0, state.TBOX_GPSLongi, state.RoundGPS).
|
||||
Signal(1, state.TBOX_GPSLati, state.RoundGPS)).
|
||||
AddMsg(models.NewCANMessage(345, 10).
|
||||
Signal(5, state.ACU_Drvr_Occpt_St, state.Int)).
|
||||
AddMsg(models.NewCANMessage(819, 12).
|
||||
Signal(4, state.BCM_PwrMod, state.Int)).
|
||||
AddMsg(models.NewCANMessage(1316, 4).
|
||||
Signal(0, state.PWC_ChrgSts, state.Int)).
|
||||
// Alexander Andrews Immobilization status possible signals
|
||||
AddMsg(models.NewCANMessage(54, 99).
|
||||
Signal(15, state.TBOX_RemCtrlCmdFb, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Void",
|
||||
1: "Successful",
|
||||
2: "Failed",
|
||||
3: "Processing",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(537, 23). // Should investigate keeping as ints, or using the human readable value? Also make auto generator for this
|
||||
Signal(3, state.VCU_IMMO_Sts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Immo_Active",
|
||||
1: "Immo_Inactive",
|
||||
2: "Reserved",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(817, 15).
|
||||
Signal(7, state.PKC_IMMO_AuthSts, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Initial",
|
||||
1: "Auth_Valid",
|
||||
2: "Auth_Invalid",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(896, 8).
|
||||
Signal(7, state.PKC_AuthFailPromt, state.GetMappedStrValues(map[float64]string{
|
||||
0: "Inactive",
|
||||
1: "VCU_Authentication_Failure",
|
||||
2: "Reserved",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(83, 7).
|
||||
Signal(2, state.TBOX_RemCtrlLockCmd, state.GetMappedStrValues(map[float64]string{
|
||||
0: "without_remote_control",
|
||||
1: "Remote_unlocking",
|
||||
2: "Remote_locking",
|
||||
3: "Invalid",
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(891, 17).
|
||||
Signal(10, state.PKC_StrtFailTyp, state.GetMappedStrValues(map[float64]string{
|
||||
0: "No_error",
|
||||
1: "Reserved",
|
||||
2: "VCU_Authentication_Failure",
|
||||
3: "Time_Out_(Crank_Off_Time)",
|
||||
4: "Auth_Pass",
|
||||
5: "Remote Immo Enabled",
|
||||
6: "No Key detected inside the vehicle",
|
||||
7: "Alcointerlock Enabled",
|
||||
8: "Initial value",
|
||||
9: "Reserved 9",
|
||||
10: "Reserved 10",
|
||||
11: "Reserved 11",
|
||||
12: "Reserved 12",
|
||||
13: "Reserved 13",
|
||||
14: "Reserved 14",
|
||||
15: "Reserved 15",
|
||||
})).
|
||||
Signal(3, state.PKC_KeyStsMod, state.GetMappedStrValues(map[float64]string{
|
||||
0: state.PKC_KeyStsMod_disabled,
|
||||
1: state.PKC_KeyStsMod_enabled,
|
||||
}))).
|
||||
AddMsg(models.NewCANMessage(377, 4).
|
||||
Signal(2, state.TBOX_Heading, state.RoundMilli)).
|
||||
// So not sure what happened, but I added these to the state but didn't add them to the parse set up
|
||||
AddMsg(models.NewCANMessage(684, 5).
|
||||
Signal(0, state.IBS_StateOfCharge, state.RoundMilli).
|
||||
Signal(1, state.IBS_StateOfHealth, state.RoundMilli)).
|
||||
SetDiagnosticFlags(diagnostics.FM29FRSD0DiagnosticFlags)
|
||||
}
|
||||
448
pkg/dbc/dbc_parsestate_test.go
Normal file
448
pkg/dbc/dbc_parsestate_test.go
Normal file
@@ -0,0 +1,448 @@
|
||||
package dbc_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"fiskerinc.com/modules/dbc"
|
||||
fm29_frs90 "fiskerinc.com/modules/dbc/fm29_frs90"
|
||||
fm29_frsd0 "fiskerinc.com/modules/dbc/fm29_frsd0"
|
||||
fm29_frsd21 "fiskerinc.com/modules/dbc/fm29_frsd21"
|
||||
fm29_frsd390 "fiskerinc.com/modules/dbc/fm29_frsd390"
|
||||
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
"fiskerinc.com/modules/grpc/kafka_grpc"
|
||||
"fiskerinc.com/modules/testhelper"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
const vin = "11111111111111111"
|
||||
|
||||
var epoch = int64(1642455023642165)
|
||||
var payloadFRS90 = kafka_grpc.GRPC_BatchPayload{
|
||||
Version: fm29_frs90.Hash,
|
||||
Data: &kafka_grpc.GRPC_CANData{
|
||||
Frames: []*kafka_grpc.GRPC_CANFrame{
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 608,
|
||||
Value: []byte("AAEAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 757,
|
||||
Value: []byte("CgAAAAAUAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 801,
|
||||
Value: []byte("AAAUKDxQ/wA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 816,
|
||||
Value: []byte("AAAAfQAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 821,
|
||||
Value: []byte("AAAAAAgAAP8="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 835,
|
||||
Value: []byte("AAAFbAAAMgA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 873,
|
||||
Value: []byte("AAB4jKAAAAE="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 882,
|
||||
Value: []byte("AAAwADCKADA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 883,
|
||||
Value: []byte("AAAAAACcAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 902,
|
||||
Value: []byte("AQAAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1284,
|
||||
Value: []byte("AAAAAAAwNAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1298,
|
||||
Value: []byte("EAAAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1304,
|
||||
Value: []byte("AgAAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1329,
|
||||
Value: []byte("AAADlAQAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1408,
|
||||
Value: []byte("AAAAABOIAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1410,
|
||||
Value: []byte("nAB4AAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1317,
|
||||
Value: []byte("AABAg6NJ64c="),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var payloadFRSD0 = kafka_grpc.GRPC_BatchPayload{
|
||||
Version: fm29_frsd0.Hash,
|
||||
Data: &kafka_grpc.GRPC_CANData{
|
||||
Frames: []*kafka_grpc.GRPC_CANFrame{
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 608,
|
||||
Value: []byte("AAAA+gH0Aec="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 757,
|
||||
Value: []byte("CgAAAAAUAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 801,
|
||||
Value: []byte("AAAUKDxQ/wA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 816,
|
||||
Value: []byte("AAAAfQAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 821,
|
||||
Value: []byte("AAAAAAgAAP8="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 835,
|
||||
Value: []byte("AAAFbAAAZAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 873,
|
||||
Value: []byte("AAB4jKAAAAE="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 882,
|
||||
Value: []byte("AAAwADCKADA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 883,
|
||||
Value: []byte("AAAAAACcAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 902,
|
||||
Value: []byte("AQAAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1284,
|
||||
Value: []byte("AAAAAAAwNAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1298,
|
||||
Value: []byte("EAAAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1304,
|
||||
Value: []byte("AgAAAAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1329,
|
||||
Value: []byte("AAADlAQAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1408,
|
||||
Value: []byte("AMgBLBOIAZA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1410,
|
||||
Value: []byte("nAB4AAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1317,
|
||||
Value: []byte("ZAVAgAAAAAA="),
|
||||
},
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 1318,
|
||||
Value: []byte("A414OAeAC0A="),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var expectedValuesFRS90 = map[string]interface{}{
|
||||
state.BCM_AP_FL_LeFrntWinPosnInfo: interface{}(10),
|
||||
state.BCM_AP_FL_LeReWinPosnInfo: interface{}(30),
|
||||
state.BCM_AP_FL_RiFrntWinPosnInfo: interface{}(20),
|
||||
state.BCM_AP_FL_RiReWinPosnInfo: interface{}(40),
|
||||
state.BCM_AP_RW_WinPosnInfo: interface{}(80),
|
||||
state.BCM_AP_TL_LeReWinPosnInfo: interface{}(60),
|
||||
state.BCM_AP_TL_RiReWinPosnInfo: interface{}(70),
|
||||
state.BCM_CenLockSwtSts: interface{}(3),
|
||||
state.BCM_DrFrntDoorSts: interface{}(false),
|
||||
state.BCM_FrntDrDoorLockSts: interface{}(true),
|
||||
state.BCM_FrntHoodLidSts: interface{}(true),
|
||||
state.BCM_HeatedSteerWhlSt: interface{}(true),
|
||||
state.BCM_LeReDoorSts: interface{}(true),
|
||||
state.BCM_PasFrntDoorSts: interface{}(false),
|
||||
state.BCM_ReDefrstHeatgCmd: interface{}(true),
|
||||
state.BCM_RiReDoorSts: interface{}(true),
|
||||
state.BCM_SunroofPosnInfo: interface{}(50),
|
||||
state.BMS_Bat_SOH: interface{}(20),
|
||||
state.BMS_Bat_SoC_usable: interface{}(10),
|
||||
state.BMS_BattAvrgT: interface{}(90),
|
||||
state.BMS_PwrBattRmngCpSOC: interface{}(50),
|
||||
state.DSMC_DrvrSeatHeatgSts: interface{}(2),
|
||||
state.ECC_InsdT: interface{}(30),
|
||||
state.ECC_OutdT: interface{}(30),
|
||||
state.ECC_RemTSetSts: interface{}(120),
|
||||
state.ICC_TotMilg_ODO: interface{}(float64(2345)),
|
||||
state.PSM_PassSeatHeatgSts: interface{}(4),
|
||||
state.TBOX_GPSHei: interface{}(float64(16)),
|
||||
state.TBOX_GPSLati: interface{}(float64(35.831)),
|
||||
state.TBOX_GPSLongi: interface{}(float64(-120.398)),
|
||||
state.VCU_DCChrgRmngTi: interface{}(5000),
|
||||
state.VCU_DrvgMilg: interface{}(1234),
|
||||
state.VCU_VehChrgDchgMod: interface{}("DC_charging"),
|
||||
state.UPDATED_AT: interface{}([]byte{34, 50, 48, 50, 50, 45, 48, 49, 45, 49, 55, 84, 50, 49, 58, 51, 48, 58, 50, 51, 46, 54, 52, 50, 49, 54, 53, 90, 34}),
|
||||
}
|
||||
var expectedValuesFRSD0 = map[string]interface{}{
|
||||
state.BCM_AP_FL_LeFrntWinPosnInfo: interface{}(10),
|
||||
state.BCM_AP_FL_LeReWinPosnInfo: interface{}(30),
|
||||
state.BCM_AP_FL_RiFrntWinPosnInfo: interface{}(20),
|
||||
state.BCM_AP_FL_RiReWinPosnInfo: interface{}(40),
|
||||
state.BCM_AP_RW_WinPosnInfo: interface{}(80),
|
||||
state.BCM_AP_TL_LeReWinPosnInfo: interface{}(60),
|
||||
state.BCM_AP_TL_RiReWinPosnInfo: interface{}(70),
|
||||
state.BCM_CenLockSwtSts: interface{}(3),
|
||||
state.BCM_DrFrntDoorSts: interface{}(false),
|
||||
state.BCM_FrntDrDoorLockSts: interface{}(true),
|
||||
state.BCM_FrntHoodLidSts: interface{}(true),
|
||||
state.BCM_HeatedSteerWhlSt: interface{}(true),
|
||||
state.BCM_LeReDoorSts: interface{}(true),
|
||||
state.BCM_PasFrntDoorSts: interface{}(false),
|
||||
state.BCM_ReDefrstHeatgCmd: interface{}(true),
|
||||
state.BCM_RiReDoorSts: interface{}(true),
|
||||
state.BCM_SunroofPosnInfo: interface{}(50),
|
||||
state.BMS_Bat_SOH: interface{}(20),
|
||||
state.BMS_Bat_SoC_usable: interface{}(10),
|
||||
state.BMS_BattAvrgT: interface{}(90),
|
||||
state.BMS_PwrBattRmngCpSOC: interface{}(50),
|
||||
state.DSMC_DrvrSeatHeatgSts: interface{}(2),
|
||||
state.ECC_InsdT: interface{}(30),
|
||||
state.ECC_OutdT: interface{}(30),
|
||||
state.ECC_RemTSetSts: interface{}(120),
|
||||
state.ICC_TotMilg_ODO: interface{}(float64(2345)),
|
||||
state.PSM_PassSeatHeatgSts: interface{}(4),
|
||||
state.TBOX_GPSHei: interface{}(float64(16)),
|
||||
state.TBOX_GPSLati: interface{}(float64(35.832)),
|
||||
state.TBOX_GPSLongi: interface{}(float64(-120.397)),
|
||||
state.VCU_DCChrgRmngTi: interface{}(5000),
|
||||
state.VCU_DrvgMilg: interface{}(1234),
|
||||
state.VCU_VehChrgDchgMod: interface{}("DC_charging"),
|
||||
state.UPDATED_AT: interface{}([]byte{34, 50, 48, 50, 50, 45, 48, 49, 45, 49, 55, 84, 50, 49, 58, 51, 48, 58, 50, 51, 46, 54, 52, 50, 49, 54, 53, 90, 34}),
|
||||
}
|
||||
|
||||
var expectedValuesFRSD21 = map[string]interface{}{
|
||||
state.BCM_AP_FL_LeFrntWinPosnInfo: interface{}(10),
|
||||
state.BCM_AP_FL_LeReWinPosnInfo: interface{}(30),
|
||||
state.BCM_AP_FL_RiFrntWinPosnInfo: interface{}(20),
|
||||
state.BCM_AP_FL_RiReWinPosnInfo: interface{}(40),
|
||||
state.BCM_AP_RW_WinPosnInfo: interface{}(80),
|
||||
state.BCM_AP_TL_LeReWinPosnInfo: interface{}(60),
|
||||
state.BCM_AP_TL_RiReWinPosnInfo: interface{}(70),
|
||||
state.BCM_CenLockSwtSts: interface{}(3),
|
||||
state.BCM_DrFrntDoorSts: interface{}(false),
|
||||
state.BCM_FrntDrDoorLockSts: interface{}(true),
|
||||
state.BCM_FrntHoodLidSts: interface{}(true),
|
||||
state.BCM_HeatedSteerWhlSt: interface{}(true),
|
||||
state.BCM_LeReDoorSts: interface{}(true),
|
||||
state.BCM_PasFrntDoorSts: interface{}(false),
|
||||
state.BCM_ReDefrstHeatgCmd: interface{}(true),
|
||||
state.BCM_RiReDoorSts: interface{}(true),
|
||||
state.BCM_SunroofPosnInfo: interface{}(50),
|
||||
state.BMS_Bat_SOH: interface{}(20),
|
||||
state.BMS_Bat_SoC_usable: interface{}(10),
|
||||
state.BMS_BattAvrgT: interface{}(90),
|
||||
state.BMS_PwrBattRmngCpSOC: interface{}(50),
|
||||
state.DSMC_DrvrSeatHeatgSts: interface{}(2),
|
||||
state.ECC_InsdT: interface{}(30),
|
||||
state.ECC_OutdT: interface{}(30),
|
||||
state.ECC_RemTSetSts: interface{}(120),
|
||||
state.ICC_TotMilg_ODO: interface{}(2345),
|
||||
state.PSM_PassSeatHeatgSts: interface{}(4),
|
||||
state.TBOX_GPSHei: interface{}(float64(2802.4)),
|
||||
state.TBOX_GPSLati: interface{}(float64(-54.168)),
|
||||
state.TBOX_GPSLongi: interface{}(float64(-300.397)),
|
||||
state.VCU_DCChrgRmngTi: interface{}(5000),
|
||||
state.VCU_DrvgMilg: interface{}(1234),
|
||||
state.VCU_VehChrgDchgMod: interface{}("DC_charging"),
|
||||
state.UPDATED_AT: interface{}([]byte{34, 50, 48, 50, 50, 45, 48, 49, 45, 49, 55, 84, 50, 49, 58, 51, 48, 58, 50, 51, 46, 54, 52, 50, 49, 54, 53, 90, 34}),
|
||||
}
|
||||
|
||||
func getExpectedValuesFRS390() map[string]interface{} {
|
||||
expectedValuesFRS390 := map[string]interface{}{}
|
||||
copier.Copy(&expectedValuesFRS390, &expectedValuesFRSD21)
|
||||
// DBC 390 does not have a definition for VCU_DCChrgRmngTi
|
||||
delete(expectedValuesFRS390, state.VCU_DCChrgRmngTi)
|
||||
expectedValuesFRS390[state.TBOX_GPSLati] = interface{}(float64(35.832))
|
||||
expectedValuesFRS390[state.TBOX_GPSLongi] = interface{}(float64(-120.397))
|
||||
|
||||
return expectedValuesFRS390
|
||||
}
|
||||
|
||||
func copyPayload(source *kafka_grpc.GRPC_BatchPayload, hash string) *kafka_grpc.GRPC_BatchPayload {
|
||||
payload := kafka_grpc.GRPC_BatchPayload{}
|
||||
proto.Merge(&payload, source)
|
||||
payload.Version = hash
|
||||
|
||||
return &payload
|
||||
}
|
||||
|
||||
func ignoreSignalUpdateTimestamp(input map[string]interface{}) map[string]interface{} {
|
||||
m := make(map[string]interface{})
|
||||
pattern, _ := regexp.Compile(`:updated$`)
|
||||
for key, val := range input {
|
||||
matched := pattern.MatchString(key)
|
||||
if matched {
|
||||
continue
|
||||
}
|
||||
m[key] = val
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func TestFM29_FRS90_ParseState(t *testing.T) {
|
||||
payloadFRSD21 := copyPayload(&payloadFRSD0, fm29_frsd21.Hash)
|
||||
payloadFRSD390 := copyPayload(&payloadFRSD0, fm29_frsd390.Hash)
|
||||
expectedValuesFRS390 := getExpectedValuesFRS390()
|
||||
|
||||
collection := dbc.NewDBCCollection()
|
||||
type testCase struct {
|
||||
name string
|
||||
payload *kafka_grpc.GRPC_BatchPayload
|
||||
expected map[string]interface{}
|
||||
expectedCommandCount int
|
||||
}
|
||||
tests := []testCase{
|
||||
{
|
||||
name: "FRS90",
|
||||
payload: &payloadFRS90,
|
||||
expected: expectedValuesFRS90,
|
||||
expectedCommandCount: 34,
|
||||
},
|
||||
{
|
||||
name: "FRSD0",
|
||||
payload: &payloadFRSD0,
|
||||
expected: expectedValuesFRSD0,
|
||||
expectedCommandCount: 34,
|
||||
},
|
||||
{
|
||||
name: "FRSD21",
|
||||
payload: payloadFRSD21,
|
||||
expected: expectedValuesFRSD21,
|
||||
expectedCommandCount: 34,
|
||||
},
|
||||
{
|
||||
name: "FRSD390",
|
||||
payload: payloadFRSD390,
|
||||
expected: expectedValuesFRS390,
|
||||
expectedCommandCount: 33,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
keyvalues, err := collection.ParseState(vin, test.payload, nil)
|
||||
if err != nil {
|
||||
t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("ParseState %s", test.name), nil, err)
|
||||
}
|
||||
expectedCommandCount := 2*test.expectedCommandCount - 1
|
||||
if len(keyvalues) != expectedCommandCount {
|
||||
t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("key value len %s", test.name), expectedCommandCount, len(keyvalues))
|
||||
}
|
||||
mKeyVal := ignoreSignalUpdateTimestamp(keyvalues)
|
||||
if !reflect.DeepEqual(mKeyVal, test.expected) {
|
||||
t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("key value compare %s", test.name), test.expected, keyvalues)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadMsgID(t *testing.T) {
|
||||
collection := dbc.NewDBCCollection()
|
||||
payload := kafka_grpc.GRPC_BatchPayload{
|
||||
Version: fm29_frsd0.Hash,
|
||||
Data: &kafka_grpc.GRPC_CANData{
|
||||
Frames: []*kafka_grpc.GRPC_CANFrame{
|
||||
{
|
||||
Epoch: epoch,
|
||||
ID: 576,
|
||||
Value: []byte("AAAAA414OAeAC0A="),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// This test should not set anything in Redis cache
|
||||
keyvalues, _ := collection.ParseState(vin, &payload, nil)
|
||||
if len(keyvalues) != 0 {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "bad message id", 0, len(keyvalues))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNewFM29_FRS90_DBC(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
dbc.NewFM29_FRS90_DBC()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseState(b *testing.B) {
|
||||
collection := dbc.NewDBCCollection()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
collection.ParseState(vin, &payloadFRS90, nil)
|
||||
}
|
||||
}
|
||||
370
pkg/dbc/dbc_tools_test.go
Normal file
370
pkg/dbc/dbc_tools_test.go
Normal file
@@ -0,0 +1,370 @@
|
||||
package dbc_test
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
fm29_frs90 "fiskerinc.com/modules/dbc/fm29_frs90"
|
||||
fm29_frsd0 "fiskerinc.com/modules/dbc/fm29_frsd0"
|
||||
fm29_frsd21 "fiskerinc.com/modules/dbc/fm29_frsd21"
|
||||
fm29_frsd390 "fiskerinc.com/modules/dbc/fm29_frsd390"
|
||||
n60 "fiskerinc.com/modules/dbc/n60"
|
||||
"fiskerinc.com/modules/testhelper"
|
||||
|
||||
can "github.com/Fisker-Inc/project-ai-can-go"
|
||||
"github.com/Fisker-Inc/project-ai-can-go/pkg/descriptor"
|
||||
)
|
||||
|
||||
// For generating test data
|
||||
|
||||
type CANMsg interface {
|
||||
Descriptor() *descriptor.Message
|
||||
Frame() can.Frame
|
||||
}
|
||||
|
||||
func displayData(msg CANMsg) {
|
||||
fmt.Println(msg.Descriptor().ID, encodeData(msg.Frame().Data))
|
||||
}
|
||||
|
||||
func encodeData(data can.Data) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(data[:]))
|
||||
}
|
||||
|
||||
func TestDBCHash(t *testing.T) {
|
||||
const fm29_frs90_hash = "0e1f0e4eb01cfdd795f7f539d6baccc85770846050a83f5ac2f3ce75ea6453a0"
|
||||
const fm29_frsd0_hash = "386c18977a1be3cda60c953e5902c680dbe82b89523f2527e80cd9db863db991"
|
||||
const fm29_frsd21_hash = "d439abd3662dd20099f49dd8f43f7b145202e961caa2b5aba2c6154c8096348b"
|
||||
const fm29_frsd390_hash = "1c9d097ab570b1f28d447f947ed9f87aeaba3e4386db02ffdfb698bb1c08808b"
|
||||
const n60_hash = "556fe1385c2bfcbdc89bfa1fda7b580e594aa2ae3267cbe6ec9668a593755e59"
|
||||
|
||||
if fm29_frsd21.Hash != fm29_frsd21_hash {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "fm29_frsd21 hash", fm29_frsd21_hash, fm29_frsd21.Hash)
|
||||
}
|
||||
|
||||
if fm29_frs90.Hash != fm29_frs90_hash {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "fm29_frs90 hash", fm29_frs90_hash, fm29_frs90.Hash)
|
||||
}
|
||||
|
||||
if fm29_frsd0.Hash != fm29_frsd0_hash {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "fm29_frsd0 hash", fm29_frsd0_hash, fm29_frsd0.Hash)
|
||||
}
|
||||
|
||||
if fm29_frsd390.Hash != fm29_frsd390_hash {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "fm29_frsd390 hash", fm29_frsd390_hash, fm29_frsd390.Hash)
|
||||
}
|
||||
|
||||
if n60.Hash != n60_hash {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "n60 hash", n60_hash, n60.Hash)
|
||||
}
|
||||
}
|
||||
func TestGenerateSignalsFM29_FRSD0(t *testing.T) {
|
||||
t.Skip()
|
||||
var msg CANMsg
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewVCU_0x260()
|
||||
x.SetVCU_VehChrgDchgMod(1)
|
||||
x.SetVCU_260_SSecOC_Fresh_Byte0(1)
|
||||
x.SetVCU_260_SSecOC_MAC_Byte0(1)
|
||||
x.SetVCU_260_SSecOC_MAC_Byte1(1)
|
||||
x.SetVCU_260_SSecOC_MAC_Byte2(1)
|
||||
x.SetVCU_ChrgSts(10)
|
||||
x.SetVCU_ChrgSysOperCmd(10)
|
||||
x.SetVCU_DCCrtCmd_OBC(10)
|
||||
x.SetVCU_DCVoltCmd_OBC(5)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBMS_SOC()
|
||||
x.SetBMS_Bat_SoC_usable(10)
|
||||
x.SetBMS_Bat_SOH(20)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBCM_0x321()
|
||||
x.SetBCM_AP_FL_LeFrntWinPosnInfo(10)
|
||||
x.SetBCM_AP_FL_RiFrntWinPosnInfo(20)
|
||||
x.SetBCM_AP_FL_LeReWinPosnInfo(30)
|
||||
x.SetBCM_AP_FL_RiReWinPosnInfo(40)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBMS_HVBatt_Status_2_TBOX()
|
||||
x.SetBMS_PwrBattRmngCpSOC(50)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBCM_0x335()
|
||||
x.SetBCM_ReDefrstHeatgCmd(true)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBCM_0x343()
|
||||
x.SetBCM_FrntHoodLidSts(true)
|
||||
x.SetBCM_FrntDrDoorLockSts(true)
|
||||
x.SetBCM_FrntDrDoorLockSts(true)
|
||||
x.SetBCM_CenLockSwtSts(2)
|
||||
x.SetBCM_RiReDoorSts(true)
|
||||
x.SetBCM_LeReDoorSts(true)
|
||||
x.SetBCM_SunroofPosnInfo(50)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBCM_0x369()
|
||||
x.SetBCM_AP_TL_LeReWinPosnInfo(60)
|
||||
x.SetBCM_AP_TL_RiReWinPosnInfo(70)
|
||||
x.SetBCM_AP_RW_WinPosnInfo(80)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBMS_CellTemp_CoolingHeating()
|
||||
x.SetBMS_BattAvrgT(90)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewECC_0x373()
|
||||
x.SetECC_OutdT(30)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewBCM_0x386()
|
||||
x.SetBCM_HeatedSteerWhlSt(1)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewVCU_0x504()
|
||||
x.SetVCU_DrvgMilg(1234)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewPSM_0x512()
|
||||
x.SetPSM_PassSeatHeatgSts(4)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewDSMC_0x518()
|
||||
x.SetDSMC_DrvrSeatHeatgSts(2)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewICC_0x531()
|
||||
x.SetICC_TotMilg_ODO(2345)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewECC_0x582()
|
||||
x.SetECC_InsdT(30)
|
||||
x.SetECC_RemTSetSts(120)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewVCU_0x580()
|
||||
x.SetVCU_DCChrgRmngTi(5000)
|
||||
x.SetVCU_ActChrgTotAh(2)
|
||||
x.SetVCU_ActDchgTotAh(3)
|
||||
x.SetVCU_PwrBattAvlEgy(4)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewTBOX_0x525()
|
||||
x.SetTBOX_GPSHei(16)
|
||||
x.SetTBOX_525_AliveCounter(5)
|
||||
x.SetTBOX_525_CheckSum(100)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frsd0.NewTBOX_0x526()
|
||||
x.SetTBOX_GPSLongi(-120.397)
|
||||
x.SetTBOX_GPSLati(35.832)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
t.Error("done")
|
||||
}
|
||||
|
||||
func TestGenerateSignalsFM29_FRS90(t *testing.T) {
|
||||
t.Skip()
|
||||
var msg CANMsg
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewVCU_0x260()
|
||||
x.SetVCU_VehChrgDchgMod(1)
|
||||
x.SetVCU_260_SSecOC_Fresh_Byte0(1)
|
||||
x.SetVCU_260_SSecOC_MAC_Byte0(1)
|
||||
x.SetVCU_260_SSecOC_MAC_Byte1(1)
|
||||
x.SetVCU_260_SSecOC_MAC_Byte2(1)
|
||||
x.SetVCU_ChrgSts(10)
|
||||
x.SetVCU_ChrgSysOperCmd(10)
|
||||
x.SetVCU_DCCrtCmd_OBC(10)
|
||||
x.SetVCU_DCDCPwrLimCmd(10)
|
||||
x.SetVCU_DCPosRlyCtrlCmd(true)
|
||||
x.SetVCU_DCVoltCmd_OBC(5)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBMS_SOC()
|
||||
x.SetBMS_Bat_SoC_usable(10)
|
||||
x.SetBMS_Bat_SOH(20)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBCM_0x321()
|
||||
x.SetBCM_AP_FL_LeFrntWinPosnInfo(10)
|
||||
x.SetBCM_AP_FL_RiFrntWinPosnInfo(20)
|
||||
x.SetBCM_AP_FL_LeReWinPosnInfo(30)
|
||||
x.SetBCM_AP_FL_RiReWinPosnInfo(40)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBMS_HVBatt_Status_2_TBOX()
|
||||
x.SetBMS_PwrBattRmngCpSOC(50)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBCM_0x335()
|
||||
x.SetBCM_ReDefrstHeatgCmd(true)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBCM_0x343()
|
||||
x.SetBCM_FrntHoodLidSts(true)
|
||||
x.SetBCM_FrntDrDoorLockSts(true)
|
||||
x.SetBCM_FrntDrDoorLockSts(true)
|
||||
x.SetBCM_CenLockSwtSts(2)
|
||||
x.SetBCM_RiReDoorSts(true)
|
||||
x.SetBCM_LeReDoorSts(true)
|
||||
x.SetBCM_SunroofPosnInfo(50)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBCM_0x369()
|
||||
x.SetBCM_AP_TL_LeReWinPosnInfo(60)
|
||||
x.SetBCM_AP_TL_RiReWinPosnInfo(70)
|
||||
x.SetBCM_AP_RW_WinPosnInfo(80)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBMS_CellTemp_CoolingHeating()
|
||||
x.SetBMS_BattAvrgT(90)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewECC_0x373()
|
||||
x.SetECC_OutdT(30)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewBCM_0x386()
|
||||
x.SetBCM_HeatedSteerWhlSt(1)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewVCU_0x504()
|
||||
x.SetVCU_DrvgMilg(1234)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewPSM_0x512()
|
||||
x.SetPSM_PassSeatHeatgSts(4)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewDSMC_0x518()
|
||||
x.SetDSMC_DrvrSeatHeatgSts(2)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewICC_0x531()
|
||||
x.SetICC_TotMilg_ODO(2345)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewECC_0x582()
|
||||
x.SetECC_InsdT(30)
|
||||
x.SetECC_RemTSetSts(120)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewVCU_0x580()
|
||||
x.SetVCU_DCChrgRmngTi(5000)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
msg = func() CANMsg {
|
||||
x := fm29_frs90.NewTBOX_0x525()
|
||||
x.SetTBOX_GPSHei(16)
|
||||
x.SetTBOX_GPSLongi(-120.397)
|
||||
x.SetTBOX_GPSLati(35.832)
|
||||
return x
|
||||
}()
|
||||
displayData(msg)
|
||||
|
||||
t.Error("done")
|
||||
}
|
||||
83
pkg/dbc/diagnostics/diagnostics.go
Normal file
83
pkg/dbc/diagnostics/diagnostics.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package diagnostics
|
||||
|
||||
type Flags map[int]map[string]float64
|
||||
|
||||
var FM29FRS90DiagnosticFlags = Flags{
|
||||
// esp
|
||||
609: {
|
||||
"ESP_ActvSig_DTC": 1,
|
||||
},
|
||||
|
||||
// bms
|
||||
816: {
|
||||
"BMS_PwrBattSysFltDisp": 1,
|
||||
},
|
||||
|
||||
// adas
|
||||
832: {
|
||||
"ADAS_FltIndcr": 2,
|
||||
"ADAS_IntegtCrsFltTxt": 1,
|
||||
"ADAS_LaneSprtFltTxt": 1,
|
||||
"ADAS_FwdWarnFltTxt": 1,
|
||||
"ADAS_IntecnFltTxt": 1,
|
||||
},
|
||||
|
||||
// mcu
|
||||
885: {
|
||||
"MCU_F_SystFltDisp": 1,
|
||||
},
|
||||
887: {
|
||||
"MCU_R_SysFltDisp": 1,
|
||||
},
|
||||
|
||||
// eps
|
||||
1136: {
|
||||
"EPS_CrtSts": 1,
|
||||
},
|
||||
|
||||
// vcu
|
||||
1284: {
|
||||
"VCU_VehSysFltLamp": 1,
|
||||
},
|
||||
1285: {
|
||||
"VCU_BattFltIndcn": 1,
|
||||
},
|
||||
}
|
||||
|
||||
var FM29FRSD0DiagnosticFlags = Flags{
|
||||
// esp
|
||||
276: {
|
||||
"ESP_ActvSig_DTC": 1,
|
||||
},
|
||||
|
||||
// bms
|
||||
816: {
|
||||
"BMS_PwrBattSysFltDisp": 1,
|
||||
},
|
||||
|
||||
// adas
|
||||
832: {
|
||||
"ADAS_FltIndcr": 2,
|
||||
},
|
||||
|
||||
// mcu
|
||||
885: {
|
||||
"MCU_F_SystFltDisp": 1,
|
||||
},
|
||||
887: {
|
||||
"MCU_R_SysFltDisp": 1,
|
||||
},
|
||||
|
||||
// eps
|
||||
1136: {
|
||||
"EPS_CrtSts": 1,
|
||||
},
|
||||
|
||||
// vcu
|
||||
1284: {
|
||||
"VCU_VehSysFltLamp": 1,
|
||||
},
|
||||
1285: {
|
||||
"VCU_BattFltIndcn": 1,
|
||||
},
|
||||
}
|
||||
9
pkg/dbc/errors.go
Normal file
9
pkg/dbc/errors.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func ErrInvalidDBC(version string) error {
|
||||
return errors.Errorf("could not find %s within collection", version)
|
||||
}
|
||||
143
pkg/dbc/models/can_message.go
Normal file
143
pkg/dbc/models/can_message.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/digitaltwin"
|
||||
)
|
||||
|
||||
type CANMessageInterface interface {
|
||||
AddSignal(signal CANSignal) CANMessageInterface
|
||||
GetID() int
|
||||
GetLength() int
|
||||
ParseState(keyvaluesOut map[string]interface{}, vin string, timestampUSec int, incomingSignals []common.CANSignal, cached digitaltwin.DigitalTwinCacheInterface) error
|
||||
Signal(position int, name string, convert func(value float64) interface{}) CANMessageInterface
|
||||
}
|
||||
|
||||
// NewCANMessage creates a top level instance for parsing a command. The id is the can signal in which individual signals exists
|
||||
// length is the number of messages inside the message, i.e. 1318 TBOX_0x526 has 2 different signals: TBOX_GPSLongi and TBOX_GPSLati
|
||||
func NewCANMessage(id int, length int) CANMessageInterface {
|
||||
return &CANMessage{
|
||||
id: id,
|
||||
length: length,
|
||||
}
|
||||
}
|
||||
|
||||
type CANMessage struct {
|
||||
id int
|
||||
length int
|
||||
signals map[int]CANSignal
|
||||
diagnostic map[int]DiagnosticSignal
|
||||
}
|
||||
|
||||
func (c *CANMessage) GetID() int {
|
||||
return c.id
|
||||
}
|
||||
|
||||
func (c *CANMessage) GetLength() int {
|
||||
return c.length
|
||||
}
|
||||
|
||||
// position is the index of the signal in its list. Starting at zero
|
||||
func (c *CANMessage) Signal(position int, name string, convert func(value float64) interface{}) CANMessageInterface {
|
||||
c.AddSignal(NewCANSignal(position, name, convert))
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CANMessage) AddSignal(signal CANSignal) CANMessageInterface {
|
||||
m := c.getSignalsMap()
|
||||
if _, ok := m[signal.Position]; ok {
|
||||
panic(fmt.Sprintf("signal position %d already exists", signal.Position))
|
||||
}
|
||||
|
||||
m[signal.Position] = signal
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CANMessage) Diagnostic(position int, name string, alert float64) CANMessageInterface {
|
||||
c.AddDiagnostic(NewDiagnosticSignal(position, name, alert))
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CANMessage) AddDiagnostic(signal DiagnosticSignal) CANMessageInterface {
|
||||
m := c.getDiagnosticMap()
|
||||
if _, ok := m[signal.Position]; ok {
|
||||
panic(fmt.Sprintf("diagnositic position %d already exists", signal.Position))
|
||||
}
|
||||
|
||||
m[signal.Position] = signal
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CANMessage) getDiagnosticMap() map[int]DiagnosticSignal {
|
||||
if c.diagnostic == nil {
|
||||
c.diagnostic = map[int]DiagnosticSignal{}
|
||||
}
|
||||
|
||||
return c.diagnostic
|
||||
}
|
||||
|
||||
func (c *CANMessage) getSignalsMap() map[int]CANSignal {
|
||||
if c.signals == nil {
|
||||
c.signals = map[int]CANSignal{}
|
||||
}
|
||||
|
||||
return c.signals
|
||||
}
|
||||
|
||||
// cached: Checks if the new signal has the same value as it did the last time, if so don't update it
|
||||
func (c *CANMessage) ParseState(keyvaluesOut map[string]interface{}, vin string, timestampUSec int, incomingSignals []common.CANSignal, cached digitaltwin.DigitalTwinCacheInterface) error {
|
||||
var can CANSignal
|
||||
var ok bool
|
||||
|
||||
s := c.getSignalsMap()
|
||||
|
||||
for i, signal := range incomingSignals {
|
||||
if can, ok = s[i]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if can.Name != signal.Name {
|
||||
return IncorrectSignalError(can.Name, signal.Name)
|
||||
}
|
||||
|
||||
val := can.ParseState(incomingSignals[i])
|
||||
|
||||
if cached != nil && cached.Exists(vin, signal.Name, val) {
|
||||
continue
|
||||
}
|
||||
keyvaluesOut[signal.Name] = val
|
||||
|
||||
// Added updated time for each signals. Key format -> "${signal_name}:updated"
|
||||
updatedAt, _ := state.SerializeTimestampUSec(timestampUSec)
|
||||
keyvaluesOut[fmt.Sprintf("%s:%s", signal.Name, "updated")] = updatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (c *CANMessage) DiagnosticAlert(vin string, timestampUSec int, signals []common.CANSignal) ([]DiagnosticSignal, error) {
|
||||
var flags []DiagnosticSignal
|
||||
|
||||
m := c.getDiagnosticMap()
|
||||
|
||||
for i, signal := range signals {
|
||||
if diag, ok := m[i]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if diag.Name != signal.Name {
|
||||
return nil, IncorrectSignalError(diag.Name, signal.Name)
|
||||
}
|
||||
|
||||
append(flags, diag)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
*/
|
||||
33
pkg/dbc/models/can_signal.go
Normal file
33
pkg/dbc/models/can_signal.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/common"
|
||||
)
|
||||
|
||||
func NewCANSignal(position int, name string, convert func(value float64) interface{}) CANSignal {
|
||||
return CANSignal{
|
||||
Position: position,
|
||||
Name: name,
|
||||
RedisKey: name,
|
||||
ConvertValue: convert,
|
||||
}
|
||||
}
|
||||
|
||||
type CANSignal struct {
|
||||
Position int
|
||||
Name string
|
||||
RedisKey string
|
||||
ConvertValue func(value float64) interface{}
|
||||
}
|
||||
|
||||
func (c *CANSignal) ParseState(signal common.CANSignal) interface{} {
|
||||
return c.getValue(signal.Value)
|
||||
}
|
||||
|
||||
func (c *CANSignal) getValue(value float64) interface{} {
|
||||
if c.ConvertValue == nil {
|
||||
return value
|
||||
}
|
||||
|
||||
return c.ConvertValue(value)
|
||||
}
|
||||
191
pkg/dbc/models/dbc_collection.go
Normal file
191
pkg/dbc/models/dbc_collection.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/dbc/state"
|
||||
"fiskerinc.com/modules/digitaltwin"
|
||||
"fiskerinc.com/modules/grpc/kafka_grpc"
|
||||
"fiskerinc.com/modules/logger"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func GetShortKey(key string) string {
|
||||
// the version (hash) is represented as hex
|
||||
// we agreed to use 2 first bytes, so we need 4 characters of hex string
|
||||
const length = 4
|
||||
|
||||
if len(key) < length {
|
||||
return key
|
||||
}
|
||||
|
||||
return key[:length]
|
||||
}
|
||||
|
||||
type DBCCollectionInterface interface {
|
||||
Get(dbcHash string) (DBCVersionInterface, error)
|
||||
AddVersion(dbcHash string, dbcVersion DBCVersionInterface) DBCCollectionInterface
|
||||
ParseState(vin string, payload *kafka_grpc.GRPC_BatchPayload, cached digitaltwin.DigitalTwinCacheInterface) (map[string]interface{}, error)
|
||||
GetOrigKey(short string) (string, error)
|
||||
GetHashesList() []string
|
||||
}
|
||||
|
||||
func NewDBCCollection(c map[string]DBCVersionInterface) DBCCollectionInterface {
|
||||
return &DBCCollection{
|
||||
collections: c,
|
||||
}
|
||||
}
|
||||
|
||||
type DBCCollection struct {
|
||||
collections map[string]DBCVersionInterface
|
||||
keys map[string]string
|
||||
options []DBCOption
|
||||
}
|
||||
|
||||
func (d *DBCCollection) getCollectionMap() map[string]DBCVersionInterface {
|
||||
if d.collections == nil {
|
||||
d.collections = map[string]DBCVersionInterface{}
|
||||
}
|
||||
|
||||
return d.collections
|
||||
}
|
||||
|
||||
func (d *DBCCollection) getKeyMap() map[string]string {
|
||||
if d.keys == nil {
|
||||
d.keys = map[string]string{}
|
||||
}
|
||||
|
||||
return d.keys
|
||||
}
|
||||
|
||||
func (d *DBCCollection) GetHashesList() []string {
|
||||
var hashs []string
|
||||
for _, hash := range d.keys {
|
||||
hashs = append(hashs, hash)
|
||||
}
|
||||
|
||||
return hashs
|
||||
}
|
||||
|
||||
func (d *DBCCollection) Get(dbcHash string) (DBCVersionInterface, error) {
|
||||
c := d.getCollectionMap()
|
||||
key := GetShortKey(dbcHash)
|
||||
if db, ok := c[key]; ok {
|
||||
return db, nil
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("DBC %s does not exists", dbcHash)
|
||||
}
|
||||
|
||||
func (d *DBCCollection) AddVersion(dbcHash string, dbcVersion DBCVersionInterface) DBCCollectionInterface {
|
||||
c := d.getCollectionMap()
|
||||
m := d.getKeyMap()
|
||||
key := GetShortKey(dbcHash)
|
||||
if _, ok := c[key]; ok {
|
||||
panic(fmt.Sprintf("DBC %s already exists", dbcHash))
|
||||
}
|
||||
|
||||
c[key] = dbcVersion
|
||||
m[key] = dbcHash
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DBCCollection) GetOrigKey(short string) (string, error) {
|
||||
m := d.getKeyMap()
|
||||
short = GetShortKey(short)
|
||||
if key, ok := m[short]; ok {
|
||||
return key, nil
|
||||
}
|
||||
|
||||
return "", ErrInvalidDBC(short)
|
||||
}
|
||||
|
||||
func (d *DBCCollection) ParseState(vin string, payload *kafka_grpc.GRPC_BatchPayload, cached digitaltwin.DigitalTwinCacheInterface) (map[string]interface{}, error) {
|
||||
keyvalues := make(map[string]interface{})
|
||||
|
||||
dbc, err := d.Get(payload.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updated_at := d.processFrames(dbc, keyvalues, vin, payload.Data.Frames, cached)
|
||||
d.processOptions(keyvalues, vin)
|
||||
|
||||
if len(keyvalues) > 0 {
|
||||
serialized, err := state.SerializeTimestampUSec(updated_at)
|
||||
if err != nil {
|
||||
return keyvalues, err
|
||||
}
|
||||
keyvalues[state.UPDATED_AT] = serialized
|
||||
}
|
||||
|
||||
return keyvalues, nil
|
||||
}
|
||||
|
||||
// cached: Local memory and digital twin, check to see if the value for that digital twin value is already saved in its given value
|
||||
func (d *DBCCollection) processFrames(dbc DBCVersionInterface, keyvaluesOut map[string]interface{}, vin string, frames []*kafka_grpc.GRPC_CANFrame, cached digitaltwin.DigitalTwinCacheInterface) int {
|
||||
var updated_at int
|
||||
|
||||
for _, msg := range frames {
|
||||
incomingSignals, err := dbc.GenerateCANSignals(vin, msg)
|
||||
if err != nil {
|
||||
logger.At(logger.Warn(), common.TRex.Key(vin), "dbc").
|
||||
Str("signal", fmt.Sprintf("%v", msg)).
|
||||
Str("dbc", dbc.Hash()).
|
||||
Err(err).Send()
|
||||
continue
|
||||
}
|
||||
|
||||
updated_at = int(msg.Epoch)
|
||||
err = dbc.ParseState(int(msg.ID), keyvaluesOut, vin, updated_at, incomingSignals, cached)
|
||||
if err != nil {
|
||||
logger.At(logger.Warn(), common.TRex.Key(vin), "dbc").
|
||||
Str("signal", fmt.Sprintf("%v", msg)).
|
||||
Str("dbc", dbc.Hash()).
|
||||
Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
return updated_at
|
||||
}
|
||||
|
||||
func (d *DBCCollection) processOptions(values map[string]interface{}, vin string) error {
|
||||
for _, option := range d.options {
|
||||
err := option.Handler(values, vin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (d *DBCCollection) DiagnosticAlert(vin string, payload *kafka_grpc.GRPC_BatchPayload) ([]DiagnosticSignal, error) {
|
||||
var flags = make([]DiagnosticSignal, 0)
|
||||
|
||||
dbc, err := d.Get(payload.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, msg := range payload.Data.Frames {
|
||||
signals, err := dbc.GenerateCANSignals(vin, msg)
|
||||
if err != nil {
|
||||
logger.Warn().Str("id", vin).Err(err).Msgf("%+v", msg)
|
||||
continue
|
||||
}
|
||||
|
||||
alerts, err := dbc.DiagnosticAlert(int(msg.ID), vin, int(msg.Epoch), signals)
|
||||
if err != nil {
|
||||
logger.Warn().Str("id", vin).Err(err).Msgf("%+v", msg)
|
||||
}
|
||||
|
||||
append(flags, alerts...)
|
||||
}
|
||||
|
||||
return flags, err
|
||||
}
|
||||
*/
|
||||
26
pkg/dbc/models/dbc_collection_test.go
Normal file
26
pkg/dbc/models/dbc_collection_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDBCCollection_AddVersion(t *testing.T) {
|
||||
hash := "abcdef1234562"
|
||||
dbc := &DBCVersion{
|
||||
diagnosticFlags: map[int]map[string]float64{},
|
||||
state: map[int]CANMessageInterface{},
|
||||
}
|
||||
col := DBCCollection{}
|
||||
col.AddVersion(hash, dbc)
|
||||
d, err := col.Get(hash)
|
||||
assert.Equal(t, dbc, d)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
hList := col.GetHashesList()
|
||||
assert.Equal(t, []string{hash}, hList)
|
||||
|
||||
oKey, err := col.GetOrigKey(GetShortKey(hash))
|
||||
assert.Equal(t, hash, oKey)
|
||||
assert.Equal(t, nil, err)
|
||||
}
|
||||
5
pkg/dbc/models/dbc_options.go
Normal file
5
pkg/dbc/models/dbc_options.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package models
|
||||
|
||||
type DBCOption struct {
|
||||
Handler func(values map[string]interface{}, vin string) error
|
||||
}
|
||||
186
pkg/dbc/models/dbc_version.go
Normal file
186
pkg/dbc/models/dbc_version.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/digitaltwin"
|
||||
"fiskerinc.com/modules/grpc/kafka_grpc"
|
||||
|
||||
can "github.com/Fisker-Inc/project-ai-can-go"
|
||||
"github.com/Fisker-Inc/project-ai-can-go/pkg/descriptor"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DBCVersionInterface interface {
|
||||
AddMsg(msg CANMessageInterface) DBCVersionInterface
|
||||
DecodeMessage(msg *kafka_grpc.GRPC_CANFrame) ([]descriptor.DecodedSignal, error)
|
||||
GenerateCANSignals(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, error)
|
||||
GetActiveDiagnosticFlags(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, bool, error)
|
||||
SetDiagnosticFlags(flags map[int]map[string]float64) DBCVersionInterface
|
||||
ParseState(id int, keyvaluesOut map[string]interface{}, vin string, timestampUSec int, incomingSignals []common.CANSignal, cached digitaltwin.DigitalTwinCacheInterface) error
|
||||
GetDatabase() *descriptor.Database
|
||||
Hash() string
|
||||
}
|
||||
|
||||
func NewDBCVersion(dbc *descriptor.Database, hash string) DBCVersionInterface {
|
||||
if len(hash) < 3 {
|
||||
panic("NewDBCVersion hash cannot be less than 3 characters")
|
||||
}
|
||||
|
||||
return &DBCVersion{
|
||||
dbc: dbc,
|
||||
hash: hash,
|
||||
}
|
||||
}
|
||||
|
||||
type DBCVersion struct {
|
||||
state map[int]CANMessageInterface
|
||||
dbc *descriptor.Database
|
||||
diagnosticFlags map[int]map[string]float64
|
||||
hash string
|
||||
}
|
||||
|
||||
func (d *DBCVersion) AddMsg(msg CANMessageInterface) DBCVersionInterface {
|
||||
m := d.getMsgMap()
|
||||
if _, ok := m[msg.GetID()]; ok {
|
||||
panic(fmt.Sprintf("CAN message %d already exists", msg.GetID()))
|
||||
}
|
||||
|
||||
m[msg.GetID()] = msg
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DBCVersion) getMsgMap() map[int]CANMessageInterface {
|
||||
if d.state == nil {
|
||||
d.state = map[int]CANMessageInterface{}
|
||||
}
|
||||
|
||||
return d.state
|
||||
}
|
||||
|
||||
func (d *DBCVersion) ParseState(id int, keyvaluesOut map[string]interface{}, vin string, timestampUSec int, incomingSignals []common.CANSignal, cached digitaltwin.DigitalTwinCacheInterface) error {
|
||||
m := d.getMsgMap()
|
||||
var msg CANMessageInterface
|
||||
var ok bool
|
||||
|
||||
if msg, ok = m[id]; !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if i := len(incomingSignals); i != msg.GetLength() {
|
||||
return IncorrectSignalsLength(id, msg.GetLength(), i)
|
||||
}
|
||||
|
||||
err := msg.ParseState(keyvaluesOut, vin, timestampUSec, incomingSignals, cached)
|
||||
|
||||
// TODO run options here
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DBCVersion) GenerateCANSignals(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, error) {
|
||||
var signals []common.CANSignal
|
||||
|
||||
decodedSignals, err := d.DecodeMessage(msg)
|
||||
if err != nil {
|
||||
return signals, err
|
||||
}
|
||||
|
||||
for _, signal := range decodedSignals {
|
||||
signals = append(signals, common.CANSignal{
|
||||
VIN: vin,
|
||||
Timestamp: float64(msg.Epoch) * math.Pow(10, -6),
|
||||
ID: int(msg.ID),
|
||||
Name: signal.Signal.Name,
|
||||
Value: signal.Value,
|
||||
})
|
||||
}
|
||||
|
||||
return signals, nil
|
||||
}
|
||||
|
||||
func (d *DBCVersion) DecodeMessage(msg *kafka_grpc.GRPC_CANFrame) ([]descriptor.DecodedSignal, error) {
|
||||
var decodedSignals []descriptor.DecodedSignal
|
||||
|
||||
if msg.ID >= 2048 || msg.ID < 0 {
|
||||
if GetInvalidCANIDCache().Exists(d.hash, msg.ID) {
|
||||
return decodedSignals, nil
|
||||
}
|
||||
return decodedSignals, errors.Errorf("message id %v out of bounds", msg.ID)
|
||||
}
|
||||
|
||||
message, ok := d.dbc.Message(uint32(msg.ID))
|
||||
if !ok {
|
||||
if GetInvalidCANIDCache().Exists(d.hash, msg.ID) {
|
||||
return decodedSignals, nil
|
||||
}
|
||||
|
||||
return decodedSignals, errors.Errorf(
|
||||
"message id %v not found in %s, version: %s",
|
||||
msg.ID, d.dbc.SourceFile, d.hash)
|
||||
}
|
||||
|
||||
strippedData := strings.TrimRight(string(msg.Value), "=")
|
||||
data, err := base64.RawStdEncoding.DecodeString(strippedData)
|
||||
if err != nil {
|
||||
return decodedSignals, errors.WithStack(err)
|
||||
}
|
||||
|
||||
p := can.Payload{Data: data}
|
||||
decodedSignals = message.Decode(&p)
|
||||
return decodedSignals, nil
|
||||
}
|
||||
|
||||
func (d *DBCVersion) GetActiveDiagnosticFlags(vin string, msg *kafka_grpc.GRPC_CANFrame) ([]common.CANSignal, bool, error) {
|
||||
var flags []common.CANSignal
|
||||
|
||||
diagnosticSignals, ok := d.diagnosticFlags[int(msg.ID)]
|
||||
if !ok {
|
||||
return flags, false, nil
|
||||
}
|
||||
|
||||
decodedSignals, err := d.DecodeMessage(msg)
|
||||
if err != nil {
|
||||
return flags, false, err
|
||||
}
|
||||
|
||||
flags = make([]common.CANSignal, 0)
|
||||
for _, signal := range decodedSignals {
|
||||
faultVal, ok := diagnosticSignals[signal.Signal.Name]
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
} else if signal.Value != faultVal {
|
||||
continue
|
||||
}
|
||||
|
||||
flags = append(flags, common.CANSignal{
|
||||
VIN: vin,
|
||||
Timestamp: float64(msg.Epoch) * math.Pow(10, -6),
|
||||
ID: int(msg.ID),
|
||||
Name: signal.Signal.Name,
|
||||
Value: signal.Value,
|
||||
})
|
||||
}
|
||||
|
||||
return flags, len(flags) != 0, nil
|
||||
}
|
||||
|
||||
func (d *DBCVersion) Hash() string {
|
||||
return d.hash
|
||||
}
|
||||
|
||||
// TODO this should be replaced by generated diagnostic alerts from the DBC
|
||||
func (d *DBCVersion) SetDiagnosticFlags(flags map[int]map[string]float64) DBCVersionInterface {
|
||||
d.diagnosticFlags = flags
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DBCVersion) GetDatabase() *descriptor.Database {
|
||||
return d.dbc
|
||||
}
|
||||
16
pkg/dbc/models/diagnostic_signal.go
Normal file
16
pkg/dbc/models/diagnostic_signal.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
func NewDiagnosticSignal(position int, name string, alert float64) DiagnosticSignal {
|
||||
return DiagnosticSignal{
|
||||
AlertValue: alert,
|
||||
CANSignal: CANSignal{
|
||||
Name: name,
|
||||
Position: position,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type DiagnosticSignal struct {
|
||||
AlertValue float64
|
||||
CANSignal
|
||||
}
|
||||
21
pkg/dbc/models/errors.go
Normal file
21
pkg/dbc/models/errors.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func IncorrectSignalsLength(msgid int, expected int, received int) error {
|
||||
return errors.Errorf("msg id %d incorrect number of signals in message expected %d received %d", msgid, expected, received)
|
||||
}
|
||||
|
||||
func IncorrectSignalError(expected string, received string) error {
|
||||
return errors.Errorf("wrong signal in message expected %s received %s", expected, received)
|
||||
}
|
||||
|
||||
func IncorrectSignalValue(expected interface{}, received interface{}) error {
|
||||
return errors.Errorf("wrong value in message expected one of %v received %v", expected, received)
|
||||
}
|
||||
|
||||
func ErrInvalidDBC(version string) error {
|
||||
return errors.Errorf("could not find %s within collection", version)
|
||||
}
|
||||
47
pkg/dbc/models/invalid_id_cache.go
Normal file
47
pkg/dbc/models/invalid_id_cache.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"fiskerinc.com/modules/cache"
|
||||
"fiskerinc.com/modules/utils/envtool"
|
||||
)
|
||||
|
||||
var (
|
||||
max_invalid_cache = envtool.GetEnvInt("MAX_INVALID_CANID_CACHE", 100)
|
||||
invalidCANIDOnce sync.Once
|
||||
invalidCANIDInstance InvalidCANIDCacheInterface
|
||||
)
|
||||
|
||||
func NewInvalidCANIDCache() InvalidCANIDCacheInterface {
|
||||
return &InvalidCANIDCache{
|
||||
ringMap: cache.NewRingMap(max_invalid_cache),
|
||||
}
|
||||
}
|
||||
|
||||
func GetInvalidCANIDCache() InvalidCANIDCacheInterface {
|
||||
invalidCANIDOnce.Do(func() {
|
||||
if invalidCANIDInstance == nil {
|
||||
invalidCANIDInstance = NewInvalidCANIDCache()
|
||||
}
|
||||
})
|
||||
|
||||
return invalidCANIDInstance
|
||||
}
|
||||
|
||||
func SetInvalidCANIDCache(instance InvalidCANIDCacheInterface) {
|
||||
invalidCANIDInstance = instance
|
||||
}
|
||||
|
||||
type InvalidCANIDCacheInterface interface {
|
||||
Exists(dbc string, can_id int32) bool
|
||||
}
|
||||
|
||||
type InvalidCANIDCache struct {
|
||||
ringMap *cache.RingMap
|
||||
}
|
||||
|
||||
func (i *InvalidCANIDCache) Exists(dbc string, can_id int32) bool {
|
||||
return !i.ringMap.Set(fmt.Sprintf("%s:%d", dbc[0:4], can_id), false)
|
||||
}
|
||||
32
pkg/dbc/new_dbc_collection.go
Normal file
32
pkg/dbc/new_dbc_collection.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package dbc
|
||||
|
||||
import (
|
||||
fm29_frs90 "fiskerinc.com/modules/dbc/fm29_frs90"
|
||||
fm29_frsd0 "fiskerinc.com/modules/dbc/fm29_frsd0"
|
||||
fm29_frsd21 "fiskerinc.com/modules/dbc/fm29_frsd21"
|
||||
fm29_frsd390 "fiskerinc.com/modules/dbc/fm29_frsd390"
|
||||
"fiskerinc.com/modules/dbc/models"
|
||||
)
|
||||
|
||||
// This is the DBC hash before frsd0 was fixed
|
||||
var fm29_frsd0aHash = "73583d63735b404f5209a71107c3d2174b0ab1ba40bd826b8cb69668598b0395"
|
||||
|
||||
func NewDBCCollection() models.DBCCollectionInterface {
|
||||
return models.NewDBCCollection(nil).
|
||||
AddVersion(fm29_frsd21.Hash, NewFM29_FRSD21_DBC()).
|
||||
AddVersion(fm29_frsd0.Hash, NewFM29_FRSD0_DBC()).
|
||||
AddVersion(fm29_frsd0aHash, NewFM29_FRSD0_DBC()).
|
||||
AddVersion(fm29_frs90.Hash, NewFM29_FRS90_DBC()).
|
||||
AddVersion(fm29_frsd390.Hash, NewFM29_FRSD390_DBC())
|
||||
}
|
||||
|
||||
// NewDBCVersionsOnly is only used for version string key translations.
|
||||
// if you need DBC parsing, use NewDBCCollection.
|
||||
func NewDBCVersionsOnly() models.DBCCollectionInterface {
|
||||
return models.NewDBCCollection(nil).
|
||||
AddVersion(fm29_frsd21.Hash, &models.DBCVersion{}).
|
||||
AddVersion(fm29_frsd0.Hash, &models.DBCVersion{}).
|
||||
AddVersion(fm29_frsd0aHash, &models.DBCVersion{}).
|
||||
AddVersion(fm29_frs90.Hash, &models.DBCVersion{}).
|
||||
AddVersion(fm29_frsd390.Hash, &models.DBCVersion{})
|
||||
}
|
||||
102
pkg/dbc/new_dbc_collection_test.go
Normal file
102
pkg/dbc/new_dbc_collection_test.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package dbc_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"fiskerinc.com/modules/dbc"
|
||||
fm29_frs90 "fiskerinc.com/modules/dbc/fm29_frs90"
|
||||
fm29_frsd0 "fiskerinc.com/modules/dbc/fm29_frsd0"
|
||||
"fiskerinc.com/modules/dbc/models"
|
||||
"fiskerinc.com/modules/testhelper"
|
||||
)
|
||||
|
||||
func TestNewDBCCollection(t *testing.T) {
|
||||
expected := "DBC 0e1f0e4eb01cfdd795f7f539d6baccc85770846050a83f5ac2f3ce75ea6453a0 already exists"
|
||||
|
||||
collection := dbc.NewDBCCollection()
|
||||
if collection == nil {
|
||||
t.Error("collection is nil")
|
||||
return
|
||||
}
|
||||
|
||||
// Should not error getting existing DBC
|
||||
_, err := collection.Get(fm29_frs90.Hash)
|
||||
if err != nil {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "Get fm29_frs90", "no error", err)
|
||||
}
|
||||
|
||||
// Should not error getting existing DBC
|
||||
_, err = collection.Get(fm29_frsd0.Hash)
|
||||
if err != nil {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "Get fm29_frsd0", "no error", err)
|
||||
}
|
||||
|
||||
// Should error getting non-existing DBC
|
||||
_, err = collection.Get("DOES NOT EXIST")
|
||||
if err == nil {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "Get non-existing DBC", "error", err)
|
||||
}
|
||||
|
||||
// Should panic if adding existing DBC hash
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
if err != expected {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "AddVersion existing hash", expected, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
collection.AddVersion(fm29_frs90.Hash, dbc.NewFM29_FRS90_DBC())
|
||||
t.Errorf(testhelper.TestErrorTemplate, "AddVersion existing hash", "should have paniced", nil)
|
||||
}
|
||||
|
||||
func TestGetShortKey(t *testing.T) {
|
||||
expected := "0e1f"
|
||||
key := models.GetShortKey(fm29_frs90.Hash)
|
||||
if key != expected {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "GetShortKey", expected, key)
|
||||
}
|
||||
|
||||
collection := dbc.NewDBCCollection()
|
||||
_, err := collection.Get(expected)
|
||||
if err != nil {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "Get fm29_frs90", "no error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDBCVersionAddMsgExisting(t *testing.T) {
|
||||
expected := "CAN message 816 already exists"
|
||||
|
||||
// Should panic if adding existing message id
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
if err != expected {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "AddMsg existing id", expected, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
dbc := dbc.NewFM29_FRS90_DBC()
|
||||
dbc.AddMsg(models.NewCANMessage(816, 14))
|
||||
t.Errorf(testhelper.TestErrorTemplate, "AddMsg existing id", "should have paniced", nil)
|
||||
}
|
||||
|
||||
func TestDBCVersionAddSignalExisting(t *testing.T) {
|
||||
expected := "signal position 2 already exists"
|
||||
|
||||
// Should panic if adding existing message id
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
if err != expected {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "AddVersion existing hash", expected, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
msg := models.NewCANMessage(816, 14).
|
||||
Signal(1, "test1", nil).
|
||||
Signal(2, "test2", nil)
|
||||
|
||||
msg.Signal(2, "test3", nil)
|
||||
t.Errorf(testhelper.TestErrorTemplate, "AddMsg existing id", "should have paniced", nil)
|
||||
}
|
||||
12
pkg/dbc/state/car_state.go
Normal file
12
pkg/dbc/state/car_state.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package state
|
||||
|
||||
type CANMessage struct {
|
||||
CANID int
|
||||
Length int
|
||||
Signals []CANSignal
|
||||
}
|
||||
|
||||
type CANSignal struct {
|
||||
Name string
|
||||
Position int
|
||||
}
|
||||
28
pkg/dbc/state/digitaltwin_props.go
Normal file
28
pkg/dbc/state/digitaltwin_props.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package state
|
||||
|
||||
const (
|
||||
AMBIENT_TEMP string = "ambient_temperature"
|
||||
CELL_TEMP = "cell_temperature"
|
||||
BATTERY = "battery"
|
||||
STATE_OF_CHARGE = "state_of_charge"
|
||||
MAX_RANGE = "max_range"
|
||||
CABIN_CLIMATE = "cabin_climate"
|
||||
DBC_VERSION = "dbc_version"
|
||||
DEFROST_REAR = "rear_defrost"
|
||||
DOORS = "doors"
|
||||
DOOR_LOCKS = "door_locks"
|
||||
GPS_ALTITUDE = "gps_altitude"
|
||||
LOCATION = "location"
|
||||
SEAT_HEAT_DRIVER = "driver_seat_heat"
|
||||
SEAT_HEAT_PASSENGER = "passenger_seat_heat"
|
||||
STEERING_WHEEL_HEAT = "steering_wheel_heat"
|
||||
SUNROOF = "sunroof"
|
||||
TREX_VERSION = "trex_version"
|
||||
TREX_IP = "ip"
|
||||
VCU0x260 = "vcu0x260"
|
||||
ICC0x531 = "icc0x531"
|
||||
CHARGING_METRICS = "charging_metrics"
|
||||
WINDOWS = "windows"
|
||||
WINDOWS_MISC = "misc_windows"
|
||||
UPDATED_AT = "updated"
|
||||
)
|
||||
17
pkg/dbc/state/errors.go
Normal file
17
pkg/dbc/state/errors.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func IncorrectSignalsLength(expected int, received int) error {
|
||||
return errors.Errorf("incorrect number of signals in message expected %d received %d", expected, received)
|
||||
}
|
||||
|
||||
func IncorrectSignalError(expected string, received string) error {
|
||||
return errors.Errorf("wrong signal in message expected %s received %s", expected, received)
|
||||
}
|
||||
|
||||
func IncorrectSignalValue(expected interface{}, received interface{}) error {
|
||||
return errors.Errorf("wrong value in message expected one of %v received %v", expected, received)
|
||||
}
|
||||
49
pkg/dbc/state/helpers.go
Normal file
49
pkg/dbc/state/helpers.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
const redisObjectExpire = 604800
|
||||
const errInvalidValue = "invalid value %f"
|
||||
|
||||
func FloatToBool(input float64) interface{} {
|
||||
return int(input) != 0
|
||||
}
|
||||
|
||||
func RoundMilli(input float64) interface{} {
|
||||
return math.Round(input*1000) / 1000
|
||||
}
|
||||
|
||||
func RoundGPS(input float64) interface{} {
|
||||
return math.Round(input*100000) / 100000
|
||||
}
|
||||
|
||||
func IntCeil(input float64) interface{} {
|
||||
return int(math.Ceil(input))
|
||||
}
|
||||
|
||||
func IntFloor(input float64) interface{} {
|
||||
return int(math.Floor(input))
|
||||
}
|
||||
|
||||
func Int(input float64) interface{} {
|
||||
return int(input)
|
||||
}
|
||||
|
||||
// WHy does this return an array of bytes instead of a string, or a time.Time
|
||||
func SerializeTimestampUSec(timestampUSec int) ([]byte, error) {
|
||||
return time.UnixMicro(int64(timestampUSec)).UTC().MarshalJSON()
|
||||
}
|
||||
|
||||
func GetMappedStrValues(valueMap map[float64]string) func(float64) interface{} {
|
||||
return func(input float64) interface{} {
|
||||
if value, ok := valueMap[input]; ok {
|
||||
return value
|
||||
}
|
||||
|
||||
return fmt.Sprintf(errInvalidValue, input)
|
||||
}
|
||||
}
|
||||
100
pkg/dbc/state/signal_names.go
Normal file
100
pkg/dbc/state/signal_names.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package state
|
||||
|
||||
const (
|
||||
BCM_AP_FL_LeFrntWinPosnInfo = "BCM_AP_FL_LeFrntWinPosnInfo"
|
||||
BCM_AP_FL_RiFrntWinPosnInfo = "BCM_AP_FL_RiFrntWinPosnInfo"
|
||||
BCM_AP_FL_LeReWinPosnInfo = "BCM_AP_FL_LeReWinPosnInfo"
|
||||
BCM_AP_FL_RiReWinPosnInfo = "BCM_AP_FL_RiReWinPosnInfo"
|
||||
BCM_AP_TL_LeReWinPosnInfo = "BCM_AP_TL_LeReWinPosnInfo"
|
||||
BCM_AP_TL_RiReWinPosnInfo = "BCM_AP_TL_RiReWinPosnInfo"
|
||||
BCM_AP_RW_WinPosnInfo = "BCM_AP_RW_WinPosnInfo"
|
||||
BMS_Bat_SoC_usable = "BMS_Bat_SoC_usable"
|
||||
BMS_Bat_SOH = "BMS_Bat_SOH"
|
||||
BMS_BattAvrgT = "BMS_BattAvrgT"
|
||||
BCM_FrntDrDoorLockSts = "BCM_FrntDrDoorLockSts"
|
||||
BCM_CenLockSwtSts = "BCM_CenLockSwtSts"
|
||||
BCM_FrntHoodLidSts = "BCM_FrntHoodLidSts"
|
||||
BCM_DrFrntDoorSts = "BCM_DrFrntDoorSts"
|
||||
BCM_PasFrntDoorSts = "BCM_PasFrntDoorSts"
|
||||
BCM_RiReDoorSts = "BCM_RiReDoorSts"
|
||||
BCM_LeReDoorSts = "BCM_LeReDoorSts"
|
||||
BCM_SunroofPosnInfo = "BCM_SunroofPosnInfo"
|
||||
PLGM_TrSts = "PLGM_TrSts"
|
||||
ECC_RemTSetSts = "ECC_RemTSetSts"
|
||||
BCM_ReDefrstHeatgCmd = "BCM_ReDefrstHeatgCmd"
|
||||
DSMC_DrvrSeatHeatgSts = "DSMC_DrvrSeatHeatgSts"
|
||||
PSM_PassSeatHeatgSts = "PSM_PassSeatHeatgSts"
|
||||
BCM_HeatedSteerWhlSt = "BCM_HeatedSteerWhlSt"
|
||||
ECC_OutdT = "ECC_OutdT"
|
||||
ECC_InsdT = "ECC_InsdT"
|
||||
BMS_PwrBattRmngCpSOC = "BMS_PwrBattRmngCpSOC"
|
||||
ESP_VehSpd = "ESP_VehSpd"
|
||||
VCU_DrvgMilg = "VCU_DrvgMilg"
|
||||
VCU_VehChrgDchgMod = "VCU_VehChrgDchgMod"
|
||||
VCU_DCChrgRmngTi = "VCU_DCChrgRmngTi"
|
||||
IBS_BatteryVoltage = "IBS_BatteryVoltage"
|
||||
VCU_GearSig = "VCU_GearSig"
|
||||
ICC_TotMilg_ODO = "ICC_TotMilg_ODO"
|
||||
TBOX_GPSHei = "TBOX_GPSHei"
|
||||
TBOX_GPSLongi = "TBOX_GPSLongi"
|
||||
TBOX_GPSLati = "TBOX_GPSLati"
|
||||
BMS_RmChrgTi_FullChrg = "BMS_RmChrgTi_FullChrg"
|
||||
BMS_RmChrgTi_TrgtSoC = "BMS_RmChrgTi_TrgtSoC"
|
||||
VCU_VehSt = "VCU_VehSt"
|
||||
VCU_VcuState = "VCU_VcuState"
|
||||
MCU_F_ActSafeSt = "MCU_F_ActSafeSt"
|
||||
MCU_R_ActSafeSt = "MCU_R_ActSafeSt"
|
||||
MCU_R_Decoup_State = "MCU_R_Decoup_State"
|
||||
MCU_F_CrtMod = "MCU_F_CrtMod"
|
||||
MCU_R_CrtMod = "MCU_R_CrtMod"
|
||||
ACU_Drvr_Occpt_St = "ACU_Drvr_Occpt_St"
|
||||
BCM_PwrMod = "BCM_PwrMod"
|
||||
PWC_ChrgSts = "PWC_ChrgSts"
|
||||
VCU_RdyLamp = "VCU_RdyLamp"
|
||||
|
||||
// New signals for Michael Fischer and Igor Lastrić
|
||||
IBS_SOCUpperTolerance = "IBS_SOCUpperTolerance"
|
||||
IBS_SOCLowerTolerance = "IBS_SOCLowerTolerance"
|
||||
IBS_StateOfCharge = "IBS_StateOfCharge"
|
||||
IBS_StateOfHealth = "IBS_StateOfHealth"
|
||||
IBS_NominalCapacity = "IBS_NominalCapacity"
|
||||
IBS_AvailableCapacity = "IBS_AvailableCapacity"
|
||||
BCM_TotMilg_ODO = "BCM_TotMilg_ODO"
|
||||
BMS_SwVersS = "BMS_SwVersS"
|
||||
BMS_SwVersM = "BMS_SwVersM"
|
||||
BMS_SwVers = "BMS_SwVers"
|
||||
BMS_AccueDchaTotAh = "BMS_AccueDchaTotAh"
|
||||
BMS_AccueChrgTotAh = "BMS_AccueChrgTotAh"
|
||||
//Attempting to add the bearing direction of the car
|
||||
TBOX_Heading = "TBOX_Heading"
|
||||
PKC_IMMO_AuthSts = "PKC_IMMO_AuthSts"
|
||||
VCU_IMMO_Sts = "VCU_IMMO_Sts"
|
||||
TBOX_RemCtrlCmdFb = "TBOX_RemCtrlCmdFb"
|
||||
PKC_AuthFailPromt = "PKC_AuthFailPromt"
|
||||
PKC_StrtFailTyp = "PKC_StrtFailTyp"
|
||||
PKC_KeyStsMod = "PKC_KeyStsMod"
|
||||
TBOX_RemCtrlLockCmd = "TBOX_RemCtrlLockCmd"
|
||||
)
|
||||
|
||||
// safe state constants
|
||||
const (
|
||||
VCU_VehSt_Safestate = "11"
|
||||
|
||||
VCU_VcuState_Safestate = "18"
|
||||
|
||||
MCU_F_ActSafeSt_AS0 = "1"
|
||||
MCU_F_ActSafeSt_ASC = "2"
|
||||
MCU_F_ActSafeSt_ASC_Emergency = "3"
|
||||
|
||||
MCU_R_ActSafeSt_AS0 = "1"
|
||||
MCU_R_ActSafeSt_ASC = "2"
|
||||
MCU_R_ActSafeSt_ASC_Emergency = "3"
|
||||
|
||||
MCU_R_Decoup_State_Connected = "4"
|
||||
|
||||
MCU_F_CrtMod_Internal_inverter_error = "7"
|
||||
MCU_F_CrtMod_Invalid = "15"
|
||||
|
||||
MCU_R_CrtMod_Internal_inverter_error = "7"
|
||||
MCU_R_CrtMod_Invalid = "15"
|
||||
)
|
||||
20
pkg/dbc/state/signal_values.go
Normal file
20
pkg/dbc/state/signal_values.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package state
|
||||
|
||||
// Converting these values to strings is bad for memory performance,
|
||||
// but it is what it is for now
|
||||
const (
|
||||
PKC_KeyStsMod_disabled = "disabled"
|
||||
PKC_KeyStsMod_enabled = "enabled"
|
||||
)
|
||||
|
||||
// const (
|
||||
// PKC_StrtFailTyp_"No_error" = "No_error"
|
||||
// PKC_StrtFailTyp_"Reserved" = "Reserved"
|
||||
// PKC_StrtFailTyp_"VCU_Authentication_Failure" = "VCU_Authentication_Failure"
|
||||
// PKC_StrtFailTyp_"Time_Out_(Crank_Off_Time)" = "Time_Out_(Crank_Off_Time)"
|
||||
// PKC_StrtFailTyp_"Auth_Pass" = "Auth_Pass"
|
||||
// PKC_StrtFailTyp_"Remote Immo Enabled" = "Remote Immo Enabled"
|
||||
// PKC_StrtFailTyp_"No Key detected inside the vehicle" = "No Key detected inside the vehicle"
|
||||
// PKC_StrtFailTyp_"Alcointerlock Enabled" = "Alcointerlock Enabled"
|
||||
// PKC_StrtFailTyp_"Initial value" = "Initial value"
|
||||
// )
|
||||
8
pkg/dbc/state/state_func.go
Normal file
8
pkg/dbc/state/state_func.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/common"
|
||||
"fiskerinc.com/modules/redis"
|
||||
)
|
||||
|
||||
type StateFunc func(*redis.RedisBatchCommands, string, int, []common.CANSignal) error
|
||||
Reference in New Issue
Block a user