Small CLI monitoring tool to decode proprietary [...] protocol and display info in human readable representation
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ycli-mon/yabl/protocol.go

345 lines
9.4 KiB

package yabl
import (
"cli-mon/can"
"encoding/binary"
"time"
)
type Packet interface {
GetUnitId() uint
}
type SignedAirTemp8BitType int
type ConnectedOut8bitType uint
type ForceModeType uint
type SignedVoltage12bitType int
type DebugSwitchModeType uint
type OtherError4BitType uint
type ContactorModeType uint
type Power14BitType uint
type AuthStateType uint
type AuthModeType uint
type BoardReadyType uint
type BooleanType uint
type ErrorType uint
type ContactorInternalOtherErrorType uint
type ContactorGroupChangedType uint
type V2GModeType uint
type Voltage11BitType uint
type Current10BitType uint
type CpLineLevelType uint
type IsolationStateType uint
type Voltage9BitType float32
type PName string
type FName string
type parameters struct {
fields []field
interval uint
name PName
}
type field struct {
length uint8
setter func(uint64 uint64)
value uint64
last time.Time
name FName
}
type key struct {
canId, unitId uint
}
var protocolMap map[key]parameters
var cpuPresentEnergyArray [CONNECTOR_MAX]*CpuPresentEnergy
var cpuPeripheryInstance *CpuPeriphery
var cpuEnergySettingsArray [CONNECTOR_MAX]*CpuEnergySettings
var cpuErrorsInstance *CpuErrors
var cpuDebugInstance *CpuDebug
var puPresentEnergyArray [CONNECTOR_MAX]*PuPresentEnergy
var puPeripheryArray [CONNECTOR_MAX]*PuPeriphery
var puErrorsArray [CONNECTOR_MAX]*PuErrors
var puDebugArray [CONNECTOR_MAX]*PuDebug
var seccTargetEnergyArray [CONNECTOR_MAX]*SeccTargetEnergy
var seccErrorsArray [CONNECTOR_MAX]*SeccErrors
var logicAuthArray [CONNECTOR_MAX]*LogicAuth
var logicEnergyMode [CONNECTOR_MAX]*LogicEnergyMode
var logicErrorsInstance *LogicErrors
var logicWorkingMode *LogicWorkingMode
var contactorInternalStateArray [CONNECTOR_MAX]*ContactorInternalState
var contactorInternalErrorsInstance *ContactorInternalErrors
var contactorsInternalForce *ContactorsInternalForce
var contactorInternalDebugArray [CONNECTOR_MAX]*ContactorInternalDebug
var peripheryStateArray [CONNECTOR_MAX]*PeripheryState
var peripheryInfoArray [CONNECTOR_MAX]*PeripheryInfo
var peripheryDebugArray [CONNECTOR_MAX]*PeripheryDebug
var converterPresentEnergyArray [CONVERTERS_MAX]*ConverterPresentEnergy
var converterErrorsArray [CONVERTERS_MAX]*ConverterErrors
var converterDebugArray [CONVERTERS_MAX]*ConverterDebug
func StartProtocolParsing(frames <-chan *can.CanFrame) <-chan Packet {
result := make(chan Packet)
go func() {
defer close(result)
var contactorsFirstState [CONTACTOR_MAX]bool
var contactorsFirstErr [CONTACTOR_MAX]bool
var puFirst [CONNECTOR_MAX]bool
var puPeripheryFirst [CONNECTOR_MAX]bool
for frame := range frames {
if frames == nil {
continue
}
var unitId = uint((frame.CanId & UNIT_ID_MASK) >> UNIT_ID_OFFSET)
switch {
case frame.CanId&ACTION_ID_MASK == can.CAN_ID_071:
changed := false
var model = ContactorInternalState{UnitId: unitId}
if val, ok := get(0, 3, frame.Payload); ok && model.ContactorReady != BoardReadyType(val) {
model.ContactorReady = BoardReadyType(val)
changed = true
}
if val, ok := get(3, 2, frame.Payload); ok && model.ContactorOn != BooleanType(val) {
model.ContactorOn = BooleanType(val)
changed = true
}
if val, ok := get(5, 2, frame.Payload); ok && model.UnexpectedState != ErrorType(val) {
model.UnexpectedState = ErrorType(val)
changed = true
}
if val, ok := get(7, 2, frame.Payload); ok && model.Isolated != ErrorType(val) {
model.Isolated = ErrorType(val)
changed = true
}
if val, ok := get(9, 2, frame.Payload); ok && model.DebugEnabled != BooleanType(val) {
model.DebugEnabled = BooleanType(val)
changed = true
}
if changed || !contactorsFirstState[unitId] {
contactorsFirstState[unitId] = true
result <- &model
}
case frame.CanId&ACTION_ID_MASK == can.CAN_ID_073:
changed := false
model := ContactorInternalErrors{UnitId: unitId}
if val, ok := get(0, 3, frame.Payload); ok && model.BoardReady != BoardReadyType(val) {
model.BoardReady = BoardReadyType(val)
changed = true
}
if val, ok := get(3, 4, frame.Payload); ok && model.OtherError != ContactorInternalOtherErrorType(val) {
model.OtherError = ContactorInternalOtherErrorType(val)
changed = true
}
if val, ok := get(7, 3, frame.Payload); ok && model.ContactorGroupChanged != ContactorGroupChangedType(val) {
model.ContactorGroupChanged = ContactorGroupChangedType(val)
changed = true
}
if val, ok := get(10, 4, frame.Payload); ok && model.UnexpectedFormation != ContactorInternalOtherErrorType(val) {
model.UnexpectedFormation = ContactorInternalOtherErrorType(val)
changed = true
}
if val, ok := get(14, 2, frame.Payload); ok && model.CpuNotReady != ErrorType(val) {
model.CpuNotReady = ErrorType(val)
changed = true
}
if val, ok := get(16, 2, frame.Payload); ok && model.PuNotReady != ErrorType(val) {
model.PuNotReady = ErrorType(val)
changed = true
}
if val, ok := get(18, 2, frame.Payload); ok && model.Debug != BooleanType(val) {
model.Debug = BooleanType(val)
changed = true
}
if changed || !contactorsFirstErr[unitId] {
contactorsFirstErr[unitId] = true
result <- &model
}
case frame.CanId&ACTION_ID_MASK == can.CAN_ID_021:
changed := false
model := PuPresentEnergy{UnitId: unitId}
if val, ok := get(0, 2, frame.Payload); ok && model.V2GMode != V2GModeType(val) {
model.V2GMode = V2GModeType(val)
changed = true
}
if val, ok := get(2, 11, frame.Payload); ok && model.VoltageBefore != Voltage11BitType(val) {
model.VoltageBefore = Voltage11BitType(val)
changed = true
}
if val, ok := get(13, 11, frame.Payload); ok && model.VoltageAfter != Voltage11BitType(val) {
model.VoltageAfter = Voltage11BitType(val)
changed = true
}
if val, ok := get(24, 10, frame.Payload); ok && model.PresentCurrent != Current10BitType(val) {
model.PresentCurrent = Current10BitType(val)
changed = true
}
if changed || !puFirst[unitId] {
puFirst[unitId] = true
result <- &model
}
case frame.CanId&ACTION_ID_MASK == can.CAN_ID_022:
changed := false
model := PuPeriphery{UnitId: unitId}
if val, ok := get(0, 2, frame.Payload); ok && model.ConnectorInsert != BooleanType(val) {
model.ConnectorInsert = BooleanType(val)
changed = true
}
if val, ok := get(2, 2, frame.Payload); ok && model.ContactorOn != BooleanType(val) {
model.ContactorOn = BooleanType(val)
changed = true
}
if val, ok := get(4, 2, frame.Payload); ok && model.ConnectorLocked != BooleanType(val) {
model.ConnectorLocked = BooleanType(val)
changed = true
}
if val, ok := get(6, 3, frame.Payload); ok && model.CpLineLevel != CpLineLevelType(val) {
model.CpLineLevel = CpLineLevelType(val)
changed = true
}
if val, ok := get(9, 3, frame.Payload); ok && model.IsolationState != IsolationStateType(val) {
model.IsolationState = IsolationStateType(val)
changed = true
}
if val, ok := get(12, 2, frame.Payload); ok && model.ChargingAllowed != BooleanType(val) {
model.ChargingAllowed = BooleanType(val)
changed = true
}
if val, ok := get(14, 2, frame.Payload); ok && model.PwmEnabled != BooleanType(val) {
model.PwmEnabled = BooleanType(val)
changed = true
}
if val, ok := get(16, 9, frame.Payload); ok && model.CpLineVoltage != (Voltage9BitType(val)*0.1-15) {
model.CpLineVoltage = Voltage9BitType(val)*0.1 - 15
changed = true
}
if changed || !puPeripheryFirst[unitId] {
puPeripheryFirst[unitId] = true
result <- &model
}
}
}
}()
return result
}
func get(from uint, size uint, buffer []byte) (uint64, bool) {
value := binary.LittleEndian.Uint64(buffer)
var mask uint64 = ^(ALL_BITS << size)
mask = mask << from
selected := mask & value
if selected == mask {
return 0, false
} else {
return selected >> from, true
}
}
func (t *ContactorInternalState) GetUnitId() uint {
return t.UnitId
}
func (t *ContactorInternalErrors) GetUnitId() uint {
return t.UnitId
}
func (t *PuPresentEnergy) GetUnitId() uint {
return t.UnitId
}
func (t *PuPeriphery) GetUnitId() uint {
return t.UnitId
}
func (a *LogicAuth) GetUnitId() uint {
return a.UnitId
}
func (l *LogicEnergyMode) GetUnitId() uint {
return l.UnitId
}
func (l *LogicErrors) GetUnitId() uint {
return l.UnitId
}
func (l *LogicWorkingMode) GetUnitId() uint {
return l.UnitId
}
func (c *CpuPresentEnergy) GetUnitId() uint {
return c.UnitId
}
func (c *CpuPeriphery) GetUnitId() uint {
return c.UnitId
}
func (c *CpuEnergySettings) GetUnitId() uint {
return c.UnitId
}
func (c *CpuErrors) GetUnitId() uint {
return c.UnitId
}
func (d *CpuDebug) GetUnitId() uint {
return d.UnitId
}
func (p *PuErrors) GetUnitId() uint {
return p.UnitId
}
func (d *PuDebug) GetUnitId() uint {
return d.UnitId
}
func (s *SeccTargetEnergy) GetUnitId() uint {
return s.UnitId
}
func (e *SeccErrors) GetUnitId() uint {
return e.UnitId
}
func (c *ContactorsInternalForce) GetUnitId() uint {
return c.UnitId
}
func (c *ContactorInternalDebug) GetUnitId() uint {
return c.UnitId
}
func (p *PeripheryState) GetUnitId() uint {
return p.UnitId
}
func (p *PeripheryInfo) GetUnitId() uint {
return p.UnitId
}
func (p *PeripheryDebug) GetUnitId() uint {
return p.UnitId
}
func (c *ConverterPresentEnergy) GetUnitId() uint {
return c.UnitId
}
func (c *ConverterErrors) GetUnitId() uint {
return c.UnitId
}
func (c *ConverterDebug) GetUnitId() uint {
return c.UnitId
}