Small CLI monitoring tool to decode proprietary [...] protocol and display info in human readable representation
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.
ycli-mon/ui/ui.go

254 lines
5.9 KiB

package ui
import (
"cli-mon/yabl"
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"os"
"time"
)
const (
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
redrawMillis = 500
)
type page struct {
left string
right string
primitive tview.Primitive
}
type UI interface {
Consume(event *yabl.Event)
Start()
Stop()
}
type gui struct {
app *tview.Application
pages *tview.Pages
redraw bool
ticker *time.Ticker
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) {
g.pu.update(event)
g.puErrors.update(event)
g.contactorsErrors.update(event)
g.contactorsState.update(event)
g.peripheryState.update(event)
g.peripheryStationState.update(event)
g.converters.update(event)
g.convertersErrors.update(event)
g.cpu.update(event)
switch event.Object.(type) {
case *yabl.PuPresentEnergy:
break
case *yabl.PuPeriphery:
break
case *yabl.PuDebug:
break
case *yabl.PuErrors:
break
case *yabl.ContactorInternalErrors:
break
case *yabl.ContactorInternalDebug:
break
case *yabl.ContactorInternalState:
break
case *yabl.ContactorsInternalForce:
break
case *yabl.PeripheryState:
break
case *yabl.PeripheryInfo:
break
case *yabl.PeripheryDebug:
break
case *yabl.ConverterPresentEnergy:
break
case *yabl.ConverterErrors:
break
case *yabl.ConverterDebug:
break
case *yabl.CpuPresentEnergy:
break
case *yabl.CpuEnergySettings:
break
case *yabl.CpuErrors:
break
case *yabl.CpuPeriphery:
break
case *yabl.CpuDebug:
break
default:
return
}
g.redraw = true
}
func NewUI() UI {
g := &gui{}
g.app = tview.NewApplication()
g.pages = tview.NewPages()
var active page
var layout map[string]page
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: cpu_page,
right: connectors_errors_page,
primitive: g.pu,
},
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.cpu,
},
}
for k, p := range layout {
g.pages.AddPage(k, p.primitive, true, true)
}
active = layout[connectors_page]
g.pages.SwitchToPage(connectors_page)
g.app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyRight:
g.pages.SwitchToPage(active.right)
active = layout[active.right]
return nil
case tcell.KeyLeft:
g.pages.SwitchToPage(active.left)
active = layout[active.left]
return nil
case tcell.KeyCtrlC:
g.Stop()
}
return event
})
g.redraw = true
return g
}
func (g *gui) Start() {
g.ticker = time.NewTicker(redrawMillis * time.Millisecond)
go func() {
for _ = range g.ticker.C {
if g.redraw {
g.app.Draw()
g.redraw = false
}
}
}()
go func() {
if err := g.app.SetRoot(g.pages, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}()
}
func (g *gui) Stop() {
g.ticker.Stop()
g.app.Stop()
os.Exit(0)
}
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() {
}