basic loop to discover providers

This commit is contained in:
2026-09-17 23:01:50 +01:00
parent afc4b794bb
commit a251f45859
6 changed files with 118 additions and 157 deletions
+33
View File
@@ -0,0 +1,33 @@
package beamng
import (
"log/slog"
"net"
"time"
)
func IsRunning() bool {
// The address should be loaded from some type of configuration
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:4443")
if err != nil {
return false
}
conn, err := net.ListenUDP("udp", addr)
defer conn.Close()
if err != nil {
slog.Debug("failed to listen to udp socket: " + err.Error())
return false
}
buf := make([]byte, 512)
conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond))
n, _, err := conn.ReadFromUDP(buf)
if err != nil {
return false
}
// Think of a better number or something
return n >= 80
}
+16
View File
@@ -0,0 +1,16 @@
package iracing
import "github.com/ESilva15/goirsdk"
func IsRunning() bool {
sdk, err := goirsdk.Init(goirsdk.Options{
SourceType: goirsdk.SharedMemoryFile,
})
if err != nil {
return false
}
sdk.Close()
return true
}
+23 -9
View File
@@ -14,28 +14,42 @@ import (
// Make this be some kind of struct where we can access a function that returns
// the selected provider by its name
type Provider struct {
Name string
Provider telemetry.TelemetryProvider
Name string
NewProvider func(*slog.Logger) telemetry.TelemetryProvider
IsRunning func() bool
}
var Providers = map[string]Provider{
beamng.NAME: {
Name: beamng.NAME,
Name: beamng.NAME,
NewProvider: NewBeamNGProvider,
IsRunning: beamng.IsRunning,
},
iracing.NAME: {
Name: iracing.NAME,
Name: iracing.NAME,
NewProvider: NewLiveIRacingProvider,
IsRunning: iracing.IsRunning,
},
}
func NewIRacingProvider(logger *slog.Logger, opts goirsdk.Options,
) telemetry.TelemetryProvider {
provider, _ := iracing.NewIRacingProvider(logger, opts)
// func NewIRacingProvider(logger *slog.Logger, opts goirsdk.Options,
// ) telemetry.TelemetryProvider {
// provider, _ := iracing.NewIRacingProvider(logger, opts)
//
// return provider
// }
func NewLiveIRacingProvider(logger *slog.Logger) telemetry.TelemetryProvider {
provider, _ := iracing.NewIRacingProvider(logger, goirsdk.Options{
SourceType: goirsdk.SharedMemoryFile,
})
return provider
}
func NewBeamNGProvider(ip string, port int) telemetry.TelemetryProvider {
provider, _ := beamng.NewBeamNGProvider(ip, port)
func NewBeamNGProvider(logger *slog.Logger) telemetry.TelemetryProvider {
// Get from some kind of config or whatever
provider, _ := beamng.NewBeamNGProvider("127.0.0.1", 4443)
return provider
}
-131
View File
@@ -1,131 +0,0 @@
package services
// 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 NewCDashService(logger *slog.Logger) *CDashService {
// // sharedChannel := make(chan string, 10)
// return &CDashService{
// Logger: logger,
// CDash: nil,
// // DevClerk: peripheral.NewPeripheralDeviceClerk(),
// // Messages: sharedChannel,
// }
// }
// func (ds *CDashService) FindDevice() {
// ds.Messages <- "looking for cdash display...\n"
// ds.Logger.Info("Looking for CDashDisplay")
// cdashdisplay.SetLogger(ds.Logger.With("[device]", "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"
// }
// 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)
// }
// func (ds *CDashService) SetTelemetryChannel(ch <-chan telemetry.TelemetryData) {
// ds.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
// 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)
// }
// }
// }
+44 -17
View File
@@ -4,11 +4,10 @@ import (
"context"
"log/slog"
"sync"
"time"
"esdi/providers"
telem "esdi/telemetry"
"github.com/ESilva15/goirsdk"
)
// TelemetryService will be our base struct to handle telemetry data
@@ -19,33 +18,61 @@ type TelemetryService struct {
// Concurrency protection
mut sync.RWMutex
ativeProvider telem.TelemetryProvider
isConnected bool
// Channel for the UI
listeners map[string]chan telem.TelemetryData
cancelForward context.CancelFunc
// Output window
Messages chan string
// Cancel looking for providers
CtxMonitor context.Context
cancelMonitor context.CancelFunc
}
func NewTelemetryService(logger *slog.Logger, devServo *DeviceService) *TelemetryService {
sharedChannel := make(chan string, 10)
newService := &TelemetryService{
logger: logger,
devService: devServo,
listeners: make(map[string]chan telem.TelemetryData),
logger: logger,
isConnected: false,
devService: devServo,
listeners: make(map[string]chan telem.TelemetryData),
Messages: sharedChannel,
}
// 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{
SourceType: goirsdk.SharedMemoryFile,
})
// firstProvider := providers.NewBeamNGProvider("127.0.0.1", 4443)
newService.SwitchProvider(firstProvider)
newService.CtxMonitor, newService.cancelMonitor = context.WithCancel(context.Background())
return newService
}
func (t *TelemetryService) OnFindProvider(prov providers.Provider) {
t.SwitchProvider(prov.NewProvider(t.logger))
t.logger.Debug("Found provider for " + prov.Name)
}
// TODO: add some way of retriggering this. Currently it should:
// start monitoring on startup -> find provider -> stop monitoring
func (t *TelemetryService) FindProvider(ctx context.Context, callback func(providers.Provider),
) {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
t.logger.Debug("monitoring for providers")
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
for _, prov := range providers.Providers {
t.logger.Debug("checking provider: " + prov.Name)
if prov.IsRunning() {
callback(prov)
return
}
t.logger.Debug(" wasn't read")
}
}
}
}
func (t *TelemetryService) SwitchProvider(newProvider telem.TelemetryProvider) error {
t.mut.Lock()
defer t.mut.Unlock()
+2
View File
@@ -31,6 +31,8 @@ func NewControlPanel(logger *slog.Logger) *ControlPanel {
panic("failed to create the telemetry service")
}
go telemService.FindProvider(telemService.CtxMonitor, telemService.OnFindProvider)
return &ControlPanel{
Controller: baseController,
DeviceController: controllers.NewDeviceController(baseController, devService, telemService),