|
|
|
package tui
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
"github.com/rivo/tview"
|
|
|
|
_ "github.com/gdamore/tcell/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TUI struct {
|
|
|
|
*Display
|
|
|
|
//*LocalView
|
|
|
|
*TUIClient
|
|
|
|
SelectedReactor <-chan uint32
|
|
|
|
Err chan error
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTUI(ip string, port int, ch chan error) *TUI {
|
|
|
|
//r := make(map[uint32]*Reactor)
|
|
|
|
t := &TUI{}
|
|
|
|
//l := new(LocalView)
|
|
|
|
//l.Reactors = r
|
|
|
|
//t.LocalView = l
|
|
|
|
t.Err = ch
|
|
|
|
client := NewTUIClient(ip, port)
|
|
|
|
t.TUIClient = client
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TUI) Start() {
|
|
|
|
// setup tview app and wait for user connection in standin modal
|
|
|
|
if err := t.TUIClient.Start(); err != nil {
|
|
|
|
t.Err <- err
|
|
|
|
}
|
|
|
|
go t.Monitor()
|
|
|
|
t.CreateDisplay()
|
|
|
|
t.Display.Start()
|
|
|
|
//go t.Refresh()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TUI) CreateDisplay() {
|
|
|
|
c := make(chan uint32)
|
|
|
|
t.Display = NewDisplay(c)
|
|
|
|
t.SelectedReactor = c
|
|
|
|
t.ReactorList.AddItem("REACTOR IS ONLINE"," ",0,nil)
|
|
|
|
t.Flex.AddItem(t.ReactorList,0,1,true).
|
|
|
|
AddItem(t.DeviceList,0,2,false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TUI) Monitor() {
|
|
|
|
// orchestrates updates and grpc requests
|
|
|
|
timer := make(chan struct{})
|
|
|
|
go func(signal chan struct{}){
|
|
|
|
for {
|
|
|
|
signal <- struct{}{}
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
}
|
|
|
|
}(timer)
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case reactor := <-t.SelectedReactor:
|
|
|
|
// reactor has been selected in tui, grabbing devs
|
|
|
|
go t.UpdateDevices(reactor)
|
|
|
|
//devs := t.GetReactorDevices(reactor)
|
|
|
|
//t.DisplayReactorDevices(devs)
|
|
|
|
case <-timer:
|
|
|
|
// time to ping for status
|
|
|
|
t.App.QueueUpdateDraw(func() {
|
|
|
|
t.UpdateReactors()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TUI) UpdateDevices(r uint32) {
|
|
|
|
// get devices for the reactor and update the tui
|
|
|
|
devs, err := t.TUIClient.GetReactorDevices(r)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
//for a, d := range devs {
|
|
|
|
// go t.LocalView.UpdateReactorDevices(r,a,d)
|
|
|
|
//}
|
|
|
|
t.DisplayReactorDevices(devs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TUI) UpdateReactors() {
|
|
|
|
// get all reactors and update the tui
|
|
|
|
reactors, err := t.TUIClient.GetReactors()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
t.DisplayReactors(reactors)
|
|
|
|
//for id, r := range reactors {
|
|
|
|
// go t.LocalView.UpdateReactors(id, r)
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// display struct and logic
|
|
|
|
type Display struct {
|
|
|
|
App *tview.Application
|
|
|
|
Flex *tview.Flex
|
|
|
|
ReactorList *tview.List
|
|
|
|
DeviceList *tview.List
|
|
|
|
SelectedReactor chan<- uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDisplay(ch chan uint32) *Display {
|
|
|
|
d := &Display{}
|
|
|
|
d.App = tview.NewApplication()
|
|
|
|
d.Flex = tview.NewFlex()
|
|
|
|
d.ReactorList = tview.NewList().ShowSecondaryText(false)
|
|
|
|
d.DeviceList = tview.NewList().ShowSecondaryText(false)
|
|
|
|
d.ReactorList.SetTitle("Reactors").SetBorder(true)
|
|
|
|
d.DeviceList.SetTitle("Devices").SetBorder(true)
|
|
|
|
d.SelectedReactor = ch
|
|
|
|
return d
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Display) Start() {
|
|
|
|
if err := d.App.SetRoot(d.Flex, true).Run(); err != nil {
|
|
|
|
d.App.Stop()
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Display) DisplayReactors(r map[uint32]*Reactor) {
|
|
|
|
// function to display reactor list to table
|
|
|
|
d.ReactorList.Clear()
|
|
|
|
for id, reactor := range r {
|
|
|
|
var status string
|
|
|
|
if reactor.Status {
|
|
|
|
status = "[green]ONLINE"
|
|
|
|
} else {
|
|
|
|
status = "[red]OFFLINE"
|
|
|
|
}
|
|
|
|
txt := fmt.Sprintf("%v is %v", id, status)
|
|
|
|
d.ReactorList.AddItem(txt,string(id),0,nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Display) SelectReactor(index int, main, id string, r rune) {
|
|
|
|
// called when reactor in list in selected
|
|
|
|
if id, err := strconv.Atoi(id); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
} else {
|
|
|
|
d.SelectedReactor <-uint32(id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Display) DisplayReactorDevices(devs map[int]*Device) {
|
|
|
|
//Function that displays devices to the table
|
|
|
|
//d.DeviceList.Clear()
|
|
|
|
for addr, dev := range devs {
|
|
|
|
var status string
|
|
|
|
if dev.Status == "ACTIVE" {
|
|
|
|
status = "[green]ACTIVE[white]"
|
|
|
|
} else if dev.Status == "KILLED" {
|
|
|
|
status = "[red]KILLED[white]"
|
|
|
|
}
|
|
|
|
txt := fmt.Sprintf("%v is %v at %x",dev.Type,status,addr)
|
|
|
|
d.DeviceList.AddItem(txt,"",0,nil)
|
|
|
|
}
|
|
|
|
d.App.Draw()
|
|
|
|
}
|