From afc4b794bbd6e138fbe1f5d18d0abc388c0bfa6b Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Tue, 25 Aug 2026 14:46:20 +0100 Subject: [PATCH] Created a devices service and moved the CDashDisplay service to the sahdow realm --- .../cdashdisplay}/connect.go | 0 .../cdashdisplay}/display.go | 3 +- devices/cdashdisplay/info.go | 9 + .../cdashdisplay}/layoutManager.go | 0 .../cdashdisplay}/transportPackets.go | 0 devices/device.go | 9 + go.mod | 2 +- peripheral/devices/devices.go | 5 +- services/cdashdisplay.go | 255 ++++++++---------- services/device.go | 9 - services/devices.go | 123 +++++++++ services/telemetry.go | 15 +- .../{layout.go => cdashdisplay_layout.go} | 116 +++++++- ...ool.go => cdashdisplay_layout_moveTool.go} | 41 ++- tui/internal/controllers/device.go | 9 +- tui/internal/controllers/streaming.go | 24 +- tui/internal/views/layoutTool.go | 2 +- tui/internal/views/layoutTool_forms.go | 2 +- tui/tui.go | 4 +- 19 files changed, 444 insertions(+), 184 deletions(-) rename {cdashdisplay => devices/cdashdisplay}/connect.go (100%) rename {cdashdisplay => devices/cdashdisplay}/display.go (98%) create mode 100644 devices/cdashdisplay/info.go rename {cdashdisplay => devices/cdashdisplay}/layoutManager.go (100%) rename {cdashdisplay => devices/cdashdisplay}/transportPackets.go (100%) create mode 100644 devices/device.go delete mode 100644 services/device.go create mode 100644 services/devices.go rename tui/internal/controllers/{layout.go => cdashdisplay_layout.go} (82%) rename tui/internal/controllers/{layout_moveTool.go => cdashdisplay_layout_moveTool.go} (64%) diff --git a/cdashdisplay/connect.go b/devices/cdashdisplay/connect.go similarity index 100% rename from cdashdisplay/connect.go rename to devices/cdashdisplay/connect.go diff --git a/cdashdisplay/display.go b/devices/cdashdisplay/display.go similarity index 98% rename from cdashdisplay/display.go rename to devices/cdashdisplay/display.go index 9f33c14..433db99 100644 --- a/cdashdisplay/display.go +++ b/devices/cdashdisplay/display.go @@ -116,7 +116,8 @@ type CDashDisplay struct { State *CDashState } -func NewCDashDisplay() (*CDashDisplay, error) { +// Connect will try to find and connect to the CDashDisplay +func Discover() (*CDashDisplay, error) { // Look for the port p, err := findDisplayPort() if err != nil { diff --git a/devices/cdashdisplay/info.go b/devices/cdashdisplay/info.go new file mode 100644 index 0000000..ecd930a --- /dev/null +++ b/devices/cdashdisplay/info.go @@ -0,0 +1,9 @@ +package cdashdisplay + +import "esdi/peripheral/devices" + +// TODO: I believe we don't need the #esdi/peripheral/devices thing anymore +const ( + ID = devices.CDashDisplayDevID + Name = devices.CDashDisplayDevName +) diff --git a/cdashdisplay/layoutManager.go b/devices/cdashdisplay/layoutManager.go similarity index 100% rename from cdashdisplay/layoutManager.go rename to devices/cdashdisplay/layoutManager.go diff --git a/cdashdisplay/transportPackets.go b/devices/cdashdisplay/transportPackets.go similarity index 100% rename from cdashdisplay/transportPackets.go rename to devices/cdashdisplay/transportPackets.go diff --git a/devices/device.go b/devices/device.go new file mode 100644 index 0000000..c7baab1 --- /dev/null +++ b/devices/device.go @@ -0,0 +1,9 @@ +// Package devices simply defines what a device should have +// and some utils if necessary +package devices + +import "esdi/telemetry" + +type Device interface { + SendData(*telemetry.TelemetryData) +} diff --git a/go.mod b/go.mod index 3d4d8fd..6dbcbdb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module esdi -go 1.25.5 +go 1.27.0 require ( github.com/ESilva15/ESgoRepl v0.1.0 diff --git a/peripheral/devices/devices.go b/peripheral/devices/devices.go index 34d2684..bfe97fa 100644 --- a/peripheral/devices/devices.go +++ b/peripheral/devices/devices.go @@ -6,8 +6,9 @@ import "esdi/peripheral/types" // IDs for our devices. They need to be correctly mapped on the devices // themselves so we can discover them const ( - CDashDisplayDevID = 0x01 - ESBtnBoxDevID = 0x02 + CDashDisplayDevID = 0x01 + CDashDisplayDevName = "CDashDisplay" + ESBtnBoxDevID = 0x02 ) // DeviceMap maps the implemented devices diff --git a/services/cdashdisplay.go b/services/cdashdisplay.go index 0821075..111b2dc 100644 --- a/services/cdashdisplay.go +++ b/services/cdashdisplay.go @@ -1,148 +1,131 @@ package services -import ( - "context" - "fmt" - "log/slog" - "sync/atomic" +// type CDashService struct { +// Logger *slog.Logger +// CDash *cdashdisplay.CDashDisplay +// // DevClerk *peripheral.PeripheralDeviceClerk +// // Messages chan string +// // Telemetry Channel +// // streamCancel context.CancelFunc +// // TelemCh <-chan telemetry.TelemetryData +// } - "esdi/cdashdisplay" - helper "esdi/helpers" - "esdi/peripheral" - "esdi/telemetry" -) +// func NewCDashService(logger *slog.Logger) *CDashService { +// // sharedChannel := make(chan string, 10) +// return &CDashService{ +// Logger: logger, +// CDash: nil, +// // DevClerk: peripheral.NewPeripheralDeviceClerk(), +// // Messages: sharedChannel, +// } +// } -type CDashService struct { - Logger *slog.Logger - CDash *cdashdisplay.CDashDisplay - DevClerk *peripheral.PeripheralDeviceClerk - Messages chan string - // Telemetry Channel - streamCancel context.CancelFunc - TelemCh <-chan telemetry.TelemetryData -} +// func (ds *CDashService) FindDevice() { +// ds.Messages <- "looking for cdash display...\n" +// ds.Logger.Info("Looking for CDashDisplay") -func NewCDashService(logger *slog.Logger) *CDashService { - sharedChannel := make(chan string, 10) - return &CDashService{ - Logger: logger, - CDash: nil, - DevClerk: peripheral.NewPeripheralDeviceClerk(), - Messages: sharedChannel, - } -} +// cdashdisplay.SetLogger(ds.Logger.With("[device]", "cdashdisplay")) -func (cds *CDashService) FindDevice() { - cds.Messages <- "looking for cdash display...\n" - cds.Logger.Info("Looking for CDashDisplay") +// display, err := cdashdisplay.Discover() +// if err != nil { +// ds.Logger.Info("didn't find cdashdisplay") +// ds.Messages <- "didn't find cdash display\n" +// return +// } +// +// ds.CDash = display +// ds.Logger.Info("found cdashdisplay on: " + display.WT.Cfg.Name) +// ds.Messages <- "found cdashdisplay on: " + display.WT.Cfg.Name + "\n" +// } - cdashdisplay.SetLogger(cds.Logger.With("[device]", "cdashdisplay")) +// func (ds *CDashService) CreateWindow( +// win *cdashdisplay.DesktopUIWindow, +// ) (*cdashdisplay.DesktopUIWindow, error) { +// updatedWindow, err := ds.CDash.CreateWindow(win) +// if err != nil { +// return nil, err +// } +// +// return updatedWindow, nil +// } +// +// func (ds *CDashService) LoadLayout(layoutPath string) error { +// return ds.CDash.LoadLayout(layoutPath) +// } +// +// func (ds *CDashService) SaveLayout(layoutPath string) error { +// return ds.CDash.SaveLayout(layoutPath) +// } +// +// func (ds *CDashService) UnloadLayout() error { +// return ds.CDash.UnloadLayout() +// } +// +// func (ds *CDashService) UpdateWindow(win *cdashdisplay.DesktopUIWindow) error { +// ds.Messages <- fmt.Sprintf("Updating a window:\n%+v\n", win) +// return ds.CDash.UpdateWindow(win) +// } +// +// func (ds *CDashService) DeleteWindow(idx int16) error { +// return ds.CDash.DestroyWindow(idx) +// } +// +// func (ds *CDashService) ResizeWindow(idx int16, vec *helper.Vector) error { +// err := ds.CDash.ResizeWindow(idx, vec) +// if err != nil { +// return err +// } +// +// return nil +// } +// +// func (ds *CDashService) MoveWindow(idx int16, vec *helper.Vector) error { +// return ds.CDash.MoveWindow(idx, vec) +// } - display, err := cdashdisplay.NewCDashDisplay() - if err != nil { - cds.Logger.Info("didn't find cdashdisplay") - cds.Messages <- "didn't find cdash display\n" - return - } +// func (ds *CDashService) SetTelemetryChannel(ch <-chan telemetry.TelemetryData) { +// ds.TelemCh = ch +// } - cds.CDash = display - cds.Logger.Info("found cdashdisplay on: " + display.WT.Cfg.Name) - cds.Messages <- "found cdashdisplay on: " + display.WT.Cfg.Name + "\n" -} - -func (cds *CDashService) CreateWindow( - win *cdashdisplay.DesktopUIWindow, -) (*cdashdisplay.DesktopUIWindow, error) { - updatedWindow, err := cds.CDash.CreateWindow(win) - if err != nil { - return nil, err - } - - return updatedWindow, nil -} - -func (cds *CDashService) LoadLayout(layoutPath string) error { - return cds.CDash.LoadLayout(layoutPath) -} - -func (cds *CDashService) SaveLayout(layoutPath string) error { - return cds.CDash.SaveLayout(layoutPath) -} - -func (cds *CDashService) UnloadLayout() error { - return cds.CDash.UnloadLayout() -} - -func (cds *CDashService) UpdateWindow(win *cdashdisplay.DesktopUIWindow) error { - cds.Messages <- fmt.Sprintf("Updating a window:\n%+v\n", win) - return cds.CDash.UpdateWindow(win) -} - -func (cds *CDashService) DeleteWindow(idx int16) error { - return cds.CDash.DestroyWindow(idx) -} - -func (cds *CDashService) ResizeWindow(idx int16, vec *helper.Vector) error { - err := cds.CDash.ResizeWindow(idx, vec) - if err != nil { - return err - } - - return nil -} - -func (cds *CDashService) MoveWindow(idx int16, vec *helper.Vector) error { - err := cds.CDash.MoveWindow(idx, vec) - if err != nil { - return err - } - - return nil -} - -func (cds *CDashService) SetTelemetryChannel(ch <-chan telemetry.TelemetryData) { - cds.TelemCh = ch -} - -func (cds *CDashService) StartStream() { - // NOTE: i'm using this pattern a whole lot. Maybe I can create a struct to handle this - var ctx context.Context - ctx, cds.streamCancel = context.WithCancel(context.Background()) - - go cds.transmit(ctx) -} - -func (cds *CDashService) StopStream() { - if cds.streamCancel == nil { - return - } - - cds.streamCancel() - cds.streamCancel = nil -} +// func (cds *CDashService) StartStream() { +// // NOTE: i'm using this pattern a whole lot. Maybe I can create a struct to handle this +// var ctx context.Context +// ctx, cds.streamCancel = context.WithCancel(context.Background()) +// +// go cds.transmit(ctx) +// } +// +// func (cds *CDashService) StopStream() { +// if cds.streamCancel == nil { +// return +// } +// +// cds.streamCancel() +// cds.streamCancel = nil +// } // INTERNAL -func (cds *CDashService) transmit(ctx context.Context) { - var isSending atomic.Bool - - for { - select { - case <-ctx.Done(): - return - case data, ok := <-cds.TelemCh: - if !ok { - return - } - - if isSending.Load() { - continue - } - - isSending.Store(true) - - cds.CDash.SendData(&data) - isSending.Store(false) - } - } -} +// func (ds *CDashService) transmit(ctx context.Context) { +// var isSending atomic.Bool +// +// for { +// select { +// case <-ctx.Done(): +// return +// case data, ok := <-ds.TelemCh: +// if !ok { +// return +// } +// +// if isSending.Load() { +// continue +// } +// +// isSending.Store(true) +// +// ds.CDash.SendData(&data) +// isSending.Store(false) +// } +// } +// } diff --git a/services/device.go b/services/device.go deleted file mode 100644 index e1b4db6..0000000 --- a/services/device.go +++ /dev/null @@ -1,9 +0,0 @@ -package services - -// DeviceService will handle sending the data from the telemetry service to the -// actual devices -// NOTE: create a virtual device and make it be the output window or something so -// we can just add it as a device or whatever instead of being a custom made thing -// that would be pretty cool I think -type DeviceService struct { -} diff --git a/services/devices.go b/services/devices.go new file mode 100644 index 0000000..d48870f --- /dev/null +++ b/services/devices.go @@ -0,0 +1,123 @@ +package services + +import ( + "context" + "fmt" + "log/slog" + "sync/atomic" + + "esdi/devices" + "esdi/devices/cdashdisplay" + "esdi/telemetry" +) + +// DeviceService will handle sending the data from the telemetry service to the +// actual devices +// NOTE: create a virtual device and make it be the output window or something so +// we can just add it as a device or whatever instead of being a custom made thing +// that would be pretty cool I think +type DeviceService struct { + Logger *slog.Logger + Devices map[string]devices.Device + // Strem handling + streamCancel context.CancelFunc + TelemCh <-chan telemetry.TelemetryData + // Output + Messages chan string +} + +func NewDeviceService(logger *slog.Logger) *DeviceService { + sharedChannel := make(chan string, 10) + return &DeviceService{ + Devices: make(map[string]devices.Device), + Logger: logger, + Messages: sharedChannel, + } +} + +func (ds *DeviceService) FindDevices() { + // Need to define a list of devices to search for + // For now lets just try to find our cdashdisplay - will think about the rest later + + // Find CDashDisplay + { + ds.Messages <- "looking for " + cdashdisplay.Name + "...\n" + ds.Logger.Info("Looking for " + cdashdisplay.Name) + + cdashdisplay.SetLogger(ds.Logger.With("[device]", cdashdisplay.Name)) + + // Create a cdashdisplay + display, err := cdashdisplay.Discover() + if err == nil { + ds.Devices[cdashdisplay.Name] = display + ds.Logger.Info("found " + cdashdisplay.Name + " on: " + display.WT.Cfg.Name) + ds.Messages <- "found " + cdashdisplay.Name + " on: " + display.WT.Cfg.Name + "\n" + return + } + + ds.Logger.Info("didn't find " + cdashdisplay.Name) + ds.Messages <- "didn't find " + cdashdisplay.Name + "\n" + // No CDashDisplay available for one reason or another, so we don't set the + // key + } +} + +func (ds *DeviceService) GetDevice(name string) (devices.Device, error) { + val, ok := ds.Devices[name] + if !ok { + return nil, fmt.Errorf("device `%s` couldn't be found", name) + } + + return val, nil +} + +func (ds *DeviceService) StartStream() { + // NOTE: i'm using this pattern a whole lot. Maybe I can create a struct to handle this + var ctx context.Context + ctx, ds.streamCancel = context.WithCancel(context.Background()) + + go ds.transmit(ctx) +} + +func (ds *DeviceService) StopStream() { + if ds.streamCancel == nil { + return + } + + ds.streamCancel() + ds.streamCancel = nil +} + +// SetTelemetryChannel sets the TelemCh to the passed channel +func (ds *DeviceService) SetTelemetryChannel(ch <-chan telemetry.TelemetryData) { + ds.TelemCh = ch +} + +// transmit will send the data to the devices themselves +func (ds *DeviceService) transmit(ctx context.Context) { + var isSending atomic.Bool + + for { + select { + case <-ctx.Done(): + return + case data, ok := <-ds.TelemCh: + if !ok { + return + } + + if isSending.Load() { + continue + } + + isSending.Store(true) + + // TODO: make a copy of the data and send that copy instead of keeping + // the data locked + for _, dev := range ds.Devices { + dev.SendData(&data) + } + isSending.Store(false) + } + } +} diff --git a/services/telemetry.go b/services/telemetry.go index b2b5b5f..f50b532 100644 --- a/services/telemetry.go +++ b/services/telemetry.go @@ -14,8 +14,8 @@ import ( // TelemetryService will be our base struct to handle telemetry data // It should hook to a data sink and handle it like iRacing, BeamNG, AC and so on type TelemetryService struct { - logger *slog.Logger - cdash *CDashService + logger *slog.Logger + devService *DeviceService // Concurrency protection mut sync.RWMutex ativeProvider telem.TelemetryProvider @@ -24,13 +24,16 @@ type TelemetryService struct { cancelForward context.CancelFunc } -func NewTelemetryService(logger *slog.Logger, cdash *CDashService) *TelemetryService { +func NewTelemetryService(logger *slog.Logger, devServo *DeviceService) *TelemetryService { newService := &TelemetryService{ - logger: logger, - cdash: cdash, - listeners: make(map[string]chan telem.TelemetryData), + logger: logger, + devService: devServo, + listeners: make(map[string]chan telem.TelemetryData), } + // TODO: do not create and set a provider here, a background job should be + // detecting providers instead + // Need to instantiate a default provider here // source := "/home/esilva/Desktop/projetos/simracing_peripherals/testTelemetry/gt3_mustang_bathurst.ibt" firstProvider := providers.NewIRacingProvider(slog.Default(), goirsdk.Options{ diff --git a/tui/internal/controllers/layout.go b/tui/internal/controllers/cdashdisplay_layout.go similarity index 82% rename from tui/internal/controllers/layout.go rename to tui/internal/controllers/cdashdisplay_layout.go index a2b3a3d..da21306 100644 --- a/tui/internal/controllers/layout.go +++ b/tui/internal/controllers/cdashdisplay_layout.go @@ -5,11 +5,12 @@ import ( "os" "strconv" - "esdi/cdashdisplay" - helper "esdi/helpers" + "esdi/devices/cdashdisplay" "esdi/services" "esdi/tui/internal/views" + helper "esdi/helpers" + "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) @@ -19,12 +20,14 @@ type LayoutController struct { OnExit func() LayoutToolView *views.LayoutToolView Messages chan string - DevService *services.CDashService + DevService *services.DeviceService MoveToolState *windowManipState SelectedLayout string // NOTE: This should be a struct to handle its own things + // TODO: create a filter to select the layout + // filter telemetry provider, then filter vehicle in use and so on } -func NewLayoutController(base *Controller, service *services.CDashService) *LayoutController { +func NewLayoutController(base *Controller, service *services.DeviceService) *LayoutController { lc := &LayoutController{ Controller: base, LayoutToolView: views.NewLayoutToolView(), @@ -207,7 +210,20 @@ func (lc *LayoutController) createWindow() { return } - window, err = lc.DevService.CreateWindow(window) + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + + window, err = display.CreateWindow(window) if err != nil { lc.Messages <- "failed to create window\n" return @@ -304,7 +320,20 @@ func (lc *LayoutController) newWindowAction() { } func (lc *LayoutController) updateWindowAction(win *cdashdisplay.DesktopUIWindow) { - err := lc.DevService.UpdateWindow(win) + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + + err = display.UpdateWindow(win) lc.Messages <- fmt.Sprintf("Window: %v\n", win) @@ -317,7 +346,20 @@ func (lc *LayoutController) updateWindowAction(win *cdashdisplay.DesktopUIWindow func (lc *LayoutController) displayLoadedLayouts() { lc.Logger.Debug("We want to view our layout!") - for _, w := range lc.DevService.CDash.State.Layout.Windows { + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + + for _, w := range display.State.Layout.Windows { lc.Logger.Debug("==========================================================================") lc.Logger.Debug(fmt.Sprintf("updating form view for a layout: %+v", w.UIData.TelemetryField)) err := lc.updateFormView(w) @@ -349,8 +391,21 @@ func (lc *LayoutController) getCurrentTreeNodeModel() (*tview.TreeNode, int16, e } func (lc *LayoutController) loadLayout() { + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + // We would get the layout path from somewhere but for nots its layout.yaml - err := lc.DevService.LoadLayout(lc.SelectedLayout) + err = display.LoadLayout(lc.SelectedLayout) if err != nil { lc.Messages <- "failed to load layout: " + err.Error() return @@ -360,7 +415,20 @@ func (lc *LayoutController) loadLayout() { } func (lc *LayoutController) unloadLayout() { - err := lc.DevService.UnloadLayout() + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + + err = display.UnloadLayout() if err != nil { lc.Logger.Error(fmt.Sprintf("Failed to unload layout: %+v", err)) return @@ -368,7 +436,20 @@ func (lc *LayoutController) unloadLayout() { } func (lc *LayoutController) saveLayout() { - err := lc.DevService.SaveLayout(lc.SelectedLayout) + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + + err = display.SaveLayout(lc.SelectedLayout) if err != nil { lc.Messages <- "failed to save layout: " + err.Error() return @@ -388,8 +469,21 @@ func (lc *LayoutController) deleteWindow() { } wID := curNode.GetReference().(int16) + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- + // Delete it - err := lc.DevService.DeleteWindow(wID) + err = display.DestroyWindow(wID) if err != nil { lc.Messages <- "failed to delete window: " + err.Error() + "\n" return diff --git a/tui/internal/controllers/layout_moveTool.go b/tui/internal/controllers/cdashdisplay_layout_moveTool.go similarity index 64% rename from tui/internal/controllers/layout_moveTool.go rename to tui/internal/controllers/cdashdisplay_layout_moveTool.go index 41bca62..d363a58 100644 --- a/tui/internal/controllers/layout_moveTool.go +++ b/tui/internal/controllers/cdashdisplay_layout_moveTool.go @@ -1,6 +1,7 @@ package controllers import ( + "esdi/devices/cdashdisplay" helper "esdi/helpers" "github.com/gdamore/tcell/v2" @@ -43,40 +44,68 @@ func keyToVector(r rune) (helper.Vector, bool) { } func (lc *LayoutController) handleMovementCapture(idx int16, - ev *tcell.EventKey) *tcell.EventKey { + ev *tcell.EventKey, +) *tcell.EventKey { vec, ok := keyToVector(ev.Rune()) if !ok { return nil } - err := lc.DevService.MoveWindow(idx, &vec) + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return nil + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return nil + } + // --- + + err = display.MoveWindow(idx, &vec) if err != nil { lc.Messages <- "failed to move window: " + err.Error() + "\n" return nil } // Success - update the form - window := lc.DevService.CDash.State.Layout.Windows[idx] + window := display.State.Layout.Windows[idx] lc.LayoutToolView.UpdateFormView(idx, window) return nil } func (lc *LayoutController) handleResizeCapture(idx int16, - ev *tcell.EventKey) *tcell.EventKey { + ev *tcell.EventKey, +) *tcell.EventKey { vec, ok := keyToVector(ev.Rune()) if !ok { return nil } - err := lc.DevService.ResizeWindow(idx, &vec) + // Acquire the cdashdisplay + displayIF, err := lc.DevService.GetDevice(cdashdisplay.Name) + if err != nil { + lc.Messages <- "failed to get " + cdashdisplay.Name + return nil + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + lc.Messages <- "failed to acquire " + cdashdisplay.Name + return nil + } + // --- + + err = display.ResizeWindow(idx, &vec) if err != nil { lc.Messages <- "failed to resize window: " + err.Error() + "\n" return nil } // Success - update the form - window := lc.DevService.CDash.State.Layout.Windows[idx] + window := display.State.Layout.Windows[idx] lc.LayoutToolView.UpdateFormView(idx, window) return nil diff --git a/tui/internal/controllers/device.go b/tui/internal/controllers/device.go index c73ff98..c0f7648 100644 --- a/tui/internal/controllers/device.go +++ b/tui/internal/controllers/device.go @@ -15,12 +15,12 @@ type DeviceController struct { DeviceAPIView *views.DeviceAPIView LayoutCtrl *LayoutController StreamCtrl *StreamingCtrl - DevService *serv.CDashService + DevService *serv.DeviceService } func NewDeviceController( base *Controller, - devService *serv.CDashService, + devService *serv.DeviceService, telemService *serv.TelemetryService, ) *DeviceController { mc := &DeviceController{ @@ -56,7 +56,7 @@ func (mc *DeviceController) setDeviceAPIViewEvents() { SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { switch ev.Rune() { case 'r': - go mc.DevService.FindDevice() + go mc.DevService.FindDevices() } return ev }) @@ -75,7 +75,8 @@ func (mc *DeviceController) AddDeviceAPIListItems() { }) mc.DeviceAPIView.DevAPIList. AddItem("stream", "stream data to the display", func() { - views.AddAndShowPage(mc.DeviceAPIView.DevAPIToolView.Pages, + views.AddAndShowPage( + mc.DeviceAPIView.DevAPIToolView.Pages, "streaming-tool", mc.StreamCtrl.StreamView.Flex, ) diff --git a/tui/internal/controllers/streaming.go b/tui/internal/controllers/streaming.go index a743de3..0edfd28 100644 --- a/tui/internal/controllers/streaming.go +++ b/tui/internal/controllers/streaming.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "esdi/config" + "esdi/devices/cdashdisplay" "esdi/providers" "esdi/services" "esdi/telemetry" @@ -17,7 +18,7 @@ import ( type StreamingCtrl struct { *Controller - Service *services.CDashService + Service *services.DeviceService StreamView *views.StreamToolView Messages chan string Internal chan string @@ -32,7 +33,7 @@ type StreamingCtrl struct { func NewStreamingCtrl( base *Controller, - serCDash *services.CDashService, + devService *services.DeviceService, serTelem *services.TelemetryService, ) *StreamingCtrl { // NOTE: looks sus, put this somewhere also. Not very good in here @@ -44,7 +45,7 @@ func NewStreamingCtrl( ctrl := &StreamingCtrl{ Controller: base, - Service: serCDash, + Service: devService, TelemServ: serTelem, Messages: make(chan string, 10), Internal: make(chan string, 10), @@ -155,9 +156,22 @@ func (sc *StreamingCtrl) updateStream() { // Performance reasoning: this is not used during the high frequency data transmission // so we can get away with using a map for convenience here func (sc *StreamingCtrl) SetInternalState() { - fields := make(map[int16]telemetry.FieldID, len(sc.Service.CDash.State.Layout.Windows)) + // Acquire the cdashdisplay + displayIF, err := sc.Service.GetDevice(cdashdisplay.Name) + if err != nil { + sc.Messages <- "failed to get " + cdashdisplay.Name + return + } + display, ok := displayIF.(*cdashdisplay.CDashDisplay) + if !ok { + sc.Messages <- "failed to acquire " + cdashdisplay.Name + return + } + // --- - for _, w := range sc.Service.CDash.State.Layout.Windows { + fields := make(map[int16]telemetry.FieldID, len(display.State.Layout.Windows)) + + for _, w := range display.State.Layout.Windows { fieldID, _ := telemetry.GetFieldID(w.UIData.TelemetryField) fields[w.UIData.IDX] = fieldID } diff --git a/tui/internal/views/layoutTool.go b/tui/internal/views/layoutTool.go index 0c6d150..a8a8b01 100644 --- a/tui/internal/views/layoutTool.go +++ b/tui/internal/views/layoutTool.go @@ -4,7 +4,7 @@ import ( "fmt" "log/slog" - "esdi/cdashdisplay" + "esdi/devices/cdashdisplay" tviewh "esdi/tui/internal/tview_helpers" "github.com/gdamore/tcell/v2" diff --git a/tui/internal/views/layoutTool_forms.go b/tui/internal/views/layoutTool_forms.go index a2a6373..6d4278b 100644 --- a/tui/internal/views/layoutTool_forms.go +++ b/tui/internal/views/layoutTool_forms.go @@ -3,7 +3,7 @@ package views import ( "fmt" - "esdi/cdashdisplay" + "esdi/devices/cdashdisplay" "esdi/telemetry" "github.com/rivo/tview" diff --git a/tui/tui.go b/tui/tui.go index bea2890..747b9d7 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -23,7 +23,9 @@ func NewControlPanel(logger *slog.Logger) *ControlPanel { App: tview.NewApplication(), } - devService := services.NewCDashService(logger) + // NOTE: create our device service here + devService := services.NewDeviceService(logger) + telemService := services.NewTelemetryService(logger, devService) if telemService == nil { panic("failed to create the telemetry service")