diff --git a/providers/iracing/iracing.go b/providers/iracing/iracing.go index 65b5c01..268cd6a 100644 --- a/providers/iracing/iracing.go +++ b/providers/iracing/iracing.go @@ -126,6 +126,10 @@ func (i *IRacing) stream(ctx context.Context) { i.data.InitialTime = time.Now() go func() { + // Put this into the configuration file + consecutiveTimeouts := 0 + maxTimeouts := 30 + dataEvTimeout := 100 for { // Explicitly intercept cancellation select { @@ -134,17 +138,8 @@ func (i *IRacing) stream(ctx context.Context) { default: } - // TODO: fix this logic - // We start by checking if we do or do not have data available - // if !i.isDataAvailable() { - // i.logger.Info("isDataAvailable check failed. Cancelling stream...") - // i.streamCancel() - // } - - select { - case <-ctx.Done(): - return - case <-i.ticker.C: + if i.SDK.CheckForDataEvent(time.Duration(dataEvTimeout) * time.Millisecond) { + consecutiveTimeouts = 0 i.readData() // Publish data @@ -153,6 +148,15 @@ func (i *IRacing) stream(ctx context.Context) { default: // skip this data, don't allow publishers to lag behind } + } else { + consecutiveTimeouts++ + if consecutiveTimeouts >= maxTimeouts { + i.logger.Info("Telemetry stream stalled") + if i.streamCancel != nil { + i.streamCancel() + } + return + } } } }() @@ -175,7 +179,6 @@ func (i *IRacing) readData() { } // Set up virtual binds - i.logger.Debug("Entering virtual binds loop") for _, vBind := range i.data.VirtualBinds { vBind.Process(i.data) } diff --git a/providers/iracing/utils.go b/providers/iracing/utils.go index ac9d2df..268bd6a 100644 --- a/providers/iracing/utils.go +++ b/providers/iracing/utils.go @@ -1,35 +1,33 @@ package iracing import ( + "log" + "log/slog" + "time" + "github.com/ESilva15/goirsdk" + eventutils "github.com/ESilva15/goirsdk/eventutils" ) func IsRunning() bool { - sdk, err := goirsdk.Init(goirsdk.Options{ - SourceType: goirsdk.SharedMemoryFile, - }) - defer sdk.Close() + irUtils, err := eventutils.Init() if err != nil { - return false + log.Fatalf("Failed to initialize mmaputils: %v", err) + } + defer irUtils.Close() + + // 2. Connect to the OS event (Win32 Event on Windows, POSIX Semaphore on Linux) + if err := irUtils.OpenEvent(goirsdk.IRSDK_DATAVALIDEVENTNAME); err != nil { + log.Fatalf("Failed to open event: %v", err) } - // if sdk.SessionStateInvalid() { - // slog.Debug("state is invalid") - // sessionState, ok := sdk.Vars.Vars["SessionState"] - // if !ok { - // slog.Debug("SessionState not ok") - // return false - // } - // - // state, ok := sessionState.Value.(int) - // if !ok { - // slog.Debug(fmt.Sprintf("can't typecast: %+v", sessionState)) - // return false - // } - // - // slog.Debug(fmt.Sprintf("%d", state)) - // return false - // } + // We now check for some consecutive data events + for range 3 { + if !irUtils.CheckValidDataEvent(1 * time.Second) { + slog.Debug("timed out waiting for DataValidEvent") + return false + } + } return true }