Add depot, attendant, jetfire, optimus, ota services with kustomize overlays

This commit is contained in:
Chris Rai
2026-01-31 15:35:07 -05:00
parent a0ec642ca1
commit 9a5cb2f547
404 changed files with 38817 additions and 16 deletions

View File

@@ -0,0 +1,56 @@
package handlers
import (
"github.com/fiskerinc/cloud-services/services/optimus/services"
"github.com/fiskerinc/cloud-services/pkg/common"
"github.com/fiskerinc/cloud-services/pkg/grpc/kafka_grpc"
"github.com/fiskerinc/cloud-services/pkg/logger"
"github.com/fiskerinc/cloud-services/pkg/validator"
"github.com/pkg/errors"
)
func ProduceSignalsFromMessageBatch(vin string, payload *kafka_grpc.GRPC_BatchPayload) ([]common.CANSignal, error) {
var batch []common.CANSignal
if payload == nil {
return nil, errors.New("payload is nil")
}
if payload.Data == nil {
return nil, errors.New("payload.Data is nil")
}
// TODO Where to report epoch_usec, dropped, and filtered stats
dbcVersion := payload.Version
dbc, err := services.GetDBCCollection().Get(dbcVersion)
if err != nil {
return nil, err
}
// r := services.RedisClientPool().GetFromPool()
// defer r.Close()
clickClient, err := services.GetClickhouseClient()
if err != nil {
return nil, err
}
filters := services.GetVehicleMessageFilters().GetFiltersForVehicle(clickClient, vin)
for _, msg := range payload.Data.Frames {
if err := validator.ValidateStruct(msg); err != nil {
logger.Warn().Str("id", vin).Err(err).Msgf("%+v", msg)
continue
}
if !filters.AllowMessage(int(msg.ID), int(msg.GetEpoch())) {
continue
}
signals, err := dbc.GenerateCANSignals(vin, msg)
if err == nil && len(signals) > 0 {
batch = append(batch, signals...)
} else if err != nil {
logger.At(logger.Warn(), vin, "dbc").Err(err).Send()
}
}
return batch, nil
}

View File

