private void Update(iRacingSDK sdk, Simulation sim) { sim.DataMutex.WaitOne(); var sessionInfoUpdate = sdk.Header.SessionInfoUpdate; var updateSessionInfo = false; if (sessionInfoUpdate != LastSessionInfoUpdate) { LastSessionInfoUpdate = sessionInfoUpdate; updateSessionInfo = true; } string sessionInfo = null; if (updateSessionInfo) { sessionInfo = sdk.GetSessionInfo(); } try { Update(sim, sessionInfo, updateSessionInfo); ((SimEventManager)sim.EventManager).ExecuteEvents(); } finally { sim.DataMutex.ReleaseMutex(); } }
/** * Very hacky/not robust regex fudge to 'discover' camera groups! Only called once per track */ private static void DiscoverCameras() { String yaml = sdk.GetSessionInfo(); int length = yaml.Length; int start = yaml.IndexOf("CameraInfo:\n", 0, length); int end = yaml.IndexOf("\n\n", start, length - start); string CameraInfo = yaml.Substring(start, end - start); length = CameraInfo.Length; start = CameraInfo.IndexOf(" Groups:\n", 0, length); end = length; string Cameras = CameraInfo.Substring(start, end - start - 1); string[] cameraList = Cameras.Split(new string[] { "\n - " }, StringSplitOptions.RemoveEmptyEntries); int groupNum; foreach (string camera in cameraList) { Regex groupNumReg = new Regex("^GroupNum: ([0-9]+)"); string[] groupNumResult = (from Match match in groupNumReg.Matches(camera) select match.Groups[1].Value).ToArray(); if (groupNumResult.Length < 1) { continue; } groupNum = Convert.ToInt16(groupNumResult[0]); Regex groupNameReg = new Regex("GroupName: ([\\w ]+)"); string[] groupNameResult = (from Match match in groupNameReg.Matches(camera) select match.Groups[1].Value).ToArray(); cameras.Add(groupNameResult[0], groupNum); } }
public void updateData() { // Check if the SDK is connected if (sdk.IsConnected()) { // telemetry gear = (Int32)sdk.GetData("Gear"); rpm = (Int32)(Single)sdk.GetData("RPM"); speed = (Int32)((Single)sdk.GetData("Speed") * 3.6); fuel = (Int32)((Single)sdk.GetData("FuelLevel")); shiftindicator = (Single)sdk.GetData("ShiftIndicatorPct"); Int32 enwarn = (Int32)sdk.GetData("EngineWarnings"); if (((Int32)sdk.GetData("EngineWarnings") & 0x10) > 0) { pitlimiter = true; } else { pitlimiter = false; } lap = (Int32)sdk.GetData("Lap"); lapsrem = (Int32)sdk.GetData("SessionLapsRemain"); Double sessionTime = new Double(); Boolean curontrack = (Boolean)sdk.GetData("IsOnTrack"); if (curontrack == false && ontrack == true) { SaveBestLap(); } ontrack = curontrack; if (ontrack) { sessionTime = (Double)sdk.GetData("SessionTime"); } else { sessionTime = (Double)sdk.GetData("ReplaySessionTime"); } if (carIdx >= 0) // skip things that require caridx if we don't have it { Int32[] driverLaps = new Int32[64]; driverLaps = (Int32[])sdk.GetData("CarIdxLap"); Single[] driverTrkPos = new Single[64]; driverTrkPos = (Single[])sdk.GetData("CarIdxLapDistPct"); Int32 lapPointer = (Int32)Math.Floor((driverTrkPos[carIdx] % 1) * (trackLength / 10)); timedelta.Update(sessionTime, driverTrkPos); if (driverTrkPos[carIdx] < 0.1 && lastTickTrackPos > 0.9) { Double distance = (1 - lastTickTrackPos) + driverTrkPos[carIdx]; Double time = sessionTime - lastTickTime; Double tickCorrection = (1 - lastTickTrackPos) / distance; // save lap time if (lapTimeValid) { Double laptime = (sessionTime - (1 - tickCorrection) * time) - lapStartTime; prevlap = new TimeSpan(0, 0, 0, (Int32)Math.Floor(laptime), (Int32)Math.Floor((laptime % 1) * 1000)); fuelcons[fuelconsPtr % fuelcons.Length] = (Single)sdk.GetData("FuelLevel"); // update fuel consumption after one full lap if (fuelconsPtr > 0) { if (fuelconsPtr >= fuelcons.Length) { Single[] consrate = new Single[fuelcons.Length - 1]; Int32 j = 0; for (int i = fuelconsPtr; i < fuelconsPtr + consrate.Length; i++) { consrate[j++] = fuelcons[(i + 1) % fuelcons.Length] - fuelcons[(i + 2) % fuelcons.Length]; } fuelneed = (Int32)(fuelcons[fuelconsPtr % fuelcons.Length] - (lapsrem * consrate.Average())); fuelconsumption = consrate.Average(); } else if (fuelconsPtr > 0) { fuelneed = (Int32)(fuelcons[fuelconsPtr % fuelcons.Length] - (lapsrem * fuelcons[(fuelconsPtr - 1) % fuelcons.Length])); fuelconsumption = fuelcons[(fuelconsPtr - 1) % fuelcons.Length] - fuelcons[fuelconsPtr % fuelcons.Length]; } } fuelconsPtr++; } // start new lap lapStartTime = sessionTime - (1 - tickCorrection) * time; lapTimeValid = true; } else if (Math.Abs(driverTrkPos[carIdx] - lastTickTrackPos) > 0.1) { // invalidate lap time if jumping too much lapTimeValid = false; } // reset fuel consumption when in pits TrackLocation[] trackSurface = (iRSDKSharp.TrackLocation[])sdk.GetData("CarIdxTrackSurface"); if (trackSurface[carIdx] == TrackLocation.irsdk_InPitStall) { fuelcons = new Single[fuelconslaps]; fuelconsPtr = 0; } lastTickTrackPos = driverTrkPos[carIdx]; // save for next tick lastTickTime = sessionTime; Int32[] driverCarIdx = new Int32[64]; if (sessiontype == SessionTypes.race) { // in race calculate who is infront using trackpct and lap number for (Int32 i = 0; i < 64; i++) { driverTrkPos[i] += (Single)driverLaps[i]; driverCarIdx[i] = i; } Array.Sort(driverTrkPos, driverCarIdx); Array.Reverse(driverCarIdx); position = (Int32)(Array.IndexOf(driverCarIdx, carIdx) + 1); delta = timedelta.GetDelta(carIdx, driverCarIdx[Math.Max(position - 2, 0)]); } else { if (sdk.Header.SessionInfoUpdate != lastSesInfoUpdate) { // parse position String yaml = sdk.GetSessionInfo(); Int32 sessionmatch = yaml.IndexOf(" - SessionNum: " + ((Int32)sdk.GetData("SessionNum")).ToString()); Int32 carmatch = yaml.IndexOf("CarIdx: " + carIdx.ToString(), sessionmatch); Int32 positionmatch = yaml.LastIndexOf("Position:", carmatch); if (positionmatch < 0) { position = 0; } else { position = Int32.Parse(yaml.Substring(positionmatch + "Position:".Length, 2)); } } delta = timedelta.GetBestLapDelta(driverTrkPos[carIdx] % 1); } } lastSesInfoUpdate = sdk.Header.SessionInfoUpdate; } else { init = false; } }
public void initialize() { sdk = new iRacingSDK(); sdk.Startup(); // check connection if (sdk.IsConnected()) { String yaml = sdk.GetSessionInfo(); // caridx Int32 start = yaml.IndexOf("DriverCarIdx: ") + "DriverCarIdx: ".Length; Int32 end = yaml.IndexOf("\n", start); carIdx = Int32.Parse(yaml.Substring(start, end - start)); // carname start = yaml.IndexOf("CarIdx: " + carIdx.ToString(), start); start = yaml.IndexOf("CarPath: ", start) + "CarPath: ".Length; end = yaml.IndexOf("\n", start); if (start < 0) { carname = "unknown"; } else { carname = yaml.Substring(start, end - start); } // track name start = yaml.IndexOf("TrackName: ") + "TrackName: ".Length; end = yaml.IndexOf("\n", start); if (start < 0) { trackname = "unknown"; } else { trackname = yaml.Substring(start, end - start); } // track length start = yaml.IndexOf("TrackLength: ") + "TrackLength: ".Length; end = yaml.IndexOf("km\n", start); String dbg = yaml.Substring(start, end - start); trackLength = (Int32)(Single.Parse(yaml.Substring(start, end - start)) * 1000); // session types RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled; MatchCollection sessionNums, sessionTypes; Regex optionRegex = new Regex(@"SessionNum: (\d+)", options); // Get matches of pattern in yaml sessionNums = optionRegex.Matches(yaml); optionRegex = new Regex(@"SessionType: (\w+)", options); sessionTypes = optionRegex.Matches(yaml); Int32 currentSessionNum = (Int32)sdk.GetData("SessionNum"); // Iterate matches for (Int32 ctr = 0; ctr < Math.Min(sessionNums.Count, sessionTypes.Count); ctr++) { if (Int32.Parse(sessionNums[ctr].Value.Substring(12)) == currentSessionNum) { switch (sessionTypes[ctr].Value.Substring(13).Trim()) { case "Practice": sessiontype = iRacing.SessionTypes.practice; break; case "Qualify": sessiontype = iRacing.SessionTypes.qualify; break; case "Race": sessiontype = iRacing.SessionTypes.race; break; default: sessiontype = iRacing.SessionTypes.invalid; break; } } } // reset laptimes lapStartTime = (Double)sdk.GetData("ReplaySessionTime"); lapTimeValid = false; // fuel consumption, last 5 lap rolling fuelcons = new Single[fuelconslaps]; fuelconsPtr = 0; // init timedelta timedelta = new TimeDelta(trackLength); timedelta.SaveBestLap(carIdx); LoadBestLap(); init = true; } else // retry next tick { init = false; } }
private void Loop(CancellationToken cancellationToken) { int lastUpdate = -1; bool hasConnected = false; while (!cancellationToken.IsCancellationRequested) { // Check if we can find the sim if (sdk.IsConnected()) { if (!IsConnected) { // If this is the first time, raise the Connected event RaiseEvent(OnStarted, EventArgs.Empty); connectionSource.TrySetResult(); } hasConnected = true; IsConnected = true; readMutex.WaitOne(8); // Update telemetry info TelemetryData = new TelemetryData(sdk); // Update session info int newUpdate = sdk.Header.SessionInfoUpdate; if (newUpdate != lastUpdate) { RawSessionData = sdk.GetSessionInfo(); SessionData = deserializer.Deserialize <SessionData>(RawSessionData); var args = new SessionInfoChangedEventArgs(SessionData, (double)sdk.GetData("SessionTime")); RaiseEvent(OnSessionInfoChanged, args); if (lastUpdate == -1) { firstDataSource.TrySetResult(); } lastUpdate = newUpdate; } // Send telemetry event now to make sure both data is updated when either event is thrown var telArgs = new TelemetryInfoChangedEventArgs(TelemetryData, (double)sdk.GetData("SessionTime")); RaiseEvent(OnTelemetryInfoChanged, telArgs); } else if (hasConnected) { // We have already been initialized before, so the sim is closing RaiseEvent(OnStopped, EventArgs.Empty); SessionData = null; TelemetryData = null; sdk.Shutdown(); lastUpdate = -1; IsConnected = false; hasConnected = false; } else { // Have not been initialized before and there is no connection. Try to find the sim. IsConnected = false; hasConnected = false; sdk.Startup(); } // Sleep for a short amount of time until the next update is available if (IsConnected) { if (waitTime <= 0 || waitTime > 1000) { waitTime = 15; } Thread.Sleep(waitTime); } else { // Not connected yet, no need to check every 16 ms, let's try again in some time Thread.Sleep(ConnectSleepTime); } } sdk.Shutdown(); IsConnected = false; }
private static string callbackCamera = "TV1"; // camera group to switch to when the client requests it static void Main(string[] args) { sdk = new iRacingSDK(); int lastUpdate = -1; //setup WebSocketServer var allSockets = new List <IWebSocketConnection>(); var server = new WebSocketServer("ws://localhost:8181"); server.Start(socket => { socket.OnOpen = () => { Console.WriteLine("Client Connected"); allSockets.Add(socket); }; socket.OnClose = () => { Console.WriteLine("Client Disconnected"); allSockets.Remove(socket); }; socket.OnMessage = message => { Console.WriteLine("Received -> " + message); int groupNum = cameras[callbackCamera]; sdk.BroadcastMessage(BroadcastMessageTypes.CamSwitchNum, Convert.ToInt32(message), groupNum, 0); }; }); while (true) { if (sdk.IsConnected()) { //If it is connected then see if the Session Info has been updated int newUpdate = sdk.Header.SessionInfoUpdate; if (telemData.getTrackId() == 0) { telemData.setTrackId(Convert.ToInt32(YamlParser.Parse(sdk.GetSessionInfo(), "WeekendInfo:TrackID:"))); DiscoverCameras(); } if (newUpdate != lastUpdate) { // Session Info updated (e.g. perhaps a client has connected/disconnected) lastUpdate = newUpdate; // Update the current Driver list string yaml = sdk.GetSessionInfo(); length = yaml.Length; start = yaml.IndexOf("DriverInfo:\n", 0, length); end = yaml.IndexOf("\n\n", start, length - start); string DriverInfo = yaml.Substring(start, end - start); ParseDrivers(DriverInfo); } UpdateDriverPositions(drivers); foreach (var socket in allSockets.ToList()) { Console.WriteLine("Broadcast sent..."); Console.WriteLine(telemData.toJson()); socket.Send(telemData.toJson()); } } else if (sdk.IsInitialized) { drivers.Clear(); cameras.Clear(); telemData.setTrackId(0); sdk.Shutdown(); lastUpdate = -1; } else { drivers.Clear(); cameras.Clear(); telemData.setTrackId(0); Console.WriteLine("NOT CONNECTED!"); sdk.Startup(); } System.Threading.Thread.Sleep(1000); } }
public void initialize() { sdk = new iRacingSDK(); sdk.Startup(); // check connection if (sdk.IsConnected()) { String yaml = sdk.GetSessionInfo(); // caridx Int32 start = yaml.IndexOf("DriverCarIdx: ") + "DriverCarIdx: ".Length; Int32 end = yaml.IndexOf("\n", start); carIdx = Int32.Parse(yaml.Substring(start, end - start)); // carname start = yaml.IndexOf("CarIdx: " + carIdx.ToString(), start); start = yaml.IndexOf("CarPath: ", start) + "CarPath: ".Length; end = yaml.IndexOf("\n", start); if (start < 0) carname = "unknown"; else carname = yaml.Substring(start, end - start); // track name start = yaml.IndexOf("TrackName: ") + "TrackName: ".Length; end = yaml.IndexOf("\n", start); if (start < 0) trackname = "unknown"; else trackname = yaml.Substring(start, end - start); // track length start = yaml.IndexOf("TrackLength: ") + "TrackLength: ".Length; end = yaml.IndexOf("km\n", start); String dbg = yaml.Substring(start, end - start); trackLength = (Int32)(Single.Parse(yaml.Substring(start, end - start)) * 1000); // session types RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled; MatchCollection sessionNums, sessionTypes; Regex optionRegex = new Regex(@"SessionNum: (\d+)", options); // Get matches of pattern in yaml sessionNums = optionRegex.Matches(yaml); optionRegex = new Regex(@"SessionType: (\w+)", options); sessionTypes = optionRegex.Matches(yaml); Int32 currentSessionNum = (Int32)sdk.GetData("SessionNum"); // Iterate matches for (Int32 ctr = 0; ctr < Math.Min(sessionNums.Count, sessionTypes.Count); ctr++) { if (Int32.Parse(sessionNums[ctr].Value.Substring(12)) == currentSessionNum) { switch (sessionTypes[ctr].Value.Substring(13).Trim()) { case "Practice": sessiontype = iRacing.SessionTypes.practice; break; case "Qualify": sessiontype = iRacing.SessionTypes.qualify; break; case "Race": sessiontype = iRacing.SessionTypes.race; break; default: sessiontype = iRacing.SessionTypes.invalid; break; } } } // reset laptimes lapStartTime = (Double)sdk.GetData("ReplaySessionTime"); lapTimeValid = false; // fuel consumption, last 5 lap rolling fuelcons = new Single[fuelconslaps]; fuelconsPtr = 0; // init timedelta timedelta = new TimeDelta(trackLength); timedelta.SaveBestLap(carIdx); LoadBestLap(); init = true; } else // retry next tick { init = false; } }