package yabl import ( "cli-mon/can" "encoding/binary" "time" ) const ( CONVERTERS_MAX = 18 + 1 CONTACTOR_MAX = 18 + 1 CONNECTOR_COUNT = 6 CONNECTOR_MAX = CONNECTOR_COUNT + 1 ALL_BITS = 0xFFFFFFFFFFFFFFFF UNIT_ID_OFFSET = 12 UNIT_ID_MASK = 0b111111111111 << UNIT_ID_OFFSET ACTION_ID_MASK = 0b111111111111 BOARD_READY_OK BoardReadyType = 0 BOARD_READY_INFO BoardReadyType = 1 BOARD_READY_WARNING BoardReadyType = 2 BOARD_READY_DEBUG BoardReadyType = 3 BOARD_READY_DEP_ERROR BoardReadyType = 4 BOARD_READY_ERROR BoardReadyType = 5 BOARD_READY_CRITICAL BoardReadyType = 6 OFF BooleanType = 0 ON BooleanType = 1 NO_ERROR ErrorType = 0 ERROR ErrorType = 1 OTHER_NO_ERROR ContactorInternalOtherErrorType = 0 NO_PENDING_CHANGES ContactorGroupChangedType = 0 INITIALIZED_CHANGE ContactorGroupChangedType = 1 CHANGE_IN_PROGRESS ContactorGroupChangedType = 2 V2G_MODE_G2V V2GModeType = 0 V2G_MODE_V2G V2GModeType = 1 V2G_MODE_INV V2GModeType = 2 NOT_ENABLE CpLineLevelType = 0 TWELVE CpLineLevelType = 1 NINE CpLineLevelType = 2 SIX CpLineLevelType = 3 THREE CpLineLevelType = 4 MINUS_TWELVE CpLineLevelType = 5 ISOLATION_STATE_UNKNOWN IsolationStateType = 0 ONGOING IsolationStateType = 1 PASSED IsolationStateType = 2 WARNING IsolationStateType = 3 FAILED IsolationStateType = 4 AUTH AuthModeType = 0 PNC AuthModeType = 1 AUTH_STATE_UNKNOWN AuthStateType = 0 AUTH_STATE_ALLOW AuthStateType = 1 AUTH_STATE_DENY AuthStateType = 2 CONTACTOR_NO_MODE ContactorModeType = 0 CONTACTOR_TRANSACTION_PROCESS ContactorModeType = 1 CONTACTOR_CUSTOM_MODE ContactorModeType = 2 CONTACTOR_ONLY_ONE_OUT_MODE ContactorModeType = 3 CONTACTOR_ONE_TO_ONE_OUT_MODE ContactorModeType = 4 CONTACTOR_SIMPLE_DYNAMIC_MODE ContactorModeType = 5 DEBUG_SWITCH_MODE_AUTO DebugSwitchModeType = 0 DEBUG_SWITCH_MODE_OFF DebugSwitchModeType = 1 DEBUG_SWITCH_MODE_ON DebugSwitchModeType = 2 DEBUG_SWITCH_MODE_PERMANENT_OFF DebugSwitchModeType = 4 DEBUG_SWITCH_MODE_PERMANENT_ON DebugSwitchModeType = 5 ) type Packet interface { GetUnitId() uint } type ContactorInternalState struct { UnitId uint ContactorReady BoardReadyType ContactorOn BooleanType UnexpectedState ErrorType Isolated ErrorType DebugEnabled BooleanType } type ContactorInternalErrors struct { UnitId uint BoardReady BoardReadyType OtherError ContactorInternalOtherErrorType ContactorGroupChanged ContactorGroupChangedType UnexpectedFormation ContactorInternalOtherErrorType CpuNotReady ErrorType PuNotReady ErrorType Debug BooleanType PresentContactorMode ContactorModeType } type ContactorsInternalForce struct { UnitId uint ForceModeEnabled BooleanType ForceModeValue ForceModeType } type ContactorInternalDebug struct { UnitId uint DebugModeOn BooleanType DebugContactorOn DebugSwitchModeType } type PuPresentEnergy struct { UnitId uint V2GMode V2GModeType VoltageBefore Voltage11BitType VoltageAfter Voltage11BitType PresentCurrent Current10BitType } type PuPeriphery struct { UnitId uint ConnectorInsert BooleanType ContactorOn BooleanType ConnectorLocked BooleanType CpLineLevel CpLineLevelType IsolationState IsolationStateType ChargingAllowed BooleanType PwmEnabled BooleanType CpLineVoltage Voltage9BitType } type LogicAuth struct { UnitId uint AuthMode AuthModeType AuthState AuthStateType } type LogicEnergyMode struct { UnitId uint V2gMode V2GModeType CurrentMax Current10BitType VoltageMax Voltage11BitType PowerMax Power14BitType } type LogicErrors struct { UnitId uint BoardReady BoardReadyType NotReadySettings ErrorType } type LogicWorkingMode struct { UnitId uint TargetContactorMode ContactorModeType Availability BooleanType } type CpuPresentEnergy struct { UnitId uint PowerDirectionMode V2GModeType PresentCurrent Current10BitType PresentVoltage Voltage11BitType } type CpuPeriphery struct { UnitId uint ContactorInput BooleanType CircuitBreakerInput BooleanType CircuitBreakerPowerCBInput BooleanType } type CpuEnergySettings struct { UnitId uint CurrentMax Current10BitType VoltageMax Voltage11BitType PowerMax Power14BitType TargetBatteryVoltage Voltage11BitType TargetGoalVoltage Voltage11BitType } type CpuErrors struct { UnitId uint BoardReady BoardReadyType OtherError OtherError4BitType RedButtonHard ErrorType RedButtonSoft ErrorType ModulesGone ErrorType GridVoltageHighErr ErrorType GridVoltageHighWarn ErrorType GridVoltageLowWarn ErrorType GridVoltageLowErr ErrorType GridVoltageLow Voltage11BitType GridVoltageHigh Voltage11BitType GridVoltageEmpty ErrorType NotReadySecc ErrorType NotReadyPu ErrorType NotReadyContactors ErrorType DebugConvertersEnabled ErrorType ContactorInputError ErrorType NotReadyPeriphery ErrorType } type CpuDebug struct { UnitId uint DebugModeOn BooleanType DebugContactorInputOn DebugSwitchModeType DebugCircuitBreakerOn DebugSwitchModeType DebugRedButtonSoftware DebugSwitchModeType } type PuErrors struct { UnitId uint BoardReady BoardReadyType OtherError OtherError4BitType IncorrectVoltage ErrorType IncorrectVoltageValue Voltage11BitType IncorrectCurrent ErrorType IncorrectCurrentValue Current10BitType IsolationBroken ErrorType CpLineBroken ErrorType CpLineGap69 ErrorType CableReady BoardReadyType NotReadyCpu ErrorType NotReadySecc ErrorType ContactorOutputError ErrorType DebugContactorOutputEnabled BooleanType OutputCircuitBreakerEnabled ErrorType OutputCircuitBreakerEnabledValue SignedVoltage12bitType } type PuDebug struct { UnitId uint DebugModeOn BooleanType DebugContactorOutputOn DebugSwitchModeType } type SeccTargetEnergy struct { UnitId uint TargetChargingAllow BooleanType TargetBatteryVoltage Voltage11BitType TargetGoalVoltage Voltage11BitType TargetCurrent Current10BitType } type SeccErrors struct { UnitId uint BoardReady BoardReadyType NotReadyLogic ErrorType } type PeripheryState struct { UnitId uint OtherErrorSeverity BoardReadyType OtherError OtherError4BitType ErrorShakeSensor ErrorType ErrorCoolingGroup ErrorType PeripheryErrorCoolingGroup ErrorType ErrorFireEmergency ErrorType ErrorFireEmergencyRun ErrorType ErrorFireEmergencyControl ErrorType ErrorOvervoltageIn ErrorType PeripheryErrorPowerSupply ErrorType ErrorFan ErrorType ErrorOvervoltageOut ErrorType ErrorStateRemoteMode ErrorType DebugShsnFanEnabled BooleanType DebugShptFanEnabled BooleanType DebugIoBoardTestLampEnabled BooleanType ErrorFireEmergencyCircuitBreaker ErrorType ErrorExtLightCircuitBreaker ErrorType ErrorIndicationCircuitBreaker ErrorType ErrorLowVoltagePowerCircuitBreaker ErrorType ErrorContactorsInternalCircuitBreaker ErrorType ErrorPlcCircuitBreaker ErrorType } type PeripheryInfo struct { UnitId uint InfoDoorOpen BooleanType TempAirIn SignedAirTemp8BitType TempAirOut SignedAirTemp8BitType StateShsnFan BooleanType StateShptFan BooleanType } type PeripheryDebug struct { UnitId uint DebugModeOn BooleanType DebugShsnFan DebugSwitchModeType DebugShptFan DebugSwitchModeType DebugIoBoardTestLamp DebugSwitchModeType } type ConverterPresentEnergy struct { UnitId uint V2gMode V2GModeType PresentVoltage Voltage11BitType PresentCurrent Current10BitType ConnectedOut ConnectedOut8bitType } type ConverterErrors struct { UnitId uint BoardReady BoardReadyType OtherError OtherError4BitType NotConnectedOut ErrorType NoCommunicationConverter ErrorType NoCommunicationPuConverter ErrorType InputGridVoltageHigh ErrorType InputGridVoltageLow ErrorType OutputGridVoltageHigh ErrorType OutputGridVoltageLow ErrorType InputGridVoltage Voltage11BitType OutputGridVoltage Voltage11BitType ShortCircuit ErrorType OverHeat ErrorType FanBroken ErrorType OtherHardwareError ErrorType DebugConvEnabled BooleanType DebugConvDisabled BooleanType } type ConverterDebug struct { UnitId uint DebugModeOn BooleanType DebugEnergyOn DebugSwitchModeType DebugTargetVoltage Voltage11BitType DebugTargetCurrent Current10BitType } 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 parameters struct { fields []content interval uint } type content struct { length uint8 setter func(uint64 uint64) value uint64 last time.Time } 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 init() { for i := 1; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_011, uint(i)} cpe := CpuPresentEnergy{} cpuPresentEnergyArray[i] = &cpe fields := []content{ {length: 2, setter: cpe.setPowerDirectionMode}, {length: 10, setter: cpe.setPresentCurrent}, {length: 11, setter: cpe.setPresentVoltage}, } protocolMap[key] = parameters{fields: fields, interval: 50} } cpuPeripheryInstance = &CpuPeriphery{} fields := []content{ {length: 2, setter: cpuPeripheryInstance.setContactorInput}, {length: 2, setter: cpuPeripheryInstance.setCircuitBreakerInput}, {length: 2, setter: cpuPeripheryInstance.setCircuitBreakerPowerCBInput}, } protocolMap[key{can.CAN_ID_014, 0}] = parameters{fields: fields, interval: 1000} for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_015, uint(i)} ces := CpuEnergySettings{} cpuEnergySettingsArray[i] = &ces fields := []content{ {length: 10, setter: ces.setCurrentMax}, {length: 11, setter: ces.setVoltageMax}, {length: 14, setter: ces.setPowerMax}, {length: 11, setter: ces.setTargetBatteryVoltage}, {length: 11, setter: ces.setTargetGoalVoltage}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } cpuErrorsInstance = &CpuErrors{} fields = []content{ {length: 3, setter: cpuErrorsInstance.setBoardReady}, {length: 4, setter: cpuErrorsInstance.setOtherError}, {length: 2, setter: cpuErrorsInstance.setRedButtonHard}, {length: 2, setter: cpuErrorsInstance.setRedButtonSoft}, {length: 2, setter: cpuErrorsInstance.setModulesGone}, {length: 2, setter: cpuErrorsInstance.setGridVoltageHighErr}, {length: 2, setter: cpuErrorsInstance.setGridVoltageHighWarn}, {length: 2, setter: cpuErrorsInstance.setGridVoltageLowWarn}, {length: 2, setter: cpuErrorsInstance.setGridVoltageLowErr}, {length: 11, setter: cpuErrorsInstance.setGridVoltageLow}, {length: 11, setter: cpuErrorsInstance.setGridVoltageHigh}, {length: 2, setter: cpuErrorsInstance.setGridVoltageEmpty}, {length: 2, setter: cpuErrorsInstance.setNotReadySecc}, {length: 2, setter: cpuErrorsInstance.setNotReadyPu}, {length: 2, setter: cpuErrorsInstance.setNotReadyContactors}, {length: 2, setter: cpuErrorsInstance.setDebugConvertersEnabled}, {length: 2, setter: cpuErrorsInstance.setContactorInputError}, {length: 2, setter: cpuErrorsInstance.setNotReadyPeriphery}, } protocolMap[key{can.CAN_ID_016, 0}] = parameters{fields: fields, interval: 1000} cpuDebugInstance = &CpuDebug{} fields = []content{ {length: 2, setter: cpuDebugInstance.setDebugModeOn}, {length: 3, setter: cpuDebugInstance.setDebugContactorInputOn}, {length: 3, setter: cpuDebugInstance.setDebugCircuitBreakerOn}, {length: 3, setter: cpuDebugInstance.setDebugRedButtonSoftware}, } protocolMap[key{can.CAN_ID_01A, 0}] = parameters{fields: fields, interval: 1000} for i := 1; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_021, uint(i)} ppe := PuPresentEnergy{} puPresentEnergyArray[i] = &ppe fields := []content{ {length: 2, setter: ppe.setV2GMode}, {length: 11, setter: ppe.setVoltageBefore}, {length: 11, setter: ppe.setVoltageAfter}, {length: 10, setter: ppe.setPresentCurrent}, } protocolMap[key] = parameters{fields: fields, interval: 50} } for i := 1; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_022, uint(i)} pp := PuPeriphery{} puPeripheryArray[i] = &pp fields := []content{ {length: 2, setter: pp.setConnectorInsert}, {length: 2, setter: pp.setContactorOn}, {length: 2, setter: pp.setConnectorLocked}, {length: 3, setter: pp.setCpLineLevel}, {length: 3, setter: pp.setIsolationState}, {length: 2, setter: pp.setChargingAllowed}, {length: 2, setter: pp.setPwmEnabled}, {length: 9, setter: pp.setCpLineVoltage}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 1; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_023, uint(i)} pe := PuErrors{} puErrorsArray[i] = &pe fields := []content{ {length: 3, setter: pe.setBoardReady}, {length: 4, setter: pe.setOtherError}, {length: 2, setter: pe.setIncorrectVoltage}, {length: 11, setter: pe.setIncorrectVoltageValue}, {length: 2, setter: pe.setIncorrectCurrent}, {length: 10, setter: pe.setIncorrectCurrentValue}, {length: 2, setter: pe.setIsolationBroken}, {length: 2, setter: pe.setCpLineBroken}, {length: 2, setter: pe.setCpLineGap69}, {length: 3, setter: pe.setCableReady}, {length: 2, setter: pe.setNotReadyCpu}, {length: 2, setter: pe.setNotReadySecc}, {length: 2, setter: pe.setContactorOutputError}, {length: 2, setter: pe.setDebugContactorOutputEnabled}, {length: 2, setter: pe.setOutputCircuitBreakerEnabled}, {length: 12, setter: pe.setOutputCircuitBreakerEnabledValue}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_02A, uint(i)} pd := PuDebug{} puDebugArray[i] = &pd fields = []content{ {length: 2, setter: pd.setDebugModeOn}, {length: 3, setter: pd.setDebugContactorOutputOn}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 1; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_041, uint(i)} ste := SeccTargetEnergy{} seccTargetEnergyArray[i] = &ste fields = []content{ {length: 2, setter: ste.setTargetChargingAllow}, {length: 11, setter: ste.setTargetBatteryVoltage}, {length: 11, setter: ste.setTargetGoalVoltage}, {length: 10, setter: ste.setTargetCurrent}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 1; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_042, uint(i)} se := SeccErrors{} seccErrorsArray[i] = &se fields = []content{ {length: 3, setter: se.setBoardReady}, {length: 2, setter: se.setNotReadyLogic}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_046, uint(i)} la := LogicAuth{} logicAuthArray[i] = &la fields = []content{ {length: 2, setter: la.setAuthMode}, {length: 3, setter: la.setAuthState}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_047, uint(i)} la := LogicEnergyMode{} logicEnergyMode[i] = &la fields = []content{ {length: 2, setter: la.setV2gMode}, {length: 10, setter: la.setCurrentMax}, {length: 11, setter: la.setVoltageMax}, {length: 14, setter: la.setPowerMax}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } logicErrorsInstance = &LogicErrors{} fields = []content{ {length: 3, setter: logicErrorsInstance.setBoardReady}, {length: 2, setter: logicErrorsInstance.setNotReadySettings}, } protocolMap[key{can.CAN_ID_048, 0}] = parameters{fields: fields, interval: 1000} logicWorkingMode = &LogicWorkingMode{} fields = []content{ {length: 5, setter: logicWorkingMode.setTargetContactorMode}, {length: 2, setter: logicWorkingMode.setAvailability}, } protocolMap[key{can.CAN_ID_049, 0}] = parameters{fields: fields, interval: 1000} for i := 0; i <= CONTACTOR_MAX; i++ { key := key{can.CAN_ID_071, uint(i)} cis := ContactorInternalState{} contactorInternalStateArray[i] = &cis fields = []content{ {length: 3, setter: cis.setContactorReady}, {length: 2, setter: cis.setContactorOn}, {length: 2, setter: cis.setUnexpectedState}, {length: 2, setter: cis.setIsolated}, {length: 2, setter: cis.setDebugEnabled}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } contactorInternalErrorsInstance = &ContactorInternalErrors{} fields = []content{ {length: 3, setter: contactorInternalErrorsInstance.setBoardReady}, {length: 4, setter: contactorInternalErrorsInstance.setOtherError}, {length: 3, setter: contactorInternalErrorsInstance.setContactorGroupChanged}, {length: 4, setter: contactorInternalErrorsInstance.setUnexpectedFormation}, {length: 2, setter: contactorInternalErrorsInstance.setCpuNotReady}, {length: 2, setter: contactorInternalErrorsInstance.setPuNotReady}, {length: 2, setter: contactorInternalErrorsInstance.setDebug}, {length: 5, setter: contactorInternalErrorsInstance.setPresentContactorMode}, } protocolMap[key{can.CAN_ID_073, 0}] = parameters{fields: fields, interval: 1000} contactorsInternalForce = &ContactorsInternalForce{} fields = []content{ {length: 2, setter: contactorsInternalForce.setForceModeEnabled}, {length: 4, setter: contactorsInternalForce.setForceModeValue}, } protocolMap[key{can.CAN_ID_074, 0}] = parameters{fields: fields, interval: 1000} for i := 0; i <= CONTACTOR_MAX; i++ { key := key{can.CAN_ID_075, uint(i)} cid := ContactorInternalDebug{} contactorInternalDebugArray[i] = &cid fields = []content{ {length: 2, setter: cid.setDebugModeOn}, {length: 3, setter: cid.setDebugContactorOn}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_067, uint(i)} ps := PeripheryState{} peripheryStateArray[i] = &ps fields = []content{ {length: 3, setter: ps.setOtherErrorSeverity}, {length: 4, setter: ps.setOtherError}, {length: 2, setter: ps.setErrorShakeSensor}, {length: 2, setter: ps.setErrorCoolingGroup}, {length: 2, setter: ps.setPeripheryErrorCoolingGroup}, {length: 2, setter: ps.setErrorFireEmergency}, {length: 2, setter: ps.setErrorFireEmergencyRun}, {length: 2, setter: ps.setErrorFireEmergencyControl}, {length: 2, setter: ps.setErrorOvervoltageIn}, {length: 2, setter: ps.setPeripheryErrorPowerSupply}, {length: 2, setter: ps.setErrorFan}, {length: 2, setter: ps.setErrorOvervoltageOut}, {length: 2, setter: ps.setErrorStateRemoteMode}, {length: 2, setter: ps.setDebugShsnFanEnabled}, {length: 2, setter: ps.setDebugShptFanEnabled}, {length: 2, setter: ps.setDebugIoBoardTestLampEnabled}, {length: 2, setter: ps.setErrorFireEmergencyCircuitBreaker}, {length: 2, setter: ps.setErrorExtLightCircuitBreaker}, {length: 2, setter: ps.setErrorIndicationCircuitBreaker}, {length: 2, setter: ps.setErrorLowVoltagePowerCircuitBreaker}, {length: 2, setter: ps.setErrorContactorsInternalCircuitBreaker}, {length: 2, setter: ps.setErrorPlcCircuitBreaker}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_068, uint(i)} pi := PeripheryInfo{} peripheryInfoArray[i] = &pi fields = []content{ {length: 2, setter: pi.setInfoDoorOpen}, {length: 8, setter: pi.setTempAirIn}, {length: 8, setter: pi.setTempAirOut}, {length: 2, setter: pi.setStateShsnFan}, {length: 2, setter: pi.setStateShptFan}, } protocolMap[key] = parameters{fields: fields, interval: 5000} } for i := 0; i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_06C, uint(i)} pd := PeripheryDebug{} peripheryDebugArray[i] = &pd fields = []content{ {length: 2, setter: pd.setDebugModeOn}, {length: 3, setter: pd.setDebugShsnFan}, {length: 3, setter: pd.setDebugShptFan}, {length: 3, setter: pd.setDebugIoBoardTestLamp}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 1; i <= CONVERTERS_MAX; i++ { key := key{can.CAN_ID_061, uint(i)} cpe := ConverterPresentEnergy{} converterPresentEnergyArray[i] = &cpe fields = []content{ {length: 2, setter: cpe.setV2gMode}, {length: 11, setter: cpe.setPresentVoltage}, {length: 10, setter: cpe.setPresentCurrent}, {length: 8, setter: cpe.setConnectedOut}, } protocolMap[key] = parameters{fields: fields, interval: 500} } for i := 1; i <= CONVERTERS_MAX; i++ { key := key{can.CAN_ID_062, uint(i)} ce := ConverterErrors{} converterErrorsArray[i] = &ce fields = []content{ {length: 3, setter: ce.setBoardReady}, {length: 4, setter: ce.setOtherError}, {length: 2, setter: ce.setNotConnectedOut}, {length: 2, setter: ce.setNoCommunicationConverter}, {length: 2, setter: ce.setNoCommunicationPuConverter}, {length: 2, setter: ce.setInputGridVoltageHigh}, {length: 2, setter: ce.setInputGridVoltageLow}, {length: 2, setter: ce.setOutputGridVoltageHigh}, {length: 2, setter: ce.setOutputGridVoltageLow}, {length: 11, setter: ce.setInputGridVoltage}, {length: 11, setter: ce.setOutputGridVoltage}, {length: 2, setter: ce.setShortCircuit}, {length: 2, setter: ce.setOverHeat}, {length: 2, setter: ce.setFanBroken}, {length: 2, setter: ce.setOtherHardwareError}, {length: 2, setter: ce.setDebugConvEnabled}, {length: 2, setter: ce.setDebugConvDisabled}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } for i := 0; i <= CONVERTERS_MAX; i++ { key := key{can.CAN_ID_065, uint(i)} cd := ConverterDebug{} converterDebugArray[i] = &cd fields = []content{ {length: 3, setter: cd.setDebugModeOn}, {length: 4, setter: cd.setDebugEnergyOn}, {length: 2, setter: cd.setDebugTargetVoltage}, {length: 2, setter: cd.setDebugTargetCurrent}, } protocolMap[key] = parameters{fields: fields, interval: 1000} } } 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 }