Add depot, attendant, jetfire, optimus, ota services with kustomize overlays
This commit is contained in:
184
services/attendant/controllers/dtc_request.go
Normal file
184
services/attendant/controllers/dtc_request.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/fiskerinc/cloud-services/services/attendant/services"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/grpc/kafka_grpc"
|
||||
"github.com/fiskerinc/cloud-services/pkg/logger"
|
||||
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/descriptor"
|
||||
)
|
||||
|
||||
type DTCEntry struct {
|
||||
CreatedAt time.Time `bson:"created_at"`
|
||||
VIN string `bson:"vin"`
|
||||
ECU string `json:"ecu" bson:"ecu"`
|
||||
DTC uint64 `json:"dtc" bson:"dtc"`
|
||||
Status uint8 `json:"status" bson:"status"`
|
||||
Timestamp time.Time `json:"timestamp" bson:"timestamp"`
|
||||
Speed uint16 `json:"speed" bson:"speed"`
|
||||
Mileage uint32 `json:"mileage" bson:"mileage"`
|
||||
Voltage uint16 `json:"voltage" bson:"voltage"`
|
||||
|
||||
SnapshotBase64 string `json:"snapshot,omitempty" bson:"snapshot,omitempty"`
|
||||
}
|
||||
|
||||
func GRPCToDTCEntry(payload *kafka_grpc.GRPC_AttendantPayload) []byte {
|
||||
|
||||
if payload.Data == nil {
|
||||
return nil
|
||||
}
|
||||
data := payload.Data.(*kafka_grpc.GRPC_AttendantPayload_DtcEntry)
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
dtc := &DTCEntry{
|
||||
VIN: data.DtcEntry.Vin,
|
||||
ECU: data.DtcEntry.Ecu,
|
||||
CreatedAt: milliToDate(data.DtcEntry.CreatedAt),
|
||||
DTC: data.DtcEntry.Dtc,
|
||||
Status: uint8(data.DtcEntry.Status),
|
||||
Timestamp: milliToDate(data.DtcEntry.Timestamp),
|
||||
Speed: uint16(data.DtcEntry.Speed),
|
||||
Mileage: data.DtcEntry.Mileage,
|
||||
Voltage: uint16(data.DtcEntry.Volt),
|
||||
SnapshotBase64: data.DtcEntry.SnapshotBase64,
|
||||
}
|
||||
bytes, _ := json.Marshal(dtc)
|
||||
return bytes
|
||||
}
|
||||
func milliToDate(timestamp int64) time.Time {
|
||||
seconds := timestamp / 1000
|
||||
nanoseconds := (timestamp % 1000) * int64(time.Millisecond)
|
||||
return time.Unix(seconds, nanoseconds)
|
||||
}
|
||||
|
||||
const SNAPSHOT_LEN = 21
|
||||
|
||||
func (entry *DTCEntry) ParseSnapshot() error {
|
||||
|
||||
data, errc := base64.StdEncoding.DecodeString(entry.SnapshotBase64)
|
||||
if errc != nil {
|
||||
return errc
|
||||
}
|
||||
payloadLen := len(data) - 2
|
||||
|
||||
if payloadLen < SNAPSHOT_LEN {
|
||||
logger.Debug().Msgf("DTC snapshot payload is too small. Required length=%d, actual=%d, ECU=%s\n", SNAPSHOT_LEN, len(data), entry.ECU)
|
||||
return errors.New("Snapshot too small")
|
||||
}
|
||||
|
||||
// Our "Basic Diagnostic" spec defines 4 mandatory DIDs that must be
|
||||
// stored inside DTCStapshotRecord:
|
||||
// 1. EF F6 - Timestamp (6 bytes).
|
||||
// 2. EF F7 - Vehicle Speed (2 bytes).
|
||||
// 3. EF F8 - Milage (idk, our spec doesn't specify exact number.
|
||||
// Empirically it's 4 bytes (same as "ICC_0x531::TotMilg_ODO").
|
||||
// 4. EF F9 - Battery Voltage (2 bytes).
|
||||
///entry.Speed = int16(speed.ToPhysical(float64(uint16(decodedBytes[0])<<8 | uint16(decodedBytes[1]))))
|
||||
//entry.Voltage = int16(voltage.ToPhysical(float64(uint16(decodedBytes[0])<<8 | uint16(decodedBytes[1]))))
|
||||
|
||||
for idx := 2; idx < len(data)-1; {
|
||||
if data[idx] != 0xEF {
|
||||
idx++
|
||||
continue
|
||||
}
|
||||
|
||||
if data[idx+1] == 0xF6 && idx+7 < len(data) {
|
||||
idx += 2
|
||||
entry.Timestamp, idx = consumeTimestamp(data, idx)
|
||||
} else if data[idx+1] == 0xF7 && idx+3 < len(data) {
|
||||
idx += 2
|
||||
entry.Speed, idx = consumeSpeed(data, idx)
|
||||
} else if data[idx+1] == 0xF8 && idx+5 < len(data) {
|
||||
idx += 2
|
||||
entry.Mileage, idx = consumeMileage(data, idx)
|
||||
} else if data[idx+1] == 0xF9 && idx+3 < len(data) {
|
||||
idx += 2
|
||||
entry.Voltage, idx = consumeVoltage(data, idx)
|
||||
} else {
|
||||
idx++
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var onceTimestamp sync.Once
|
||||
var (
|
||||
day *descriptor.Signal
|
||||
hr *descriptor.Signal
|
||||
mins *descriptor.Signal
|
||||
yr *descriptor.Signal
|
||||
month *descriptor.Signal
|
||||
sec *descriptor.Signal
|
||||
)
|
||||
|
||||
func consumeTimestamp(data []byte, idx int) (res time.Time, idx_ret int) {
|
||||
|
||||
onceTimestamp.Do(func() {
|
||||
day, _ = services.GetDBC().Signal(0x62F, "TBOX_CrtTi_Day")
|
||||
hr, _ = services.GetDBC().Signal(0x62F, "TBOX_CrtTi_Hr")
|
||||
mins, _ = services.GetDBC().Signal(0x62F, "TBOX_CrtTi_Mins")
|
||||
yr, _ = services.GetDBC().Signal(0x62F, "TBOX_CrtTi_Yr")
|
||||
month, _ = services.GetDBC().Signal(0x62F, "TBOX_CrtTi_Mth")
|
||||
sec, _ = services.GetDBC().Signal(0x62F, "TBOX_CrtTi_Sec")
|
||||
|
||||
})
|
||||
|
||||
res = time.Date(int(yr.ToPhysical(float64(data[idx]))),
|
||||
time.Month(month.ToPhysical(float64(data[idx+1]))),
|
||||
int(day.ToPhysical(float64(data[idx+2]))),
|
||||
int(hr.ToPhysical(float64(data[idx+3]))),
|
||||
int(mins.ToPhysical(float64(data[idx+4]))),
|
||||
int(sec.ToPhysical(float64(data[idx+5]))), 0, time.UTC)
|
||||
idx_ret = idx + 6
|
||||
return res, idx_ret
|
||||
}
|
||||
|
||||
var onceSpeed sync.Once
|
||||
var speed *descriptor.Signal
|
||||
|
||||
func consumeSpeed(data []byte, idx int) (res uint16, idx_ret int) {
|
||||
|
||||
onceSpeed.Do(func() {
|
||||
speed, _ = services.GetDBC().Signal(0x318, "ESP_VehSpd")
|
||||
})
|
||||
res = uint16(speed.ToPhysical(float64(uint16(data[idx])<<8 | uint16(data[idx+1]))))
|
||||
idx_ret = idx + 2
|
||||
return res, idx_ret
|
||||
}
|
||||
|
||||
var onceMileage sync.Once
|
||||
var mileage *descriptor.Signal
|
||||
|
||||
func consumeMileage(data []byte, idx int) (res uint32, idx_ret int) {
|
||||
onceMileage.Do(func() {
|
||||
mileage, _ = services.GetDBC().Signal(0x531, "ICC_TotMilg_ODO")
|
||||
})
|
||||
res = uint32(mileage.ToPhysical(
|
||||
float64(
|
||||
uint64(data[idx])<<24 |
|
||||
uint64(data[idx+1])<<16 |
|
||||
uint64(data[idx+2])<<8 | uint64(data[idx+3]))))
|
||||
idx_ret = idx + 4
|
||||
return res, idx_ret
|
||||
}
|
||||
|
||||
var onceVoltage sync.Once
|
||||
var voltage *descriptor.Signal
|
||||
|
||||
func consumeVoltage(data []byte, idx int) (res uint16, idx_ret int) {
|
||||
onceVoltage.Do(func() {
|
||||
voltage, _ = services.GetDBC().Signal(0x507, "VCU_BattVolt")
|
||||
})
|
||||
|
||||
res = uint16(voltage.ToPhysical(float64(uint16(data[idx])<<8 | uint16(data[idx+1]))))
|
||||
idx_ret = idx + 2
|
||||
return res, idx_ret
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user