@@ -0,0 +1,211 @@
package handlers_test
import (
"encoding/base64"
"fmt"
"testing"
"github.com/fiskerinc/cloud-services/services/optimus/handlers"
"github.com/fiskerinc/cloud-services/pkg/common"
fm29 "github.com/fiskerinc/cloud-services/pkg/dbc/fm29_frsd0"
fm390 "github.com/fiskerinc/cloud-services/pkg/dbc/fm29_frsd390"
dbc "github.com/fiskerinc/cloud-services/pkg/dbc/models"
"github.com/fiskerinc/cloud-services/pkg/grpc/kafka_grpc"
rutils "github.com/fiskerinc/cloud-services/pkg/redis/redisutils"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
var produceSignalsCorrectPayload = kafka_grpc.GRPC_BatchPayload{
Handler: "canbus",
Data: &kafka_grpc.GRPC_CANData{
EpochUsec: 1653255445,
Dropped: 10,
Filtered: 20,
Frames: []*kafka_grpc.GRPC_CANFrame{
{ID: 5, Value: []byte("AAAGAB6cCBY=")},
{ID: 624, Value: []byte("AAAGAB6cCBY=")},
{ID: 1290, Value: []byte("CACAAIAAAAA=")},
{ID: 1287, Value: []byte("ACBAAAoANLI=")},
{ID: 1311, Value: []byte("afaA9wBkkgA=")},
{ID: 1317, Value: []byte("MAAwIAAAAAA=")},
{ID: 1318, Value: []byte("D9M1YAF78aA=")},
{ID: 5, Value: []byte("AAAGAB6cCBY=")},
},
},
Version: fm29.Hash,
}
var produceInvalidSignalsPayload = kafka_grpc.GRPC_BatchPayload{
Handler: "canbus",
Data: &kafka_grpc.GRPC_CANData{
EpochUsec: 1653255445,
Dropped: 10,
Filtered: 20,
Frames: []*kafka_grpc.GRPC_CANFrame{
{ID: 1169, Value: []byte("MDAwMDgwMDA=")},
{ID: 576, Value: []byte("3wBMc0yCAAA=")},
{ID: 624, Value: []byte("MDAwMDA2MDA=")},
{ID: 640, Value: []byte("MDAwMDI4RTY=")},
{ID: 1168, Value: []byte("MDAwMDRFRTg=")},
{ID: 1169, Value: []byte("MDAwMDgwMDA=")},
{ID: 576, Value: []byte("3wBMc0yCAAA=")},
{ID: 624, Value: []byte("MDAwMDA2MDA=")},
{ID: 640, Value: []byte("MDAwMDI4RTY=")},
{ID: 1168, Value: []byte("MDAwMDRFRTg=")},
},
},
Version: fm390.Hash,
}
var produceOutOfRangeSignalsPayload = kafka_grpc.GRPC_BatchPayload{
Handler: "canbus",
Data: &kafka_grpc.GRPC_CANData{
EpochUsec: 1653255445,
Dropped: 10,
Filtered: 20,
Frames: []*kafka_grpc.GRPC_CANFrame{
{ID: 1073741824, Value: []byte("MDAwMDgwMDA=")},
{ID: 1073756897, Value: []byte("3wBMc0yCAAA=")},
{ID: 5242880, Value: []byte("MDAwMDA2MDA=")},
{ID: 308346880, Value: []byte("MDAwMDI4RTY=")},
{ID: 1188096, Value: []byte("MDAwMDRFRTg=")},
{ID: -318242816, Value: []byte("MDAwMDgwMDA=")},
{ID: 1073741824, Value: []byte("MDAwMDgwMDA=")},
{ID: 1073756897, Value: []byte("3wBMc0yCAAA=")},
{ID: 5242880, Value: []byte("MDAwMDA2MDA=")},
{ID: 308346880, Value: []byte("MDAwMDI4RTY=")},
{ID: 1188096, Value: []byte("MDAwMDRFRTg=")},
{ID: -318242816, Value: []byte("MDAwMDgwMDA=")},
},
},
Version: fm390.Hash,
}
var produceSignalsAllValidPayload = kafka_grpc.GRPC_BatchPayload{
Handler: "canbus",
Data: &kafka_grpc.GRPC_CANData{
EpochUsec: 1653255445,
Dropped: 10,
Filtered: 20,
Frames: []*kafka_grpc.GRPC_CANFrame{
{ID: 1290, Value: []byte("CACAAIAAAAA=")},
{ID: 1287, Value: []byte("ACBAAAoANLI=")},
{ID: 1317, Value: []byte("MAAwIAAAAAA=")},
{ID: 1318, Value: []byte("D9M1YAF78aA=")},
},
},
Version: fm29.Hash,
}
var correctExpBatch = []common.CANSignal{
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_PwrBattHVChkTiOut", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_HVSysPrecTiOut", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_HVSysChkTiOut", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_PwrBattPosBreakStsTiOut", Value: 1, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_HVDchaStsTiOut", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_PartSaveStsTiOut", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_CellVoltLoHVPwrOffFlg", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_EEPROMCellVoltLoHVPwrOffFlg", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_VehBootLoaderFlg", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_FobdHVPwrOnFlg", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_HVPwrOffReq", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_VehRemSCModPwrOnReq", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_VehRemOperModPwrOnReq", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_DDmdTq", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_TqLim", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_MotDampgFobdSts", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1290, Name: "VCU_EEPROMSts", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_OTAVehInhb_QM_Fb", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_OTAVehCdnChk_QM_sts", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_DrvAvl", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_CllsnSigSts", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_VehSts_GB", Value: 2, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_MCUOverTFlt_GB", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_DrvrMotOverTFlt_GB", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_SOCTooLoAlrm", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_SOCJumpAlrm", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_PwrBattPackMismatAlrm", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_SOCTooHiAlrm", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_DCDCEnaCmd", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_PwrBattECCEnaCmd", Value: 1, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_MstRlyCtrlCmd", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_DCDCOutpVoltCmd", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_CCCnctnVolt", Value: 1, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_GearSig_GB", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_DrvrMotNr_GB", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1287, Name: "VCU_BattVolt", Value: 13.49, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1317, Name: "TBOX_525_CheckSum", Value: 48, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1317, Name: "TBOX_525_AliveCounter", Value: 0, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1317, Name: "TBOX_GPSHei", Value: -115, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1318, Name: "TBOX_GPSLongi", Value: 85.5, Description: ""},
{VIN: "TESTVIN123", Timestamp: 0, ID: 1318, Name: "TBOX_GPSLati", Value: -65.1, Description: ""},
}
func TestProduceSignalsFromMessageBatch(t *testing.T) {
invalidVersionPayload := produceSignalsCorrectPayload
invalidVersionPayload.Version = "12"
tests := map[string]struct {
payload *kafka_grpc.GRPC_BatchPayload
cacheSetMock rutils.CacheSetMock
batchError error
expBatch []common.CANSignal
expError error
}{
"correct": {
payload: &produceSignalsCorrectPayload,
expBatch: correctExpBatch,
},
"all valid": {
payload: &produceSignalsAllValidPayload,
expBatch: correctExpBatch,
},
"invalid_payload": {
payload: nil,
expError: errors.WithStack(errors.New("payload is nil")),
},
"invalid_version": {
payload: &invalidVersionPayload,
expError: errors.New("DBC 12 does not exists"),
},
"invalid_signals": {
payload: &produceInvalidSignalsPayload,
},
"out_of_range_signals": {
payload: &produceOutOfRangeSignalsPayload,
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
dbc.SetInvalidCANIDCache(dbc.NewInvalidCANIDCache())
batch, err := handlers.ProduceSignalsFromMessageBatch("TESTVIN123", tt.payload)
if err != nil && tt.expError != nil {
assert.Equal(t, tt.expError.Error(), err.Error())
return
}
assert.Equal(t, tt.expError, err)
assert.Equal(t, tt.expBatch, batch)
})
}
}
func TestGenB64(t *testing.T) {
t.Skip()
// example of generating binary CAN signal data
msg := fm29.NewESP_0x114()
msg.SetESP_ActvSig_DTC(true)
data := msg.Frame().Data
b64 := base64.StdEncoding.EncodeToString([]byte(data[:]))
fmt.Println(msg.Descriptor().ID)
fmt.Println(b64)
t.Error("done")
}

View File

@@ -0,0 +1,14 @@
package handlers
import (
"net/http"
"github.com/fiskerinc/cloud-services/services/optimus/services"
"github.com/fiskerinc/cloud-services/pkg/logger"
)
func ResetFilters(w http.ResponseWriter, r *http.Request) {
logger.Info().Msg("resetting filters")
services.ResetVehicleMessageFilters()
}

View File

@@ -0,0 +1,23 @@
package handlers_test
import (
"net/http"
"testing"
"github.com/fiskerinc/cloud-services/services/optimus/handlers"
th "github.com/fiskerinc/cloud-services/pkg/testhelper"
)
func TestResetFilters(t *testing.T) {
tests := []th.BasicHttpTest{
{
Name: "Reset",
Request: th.MakeTestRequest(http.MethodGet, "http://example.com/reset", nil),
ExpectedStatus: http.StatusOK,
ExpectedResponse: "",
},
}
th.RunBasicHttpTests(t, tests, handlers.ResetFilters)
}