package main import ( "fmt" ) const ( CAN_ID_100 = 100 CAN_ID_101 = 101 CAN_ID_102 = 102 DISABLED VehicleCharging = iota ENABLED PARKING ShiftLever = iota OTHER NORMAL SystemFault = iota FAULT CONTACTOR_CLOSED VehicleStatus = iota CONTACTOR_OPEN NO_REQUEST StopRequest = iota STOP_REQUEST ) type VehicleCharging uint8 type ShiftLever uint8 type SystemFault uint8 type VehicleStatus uint8 type StopRequest uint8 type ChademoEvent interface { GetValue() interface{} } type MaximumBatteryVoltage interface { // GetMaxBattVoltage Maximum battery voltage GetMaxBattVoltage() uint16 } type ConstChargingRateInd interface { // GetChargingRate Constant of charging rate indication GetChargingRate() uint8 } type frame100 struct { maxBattVoltage uint16 // The maximum voltage value at the vehicle inlet terminals, at which the station stops charging to protect the vehicle battery chargingRateInd uint8 // Fixed value for charging rate indication, which is the maximum charging rate (100 %) of vehicle battery date string } type frame101 struct { batteryCapacity float32 // Rated capacity of battery maxChargingTimeS uint16 // Maximum charging time permitted by EV, set by 10 s maxChargingTimeM uint8 // Maximum charging time permitted by EV, set by minute estChargingTimeM uint8 // Estimated remaining time before the end of charging calculated by EV date string } type frame102 struct { controlProtocolNumber uint8 // Software version of control protocol to which EV corresponds targetBatteryVoltage uint16 // Target battery voltage ed charging voltage at the vehicle inlet terminals chargingCurrentReq uint8 // Current value requested by EV during charging chargingRate uint8 // Charging rate of vehicle battery vehicleCharging VehicleCharging // Status flag indicating charge permission status of EV shiftLever ShiftLever // Status flag indicating the shift lever position chargingSystemFault SystemFault // Status flag indicating Charging system fault a malfunction caused by EV or the station, and detected by EV vehicleStatus VehicleStatus // Status flag indicating the EV contactor status normalStopReq StopRequest // Status flag indicating the request of EV to stop charging control battOvervoltage SystemFault // Status flag indicating whether or not the vehicle battery voltage exceeds the maximum limit specified by EV battUndervoltage SystemFault // Status flag indicating whether or not the vehicle battery voltage is less than the lower limit specified by EV battCurrentDeviationErr SystemFault // Status flag indicating whether or not the output current deviates from EV requested current highBattTemperature SystemFault // Status flag indicating whether or not the temperature of vehicle battery exceeds the maximum limit battVoltageDeviationErr SystemFault // Status flag indicating whether or not the vehicle battery voltage deviates from the output voltage measured by the station date string } 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: event := &frame100{ maxBattVoltage: bytesToUint16(frame.payload[4:6]), chargingRateInd: frame.payload[6], date: frame.date, } events <- event case CAN_ID_101: event := &frame101{ batteryCapacity: 0.1 * float32(bytesToUint16(frame.payload[5:7])), maxChargingTimeS: 10 * uint16(frame.payload[1]), maxChargingTimeM: frame.payload[2], estChargingTimeM: frame.payload[3], date: frame.date, } fmt.Println(event) //events <- event case CAN_ID_102: event := &frame102{ controlProtocolNumber: frame.payload[0], targetBatteryVoltage: bytesToUint16(frame.payload[1:3]), chargingCurrentReq: frame.payload[3], chargingRate: frame.payload[6], vehicleCharging: getVehicleCharging(&frame.payload), shiftLever: getVehicleShiftLever(&frame.payload), chargingSystemFault: getFault(&frame.payload, 5, 2), vehicleStatus: getVehicleStatus(&frame.payload), normalStopReq: getNormalStopReq(&frame.payload), battOvervoltage: getFault(&frame.payload, 4, 0), battUndervoltage: getFault(&frame.payload, 4, 1), battCurrentDeviationErr: getFault(&frame.payload, 4, 2), highBattTemperature: getFault(&frame.payload, 4, 3), battVoltageDeviationErr: getFault(&frame.payload, 4, 4), } fmt.Println(event) //events <- event } } }() return events } func getVehicleShiftLever(bytes *[]byte) ShiftLever { if isBitSet((*bytes)[5], 1) { return OTHER } return PARKING } func getVehicleStatus(bytes *[]byte) VehicleStatus { 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) VehicleCharging { 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 (f frame100) GetMaxBattVoltage() uint16 { return f.maxBattVoltage } func (f frame100) GetChargingRate() uint8 { return f.chargingRateInd } func (f frame100) GetValue() interface{} { return fmt.Sprintf("%v | MaxBattVoltage = %vV, ChargingRate = %v%%", f.date, f.maxBattVoltage, f.chargingRateInd) } func (f frame101) GetValue() interface{} { return fmt.Sprintf("%v | batteryCapacity = %vkWh, maxChargingTime = %vsec, maxChargingTime = %vmin, estChargingTime = %vmin", f.date, f.batteryCapacity, f.maxChargingTimeS, f.maxChargingTimeM, f.estChargingTimeM) } func (f frame102) GetValue() interface{} { //TODO implement me return "" }