Created a devices service and moved the CDashDisplay service to the sahdow realm

This commit is contained in:
2026-08-25 14:46:20 +01:00
parent fe86993c6d
commit f4bde52f40
19 changed files with 444 additions and 184 deletions
@@ -116,7 +116,8 @@ type CDashDisplay struct {
State *CDashState State *CDashState
} }
func NewCDashDisplay() (*CDashDisplay, error) { // Connect will try to find and connect to the CDashDisplay
func Discover() (*CDashDisplay, error) {
// Look for the port // Look for the port
p, err := findDisplayPort() p, err := findDisplayPort()
if err != nil { if err != nil {
+9
View File
@@ -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
)
+9
View File
@@ -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)
}
+1 -1
View File
@@ -1,6 +1,6 @@
module esdi module esdi
go 1.25.5 go 1.27.0
require ( require (
github.com/ESilva15/ESgoRepl v0.1.0 github.com/ESilva15/ESgoRepl v0.1.0
+3 -2
View File
@@ -6,8 +6,9 @@ import "esdi/peripheral/types"
// IDs for our devices. They need to be correctly mapped on the devices // IDs for our devices. They need to be correctly mapped on the devices
// themselves so we can discover them // themselves so we can discover them
const ( const (
CDashDisplayDevID = 0x01 CDashDisplayDevID = 0x01
ESBtnBoxDevID = 0x02 CDashDisplayDevName = "CDashDisplay"
ESBtnBoxDevID = 0x02
) )
// DeviceMap maps the implemented devices // DeviceMap maps the implemented devices
+119 -136
View File
@@ -1,148 +1,131 @@
package services package services
import ( // type CDashService struct {
"context" // Logger *slog.Logger
"fmt" // CDash *cdashdisplay.CDashDisplay
"log/slog" // // DevClerk *peripheral.PeripheralDeviceClerk
"sync/atomic" // // Messages chan string
// // Telemetry Channel
// // streamCancel context.CancelFunc
// // TelemCh <-chan telemetry.TelemetryData
// }
"esdi/cdashdisplay" // func NewCDashService(logger *slog.Logger) *CDashService {
helper "esdi/helpers" // // sharedChannel := make(chan string, 10)
"esdi/peripheral" // return &CDashService{
"esdi/telemetry" // Logger: logger,
) // CDash: nil,
// // DevClerk: peripheral.NewPeripheralDeviceClerk(),
// // Messages: sharedChannel,
// }
// }
type CDashService struct { // func (ds *CDashService) FindDevice() {
Logger *slog.Logger // ds.Messages <- "looking for cdash display...\n"
CDash *cdashdisplay.CDashDisplay // ds.Logger.Info("Looking for CDashDisplay")
DevClerk *peripheral.PeripheralDeviceClerk
Messages chan string
// Telemetry Channel
streamCancel context.CancelFunc
TelemCh <-chan telemetry.TelemetryData
}
func NewCDashService(logger *slog.Logger) *CDashService { // cdashdisplay.SetLogger(ds.Logger.With("[device]", "cdashdisplay"))
sharedChannel := make(chan string, 10)
return &CDashService{
Logger: logger,
CDash: nil,
DevClerk: peripheral.NewPeripheralDeviceClerk(),
Messages: sharedChannel,
}
}
func (cds *CDashService) FindDevice() { // display, err := cdashdisplay.Discover()
cds.Messages <- "looking for cdash display...\n" // if err != nil {
cds.Logger.Info("Looking for CDashDisplay") // 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() // func (ds *CDashService) SetTelemetryChannel(ch <-chan telemetry.TelemetryData) {
if err != nil { // ds.TelemCh = ch
cds.Logger.Info("didn't find cdashdisplay") // }
cds.Messages <- "didn't find cdash display\n"
return
}
cds.CDash = display // func (cds *CDashService) StartStream() {
cds.Logger.Info("found cdashdisplay on: " + display.WT.Cfg.Name) // // NOTE: i'm using this pattern a whole lot. Maybe I can create a struct to handle this
cds.Messages <- "found cdashdisplay on: " + display.WT.Cfg.Name + "\n" // var ctx context.Context
} // ctx, cds.streamCancel = context.WithCancel(context.Background())
//
func (cds *CDashService) CreateWindow( // go cds.transmit(ctx)
win *cdashdisplay.DesktopUIWindow, // }
) (*cdashdisplay.DesktopUIWindow, error) { //
updatedWindow, err := cds.CDash.CreateWindow(win) // func (cds *CDashService) StopStream() {
if err != nil { // if cds.streamCancel == nil {
return nil, err // return
} // }
//
return updatedWindow, nil // cds.streamCancel()
} // cds.streamCancel = 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
}
// INTERNAL // INTERNAL
func (cds *CDashService) transmit(ctx context.Context) { // func (ds *CDashService) transmit(ctx context.Context) {
var isSending atomic.Bool // var isSending atomic.Bool
//
for { // for {
select { // select {
case <-ctx.Done(): // case <-ctx.Done():
return // return
case data, ok := <-cds.TelemCh: // case data, ok := <-ds.TelemCh:
if !ok { // if !ok {
return // return
} // }
//
if isSending.Load() { // if isSending.Load() {
continue // continue
} // }
//
isSending.Store(true) // isSending.Store(true)
//
cds.CDash.SendData(&data) // ds.CDash.SendData(&data)
isSending.Store(false) // isSending.Store(false)
} // }
} // }
} // }
-9
View File
@@ -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 {
}
+123
View File
@@ -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)
}
}
}
+9 -6
View File
@@ -14,8 +14,8 @@ import (
// TelemetryService will be our base struct to handle telemetry data // 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 // It should hook to a data sink and handle it like iRacing, BeamNG, AC and so on
type TelemetryService struct { type TelemetryService struct {
logger *slog.Logger logger *slog.Logger
cdash *CDashService devService *DeviceService
// Concurrency protection // Concurrency protection
mut sync.RWMutex mut sync.RWMutex
ativeProvider telem.TelemetryProvider ativeProvider telem.TelemetryProvider
@@ -24,13 +24,16 @@ type TelemetryService struct {
cancelForward context.CancelFunc cancelForward context.CancelFunc
} }
func NewTelemetryService(logger *slog.Logger, cdash *CDashService) *TelemetryService { func NewTelemetryService(logger *slog.Logger, devServo *DeviceService) *TelemetryService {
newService := &TelemetryService{ newService := &TelemetryService{
logger: logger, logger: logger,
cdash: cdash, devService: devServo,
listeners: make(map[string]chan telem.TelemetryData), 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 // Need to instantiate a default provider here
// source := "/home/esilva/Desktop/projetos/simracing_peripherals/testTelemetry/gt3_mustang_bathurst.ibt" // source := "/home/esilva/Desktop/projetos/simracing_peripherals/testTelemetry/gt3_mustang_bathurst.ibt"
firstProvider := providers.NewIRacingProvider(slog.Default(), goirsdk.Options{ firstProvider := providers.NewIRacingProvider(slog.Default(), goirsdk.Options{
@@ -5,11 +5,12 @@ import (
"os" "os"
"strconv" "strconv"
"esdi/cdashdisplay" "esdi/devices/cdashdisplay"
helper "esdi/helpers"
"esdi/services" "esdi/services"
"esdi/tui/internal/views" "esdi/tui/internal/views"
helper "esdi/helpers"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/rivo/tview" "github.com/rivo/tview"
) )
@@ -19,12 +20,14 @@ type LayoutController struct {
OnExit func() OnExit func()
LayoutToolView *views.LayoutToolView LayoutToolView *views.LayoutToolView
Messages chan string Messages chan string
DevService *services.CDashService DevService *services.DeviceService
MoveToolState *windowManipState MoveToolState *windowManipState
SelectedLayout string // NOTE: This should be a struct to handle its own things 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{ lc := &LayoutController{
Controller: base, Controller: base,
LayoutToolView: views.NewLayoutToolView(), LayoutToolView: views.NewLayoutToolView(),
@@ -207,7 +210,20 @@ func (lc *LayoutController) createWindow() {
return 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 { if err != nil {
lc.Messages <- "failed to create window\n" lc.Messages <- "failed to create window\n"
return return
@@ -304,7 +320,20 @@ func (lc *LayoutController) newWindowAction() {
} }
func (lc *LayoutController) updateWindowAction(win *cdashdisplay.DesktopUIWindow) { 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) lc.Messages <- fmt.Sprintf("Window: %v\n", win)
@@ -317,7 +346,20 @@ func (lc *LayoutController) updateWindowAction(win *cdashdisplay.DesktopUIWindow
func (lc *LayoutController) displayLoadedLayouts() { func (lc *LayoutController) displayLoadedLayouts() {
lc.Logger.Debug("We want to view our layout!") 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("==========================================================================")
lc.Logger.Debug(fmt.Sprintf("updating form view for a layout: %+v", w.UIData.TelemetryField)) lc.Logger.Debug(fmt.Sprintf("updating form view for a layout: %+v", w.UIData.TelemetryField))
err := lc.updateFormView(w) err := lc.updateFormView(w)
@@ -349,8 +391,21 @@ func (lc *LayoutController) getCurrentTreeNodeModel() (*tview.TreeNode, int16, e
} }
func (lc *LayoutController) loadLayout() { 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 // 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 { if err != nil {
lc.Messages <- "failed to load layout: " + err.Error() lc.Messages <- "failed to load layout: " + err.Error()
return return
@@ -360,7 +415,20 @@ func (lc *LayoutController) loadLayout() {
} }
func (lc *LayoutController) unloadLayout() { 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 { if err != nil {
lc.Logger.Error(fmt.Sprintf("Failed to unload layout: %+v", err)) lc.Logger.Error(fmt.Sprintf("Failed to unload layout: %+v", err))
return return
@@ -368,7 +436,20 @@ func (lc *LayoutController) unloadLayout() {
} }
func (lc *LayoutController) saveLayout() { 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 { if err != nil {
lc.Messages <- "failed to save layout: " + err.Error() lc.Messages <- "failed to save layout: " + err.Error()
return return
@@ -388,8 +469,21 @@ func (lc *LayoutController) deleteWindow() {
} }
wID := curNode.GetReference().(int16) 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 // Delete it
err := lc.DevService.DeleteWindow(wID) err = display.DestroyWindow(wID)
if err != nil { if err != nil {
lc.Messages <- "failed to delete window: " + err.Error() + "\n" lc.Messages <- "failed to delete window: " + err.Error() + "\n"
return return
@@ -1,6 +1,7 @@
package controllers package controllers
import ( import (
"esdi/devices/cdashdisplay"
helper "esdi/helpers" helper "esdi/helpers"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
@@ -43,40 +44,68 @@ func keyToVector(r rune) (helper.Vector, bool) {
} }
func (lc *LayoutController) handleMovementCapture(idx int16, func (lc *LayoutController) handleMovementCapture(idx int16,
ev *tcell.EventKey) *tcell.EventKey { ev *tcell.EventKey,
) *tcell.EventKey {
vec, ok := keyToVector(ev.Rune()) vec, ok := keyToVector(ev.Rune())
if !ok { if !ok {
return nil 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 { if err != nil {
lc.Messages <- "failed to move window: " + err.Error() + "\n" lc.Messages <- "failed to move window: " + err.Error() + "\n"
return nil return nil
} }
// Success - update the form // Success - update the form
window := lc.DevService.CDash.State.Layout.Windows[idx] window := display.State.Layout.Windows[idx]
lc.LayoutToolView.UpdateFormView(idx, window) lc.LayoutToolView.UpdateFormView(idx, window)
return nil return nil
} }
func (lc *LayoutController) handleResizeCapture(idx int16, func (lc *LayoutController) handleResizeCapture(idx int16,
ev *tcell.EventKey) *tcell.EventKey { ev *tcell.EventKey,
) *tcell.EventKey {
vec, ok := keyToVector(ev.Rune()) vec, ok := keyToVector(ev.Rune())
if !ok { if !ok {
return nil 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 { if err != nil {
lc.Messages <- "failed to resize window: " + err.Error() + "\n" lc.Messages <- "failed to resize window: " + err.Error() + "\n"
return nil return nil
} }
// Success - update the form // Success - update the form
window := lc.DevService.CDash.State.Layout.Windows[idx] window := display.State.Layout.Windows[idx]
lc.LayoutToolView.UpdateFormView(idx, window) lc.LayoutToolView.UpdateFormView(idx, window)
return nil return nil
+5 -4
View File
@@ -15,12 +15,12 @@ type DeviceController struct {
DeviceAPIView *views.DeviceAPIView DeviceAPIView *views.DeviceAPIView
LayoutCtrl *LayoutController LayoutCtrl *LayoutController
StreamCtrl *StreamingCtrl StreamCtrl *StreamingCtrl
DevService *serv.CDashService DevService *serv.DeviceService
} }
func NewDeviceController( func NewDeviceController(
base *Controller, base *Controller,
devService *serv.CDashService, devService *serv.DeviceService,
telemService *serv.TelemetryService, telemService *serv.TelemetryService,
) *DeviceController { ) *DeviceController {
mc := &DeviceController{ mc := &DeviceController{
@@ -56,7 +56,7 @@ func (mc *DeviceController) setDeviceAPIViewEvents() {
SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey {
switch ev.Rune() { switch ev.Rune() {
case 'r': case 'r':
go mc.DevService.FindDevice() go mc.DevService.FindDevices()
} }
return ev return ev
}) })
@@ -75,7 +75,8 @@ func (mc *DeviceController) AddDeviceAPIListItems() {
}) })
mc.DeviceAPIView.DevAPIList. mc.DeviceAPIView.DevAPIList.
AddItem("stream", "stream data to the display", func() { AddItem("stream", "stream data to the display", func() {
views.AddAndShowPage(mc.DeviceAPIView.DevAPIToolView.Pages, views.AddAndShowPage(
mc.DeviceAPIView.DevAPIToolView.Pages,
"streaming-tool", "streaming-tool",
mc.StreamCtrl.StreamView.Flex, mc.StreamCtrl.StreamView.Flex,
) )
+19 -5
View File
@@ -6,6 +6,7 @@ import (
"sync/atomic" "sync/atomic"
"esdi/config" "esdi/config"
"esdi/devices/cdashdisplay"
"esdi/providers" "esdi/providers"
"esdi/services" "esdi/services"
"esdi/telemetry" "esdi/telemetry"
@@ -17,7 +18,7 @@ import (
type StreamingCtrl struct { type StreamingCtrl struct {
*Controller *Controller
Service *services.CDashService Service *services.DeviceService
StreamView *views.StreamToolView StreamView *views.StreamToolView
Messages chan string Messages chan string
Internal chan string Internal chan string
@@ -32,7 +33,7 @@ type StreamingCtrl struct {
func NewStreamingCtrl( func NewStreamingCtrl(
base *Controller, base *Controller,
serCDash *services.CDashService, devService *services.DeviceService,
serTelem *services.TelemetryService, serTelem *services.TelemetryService,
) *StreamingCtrl { ) *StreamingCtrl {
// NOTE: looks sus, put this somewhere also. Not very good in here // NOTE: looks sus, put this somewhere also. Not very good in here
@@ -44,7 +45,7 @@ func NewStreamingCtrl(
ctrl := &StreamingCtrl{ ctrl := &StreamingCtrl{
Controller: base, Controller: base,
Service: serCDash, Service: devService,
TelemServ: serTelem, TelemServ: serTelem,
Messages: make(chan string, 10), Messages: make(chan string, 10),
Internal: 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 // Performance reasoning: this is not used during the high frequency data transmission
// so we can get away with using a map for convenience here // so we can get away with using a map for convenience here
func (sc *StreamingCtrl) SetInternalState() { 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) fieldID, _ := telemetry.GetFieldID(w.UIData.TelemetryField)
fields[w.UIData.IDX] = fieldID fields[w.UIData.IDX] = fieldID
} }
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"esdi/cdashdisplay" "esdi/devices/cdashdisplay"
tviewh "esdi/tui/internal/tview_helpers" tviewh "esdi/tui/internal/tview_helpers"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
+1 -1
View File
@@ -3,7 +3,7 @@ package views
import ( import (
"fmt" "fmt"
"esdi/cdashdisplay" "esdi/devices/cdashdisplay"
"esdi/telemetry" "esdi/telemetry"
"github.com/rivo/tview" "github.com/rivo/tview"
+3 -1
View File
@@ -23,7 +23,9 @@ func NewControlPanel(logger *slog.Logger) *ControlPanel {
App: tview.NewApplication(), App: tview.NewApplication(),
} }
devService := services.NewCDashService(logger) // NOTE: create our device service here
devService := services.NewDeviceService(logger)
telemService := services.NewTelemetryService(logger, devService) telemService := services.NewTelemetryService(logger, devService)
if telemService == nil { if telemService == nil {
panic("failed to create the telemetry service") panic("failed to create the telemetry service")