From f00c7431605459745542cb1aa128354fa4f4b5fd Mon Sep 17 00:00:00 2001 From: Terekhin Alexandr Date: Sat, 5 Aug 2023 14:26:56 +0300 Subject: [PATCH] Refactoring and optimization --- cli-mon.go | 28 ++--- ui/ui.go | 113 ++++++++++++++------ yabl/init.go | 238 ++++++++++++++++++++--------------------- yabl/protocol.go | 271 ++++++++++++----------------------------------- yabl/types.go | 93 +++++++++++----- 5 files changed, 357 insertions(+), 386 deletions(-) diff --git a/cli-mon.go b/cli-mon.go index 46a6635..dd554f2 100644 --- a/cli-mon.go +++ b/cli-mon.go @@ -3,11 +3,10 @@ package main import ( "cli-mon/can" "cli-mon/ui" - "cli-mon/yabl" + yabl "cli-mon/yabl" "flag" "fmt" "os" - "reflect" ) func main() { @@ -40,20 +39,25 @@ func main() { os.Exit(0) } - var messages = yabl.StartProtocolParsing(frames) + converter := yabl.NewProtocolConverter() + + var display ui.UI if *gui { - ui.InitCliApp(messages) + display = ui.NewUI() } else { - for msg := range messages { - // val := getField(msg.Object, msg.Field) - fmt.Printf("%v %v.%v [%d] %v\n", msg.Updated.Format("Jan _2 15:04:05.000"), msg.ActionName, msg.Field, msg.UnitId, msg.Value) + display = ui.NewLog() + } + + display.Start() + + for frame := range frames { + if events, ok := converter.EventsFromFrame(frame); ok { + for _, event := range events { + display.Consume(event) + } } } -} -func getField(v yabl.Action, field yabl.FName) interface{} { - r := reflect.ValueOf(v) - f := reflect.Indirect(r).FieldByName(string(field)) - return f.Interface() + display.Stop() } diff --git a/ui/ui.go b/ui/ui.go index 95968b8..36b714e 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -2,9 +2,10 @@ package ui import ( "cli-mon/yabl" + "fmt" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" - "os" + "reflect" ) const ( @@ -17,70 +18,122 @@ type page struct { primitive tview.Primitive } -func InitCliApp(events <-chan *yabl.Event) { - var app = tview.NewApplication() - pages := tview.NewPages() +type UI interface { + Consume(event *yabl.Event) + Start() + Stop() +} + +type gui struct { + app *tview.Application + pages *tview.Pages + connPage *cTable + page2 tview.Primitive +} + +type log struct { +} + +func (g *gui) Consume(event *yabl.Event) { + switch obj := event.Object.(type) { + case *yabl.PuPresentEnergy: + g.connPage.updatePU(event.GetUnitId(), event.Field, event.Value) + case *yabl.PuPeriphery: + g.connPage.updatePU(event.GetUnitId(), event.Field, event.Value) + case *yabl.PuDebug: + g.connPage.updatePU(event.GetUnitId(), event.Field, event.Value) + case *yabl.PuErrors: + g.connPage.updatePuErrors(obj) + } + g.app.Draw() +} + +func NewUI() UI { + g := &gui{} + + g.app = tview.NewApplication() + g.pages = tview.NewPages() var active page var layout map[string]page - connectors := newConnectorsGrid() - page2 := tview.NewBox().SetBorder(true).SetTitle("Bbbbbb") + g.connPage = newConnectorsGrid() + g.page2 = tview.NewBox().SetBorder(true).SetTitle("Bbbbbb") layout = map[string]page{ connectors_page: { left: "Page2", right: "Page2", - primitive: connectors, + primitive: g.connPage, }, "Page2": { left: connectors_page, right: connectors_page, - primitive: page2, + primitive: g.page2, }, } for k, p := range layout { - pages.AddPage(k, p.primitive, true, true) + g.pages.AddPage(k, p.primitive, true, true) } - active = layout["Page1"] - pages.SwitchToPage("Page1") + active = layout[connectors_page] + g.pages.SwitchToPage(connectors_page) - app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + g.app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { switch event.Key() { case tcell.KeyRight: - pages.SwitchToPage(active.right) + g.pages.SwitchToPage(active.right) active = layout[active.right] return nil case tcell.KeyLeft: - pages.SwitchToPage(active.left) + g.pages.SwitchToPage(active.left) active = layout[active.left] return nil case tcell.KeyCtrlC: - app.Stop() + g.app.Stop() } return event }) + return g +} + +func (g *gui) Start() { go func() { - if err := app.SetRoot(pages, true).EnableMouse(true).Run(); err != nil { + if err := g.app.SetRoot(g.pages, true).EnableMouse(true).Run(); err != nil { panic(err) } - os.Exit(0) }() +} - for event := range events { - switch obj := event.Object.(type) { - case *yabl.PuPresentEnergy: - connectors.updatePU(event.UnitId, event.Field, event.Value) - case *yabl.PuPeriphery: - connectors.updatePU(event.UnitId, event.Field, event.Value) - case *yabl.PuDebug: - connectors.updatePU(event.UnitId, event.Field, event.Value) - case *yabl.PuErrors: - connectors.updatePuErrors(obj) - } - app.Draw() - } +func (g *gui) Stop() { + g.app.Stop() +} + +func NewLog() UI { + return &log{} + +} + +func (l log) Consume(event *yabl.Event) { + fmt.Printf( + "%v %v.%v [%d] %v\n", + event.Updated.Format("Jan _2 15:04:05.000"), + event.ActionName, + event.Field, + event.GetUnitId(), + event.Value) +} + +func (l log) Start() { +} + +func (l log) Stop() { +} + +func getField(v yabl.Action, field yabl.FName) interface{} { + r := reflect.ValueOf(v) + f := reflect.Indirect(r).FieldByName(string(field)) + return f.Interface() } diff --git a/yabl/init.go b/yabl/init.go index 2578857..d905740 100644 --- a/yabl/init.go +++ b/yabl/init.go @@ -2,36 +2,38 @@ package yabl import "cli-mon/can" -func initialize() { +func (c *converter) initialize() { + c.protocolMap = make(map[key]action) + for i := uint(1); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_011, i} - cpe := &CpuPresentEnergy{UnitId: 1} - cpuPresentEnergyArray[i] = cpe + cpe := &CpuPresentEnergy{unit: 1} + c.cpuPresentEnergyArray[i] = cpe fields := []*field{ {length: 2, setter: cpe.setPowerDirectionMode, name: FPowerDirectionMode}, {length: 10, setter: cpe.setPresentCurrent, name: FPresentCurrent}, {length: 11, setter: cpe.setPresentVoltage, name: FPresentVoltage}, } - protocolMap[key] = action{fields: fields, interval: 50, name: PCpuPresentEnergy, object: cpe} + c.protocolMap[key] = action{fields: fields, interval: 50, name: PCpuPresentEnergy, object: cpe} } - cpuPeripheryInstance = &CpuPeriphery{UnitId: 0} + c.cpuPeripheryInstance = &CpuPeriphery{unit: 0} fields := []*field{ - {length: 2, setter: cpuPeripheryInstance.setContactorInput, name: FContactorInput}, - {length: 2, setter: cpuPeripheryInstance.setCircuitBreakerInput, name: FCircuitBreakerInput}, - {length: 2, setter: cpuPeripheryInstance.setCircuitBreakerPowerCBInput, name: FCircuitBreakerPowerCBInput}, + {length: 2, setter: c.cpuPeripheryInstance.setContactorInput, name: FContactorInput}, + {length: 2, setter: c.cpuPeripheryInstance.setCircuitBreakerInput, name: FCircuitBreakerInput}, + {length: 2, setter: c.cpuPeripheryInstance.setCircuitBreakerPowerCBInput, name: FCircuitBreakerPowerCBInput}, } - protocolMap[key{can.CAN_ID_014, 0}] = action{ + c.protocolMap[key{can.CAN_ID_014, 0}] = action{ fields: fields, interval: 1000, name: PCpuPeriphery, - object: cpuPeripheryInstance, + object: c.cpuPeripheryInstance, } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_015, i} - ces := &CpuEnergySettings{UnitId: i} - cpuEnergySettingsArray[i] = ces + ces := &CpuEnergySettings{unit: unit(i)} + c.cpuEnergySettingsArray[i] = ces fields := []*field{ {length: 10, setter: ces.setCurrentMax, name: FCurrentMax}, {length: 11, setter: ces.setVoltageMax, name: FVoltageMax}, @@ -39,68 +41,68 @@ func initialize() { {length: 11, setter: ces.setTargetBatteryVoltage, name: FTargetBatteryVoltage}, {length: 11, setter: ces.setTargetGoalVoltage, name: FTargetGoalVoltage}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PCpuEnergySettings, object: ces} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PCpuEnergySettings, object: ces} } - cpuErrorsInstance = &CpuErrors{UnitId: 0} + c.cpuErrorsInstance = &CpuErrors{unit: 0} fields = []*field{ - {length: 3, setter: cpuErrorsInstance.setBoardReady, name: FBoardReady}, - {length: 4, setter: cpuErrorsInstance.setOtherError, name: FOtherError}, - {length: 2, setter: cpuErrorsInstance.setRedButtonHard, name: FRedButtonHard}, - {length: 2, setter: cpuErrorsInstance.setRedButtonSoft, name: FRedButtonSoft}, - {length: 2, setter: cpuErrorsInstance.setModulesGone, name: FModulesGone}, - {length: 2, setter: cpuErrorsInstance.setGridVoltageHighErr, name: FGridVoltageHighErr}, - {length: 2, setter: cpuErrorsInstance.setGridVoltageHighWarn, name: FGridVoltageHighWarn}, - {length: 2, setter: cpuErrorsInstance.setGridVoltageLowWarn, name: FGridVoltageLowWarn}, - {length: 2, setter: cpuErrorsInstance.setGridVoltageLowErr, name: FGridVoltageLowErr}, - {length: 11, setter: cpuErrorsInstance.setGridVoltageLow, name: FGridVoltageLow}, - {length: 11, setter: cpuErrorsInstance.setGridVoltageHigh, name: FGridVoltageHigh}, - {length: 2, setter: cpuErrorsInstance.setGridVoltageEmpty, name: FGridVoltageEmpty}, - {length: 2, setter: cpuErrorsInstance.setNotReadySecc, name: FNotReadySecc}, - {length: 2, setter: cpuErrorsInstance.setNotReadyPu, name: FNotReadyPu}, - {length: 2, setter: cpuErrorsInstance.setNotReadyContactors, name: FNotReadyContactors}, - {length: 2, setter: cpuErrorsInstance.setDebugConvertersEnabled, name: FDebugConvertersEnabled}, - {length: 2, setter: cpuErrorsInstance.setContactorInputError, name: FContactorInputError}, - {length: 2, setter: cpuErrorsInstance.setNotReadyPeriphery, name: FNotReadyPeriphery}, - } - protocolMap[key{can.CAN_ID_016, 0}] = action{ + {length: 3, setter: c.cpuErrorsInstance.setBoardReady, name: FBoardReady}, + {length: 4, setter: c.cpuErrorsInstance.setOtherError, name: FOtherError}, + {length: 2, setter: c.cpuErrorsInstance.setRedButtonHard, name: FRedButtonHard}, + {length: 2, setter: c.cpuErrorsInstance.setRedButtonSoft, name: FRedButtonSoft}, + {length: 2, setter: c.cpuErrorsInstance.setModulesGone, name: FModulesGone}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageHighErr, name: FGridVoltageHighErr}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageHighWarn, name: FGridVoltageHighWarn}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageLowWarn, name: FGridVoltageLowWarn}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageLowErr, name: FGridVoltageLowErr}, + {length: 11, setter: c.cpuErrorsInstance.setGridVoltageLow, name: FGridVoltageLow}, + {length: 11, setter: c.cpuErrorsInstance.setGridVoltageHigh, name: FGridVoltageHigh}, + {length: 2, setter: c.cpuErrorsInstance.setGridVoltageEmpty, name: FGridVoltageEmpty}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadySecc, name: FNotReadySecc}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadyPu, name: FNotReadyPu}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadyContactors, name: FNotReadyContactors}, + {length: 2, setter: c.cpuErrorsInstance.setDebugConvertersEnabled, name: FDebugConvertersEnabled}, + {length: 2, setter: c.cpuErrorsInstance.setContactorInputError, name: FContactorInputError}, + {length: 2, setter: c.cpuErrorsInstance.setNotReadyPeriphery, name: FNotReadyPeriphery}, + } + c.protocolMap[key{can.CAN_ID_016, 0}] = action{ fields: fields, interval: 1000, name: PCpuErrors, - object: cpuErrorsInstance, + object: c.cpuErrorsInstance, } - cpuDebugInstance = &CpuDebug{UnitId: 0} + c.cpuDebugInstance = &CpuDebug{unit: 0} fields = []*field{ - {length: 2, setter: cpuDebugInstance.setDebugModeOn, name: FDebugModeOn}, - {length: 3, setter: cpuDebugInstance.setDebugContactorInputOn, name: FDebugContactorInputOn}, - {length: 3, setter: cpuDebugInstance.setDebugCircuitBreakerOn, name: FDebugCircuitBreakerOn}, - {length: 3, setter: cpuDebugInstance.setDebugRedButtonSoftware, name: FDebugRedButtonSoftware}, + {length: 2, setter: c.cpuDebugInstance.setDebugModeOn, name: FDebugModeOn}, + {length: 3, setter: c.cpuDebugInstance.setDebugContactorInputOn, name: FDebugContactorInputOn}, + {length: 3, setter: c.cpuDebugInstance.setDebugCircuitBreakerOn, name: FDebugCircuitBreakerOn}, + {length: 3, setter: c.cpuDebugInstance.setDebugRedButtonSoftware, name: FDebugRedButtonSoftware}, } - protocolMap[key{can.CAN_ID_01A, 0}] = action{ + c.protocolMap[key{can.CAN_ID_01A, 0}] = action{ fields: fields, interval: 1000, name: PCpuDebug, - object: cpuDebugInstance, + object: c.cpuDebugInstance, } for i := uint(1); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_021, i} - ppe := &PuPresentEnergy{UnitId: i} - puPresentEnergyArray[i] = ppe + ppe := &PuPresentEnergy{unit: unit(i)} + c.puPresentEnergyArray[i] = ppe fields := []*field{ {length: 2, setter: ppe.setV2GMode, name: FV2GMode}, {length: 11, setter: ppe.setVoltageBefore, name: FVoltageBefore}, {length: 11, setter: ppe.setVoltageAfter, name: FVoltageAfter}, {length: 10, setter: ppe.setPresentCurrent, name: FPresentCurrent}, } - protocolMap[key] = action{fields: fields, interval: 50, name: PPuPresentEnergy, object: ppe} + c.protocolMap[key] = action{fields: fields, interval: 50, name: PPuPresentEnergy, object: ppe} } for i := uint(1); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_022, i} - pp := &PuPeriphery{UnitId: i} - puPeripheryArray[i] = pp + pp := &PuPeriphery{unit: unit(i)} + c.puPeripheryArray[i] = pp fields := []*field{ {length: 2, setter: pp.setConnectorInsert, name: FConnectorInsert}, {length: 2, setter: pp.setContactorOn, name: FContactorOn}, @@ -111,13 +113,13 @@ func initialize() { {length: 2, setter: pp.setPwmEnabled, name: FPwmEnabled}, {length: 9, setter: pp.setCpLineVoltage, name: FCpLineVoltage}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PPuPeriphery, object: pp} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPuPeriphery, object: pp} } for i := uint(1); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_023, i} - pe := &PuErrors{UnitId: 1} - puErrorsArray[i] = pe + pe := &PuErrors{unit: 1} + c.puErrorsArray[i] = pe fields := []*field{ {length: 3, setter: pe.setBoardReady, name: FBoardReady}, {length: 4, setter: pe.setOtherError, name: FOtherError}, @@ -136,96 +138,96 @@ func initialize() { {length: 2, setter: pe.setOutputCircuitBreakerEnabled, name: FOutputCircuitBreakerEnabled}, {length: 12, setter: pe.setOutputCircuitBreakerEnabledValue, name: FOutputCircuitBreakerEnabledValue}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PPuErrors, object: pe} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPuErrors, object: pe} } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_02A, i} - pd := &PuDebug{UnitId: i} - puDebugArray[i] = pd + pd := &PuDebug{unit: unit(i)} + c.puDebugArray[i] = pd fields = []*field{ {length: 2, setter: pd.setDebugModeOn, name: FDebugModeOn}, {length: 3, setter: pd.setDebugContactorOutputOn, name: FDebugContactorOutputOn}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PPuDebug, object: pd} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPuDebug, object: pd} } for i := uint(1); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_041, i} - ste := &SeccTargetEnergy{UnitId: i} - seccTargetEnergyArray[i] = ste + ste := &SeccTargetEnergy{unit: unit(i)} + c.seccTargetEnergyArray[i] = ste fields = []*field{ {length: 2, setter: ste.setTargetChargingAllow, name: FTargetChargingAllow}, {length: 11, setter: ste.setTargetBatteryVoltage, name: FTargetBatteryVoltage}, {length: 11, setter: ste.setTargetGoalVoltage, name: FTargetGoalVoltage}, {length: 10, setter: ste.setTargetCurrent, name: FTargetCurrent}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PSeccTargetEnergy, object: ste} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PSeccTargetEnergy, object: ste} } for i := uint(1); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_042, i} - se := &SeccErrors{UnitId: i} - seccErrorsArray[i] = se + se := &SeccErrors{unit: unit(i)} + c.seccErrorsArray[i] = se fields = []*field{ {length: 3, setter: se.setBoardReady, name: FBoardReady}, {length: 2, setter: se.setNotReadyLogic, name: FNotReadyLogic}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PSeccErrors, object: se} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PSeccErrors, object: se} } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_046, i} - la := &LogicAuth{UnitId: i} - logicAuthArray[i] = la + la := &LogicAuth{unit: unit(i)} + c.logicAuthArray[i] = la fields = []*field{ {length: 2, setter: la.setAuthMode, name: FAuthMode}, {length: 3, setter: la.setAuthState, name: FAuthState}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PLogicAuth, object: la} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PLogicAuth, object: la} } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_047, i} - lem := &LogicEnergyMode{UnitId: i} - logicEnergyMode[i] = lem + lem := &LogicEnergyMode{unit: unit(i)} + c.logicEnergyMode[i] = lem fields = []*field{ {length: 2, setter: lem.setV2gMode, name: FV2gMode}, {length: 10, setter: lem.setCurrentMax, name: FCurrentMax}, {length: 11, setter: lem.setVoltageMax, name: FVoltageMax}, {length: 14, setter: lem.setPowerMax, name: FPowerMax}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PLogicEnergyMode, object: lem} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PLogicEnergyMode, object: lem} } - logicErrorsInstance = &LogicErrors{UnitId: 0} + c.logicErrorsInstance = &LogicErrors{unit: 0} fields = []*field{ - {length: 3, setter: logicErrorsInstance.setBoardReady, name: FBoardReady}, - {length: 2, setter: logicErrorsInstance.setNotReadySettings, name: FNotReadySettings}, + {length: 3, setter: c.logicErrorsInstance.setBoardReady, name: FBoardReady}, + {length: 2, setter: c.logicErrorsInstance.setNotReadySettings, name: FNotReadySettings}, } - protocolMap[key{can.CAN_ID_048, 0}] = action{ + c.protocolMap[key{can.CAN_ID_048, 0}] = action{ fields: fields, interval: 1000, name: PLogicErrors, - object: logicErrorsInstance, + object: c.logicErrorsInstance, } - logicWorkingMode = &LogicWorkingMode{UnitId: 0} + c.logicWorkingMode = &LogicWorkingMode{unit: 0} fields = []*field{ - {length: 5, setter: logicWorkingMode.setTargetContactorMode, name: FTargetContactorMode}, - {length: 2, setter: logicWorkingMode.setAvailability, name: FAvailability}, + {length: 5, setter: c.logicWorkingMode.setTargetContactorMode, name: FTargetContactorMode}, + {length: 2, setter: c.logicWorkingMode.setAvailability, name: FAvailability}, } - protocolMap[key{can.CAN_ID_049, 0}] = action{ + c.protocolMap[key{can.CAN_ID_049, 0}] = action{ fields: fields, interval: 1000, name: PLogicWorkingMode, - object: logicWorkingMode, + object: c.logicWorkingMode, } for i := uint(0); i < CONTACTOR_MAX; i++ { key := key{can.CAN_ID_071, i} - cis := &ContactorInternalState{UnitId: i} - contactorInternalStateArray[i] = cis + cis := &ContactorInternalState{unit: unit(i)} + c.contactorInternalStateArray[i] = cis fields = []*field{ {length: 3, setter: cis.setContactorReady, name: FContactorReady}, {length: 2, setter: cis.setContactorOn, name: FContactorOn}, @@ -233,54 +235,54 @@ func initialize() { {length: 2, setter: cis.setIsolated, name: FIsolated}, {length: 2, setter: cis.setDebugEnabled, name: FDebugEnabled}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PContactorInternalState, object: cis} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PContactorInternalState, object: cis} } - contactorInternalErrorsInstance = &ContactorInternalErrors{UnitId: 0} + c.contactorInternalErrorsInstance = &ContactorInternalErrors{unit: 0} fields = []*field{ - {length: 3, setter: contactorInternalErrorsInstance.setBoardReady, name: FBoardReady}, - {length: 4, setter: contactorInternalErrorsInstance.setOtherError, name: FOtherError}, - {length: 3, setter: contactorInternalErrorsInstance.setContactorGroupChanged, name: FContactorGroupChanged}, - {length: 4, setter: contactorInternalErrorsInstance.setUnexpectedFormation, name: FUnexpectedFormation}, - {length: 2, setter: contactorInternalErrorsInstance.setCpuNotReady, name: FCpuNotReady}, - {length: 2, setter: contactorInternalErrorsInstance.setPuNotReady, name: FPuNotReady}, - {length: 2, setter: contactorInternalErrorsInstance.setDebug, name: FDebug}, - {length: 5, setter: contactorInternalErrorsInstance.setPresentContactorMode, name: FPresentContactorMode}, - } - protocolMap[key{can.CAN_ID_073, 0}] = action{ + {length: 3, setter: c.contactorInternalErrorsInstance.setBoardReady, name: FBoardReady}, + {length: 4, setter: c.contactorInternalErrorsInstance.setOtherError, name: FOtherError}, + {length: 3, setter: c.contactorInternalErrorsInstance.setContactorGroupChanged, name: FContactorGroupChanged}, + {length: 4, setter: c.contactorInternalErrorsInstance.setUnexpectedFormation, name: FUnexpectedFormation}, + {length: 2, setter: c.contactorInternalErrorsInstance.setCpuNotReady, name: FCpuNotReady}, + {length: 2, setter: c.contactorInternalErrorsInstance.setPuNotReady, name: FPuNotReady}, + {length: 2, setter: c.contactorInternalErrorsInstance.setDebug, name: FDebug}, + {length: 5, setter: c.contactorInternalErrorsInstance.setPresentContactorMode, name: FPresentContactorMode}, + } + c.protocolMap[key{can.CAN_ID_073, 0}] = action{ fields: fields, interval: 1000, name: PContactorInternalErrors, - object: contactorInternalErrorsInstance, + object: c.contactorInternalErrorsInstance, } - contactorsInternalForce = &ContactorsInternalForce{UnitId: 0} + c.contactorsInternalForce = &ContactorsInternalForce{unit: 0} fields = []*field{ - {length: 2, setter: contactorsInternalForce.setForceModeEnabled, name: FForceModeEnabled}, - {length: 4, setter: contactorsInternalForce.setForceModeValue, name: FForceModeValue}, + {length: 2, setter: c.contactorsInternalForce.setForceModeEnabled, name: FForceModeEnabled}, + {length: 4, setter: c.contactorsInternalForce.setForceModeValue, name: FForceModeValue}, } - protocolMap[key{can.CAN_ID_074, 0}] = action{ + c.protocolMap[key{can.CAN_ID_074, 0}] = action{ fields: fields, interval: 1000, name: PContactorsInternalForce, - object: contactorsInternalForce, + object: c.contactorsInternalForce, } for i := uint(0); i < CONTACTOR_MAX; i++ { key := key{can.CAN_ID_075, i} - cid := &ContactorInternalDebug{UnitId: i} - contactorInternalDebugArray[i] = cid + cid := &ContactorInternalDebug{unit: unit(i)} + c.contactorInternalDebugArray[i] = cid fields = []*field{ {length: 2, setter: cid.setDebugModeOn, name: FDebugModeOn}, {length: 3, setter: cid.setDebugContactorOn, name: FDebugContactorOn}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PContactorInternalDebug, object: cid} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PContactorInternalDebug, object: cid} } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_067, i} - ps := &PeripheryState{UnitId: i} - peripheryStateArray[i] = ps + ps := &PeripheryState{unit: unit(i)} + c.peripheryStateArray[i] = ps fields = []*field{ {length: 3, setter: ps.setOtherErrorSeverity, name: FOtherErrorSeverity}, {length: 4, setter: ps.setOtherError, name: FOtherError}, @@ -305,13 +307,13 @@ func initialize() { {length: 2, setter: ps.setErrorContactorsInternalCircuitBreaker, name: FErrorContactorsInternalCircuitBreaker}, {length: 2, setter: ps.setErrorPlcCircuitBreaker, name: FErrorPlcCircuitBreaker}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PPeripheryState, object: ps} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPeripheryState, object: ps} } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_068, i} - pi := &PeripheryInfo{UnitId: i} - peripheryInfoArray[i] = pi + pi := &PeripheryInfo{unit: unit(i)} + c.peripheryInfoArray[i] = pi fields = []*field{ {length: 2, setter: pi.setInfoDoorOpen, name: FInfoDoorOpen}, {length: 8, setter: pi.setTempAirIn, name: FTempAirIn}, @@ -319,39 +321,39 @@ func initialize() { {length: 2, setter: pi.setStateShsnFan, name: FStateShsnFan}, {length: 2, setter: pi.setStateShptFan, name: FStateShptFan}, } - protocolMap[key] = action{fields: fields, interval: 5000, name: PPeripheryInfo, object: pi} + c.protocolMap[key] = action{fields: fields, interval: 5000, name: PPeripheryInfo, object: pi} } for i := uint(0); i <= CONNECTOR_COUNT; i++ { key := key{can.CAN_ID_06C, i} - pd := &PeripheryDebug{UnitId: i} - peripheryDebugArray[i] = pd + pd := &PeripheryDebug{unit: unit(i)} + c.peripheryDebugArray[i] = pd fields = []*field{ {length: 2, setter: pd.setDebugModeOn, name: FDebugModeOn}, {length: 3, setter: pd.setDebugShsnFan, name: FDebugShsnFan}, {length: 3, setter: pd.setDebugShptFan, name: FDebugShptFan}, {length: 3, setter: pd.setDebugIoBoardTestLamp, name: FDebugIoBoardTestLamp}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PPeripheryDebug, object: pd} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PPeripheryDebug, object: pd} } for i := uint(1); i < CONVERTERS_MAX; i++ { key := key{can.CAN_ID_061, i} - cpe := &ConverterPresentEnergy{UnitId: i} - converterPresentEnergyArray[i] = cpe + cpe := &ConverterPresentEnergy{unit: unit(i)} + c.converterPresentEnergyArray[i] = cpe fields = []*field{ {length: 2, setter: cpe.setV2gMode, name: FV2gMode}, {length: 11, setter: cpe.setPresentVoltage, name: FPresentVoltage}, {length: 10, setter: cpe.setPresentCurrent, name: FPresentCurrent}, {length: 8, setter: cpe.setConnectedOut, name: FConnectedOut}, } - protocolMap[key] = action{fields: fields, interval: 500, name: PConverterPresentEnergy, object: cpe} + c.protocolMap[key] = action{fields: fields, interval: 500, name: PConverterPresentEnergy, object: cpe} } for i := uint(1); i < CONVERTERS_MAX; i++ { key := key{can.CAN_ID_062, i} - ce := &ConverterErrors{UnitId: i} - converterErrorsArray[i] = ce + ce := &ConverterErrors{unit: unit(i)} + c.converterErrorsArray[i] = ce fields = []*field{ {length: 3, setter: ce.setBoardReady, name: FBoardReady}, {length: 4, setter: ce.setOtherError, name: FOtherError}, @@ -371,24 +373,24 @@ func initialize() { {length: 2, setter: ce.setDebugConvEnabled, name: FDebugConvEnabled}, {length: 2, setter: ce.setDebugConvDisabled, name: FDebugConvDisabled}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PConverterErrors, object: ce} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PConverterErrors, object: ce} } for i := uint(0); i < CONVERTERS_MAX; i++ { key := key{can.CAN_ID_065, i} - cd := &ConverterDebug{UnitId: i} - converterDebugArray[i] = cd + cd := &ConverterDebug{unit: unit(i)} + c.converterDebugArray[i] = cd fields = []*field{ {length: 2, setter: cd.setDebugModeOn, name: FDebugModeOn}, {length: 3, setter: cd.setDebugEnergyOn, name: FDebugEnergyOn}, {length: 11, setter: cd.setDebugTargetVoltage, name: FDebugTargetVoltage}, {length: 10, setter: cd.setDebugTargetCurrent, name: FDebugTargetCurrent}, } - protocolMap[key] = action{fields: fields, interval: 1000, name: PConverterDebug, object: cd} + c.protocolMap[key] = action{fields: fields, interval: 1000, name: PConverterDebug, object: cd} } // set "null" values - for _, element := range protocolMap { + for _, element := range c.protocolMap { var from uint8 = 0 for _, f := range element.fields { var mask uint64 = ^(ALL_BITS << f.length) diff --git a/yabl/protocol.go b/yabl/protocol.go index 310e4b2..428c719 100644 --- a/yabl/protocol.go +++ b/yabl/protocol.go @@ -6,44 +6,6 @@ import ( time "time" ) -type Action interface { - GetUnitId() uint -} - -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 AName string -type FName string - -type Event struct { - UnitId uint - ActionName AName - Field FName - Object Action - Updated *time.Time - Value any -} - type action struct { object Action fields []*field @@ -64,75 +26,78 @@ type key struct { unitId uint } -var protocolMap map[key]action = make(map[key]action) -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 [CONTACTOR_MAX]*ContactorInternalState -var contactorInternalErrorsInstance *ContactorInternalErrors -var contactorsInternalForce *ContactorsInternalForce -var contactorInternalDebugArray [CONTACTOR_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 StartProtocolParsing(frames <-chan *can.CanFrame) <-chan *Event { - result := make(chan *Event) - initialize() - - go func() { - defer close(result) - - for frame := range frames { - if frames == nil { - continue - } - - var unitId = uint((frame.CanId & UNIT_ID_MASK) >> UNIT_ID_OFFSET) - var canId = frame.CanId & ACTION_ID_MASK - var k = key{canId: canId, unitId: unitId} - - param := protocolMap[k] - - var start uint8 = 0 - for _, f := range param.fields { - if val, found := get(start, f.length, frame.Payload); found { - f.last = frame.Date - if f.value != val { - f.value = val - obj := f.setter(val) - result <- &Event{ - Field: f.name, - ActionName: param.name, - Object: param.object, - UnitId: unitId, - Updated: frame.Date, - Value: obj, - } +type converter struct { + protocolMap map[key]action + cpuPresentEnergyArray [CONNECTOR_MAX]*CpuPresentEnergy + cpuPeripheryInstance *CpuPeriphery + cpuEnergySettingsArray [CONNECTOR_MAX]*CpuEnergySettings + cpuErrorsInstance *CpuErrors + cpuDebugInstance *CpuDebug + puPresentEnergyArray [CONNECTOR_MAX]*PuPresentEnergy + puPeripheryArray [CONNECTOR_MAX]*PuPeriphery + puErrorsArray [CONNECTOR_MAX]*PuErrors + puDebugArray [CONNECTOR_MAX]*PuDebug + seccTargetEnergyArray [CONNECTOR_MAX]*SeccTargetEnergy + seccErrorsArray [CONNECTOR_MAX]*SeccErrors + logicAuthArray [CONNECTOR_MAX]*LogicAuth + logicEnergyMode [CONNECTOR_MAX]*LogicEnergyMode + logicErrorsInstance *LogicErrors + logicWorkingMode *LogicWorkingMode + contactorInternalStateArray [CONTACTOR_MAX]*ContactorInternalState + contactorInternalErrorsInstance *ContactorInternalErrors + contactorsInternalForce *ContactorsInternalForce + contactorInternalDebugArray [CONTACTOR_MAX]*ContactorInternalDebug + peripheryStateArray [CONNECTOR_MAX]*PeripheryState + peripheryInfoArray [CONNECTOR_MAX]*PeripheryInfo + peripheryDebugArray [CONNECTOR_MAX]*PeripheryDebug + converterPresentEnergyArray [CONVERTERS_MAX]*ConverterPresentEnergy + converterErrorsArray [CONVERTERS_MAX]*ConverterErrors + converterDebugArray [CONVERTERS_MAX]*ConverterDebug +} + +type Converter interface { + EventsFromFrame(*can.CanFrame) ([]*Event, bool) +} + +func NewProtocolConverter() Converter { + c := &converter{} + c.initialize() + return c +} + +func (c *converter) EventsFromFrame(frame *can.CanFrame) ([]*Event, bool) { + var unitId = uint((frame.CanId & UNIT_ID_MASK) >> UNIT_ID_OFFSET) + var canId = frame.CanId & ACTION_ID_MASK + var k = key{canId: canId, unitId: unitId} + + if param, ok := c.protocolMap[k]; ok { + result := make([]*Event, 0, len(param.fields)) + + var start uint8 = 0 + for _, f := range param.fields { + if val, found := get(start, f.length, frame.Payload); found { + f.last = frame.Date + if f.value != val { // value changed + f.value = val + obj := f.setter(val) + + event := &Event{ + Field: f.name, + ActionName: param.name, + Object: param.object, + unit: unit(unitId), + Updated: frame.Date, + Value: obj, } + + result = append(result, event) } - start += f.length } - + start += f.length // next field } - }() - - return result + return result, len(result) > 0 + } + return nil, false } func get(from uint8, size uint8, buffer []byte) (uint64, bool) { @@ -149,102 +114,6 @@ func get(from uint8, size uint8, buffer []byte) (uint64, bool) { } } -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 +func (u unit) GetUnitId() uint { + return uint(u) } diff --git a/yabl/types.go b/yabl/types.go index 9e7e07f..a193625 100644 --- a/yabl/types.go +++ b/yabl/types.go @@ -1,7 +1,50 @@ package yabl +import "time" + +type AName string +type FName string + +type unit uint + +type Action interface { + GetUnitId() uint +} + +type Event struct { + unit + ActionName AName + Field FName + Object Action + Updated *time.Time + Value any +} + +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 ContactorInternalState struct { - UnitId uint + unit + //UnitId uint ContactorReady *BoardReadyType ContactorOn *BooleanType UnexpectedState *ErrorType @@ -10,7 +53,7 @@ type ContactorInternalState struct { } type ContactorInternalErrors struct { - UnitId uint + unit BoardReady *BoardReadyType OtherError *ContactorInternalOtherErrorType ContactorGroupChanged *ContactorGroupChangedType @@ -22,19 +65,19 @@ type ContactorInternalErrors struct { } type ContactorsInternalForce struct { - UnitId uint + unit ForceModeEnabled *BooleanType ForceModeValue *ForceModeType } type ContactorInternalDebug struct { - UnitId uint + unit DebugModeOn *BooleanType DebugContactorOn *DebugSwitchModeType } type PuPresentEnergy struct { - UnitId uint + unit V2GMode *V2GModeType VoltageBefore *Voltage11BitType VoltageAfter *Voltage11BitType @@ -42,7 +85,7 @@ type PuPresentEnergy struct { } type PuPeriphery struct { - UnitId uint + unit ConnectorInsert *BooleanType ContactorOn *BooleanType ConnectorLocked *BooleanType @@ -54,13 +97,13 @@ type PuPeriphery struct { } type LogicAuth struct { - UnitId uint + unit AuthMode *AuthModeType AuthState *AuthStateType } type LogicEnergyMode struct { - UnitId uint + unit V2gMode *V2GModeType CurrentMax *Current10BitType VoltageMax *Voltage11BitType @@ -68,33 +111,33 @@ type LogicEnergyMode struct { } type LogicErrors struct { - UnitId uint + unit BoardReady *BoardReadyType NotReadySettings *ErrorType } type LogicWorkingMode struct { - UnitId uint + unit TargetContactorMode *ContactorModeType Availability *BooleanType } type CpuPresentEnergy struct { - UnitId uint + unit PowerDirectionMode *V2GModeType PresentCurrent *Current10BitType PresentVoltage *Voltage11BitType } type CpuPeriphery struct { - UnitId uint + unit ContactorInput *BooleanType CircuitBreakerInput *BooleanType CircuitBreakerPowerCBInput *BooleanType } type CpuEnergySettings struct { - UnitId uint + unit CurrentMax *Current10BitType VoltageMax *Voltage11BitType PowerMax *Power14BitType @@ -103,7 +146,7 @@ type CpuEnergySettings struct { } type CpuErrors struct { - UnitId uint + unit BoardReady *BoardReadyType OtherError *OtherError4BitType RedButtonHard *ErrorType @@ -125,7 +168,7 @@ type CpuErrors struct { } type CpuDebug struct { - UnitId uint + unit DebugModeOn *BooleanType DebugContactorInputOn *DebugSwitchModeType DebugCircuitBreakerOn *DebugSwitchModeType @@ -133,7 +176,7 @@ type CpuDebug struct { } type PuErrors struct { - UnitId uint + unit BoardReady *BoardReadyType OtherError *OtherError4BitType IncorrectVoltage *ErrorType @@ -153,13 +196,13 @@ type PuErrors struct { } type PuDebug struct { - UnitId uint + unit DebugModeOn *BooleanType DebugContactorOutputOn *DebugSwitchModeType } type SeccTargetEnergy struct { - UnitId uint + unit TargetChargingAllow *BooleanType TargetBatteryVoltage *Voltage11BitType TargetGoalVoltage *Voltage11BitType @@ -167,13 +210,13 @@ type SeccTargetEnergy struct { } type SeccErrors struct { - UnitId uint + unit BoardReady *BoardReadyType NotReadyLogic *ErrorType } type PeripheryState struct { - UnitId uint + unit OtherErrorSeverity *BoardReadyType OtherError *OtherError4BitType ErrorShakeSensor *ErrorType @@ -199,7 +242,7 @@ type PeripheryState struct { } type PeripheryInfo struct { - UnitId uint + unit InfoDoorOpen *BooleanType TempAirIn *SignedAirTemp8BitType TempAirOut *SignedAirTemp8BitType @@ -208,7 +251,7 @@ type PeripheryInfo struct { } type PeripheryDebug struct { - UnitId uint + unit DebugModeOn *BooleanType DebugShsnFan *DebugSwitchModeType DebugShptFan *DebugSwitchModeType @@ -216,7 +259,7 @@ type PeripheryDebug struct { } type ConverterPresentEnergy struct { - UnitId uint + unit V2gMode *V2GModeType PresentVoltage *Voltage11BitType PresentCurrent *Current10BitType @@ -224,7 +267,7 @@ type ConverterPresentEnergy struct { } type ConverterErrors struct { - UnitId uint + unit BoardReady *BoardReadyType OtherError *OtherError4BitType NotConnectedOut *ErrorType @@ -245,7 +288,7 @@ type ConverterErrors struct { } type ConverterDebug struct { - UnitId uint + unit DebugModeOn *BooleanType DebugEnergyOn *DebugSwitchModeType DebugTargetVoltage *Voltage11BitType