Initial commit
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
package yabl
|
||||
|
||||
import (
|
||||
can "cli-mon/can"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
const (
|
||||
CONTACTOR_MAX = 18 + 1
|
||||
CONNECTOR_MAX = 6 + 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
|
||||
UNKNOWN IsolationStateType = 0
|
||||
ONGOING IsolationStateType = 1
|
||||
PASSED IsolationStateType = 2
|
||||
WARNING IsolationStateType = 3
|
||||
FAILED IsolationStateType = 4
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 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
|
||||
|
||||
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 = 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
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package yabl
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (t BooleanType) String() string {
|
||||
switch t {
|
||||
case ON:
|
||||
return "ON"
|
||||
case OFF:
|
||||
return "OFF"
|
||||
default:
|
||||
panic("BooleanType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t ErrorType) String() string {
|
||||
switch t {
|
||||
case NO_ERROR:
|
||||
return "OK"
|
||||
case ERROR:
|
||||
return "ERROR"
|
||||
default:
|
||||
panic("ErrorType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t BoardReadyType) String() string {
|
||||
switch t {
|
||||
case BOARD_READY_OK:
|
||||
return "OK"
|
||||
case BOARD_READY_INFO:
|
||||
return "INFO"
|
||||
case BOARD_READY_WARNING:
|
||||
return "WARNING"
|
||||
case BOARD_READY_DEBUG:
|
||||
return "DEBUG"
|
||||
case BOARD_READY_DEP_ERROR:
|
||||
return "DEP_ERROR"
|
||||
case BOARD_READY_ERROR:
|
||||
return "ERROR"
|
||||
case BOARD_READY_CRITICAL:
|
||||
return "CRITICAL"
|
||||
default:
|
||||
panic("BoardReadyType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t ContactorInternalOtherErrorType) String() string {
|
||||
switch t {
|
||||
case OTHER_NO_ERROR:
|
||||
return "OK"
|
||||
default:
|
||||
return fmt.Sprintf("ERROR_CODE_%d", t)
|
||||
}
|
||||
}
|
||||
|
||||
func (t ContactorGroupChangedType) String() string {
|
||||
switch t {
|
||||
case NO_PENDING_CHANGES:
|
||||
return "NO_PENDING"
|
||||
case INITIALIZED_CHANGE:
|
||||
return "INITIALIZED"
|
||||
case CHANGE_IN_PROGRESS:
|
||||
return "IN_PROGRESS"
|
||||
default:
|
||||
panic("ContactorGroupChangedType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t V2GModeType) String() string {
|
||||
switch t {
|
||||
case V2G_MODE_G2V:
|
||||
return "G2V"
|
||||
case V2G_MODE_V2G:
|
||||
return "V2G"
|
||||
case V2G_MODE_INV:
|
||||
return "INV"
|
||||
default:
|
||||
panic("V2GModeType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t Voltage11BitType) String() string {
|
||||
return fmt.Sprintf("%dV", t)
|
||||
}
|
||||
|
||||
func (t Current10BitType) String() string {
|
||||
return fmt.Sprintf("%dA", t)
|
||||
}
|
||||
|
||||
func (t CpLineLevelType) String() string {
|
||||
switch t {
|
||||
case NOT_ENABLE:
|
||||
return "NOT_ENABLE"
|
||||
case TWELVE:
|
||||
return "12V_NOT_CONNECTED"
|
||||
case NINE:
|
||||
return "9V_CONNECTED"
|
||||
case SIX:
|
||||
return "6V_CHARGING"
|
||||
case THREE:
|
||||
return "3V"
|
||||
case MINUS_TWELVE:
|
||||
return "-12V"
|
||||
default:
|
||||
panic("CpLineLevelType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t IsolationStateType) String() string {
|
||||
switch t {
|
||||
case UNKNOWN:
|
||||
return "UNKNOWN"
|
||||
case ONGOING:
|
||||
return "ONGOING"
|
||||
case PASSED:
|
||||
return "PASSED"
|
||||
case WARNING:
|
||||
return "WARNING"
|
||||
case FAILED:
|
||||
return "FAILED"
|
||||
default:
|
||||
panic("IsolationStateType not defended")
|
||||
}
|
||||
}
|
||||
|
||||
func (t Voltage9BitType) String() string {
|
||||
return fmt.Sprintf("%.1fV", t)
|
||||
}
|
||||
Reference in New Issue
Block a user