package main import ( "fmt" "time" ) type ChademoEvent interface { // GetValue Return processed/calculated value and timestamp string GetValue() (interface{}, *time.Time) } type frame struct { *CanFrame } // MaximumBatteryVoltage The maximum voltage value at the vehicle inlet terminals, at which the station stops charging to protect the vehicle battery type MaximumBatteryVoltage frame // ConstChargingRateInd Fixed value for charging rate indication, which is the maximum charging rate (100 %) of vehicle battery type ConstChargingRateInd frame // BatteryCapacity Rated capacity of battery type BatteryCapacity frame // MaxChargingTimeS Maximum charging time permitted by EV, set by 10 s type MaxChargingTimeS frame // MaxChargingTimeM Maximum charging time permitted by EV, set by minute type MaxChargingTimeM frame // EstChargingTimeM Estimated remaining time before the end of charging calculated by EV type EstChargingTimeM frame // EVControlProtocolNumber Software version of control protocol to which EV corresponds type EVControlProtocolNumber frame // TargetBatteryVoltage Target battery voltage ed charging voltage at the vehicle inlet terminals type TargetBatteryVoltage frame // ChargingCurrentReq Current value requested by EV during charging type ChargingCurrentReq frame // ChargingRate Charging rate of vehicle battery type ChargingRate frame // VehicleCharging Status flag indicating charge permission status of EV type VehicleCharging frame // ShiftLever Status flag indicating the shift lever position type ShiftLever frame // ChargingSystemFault Status flag indicating Charging system fault a malfunction caused by EV or the station, and detected by EV type ChargingSystemFault frame // VehicleStatus Status flag indicating the EV contactor status type VehicleStatus frame // NormalStopReq Status flag indicating the request of EV to stop charging control type NormalStopReq frame // BattOvervoltage Status flag indicating whether or not the vehicle battery voltage exceeds the maximum limit specified by EV type BattOvervoltage frame // BattUndervoltage Status flag indicating whether or not the vehicle battery voltage is less than the lower limit specified by EV type BattUndervoltage frame // BattCurrentDeviationErr Status flag indicating whether or not the output current deviates from EV requested current type BattCurrentDeviationErr frame // HighBattTemperature Status flag indicating whether or not the temperature of vehicle battery exceeds the maximum limit type HighBattTemperature frame // BattVoltageDeviationErr Status flag indicating whether or not the vehicle battery voltage deviates from the output voltage measured by the station type BattVoltageDeviationErr frame // EVSE entity from here // EVcontWeldingDetectSupport Identifier indicating whether or not the station deals with EV contactor welding detection type EVcontWeldingDetectSupport frame // AvailableOutputVoltage Maximum output voltage value at the vehicle connector terminals type AvailableOutputVoltage frame // AvailableOutputCurrent Maximum output current value of the station type AvailableOutputCurrent frame // ThresholdVoltage Threshold voltage to stop the charging process in order to protect vehicle battery type ThresholdVoltage frame // EVSEControlProtocolNumber Software version number of control protocol or charging sequences that the station deals with type EVSEControlProtocolNumber frame // OutputVoltage Supply voltage value of the output circuit in the station type OutputVoltage frame // OutputCurrent Supply current value of the output circuit in the station type OutputCurrent frame // RemainingChargingTimeS Remaining time before the end of charging (counted by 10 s) type RemainingChargingTimeS frame // RemainingChargingTimeM Remaining time before the end of charging (counted by min) type RemainingChargingTimeM frame // StationStatus Status flag indicating the energy transfer from the station type StationStatus frame // StationMalfunction Status flag indicating whether or not there is a malfunction caused by the station type StationMalfunction frame // VehicleConnectorLock Status flag indicating Vehicle connector lock the electromagnetic lock status of vehicle connector type VehicleConnectorLock frame // BatteryIncompatibility Status flag indicating the compatibility of vehicle battery with the output voltage of station type BatteryIncompatibility frame // ChargingSystemMalfunction Status flag indicating whether or not there is a problem with EV, such as improper connection type ChargingSystemMalfunction frame // ChargerStopControl Status flag indicating whether or not the station proceeds with shutdown process type ChargerStopControl frame func FromCanFrames(frames <-chan *CanFrame) <-chan ChademoEvent { events := make(chan ChademoEvent) go func() { defer close(events) for frame := range frames { switch frame.canid { case CAN_ID_100: events <- &MaximumBatteryVoltage{frame} events <- &ConstChargingRateInd{frame} case CAN_ID_101: events <- &BatteryCapacity{frame} events <- &MaxChargingTimeS{frame} events <- &MaxChargingTimeM{frame} events <- &EstChargingTimeM{frame} case CAN_ID_102: events <- &EVControlProtocolNumber{frame} events <- &TargetBatteryVoltage{frame} events <- &ChargingCurrentReq{frame} events <- &ChargingRate{frame} events <- &VehicleCharging{frame} events <- &ShiftLever{frame} events <- &ChargingSystemFault{frame} events <- &VehicleStatus{frame} events <- &NormalStopReq{frame} events <- &BattOvervoltage{frame} events <- &BattUndervoltage{frame} events <- &BattCurrentDeviationErr{frame} events <- &HighBattTemperature{frame} events <- &BattVoltageDeviationErr{frame} case CAN_ID_108: events <- &EVcontWeldingDetectSupport{frame} events <- &AvailableOutputVoltage{frame} events <- &AvailableOutputCurrent{frame} events <- &ThresholdVoltage{frame} case CAN_ID_109: events <- &EVSEControlProtocolNumber{frame} events <- &OutputVoltage{frame} events <- &OutputCurrent{frame} events <- &RemainingChargingTimeS{frame} events <- &RemainingChargingTimeM{frame} events <- &StationStatus{frame} events <- &StationMalfunction{frame} events <- &VehicleConnectorLock{frame} events <- &BatteryIncompatibility{frame} events <- &ChargingSystemMalfunction{frame} events <- &ChargerStopControl{frame} } } }() return events } func getVehicleShiftLever(bytes *[]byte) ShiftLeverPosition { if isBitSet((*bytes)[5], 1) { return OTHER } return PARKING } func getVehicleStatus(bytes *[]byte) ContactorVehicleStatus { if isBitSet((*bytes)[5], 3) { return CONTACTOR_OPEN } return CONTACTOR_CLOSED } func getNormalStopReq(bytes *[]byte) StopRequest { if isBitSet((*bytes)[5], 4) { return STOP_REQUEST } return NO_REQUEST } func getFault(bytes *[]byte, octet byte, bit byte) SystemFault { if isBitSet((*bytes)[octet], bit) { return FAULT } return NORMAL } func getVehicleCharging(bytes *[]uint8) VehicleChargingEnabled { if isBitSet((*bytes)[5], 0) { return ENABLED } return DISABLED } func isBitSet(buf uint8, num uint8) bool { mask := uint8(1) << num val := buf & mask if val == mask { return true } return false } func bytesToUint16(bytes []uint8) uint16 { if len(bytes) != 2 { fmt.Println("Wrong array size in bytesToUint16()") return 0 } var result uint16 result = uint16(bytes[1]) << 8 result = result | uint16(bytes[0]) return result } func evWeldingDetectionSupport(bytes *[]uint8) SuppVehicleWeldingDetection { if (*bytes)[0] == 0 { return VEHICLE_WELDING_DETECTION_NOT_SUPPORTED } return VEHICLE_WELDING_DETECTION_SUPPORTED } func getStationState(bytes *[]uint8) StationState { if isBitSet((*bytes)[5], 0) { return CHARGING } return STANDBY } func getConnectorLock(bytes *[]byte) ConnectorLock { if isBitSet((*bytes)[5], 2) { return CONNECTOR_LOCKED } return CONNECTOR_UNLOCKED } func getBatteryCompatibility(bytes *[]uint8) BatteryCompatible { if isBitSet((*bytes)[5], 3) { return BATTERY_INCOMPATIBLE } return BATTERY_COMPATIBLE } func getChargerStopControl(bytes *[]uint8) StopControl { if isBitSet((*bytes)[5], 5) { return SHUTDOWN_STOP } return OPERATING } func (m MaximumBatteryVoltage) GetValue() (interface{}, *time.Time) { return bytesToUint16((*m.payload)[4:6]), m.date } func (c ConstChargingRateInd) GetValue() (interface{}, *time.Time) { return (*c.payload)[6], c.date } func (b BatteryCapacity) GetValue() (interface{}, *time.Time) { return 0.1 * float32(bytesToUint16((*b.payload)[5:7])), b.date } func (m MaxChargingTimeS) GetValue() (interface{}, *time.Time) { return 10 * uint16((*m.payload)[1]), m.date } func (m MaxChargingTimeM) GetValue() (interface{}, *time.Time) { return (*m.payload)[2], m.date } func (e EstChargingTimeM) GetValue() (interface{}, *time.Time) { return (*e.payload)[3], e.date } func (c EVControlProtocolNumber) GetValue() (interface{}, *time.Time) { return (*c.payload)[0], c.date } func (t TargetBatteryVoltage) GetValue() (interface{}, *time.Time) { return bytesToUint16((*t.payload)[1:3]), t.date } func (c ChargingCurrentReq) GetValue() (interface{}, *time.Time) { return (*c.payload)[3], c.date } func (c ChargingRate) GetValue() (interface{}, *time.Time) { return (*c.payload)[6], c.date } func (s ShiftLever) GetValue() (interface{}, *time.Time) { return getVehicleShiftLever(s.payload), s.date } func (v VehicleCharging) GetValue() (interface{}, *time.Time) { return getVehicleCharging(v.payload), v.date } func (c ChargingSystemFault) GetValue() (interface{}, *time.Time) { return getFault(c.payload, 5, 2), c.date } func (v VehicleStatus) GetValue() (interface{}, *time.Time) { return getVehicleStatus(v.payload), v.date } func (n NormalStopReq) GetValue() (interface{}, *time.Time) { return getNormalStopReq(n.payload), n.date } func (b BattOvervoltage) GetValue() (interface{}, *time.Time) { return getFault(b.payload, 4, 0), b.date } func (b BattUndervoltage) GetValue() (interface{}, *time.Time) { return getFault(b.payload, 4, 1), b.date } func (b BattCurrentDeviationErr) GetValue() (interface{}, *time.Time) { return getFault(b.payload, 4, 2), b.date } func (h HighBattTemperature) GetValue() (interface{}, *time.Time) { return getFault(h.payload, 4, 3), h.date } func (b BattVoltageDeviationErr) GetValue() (interface{}, *time.Time) { return getFault(b.payload, 4, 4), b.date } func (e EVcontWeldingDetectSupport) GetValue() (interface{}, *time.Time) { return evWeldingDetectionSupport(e.payload), e.date } func (a AvailableOutputVoltage) GetValue() (interface{}, *time.Time) { return bytesToUint16((*a.payload)[1:3]), a.date } func (a AvailableOutputCurrent) GetValue() (interface{}, *time.Time) { return (*a.payload)[3], a.date } func (t ThresholdVoltage) GetValue() (interface{}, *time.Time) { return bytesToUint16((*t.payload)[4:6]), t.date } func (e EVSEControlProtocolNumber) GetValue() (interface{}, *time.Time) { return (*e.payload)[0], e.date } func (o OutputVoltage) GetValue() (interface{}, *time.Time) { return bytesToUint16((*o.payload)[1:3]), o.date } func (o OutputCurrent) GetValue() (interface{}, *time.Time) { return (*o.payload)[3], o.date } func (r RemainingChargingTimeS) GetValue() (interface{}, *time.Time) { return (*r.payload)[6] * 10, r.date } func (r RemainingChargingTimeM) GetValue() (interface{}, *time.Time) { return (*r.payload)[7], r.date } func (s StationStatus) GetValue() (interface{}, *time.Time) { return getStationState(s.payload), s.date } func (s StationMalfunction) GetValue() (interface{}, *time.Time) { return getFault(s.payload, 5, 1), s.date } func (v VehicleConnectorLock) GetValue() (interface{}, *time.Time) { return getConnectorLock(v.payload), v.date } func (b BatteryIncompatibility) GetValue() (interface{}, *time.Time) { return getBatteryCompatibility(b.payload), b.date } func (c ChargingSystemMalfunction) GetValue() (interface{}, *time.Time) { return getFault(c.payload, 5, 4), c.date } func (c ChargerStopControl) GetValue() (interface{}, *time.Time) { return getChargerStopControl(c.payload), c.date }