144 lines
3.7 KiB
Go
144 lines
3.7 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/dbc/state"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/common"
|
|
"github.com/fiskerinc/cloud-services/pkg/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
|
|
}
|
|
*/
|