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 }