Simple app to transform IEC 61851-24 CAN bus dump to human readable messages.
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.
chademo-log/chademo.go

334 lines
8.2 KiB

package main
import (
"fmt"
)
const (
CAN_ID_100 = 100
CAN_ID_101 = 101
CAN_ID_102 = 102
DISABLED VehicleChargingEnabled = iota
ENABLED
PARKING ShiftLeverPosition = iota
OTHER
NORMAL SystemFault = iota
FAULT
CONTACTOR_CLOSED ContactorVehicleStatus = iota
CONTACTOR_OPEN
NO_REQUEST StopRequest = iota
STOP_REQUEST
)
type VehicleChargingEnabled uint8
type ShiftLeverPosition uint8
type SystemFault uint8
type ContactorVehicleStatus uint8
type StopRequest uint8
type ChademoEvent interface {
// GetValue Return processed/calculated value and timestamp string
GetValue() (interface{}, *string)
}
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
// ControlProtocolNumber Software version of control protocol to which EV corresponds
type ControlProtocolNumber 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
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 <- &ControlProtocolNumber{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}
}
}
}()
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 (m MaximumBatteryVoltage) GetValue() (interface{}, *string) {
return bytesToUint16(m.payload[4:6]), &m.date
}
func (c ConstChargingRateInd) GetValue() (interface{}, *string) {
return c.payload[6], &c.date
}
func (b BatteryCapacity) GetValue() (interface{}, *string) {
return 0.1 * float32(bytesToUint16(b.payload[5:7])), &b.date
}
func (m MaxChargingTimeS) GetValue() (interface{}, *string) {
return 10 * uint16(m.payload[1]), &m.date
}
func (m MaxChargingTimeM) GetValue() (interface{}, *string) {
return m.payload[2], &m.date
}
func (e EstChargingTimeM) GetValue() (interface{}, *string) {
return e.payload[3], &e.date
}
func (c ControlProtocolNumber) GetValue() (interface{}, *string) {
return c.payload[0], &c.date
}
func (t TargetBatteryVoltage) GetValue() (interface{}, *string) {
return bytesToUint16(t.payload[1:3]), &t.date
}
func (c ChargingCurrentReq) GetValue() (interface{}, *string) {
return c.payload[3], &c.date
}
func (c ChargingRate) GetValue() (interface{}, *string) {
return c.payload[6], &c.date
}
func (s ShiftLever) GetValue() (interface{}, *string) {
return getVehicleShiftLever(&s.payload), &s.date
}
func (v VehicleCharging) GetValue() (interface{}, *string) {
return getVehicleCharging(&v.payload), &v.date
}
func (c ChargingSystemFault) GetValue() (interface{}, *string) {
return getFault(&c.payload, 5, 2), &c.date
}
func (v VehicleStatus) GetValue() (interface{}, *string) {
return getVehicleStatus(&v.payload), &v.date
}
func (n NormalStopReq) GetValue() (interface{}, *string) {
return getNormalStopReq(&n.payload), &n.date
}
func (b BattOvervoltage) GetValue() (interface{}, *string) {
return getFault(&b.payload, 4, 0), &b.date
}
func (b BattUndervoltage) GetValue() (interface{}, *string) {
return getFault(&b.payload, 4, 1), &b.date
}
func (b BattCurrentDeviationErr) GetValue() (interface{}, *string) {
return getFault(&b.payload, 4, 2), &b.date
}
func (h HighBattTemperature) GetValue() (interface{}, *string) {
return getFault(&h.payload, 4, 3), &h.date
}
func (b BattVoltageDeviationErr) GetValue() (interface{}, *string) {
return getFault(&b.payload, 4, 4), &b.date
}
func (v VehicleChargingEnabled) String() string {
switch v {
case DISABLED:
return "disabled"
case ENABLED:
return "enabled"
default:
panic("VehicleChargingEnabled not implemented")
}
}
func (s ShiftLeverPosition) String() string {
switch s {
case PARKING:
return "parking"
case OTHER:
return "other"
default:
panic("ShiftLeverPosition not implemented")
}
}
func (s SystemFault) String() string {
switch s {
case NORMAL:
return "normal"
case FAULT:
return "fault"
default:
panic("SystemFault not implemented")
}
}
func (c ContactorVehicleStatus) String() string {
switch c {
case CONTACTOR_CLOSED:
return "contactor closed"
case CONTACTOR_OPEN:
return "contactor open"
default:
panic("ContactorVehicleStatus not implemented")
}
}
func (s StopRequest) String() string {
switch s {
case NO_REQUEST:
return "no request"
case STOP_REQUEST:
return "stop request"
default:
panic("StopRequest not implemented")
}
}