diff --git a/cli-mon.go b/cli-mon.go index dd554f2..26f433e 100644 --- a/cli-mon.go +++ b/cli-mon.go @@ -3,10 +3,11 @@ package main import ( "cli-mon/can" "cli-mon/ui" - yabl "cli-mon/yabl" + "cli-mon/yabl" "flag" "fmt" "os" + "time" ) func main() { @@ -51,12 +52,33 @@ func main() { display.Start() - for frame := range frames { - if events, ok := converter.EventsFromFrame(frame); ok { + updates := make(chan *yabl.Event) + + var f func() + f = func() { + if events, ok := converter.CheckTimeouts(); ok { for _, event := range events { - display.Consume(event) + updates <- event } } + time.AfterFunc(50*time.Millisecond, f) + } + + time.AfterFunc(5*time.Second, f) + + go func() { + for frame := range frames { + if events, ok := converter.EventsFromFrame(frame); ok { + for _, event := range events { + updates <- event + } + } + } + close(updates) + }() + + for event := range updates { + display.Consume(event) } display.Stop() diff --git a/ui/connectors.go b/ui/connectors.go deleted file mode 100644 index 53460d1..0000000 --- a/ui/connectors.go +++ /dev/null @@ -1,140 +0,0 @@ -package ui - -import ( - "cli-mon/yabl" - "fmt" - "github.com/gdamore/tcell/v2" - "github.com/rivo/tview" -) - -const connectorCount = 6 - -type cTable struct { - tview.Table - voltageBefore [connectorCount + 1]*tview.TableCell - voltageAfter [connectorCount + 1]*tview.TableCell - presentCurrent [connectorCount + 1]*tview.TableCell - connectorInsert [connectorCount + 1]*tview.TableCell - contactorClosed [connectorCount + 1]*tview.TableCell - connectorLocked [connectorCount + 1]*tview.TableCell - cpLevel [connectorCount + 1]*tview.TableCell - isolationState [connectorCount + 1]*tview.TableCell - chargingAllowed [connectorCount + 1]*tview.TableCell - pwmEnabled [connectorCount + 1]*tview.TableCell - cpAccurate [connectorCount + 1]*tview.TableCell - debugModeOn [connectorCount + 1]*tview.TableCell - debugContactorOutOn [connectorCount + 1]*tview.TableCell - boardReady [connectorCount + 1]*tview.TableCell -} - -func (t *cTable) updatePU(id uint, field yabl.FName, value any) { - var view *tview.TableCell - - switch field { - case yabl.FVoltageBefore: - view = t.voltageBefore[id] - case yabl.FVoltageAfter: - view = t.voltageAfter[id] - case yabl.FPresentCurrent: - view = t.presentCurrent[id] - case yabl.FConnectorInsert: - view = t.connectorInsert[id] - case yabl.FContactorOn: - view = t.contactorClosed[id] - case yabl.FConnectorLocked: - view = t.connectorLocked[id] - case yabl.FCpLineLevel: - view = t.cpLevel[id] - case yabl.FIsolationState: - view = t.isolationState[id] - case yabl.FChargingAllowed: - view = t.chargingAllowed[id] - case yabl.FPwmEnabled: - view = t.pwmEnabled[id] - case yabl.FCpLineVoltage: - view = t.cpAccurate[id] - case yabl.FDebugModeOn: - view = t.debugModeOn[id] - case yabl.FDebugContactorOutputOn: - view = t.debugContactorOutOn[id] - } - - if view != nil { - view.SetText(fmt.Sprintf("%v", value)) - } -} - -func (t *cTable) updatePuErrors(obj *yabl.PuErrors) { - id := obj.GetUnitId() - ready := t.boardReady[id] - ready.SetText(fmt.Sprintf("%v", obj.BoardReady)) - - if *obj.BoardReady != yabl.BOARD_READY_OK { - ready.SetBackgroundColor(tcell.ColorDarkRed) - } else { - ready.SetBackgroundColor(tcell.ColorDefault) - } -} - -func newConnectorsGrid() *cTable { - t := &cTable{} - t.Box = tview.NewBox() - t.SetBorderColor(tview.Styles.GraphicsColor) - t.SetSeparator(' ') - t.SetContent(nil) - t.SetTitle("Connectors") - t.SetBorders(true) - t.SetBorder(true) - - t.SetCell(1, 0, tview.NewTableCell("voltageBefore")) - t.SetCell(2, 0, tview.NewTableCell("voltageAfter")) - t.SetCell(3, 0, tview.NewTableCell("presentCurrent")) - t.SetCell(4, 0, tview.NewTableCell("connectorInsert")) - t.SetCell(5, 0, tview.NewTableCell("contactorClosed")) - t.SetCell(6, 0, tview.NewTableCell("connectorLocked")) - t.SetCell(7, 0, tview.NewTableCell("cpLevel")) - t.SetCell(8, 0, tview.NewTableCell("isolationState")) - t.SetCell(9, 0, tview.NewTableCell("chargingAllowed")) - t.SetCell(10, 0, tview.NewTableCell("pwmEnabled")) - t.SetCell(11, 0, tview.NewTableCell("cpAccurate")) - t.SetCell(12, 0, tview.NewTableCell("debugModeOn")) - t.SetCell(13, 0, tview.NewTableCell("debugContactorOutOn")) - t.SetCell(14, 0, tview.NewTableCell("boardReady")) - - for i := 1; i <= 6; i++ { - t.SetCell(0, i, tview.NewTableCell(fmt.Sprintf("Connector %d", i)).SetExpansion(2)) - - t.voltageBefore[i] = tview.NewTableCell("") - t.voltageAfter[i] = tview.NewTableCell("") - t.presentCurrent[i] = tview.NewTableCell("") - t.connectorInsert[i] = tview.NewTableCell("") - t.contactorClosed[i] = tview.NewTableCell("") - t.connectorLocked[i] = tview.NewTableCell("") - t.cpLevel[i] = tview.NewTableCell("") - t.isolationState[i] = tview.NewTableCell("") - t.chargingAllowed[i] = tview.NewTableCell("") - t.pwmEnabled[i] = tview.NewTableCell("") - t.cpAccurate[i] = tview.NewTableCell("") - t.debugModeOn[i] = tview.NewTableCell("") - t.debugContactorOutOn[i] = tview.NewTableCell("") - t.boardReady[i] = tview.NewTableCell("") - - t.SetCell(1, i, t.voltageBefore[i]) - t.SetCell(2, i, t.voltageAfter[i]) - t.SetCell(3, i, t.presentCurrent[i]) - t.SetCell(4, i, t.connectorInsert[i]) - t.SetCell(5, i, t.contactorClosed[i]) - t.SetCell(6, i, t.connectorLocked[i]) - t.SetCell(7, i, t.cpLevel[i]) - t.SetCell(8, i, t.isolationState[i]) - t.SetCell(9, i, t.chargingAllowed[i]) - t.SetCell(10, i, t.pwmEnabled[i]) - t.SetCell(11, i, t.cpAccurate[i]) - t.SetCell(12, i, t.debugModeOn[i]) - t.SetCell(13, i, t.debugContactorOutOn[i]) - t.SetCell(14, i, t.boardReady[i]) - - } - - return t -} diff --git a/ui/parameters.go b/ui/parameters.go new file mode 100644 index 0000000..4bf225d --- /dev/null +++ b/ui/parameters.go @@ -0,0 +1,174 @@ +package ui + +import "cli-mon/yabl" + +var pu = []key{ + {yabl.PPuPresentEnergy, yabl.FVoltageBefore, 1}, + {yabl.PPuPresentEnergy, yabl.FVoltageAfter, 2}, + {yabl.PCpuPresentEnergy, yabl.FPresentVoltage, 3}, + {yabl.PPuPresentEnergy, yabl.FPresentCurrent, 4}, + {yabl.PCpuPresentEnergy, yabl.FPresentCurrent, 5}, + {yabl.PPuPeriphery, yabl.FConnectorInsert, 6}, + {yabl.PPuPeriphery, yabl.FDebugContactorOn, 7}, + {yabl.PPuPeriphery, yabl.FConnectorLocked, 8}, + {yabl.PPuPeriphery, yabl.FCpLineLevel, 9}, + {yabl.PPuPeriphery, yabl.FIsolationState, 10}, + {yabl.PPuPeriphery, yabl.FChargingAllowed, 11}, + {yabl.PPuPeriphery, yabl.FPwmEnabled, 12}, + {yabl.PPuPeriphery, yabl.FCpLineVoltage, 13}, + {yabl.PCpuEnergySettings, yabl.FTargetBatteryVoltage, 14}, + {yabl.PCpuEnergySettings, yabl.FTargetGoalVoltage, 15}, + {yabl.PCpuEnergySettings, yabl.FPowerMax, 16}, + {yabl.PCpuEnergySettings, yabl.FCurrentMax, 17}, + {yabl.PCpuEnergySettings, yabl.FVoltageMax, 18}, + {yabl.PPuDebug, yabl.FDebugModeOn, 19}, + {yabl.PPuDebug, yabl.FDebugContactorOutputOn, 20}, + {yabl.PPuErrors, yabl.FBoardReady, 21}, +} + +var pu_errors = []key{ + {yabl.PPuErrors, yabl.FBoardReady, 1}, + {yabl.PPuErrors, yabl.FOtherError, 2}, + {yabl.PPuErrors, yabl.FIncorrectVoltage, 3}, + {yabl.PPuErrors, yabl.FIncorrectVoltageValue, 4}, + {yabl.PPuErrors, yabl.FIncorrectCurrent, 5}, + {yabl.PPuErrors, yabl.FIncorrectCurrentValue, 6}, + {yabl.PPuErrors, yabl.FIsolationBroken, 7}, + {yabl.PPuErrors, yabl.FCpLineBroken, 8}, + {yabl.PPuErrors, yabl.FCpLineGap69, 9}, + {yabl.PPuErrors, yabl.FCableReady, 10}, + {yabl.PPuErrors, yabl.FNotReadyCpu, 11}, + {yabl.PPuErrors, yabl.FNotReadySecc, 12}, + {yabl.PPuErrors, yabl.FContactorOutputError, 13}, + {yabl.PPuErrors, yabl.FDebugContactorOutputEnabled, 14}, + {yabl.PPuErrors, yabl.FOutputCircuitBreakerEnabled, 15}, + {yabl.PPuDebug, yabl.FDebugModeOn, 16}, + {yabl.PPuDebug, yabl.FDebugContactorOutputOn, 17}, +} + +var contactors_errors = []key{ + {yabl.PContactorInternalErrors, yabl.FBoardReady, 1}, + {yabl.PContactorInternalErrors, yabl.FOtherError, 2}, + {yabl.PContactorInternalErrors, yabl.FContactorGroupChanged, 3}, + {yabl.PContactorInternalErrors, yabl.FUnexpectedFormation, 4}, + {yabl.PContactorInternalErrors, yabl.FCpuNotReady, 5}, + {yabl.PContactorInternalErrors, yabl.FPuNotReady, 6}, + {yabl.PContactorInternalErrors, yabl.FDebug, 7}, + {yabl.PContactorInternalErrors, yabl.FPresentContactorMode, 8}, + {yabl.PContactorsInternalForce, yabl.FForceModeEnabled, 9}, + {yabl.PContactorsInternalForce, yabl.FForceModeValue, 10}, + {yabl.PContactorInternalDebug, yabl.FDebugModeOn, 11}, +} + +var contactors_state = []key{ + {yabl.PContactorInternalState, yabl.FContactorReady, 1}, + {yabl.PContactorInternalState, yabl.FContactorOn, 2}, + {yabl.PContactorInternalState, yabl.FUnexpectedState, 3}, + {yabl.PContactorInternalState, yabl.FIsolated, 4}, + {yabl.PContactorInternalState, yabl.FDebugEnabled, 5}, + {yabl.PContactorInternalDebug, yabl.FDebugContactorOn, 6}, +} + +var periphery_state = []key{ + {yabl.PPeripheryState, yabl.FErrorShakeSensor, 1}, + {yabl.PPeripheryState, yabl.FErrorCoolingGroup, 2}, + {yabl.PPeripheryState, yabl.FOtherError, 3}, + {yabl.PPeripheryState, yabl.FDebugShptFanEnabled, 4}, + {yabl.PPeripheryState, yabl.FDebugIoBoardTestLampEnabled, 5}, + {yabl.PPeripheryInfo, yabl.FStateShptFan, 6}, + {yabl.PPeripheryDebug, yabl.FDebugShptFan, 7}, + {yabl.PPeripheryDebug, yabl.FDebugIoBoardTestLamp, 8}, +} + +var periphery_station_state = []key{ + {yabl.PPeripheryState, yabl.FOtherErrorSeverity, 1}, + {yabl.PPeripheryState, yabl.FOtherError, 2}, + {yabl.PPeripheryState, yabl.FPeripheryErrorCoolingGroup, 3}, + {yabl.PPeripheryState, yabl.FErrorFireEmergency, 4}, + {yabl.PPeripheryState, yabl.FErrorFireEmergencyRun, 5}, + {yabl.PPeripheryState, yabl.FErrorFireEmergencyControl, 6}, + {yabl.PPeripheryState, yabl.FErrorOvervoltageIn, 7}, + {yabl.PPeripheryState, yabl.FPeripheryErrorPowerSupply, 8}, + {yabl.PPeripheryState, yabl.FErrorFan, 9}, + {yabl.PPeripheryState, yabl.FErrorOvervoltageOut, 10}, + {yabl.PPeripheryState, yabl.FErrorStateRemoteMode, 11}, + {yabl.PPeripheryState, yabl.FDebugShsnFanEnabled, 12}, + {yabl.PPeripheryState, yabl.FDebugShptFanEnabled, 13}, + {yabl.PPeripheryState, yabl.FDebugIoBoardTestLampEnabled, 14}, + {yabl.PPeripheryState, yabl.FErrorFireEmergencyCircuitBreaker, 15}, + {yabl.PPeripheryState, yabl.FErrorExtLightCircuitBreaker, 16}, + {yabl.PPeripheryState, yabl.FErrorIndicationCircuitBreaker, 17}, + {yabl.PPeripheryState, yabl.FErrorLowVoltagePowerCircuitBreaker, 18}, + {yabl.PPeripheryState, yabl.FErrorContactorsInternalCircuitBreaker, 19}, + {yabl.PPeripheryState, yabl.FErrorPlcCircuitBreaker, 20}, + {yabl.PPeripheryInfo, yabl.FInfoDoorOpen, 21}, + {yabl.PPeripheryInfo, yabl.FTempAirIn, 22}, + {yabl.PPeripheryInfo, yabl.FTempAirOut, 23}, + {yabl.PPeripheryInfo, yabl.FStateShsnFan, 24}, + {yabl.PPeripheryDebug, yabl.FDebugModeOn, 25}, + {yabl.PPeripheryDebug, yabl.FDebugShsnFan, 26}, +} + +var converters = []key{ + {yabl.PConverterPresentEnergy, yabl.FPresentVoltage, 1}, + {yabl.PConverterPresentEnergy, yabl.FPresentCurrent, 2}, + {yabl.PConverterPresentEnergy, yabl.FConnectedOut, 3}, + {yabl.PConverterErrors, yabl.FBoardReady, 4}, + {yabl.PConverterErrors, yabl.FOtherError, 5}, + {yabl.PConverterErrors, yabl.FNotConnectedOut, 6}, + {yabl.PConverterErrors, yabl.FNoCommunicationConverter, 7}, + {yabl.PConverterErrors, yabl.FNoCommunicationPuConverter, 8}, + {yabl.PConverterPresentEnergy, yabl.FV2gMode, 9}, + {yabl.PConverterErrors, yabl.FDebugConvEnabled, 10}, + {yabl.PConverterErrors, yabl.FDebugConvDisabled, 11}, + {yabl.PConverterDebug, yabl.FDebugModeOn, 12}, + {yabl.PConverterDebug, yabl.FDebugEnergyOn, 13}, + {yabl.PConverterDebug, yabl.FDebugTargetVoltage, 14}, + {yabl.PConverterDebug, yabl.FDebugTargetCurrent, 15}, +} + +var converters_errors = []key{ + {yabl.PConverterErrors, yabl.FBoardReady, 1}, + {yabl.PConverterErrors, yabl.FOtherError, 2}, + {yabl.PConverterErrors, yabl.FNotConnectedOut, 3}, + {yabl.PConverterErrors, yabl.FNoCommunicationConverter, 4}, + {yabl.PConverterErrors, yabl.FNoCommunicationPuConverter, 5}, + {yabl.PConverterErrors, yabl.FInputGridVoltageHigh, 6}, + {yabl.PConverterErrors, yabl.FInputGridVoltageLow, 7}, + {yabl.PConverterErrors, yabl.FOutputGridVoltageHigh, 8}, + {yabl.PConverterErrors, yabl.FOutputGridVoltageLow, 9}, + {yabl.PConverterErrors, yabl.FInputGridVoltage, 10}, + {yabl.PConverterErrors, yabl.FOutputGridVoltage, 11}, + {yabl.PConverterErrors, yabl.FShortCircuit, 12}, + {yabl.PConverterErrors, yabl.FOverHeat, 13}, + {yabl.PConverterErrors, yabl.FFanBroken, 14}, + {yabl.PConverterErrors, yabl.FOtherHardwareError, 15}, +} + +var cpu = []key{ + {yabl.PCpuErrors, yabl.FBoardReady, 1}, + {yabl.PCpuErrors, yabl.FOtherError, 2}, + {yabl.PCpuErrors, yabl.FRedButtonHard, 3}, + {yabl.PCpuErrors, yabl.FRedButtonSoft, 4}, + {yabl.PCpuErrors, yabl.FModulesGone, 5}, + {yabl.PCpuErrors, yabl.FGridVoltageHighErr, 6}, + {yabl.PCpuErrors, yabl.FGridVoltageHighWarn, 7}, + {yabl.PCpuErrors, yabl.FGridVoltageLowWarn, 8}, + {yabl.PCpuErrors, yabl.FGridVoltageLowErr, 9}, + {yabl.PCpuErrors, yabl.FGridVoltageLow, 10}, + {yabl.PCpuErrors, yabl.FGridVoltageHigh, 11}, + {yabl.PCpuErrors, yabl.FGridVoltageEmpty, 12}, + {yabl.PCpuErrors, yabl.FNotReadySecc, 13}, + {yabl.PCpuErrors, yabl.FNotReadyPu, 14}, + {yabl.PCpuErrors, yabl.FNotReadyContactors, 15}, + {yabl.PCpuErrors, yabl.FDebugConvertersEnabled, 16}, + {yabl.PCpuErrors, yabl.FContactorInputError, 17}, + {yabl.PCpuErrors, yabl.FNotReadyPeriphery, 18}, + {yabl.PCpuPeriphery, yabl.FContactorInput, 19}, + {yabl.PCpuPeriphery, yabl.FCircuitBreakerInput, 20}, + {yabl.PCpuPeriphery, yabl.FCircuitBreakerPowerCBInput, 21}, + {yabl.PCpuDebug, yabl.FDebugModeOn, 22}, + {yabl.PCpuDebug, yabl.FDebugContactorInputOn, 23}, + {yabl.PCpuDebug, yabl.FDebugCircuitBreakerOn, 24}, + {yabl.PCpuDebug, yabl.FDebugRedButtonSoftware, 25}, +} diff --git a/ui/table.go b/ui/table.go new file mode 100644 index 0000000..8bf898a --- /dev/null +++ b/ui/table.go @@ -0,0 +1,96 @@ +package ui + +import ( + "cli-mon/yabl" + "fmt" + tview "github.com/rivo/tview" + "reflect" +) + +type table struct { + tview.Table + views map[key]*tview.TableCell + content []key +} + +type key struct { + action yabl.AName + field yabl.FName + id uint +} + +func (t *table) update(event *yabl.Event) { + if cell, ok := t.views[key{event.ActionName, event.Field, event.GetUnitId()}]; ok { + cell.SetText(fmt.Sprintf("%v", event.Value)) + } +} + +func (t *table) header(header string) *table { + t.SetTitle(header) + return t +} + +func (t *table) columns(name string, cols int) *table { + for i := 1; i <= cols; i++ { + t.SetCell(0, i, tview.NewTableCell(fmt.Sprintf("%s %d", name, i)).SetExpansion(2)) + } + return t +} + +func (t *table) rows(name string, rows int) *table { + for i := 1; i <= rows; i++ { + t.SetCell(i, 0, tview.NewTableCell(fmt.Sprintf("%s %d", name, i))) //.SetExpansion(2)) + } + return t +} + +func newTable(params []key, min, max int, invert bool, short bool) *table { + t := &table{} + t.Box = tview.NewBox() + t.SetBorderColor(tview.Styles.GraphicsColor) + t.SetSeparator(' ') + t.SetContent(nil) + t.SetBorders(true) + t.SetBorder(true) + + t.views = make(map[key]*tview.TableCell) + + for _, param := range params { + for i := min; i <= max; i++ { + k := param + k.id = uint(i) + cell := tview.NewTableCell("") + t.views[k] = cell + var col = i + if min == 0 { + col++ + } + if !invert { + t.SetCell(int(param.id), col, cell) + } else { + t.SetCell(col, int(param.id), cell) + } + + } + var desc string + if short { + desc = fmt.Sprintf("%s", param.field) + } else { + desc = fmt.Sprintf("%s.%s", param.action, param.field) + } + + if !invert { + t.SetCell(int(param.id), 0, tview.NewTableCell(desc)) + } else { + t.SetCell(0, int(param.id), tview.NewTableCell(desc)) + } + } + + return t +} + +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/ui/ui.go b/ui/ui.go index 36b714e..2487c43 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -5,11 +5,22 @@ import ( "fmt" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" - "reflect" + "os" ) const ( - connectors_page = "Connectors" + connectors_page = "Connectors" + connectors_errors_page = "Connectors errors" + contactors_errors_page = "Contactors errors" + contactors_state_page = "Contactors states" + periphery_state_page = "Periphery state" + periphery_station_state_page = "Periphery station state" + converters_page = "Converters" + converters_errors_page = "Converters errors" + cpu_page = "CPU" + connectorCount = 6 + contactorsCount = 18 + convertersCount = 18 ) type page struct { @@ -25,25 +36,69 @@ type UI interface { } type gui struct { - app *tview.Application - pages *tview.Pages - connPage *cTable - page2 tview.Primitive + app *tview.Application + pages *tview.Pages + pu *table + puErrors *table + contactorsErrors *table + contactorsState *table + peripheryState *table + peripheryStationState *table + converters *table + convertersErrors *table + cpu *table } type log struct { } func (g *gui) Consume(event *yabl.Event) { - switch obj := event.Object.(type) { + switch event.Object.(type) { case *yabl.PuPresentEnergy: - g.connPage.updatePU(event.GetUnitId(), event.Field, event.Value) + g.pu.update(event) case *yabl.PuPeriphery: - g.connPage.updatePU(event.GetUnitId(), event.Field, event.Value) + g.pu.update(event) case *yabl.PuDebug: - g.connPage.updatePU(event.GetUnitId(), event.Field, event.Value) + g.pu.update(event) + g.puErrors.update(event) case *yabl.PuErrors: - g.connPage.updatePuErrors(obj) + g.pu.update(event) + g.puErrors.update(event) + case *yabl.ContactorInternalErrors: + g.contactorsErrors.update(event) + case *yabl.ContactorInternalDebug: + g.contactorsErrors.update(event) + g.contactorsState.update(event) + case *yabl.ContactorInternalState: + g.contactorsState.update(event) + case *yabl.ContactorsInternalForce: + g.contactorsErrors.update(event) + case *yabl.PeripheryState: + g.peripheryState.update(event) + g.peripheryStationState.update(event) + case *yabl.PeripheryInfo: + g.peripheryState.update(event) + g.peripheryStationState.update(event) + case *yabl.PeripheryDebug: + g.peripheryState.update(event) + g.peripheryStationState.update(event) + case *yabl.ConverterPresentEnergy: + g.converters.update(event) + case *yabl.ConverterErrors: + g.converters.update(event) + g.convertersErrors.update(event) + case *yabl.ConverterDebug: + g.converters.update(event) + case *yabl.CpuPresentEnergy: + g.pu.update(event) + case *yabl.CpuEnergySettings: + g.pu.update(event) + case *yabl.CpuErrors: + g.cpu.update(event) + case *yabl.CpuPeriphery: + g.cpu.update(event) + case *yabl.CpuDebug: + g.cpu.update(event) } g.app.Draw() } @@ -57,19 +112,61 @@ func NewUI() UI { var active page var layout map[string]page - g.connPage = newConnectorsGrid() - g.page2 = tview.NewBox().SetBorder(true).SetTitle("Bbbbbb") + g.pu = newTable(pu, 1, connectorCount, false, false).header(connectors_page).columns("Connector", connectorCount) + g.puErrors = newTable(pu_errors, 1, connectorCount, false, false).header(connectors_errors_page).columns("Connector", connectorCount) + g.contactorsErrors = newTable(contactors_errors, 0, 0, false, false).header(contactors_errors_page) + g.contactorsState = newTable(contactors_state, 1, contactorsCount, true, true).header(contactors_state_page).rows("Contactor", contactorsCount) + g.peripheryState = newTable(periphery_state, 1, connectorCount, false, false).header(periphery_state_page).columns("Connector", connectorCount) + g.peripheryStationState = newTable(periphery_station_state, 0, 1, false, false).header(periphery_station_state_page) + g.converters = newTable(converters, 1, convertersCount, false, true).header(converters_page).columns("", convertersCount) + g.convertersErrors = newTable(converters_errors, 1, convertersCount, false, true).header(converters_errors_page).columns("", convertersCount) + g.cpu = newTable(cpu, 0, 0, false, false).header(cpu_page) layout = map[string]page{ connectors_page: { - left: "Page2", - right: "Page2", - primitive: g.connPage, + left: cpu_page, + right: connectors_errors_page, + primitive: g.pu, }, - "Page2": { + connectors_errors_page: { left: connectors_page, + right: contactors_errors_page, + primitive: g.puErrors, + }, + contactors_errors_page: { + left: connectors_errors_page, + right: contactors_state_page, + primitive: g.contactorsErrors, + }, + contactors_state_page: { + left: contactors_errors_page, + right: periphery_state_page, + primitive: g.contactorsState, + }, + periphery_state_page: { + left: contactors_state_page, + right: periphery_station_state_page, + primitive: g.peripheryState, + }, + periphery_station_state_page: { + left: periphery_state_page, + right: converters_page, + primitive: g.peripheryStationState, + }, + converters_page: { + left: periphery_station_state_page, + right: converters_errors_page, + primitive: g.converters, + }, + converters_errors_page: { + left: converters_page, + right: cpu_page, + primitive: g.convertersErrors, + }, + cpu_page: { + left: converters_errors_page, right: connectors_page, - primitive: g.page2, + primitive: g.cpu, }, } @@ -91,7 +188,7 @@ func NewUI() UI { active = layout[active.left] return nil case tcell.KeyCtrlC: - g.app.Stop() + g.Stop() } return event }) @@ -109,6 +206,7 @@ func (g *gui) Start() { func (g *gui) Stop() { g.app.Stop() + os.Exit(0) } func NewLog() UI { @@ -131,9 +229,3 @@ 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/protocol.go b/yabl/protocol.go index 428c719..3bd80f0 100644 --- a/yabl/protocol.go +++ b/yabl/protocol.go @@ -57,6 +57,7 @@ type converter struct { type Converter interface { EventsFromFrame(*can.CanFrame) ([]*Event, bool) + CheckTimeouts() ([]*Event, bool) } func NewProtocolConverter() Converter { @@ -66,6 +67,9 @@ func NewProtocolConverter() Converter { } func (c *converter) EventsFromFrame(frame *can.CanFrame) ([]*Event, bool) { + if frame == nil { + return nil, false + } 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} @@ -117,3 +121,43 @@ func get(from uint8, size uint8, buffer []byte) (uint64, bool) { func (u unit) GetUnitId() uint { return uint(u) } + +func (c *converter) CheckTimeouts() ([]*Event, bool) { + var multipler uint = 2 + var events []*Event + + for k, param := range c.protocolMap { + now := time.Now() + deadline := now.Add(-time.Duration(param.interval*multipler) * time.Millisecond) + + var from uint8 = 0 + + for _, fld := range param.fields { + if fld.last == nil { + continue + } else if deadline.After(*fld.last) { + if events == nil { + events = make([]*Event, 0, len(param.fields)) + } + + event := &Event{ + Field: fld.name, + ActionName: param.name, + Object: param.object, + unit: unit(k.unitId), + Updated: &now, + Value: nil, + } + + var mask uint64 = ^(ALL_BITS << fld.length) + mask = mask << from + fld.value = mask + + events = append(events, event) + fld.last = nil + } + from += fld.length + } + } + return events, events != nil +} diff --git a/yabl/types.go b/yabl/types.go index a193625..1d60d82 100644 --- a/yabl/types.go +++ b/yabl/types.go @@ -44,7 +44,6 @@ type Voltage9BitType float32 type ContactorInternalState struct { unit - //UnitId uint ContactorReady *BoardReadyType ContactorOn *BooleanType UnexpectedState *ErrorType