Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
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
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user