So, we got the telemetry service going and it polls back to the UI
This commit is contained in:
@@ -9,18 +9,21 @@ import (
|
||||
)
|
||||
|
||||
type CDashService struct {
|
||||
Logger *slog.Logger
|
||||
CDash *cdashdisplay.CDashDisplay
|
||||
DevClerk *peripheral.PeripheralDeviceClerk
|
||||
Messages chan string
|
||||
Logger *slog.Logger
|
||||
CDash *cdashdisplay.CDashDisplay
|
||||
iRacingTelemetry *IRacingService
|
||||
DevClerk *peripheral.PeripheralDeviceClerk
|
||||
Messages chan string
|
||||
}
|
||||
|
||||
func NewCDashService(logger *slog.Logger) *CDashService {
|
||||
sharedChannel := make(chan string, 10)
|
||||
return &CDashService{
|
||||
Logger: logger,
|
||||
CDash: nil,
|
||||
DevClerk: peripheral.NewPeripheralDeviceClerk(),
|
||||
Messages: make(chan string, 10),
|
||||
Logger: logger,
|
||||
CDash: nil,
|
||||
DevClerk: peripheral.NewPeripheralDeviceClerk(),
|
||||
Messages: sharedChannel,
|
||||
iRacingTelemetry: NewIRacingService(sharedChannel),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,3 +93,15 @@ func (cds *CDashService) MoveWindow(win *models.UIWindow, vec *helper.Vector) er
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cds *CDashService) StartStream() {
|
||||
cds.iRacingTelemetry.StartStream()
|
||||
}
|
||||
|
||||
func (cds *CDashService) GetStream() <-chan string {
|
||||
return cds.iRacingTelemetry.GetStream()
|
||||
}
|
||||
|
||||
func (cds *CDashService) StopStream() {
|
||||
cds.iRacingTelemetry.StopStream()
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package services
|
||||
|
||||
// NOTE: I have to think about how to implement this, for now I'm bruteforcing
|
||||
// iracing support only. But I should have a generic service that can gather
|
||||
// telemetry from multiples sims and just publish it in an internal format
|
||||
|
||||
import (
|
||||
"context"
|
||||
esdi "esdi/oldEsdi"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ESilva15/goirsdk"
|
||||
)
|
||||
|
||||
// Car data lengths
|
||||
const (
|
||||
SpeedLen = 5
|
||||
GearLen = 3
|
||||
RpmLen = 6
|
||||
BrakeBiasLen = 6
|
||||
)
|
||||
|
||||
type StreamState int
|
||||
|
||||
const (
|
||||
StreamStatePaused StreamState = 0
|
||||
StreamStateRunning StreamState = 1
|
||||
StreamStateOff StreamState = 2
|
||||
)
|
||||
|
||||
type IRacingService struct {
|
||||
Message chan string
|
||||
LastMessageTime time.Time
|
||||
Data *esdi.SimulationData
|
||||
DataView *esdi.DataPacket
|
||||
InitialTime time.Time
|
||||
LastTime time.Time
|
||||
Mut sync.Mutex
|
||||
ticker *time.Ticker
|
||||
Irsdk *goirsdk.IBT
|
||||
//
|
||||
isRunning bool
|
||||
Stream chan string
|
||||
StreamCancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewIRacingService(msg chan string) *IRacingService {
|
||||
// Open the telemetry file
|
||||
file, err := os.Open("/home/esilva/Desktop/projetos/simracing_peripherals/testTelemetry/supercars_indianapolis.ibt")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open IBT file: %v", err)
|
||||
}
|
||||
|
||||
irsdk, err := goirsdk.Init(file, "./out.ibt", "./out.yaml")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load iRacing data")
|
||||
}
|
||||
|
||||
return &IRacingService{
|
||||
Message: msg,
|
||||
ticker: time.NewTicker(time.Second / 60),
|
||||
Irsdk: irsdk,
|
||||
Stream: make(chan string, 10),
|
||||
Data: &esdi.SimulationData{},
|
||||
DataView: &esdi.DataPacket{},
|
||||
isRunning: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (irs *IRacingService) GetStream() <-chan string {
|
||||
return irs.Stream
|
||||
}
|
||||
|
||||
func (irs *IRacingService) StartStream() {
|
||||
if irs.isRunning {
|
||||
return
|
||||
}
|
||||
|
||||
var ctx context.Context
|
||||
ctx, irs.StreamCancel = context.WithCancel(context.Background())
|
||||
|
||||
irs.startStream(ctx)
|
||||
irs.isRunning = true
|
||||
}
|
||||
|
||||
func (irs *IRacingService) StopStream() {
|
||||
if irs.StreamCancel != nil {
|
||||
irs.StreamCancel()
|
||||
}
|
||||
}
|
||||
|
||||
func (irs *IRacingService) startStream(ctx context.Context) {
|
||||
irs.Message <- "STARTING THIS\n"
|
||||
irs.InitialTime = time.Now()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
irs.Message <- "CONTEXT SAID WE ARE DONE\n"
|
||||
return
|
||||
case <-irs.ticker.C:
|
||||
irs.Message <- "GOT A TICK\n"
|
||||
irs.ReadData(ctx)
|
||||
irs.Stream <- irs.Stringified()
|
||||
}
|
||||
irs.Message <- "we are we going???\n"
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (irs *IRacingService) ReadData(ctx context.Context) {
|
||||
irs.Mut.Lock()
|
||||
defer irs.Mut.Unlock()
|
||||
|
||||
var err error
|
||||
|
||||
_, err = irs.Irsdk.Update(time.Millisecond * 100)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
irs.getVehicleData()
|
||||
|
||||
// Test the actual dataPacket we are sending over the wire
|
||||
copyBytes(irs.DataView.Speed[:], SpeedLen, fmt.Sprintf("%3d", irs.Data.Speed))
|
||||
copyBytes(irs.DataView.Gear[:], GearLen, fmt.Sprintf("%2d", irs.Data.Gear))
|
||||
copyBytes(irs.DataView.RPM[:], RpmLen, fmt.Sprintf("%3d", irs.Data.RPM))
|
||||
|
||||
irs.LastMessageTime = time.Now()
|
||||
}
|
||||
|
||||
func (irs *IRacingService) getVehicleData() {
|
||||
curGear := irs.Irsdk.Vars.Vars["Gear"].Value
|
||||
curRPM := irs.Irsdk.Vars.Vars["RPM"].Value
|
||||
curSpeed := irs.Irsdk.Vars.Vars["Speed"].Value
|
||||
|
||||
irs.Data.Gear = int32(curGear.(int))
|
||||
irs.Data.RPM = int32(curRPM.(float32))
|
||||
irs.Data.Speed = int32(msToKph(curSpeed.(float32)))
|
||||
}
|
||||
|
||||
func copyBytes(dest []byte, destSize int, src string) {
|
||||
copy(dest[:], []byte(src))
|
||||
dest[min(destSize-1, len(src))] = '\x00'
|
||||
}
|
||||
|
||||
func msToKph(v float32) int {
|
||||
return int((3600 * v) / 1000)
|
||||
}
|
||||
|
||||
func (irs *IRacingService) Stringified() string {
|
||||
var buffer strings.Builder
|
||||
|
||||
irs.Mut.Lock()
|
||||
sessionTimeR := irs.Irsdk.Vars.Vars["SessionTime"].Value
|
||||
sessionTime := float64(sessionTimeR.(float64))
|
||||
|
||||
currTime := time.Now()
|
||||
delta := currTime.Sub(irs.LastTime)
|
||||
buffer.WriteString(fmt.Sprintf("[%s]\n", currTime.Format("2006/01/02 15:04:05.000")))
|
||||
buffer.WriteString(fmt.Sprintf("Delta: %d [%f]\n\n", delta.Milliseconds(), 1000.0/60.0))
|
||||
irs.LastTime = currTime
|
||||
|
||||
elapsed := currTime.Sub(irs.InitialTime)
|
||||
softwareElapsed := time.Unix(0, 0).Add(elapsed).Format("04:05.000")
|
||||
sessionElapsed := time.Unix(0, 0).
|
||||
Add(time.Duration(sessionTime * float64(time.Second))).
|
||||
Format("04:05.000")
|
||||
|
||||
buffer.WriteString(fmt.Sprintf("Elapsed (software): %s\n",
|
||||
softwareElapsed))
|
||||
buffer.WriteString(fmt.Sprintf("Elapsed (session): %s\n\n",
|
||||
sessionElapsed))
|
||||
|
||||
// buffer.WriteString("Car data:\n")
|
||||
buffer.WriteString(fmt.Sprintf("Gear: %d, RPM: %d, Speed: %d\n\n",
|
||||
irs.Data.Gear, irs.Data.RPM, irs.Data.Speed))
|
||||
|
||||
// buffer.WriteString("Fuel data:\n")
|
||||
// buffer.WriteString(fmt.Sprintf("Fuel Est: %s\n\n", e.dataPacket.FuelEst))
|
||||
|
||||
// buffer.WriteString("Lap data:\n")
|
||||
// buffer.WriteString(fmt.Sprintf("Delta: [%s] [%f] [%s]\n", e.dataPacket.DeltaToBestLap,
|
||||
// e.data.LapDeltaFloat, lapTimeDeltaRepresentation(e.data.LapDeltaFloat)))
|
||||
// buffer.WriteString(fmt.Sprintf("LapTime: %s\n", e.dataPacket.CurrLapTime))
|
||||
// buffer.WriteString(fmt.Sprintf("Best Lap Time: %s\n", e.dataPacket.BestLapTime))
|
||||
// buffer.WriteString(fmt.Sprintf("Last Lap Time: %s\n", e.dataPacket.LastLapTime))
|
||||
// buffer.WriteString(fmt.Sprintf("LapBestNLapTi: %f\n\n", e.data.LapBestNLapTime))
|
||||
|
||||
// buffer.WriteString("Position data:\n")
|
||||
// buffer.WriteString(fmt.Sprintf("Pos: %d\n", e.dataPacket.Position))
|
||||
|
||||
// for p, v := range e.dataPacket.Standings {
|
||||
// s := fmt.Sprintf("[%2d] %s %-16s %-16s\n",
|
||||
// p+1, v.Lap, string(bytes.Trim(v.DriverName[:], "\x00")), v.TimeBehindString)
|
||||
// buffer.WriteString(s)
|
||||
// }
|
||||
|
||||
// buffer.WriteString(fmt.Sprintf("Size: %v\n", binary.Size(DataPacket{})))
|
||||
// buffer.WriteString(fmt.Sprintf("Recv: %d\n", e.data.Recv))
|
||||
// buffer.WriteString(fmt.Sprintf("Recv Err: %v\n", e.data.ReadError))
|
||||
|
||||
irs.Mut.Unlock()
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package services interacts with the other libraries required for this UI
|
||||
package services
|
||||
Reference in New Issue
Block a user