public async Task SendTrafficAsync(AircraftStatus status) { int icaoAddress; try { await sm.WaitAsync(); if (callsignToICAO.TryGetValue(status.Callsign, out var icao)) { icaoAddress = icao; } else { icaoAddress = currentIcao++; callsignToICAO.TryAdd(status.Callsign, currentIcao); } } finally { sm.Release(); } if (udpClient != null) { var dataString = $"XTRAFFICFlight Events,{icaoAddress},{status.Latitude:0.######},{status.Longitude:0.######},{status.Altitude:0.#},{status.VerticalSpeed:0.#},{(status.IsOnGround ? 0 : 1)},{status.TrueHeading:0.#},{status.GroundSpeed:0.#},{status.Callsign}"; var trafficData = Encoding.UTF8.GetBytes(dataString); var sent = await udpClient.SendAsync(trafficData, trafficData.Length); logger.LogDebug($"Sent {sent}/{trafficData.Length} bytes for Traffic."); logger.LogTrace(dataString); } }
private void DetectTakeOffLanding(AircraftStatus status) { if (lastStatus == null || status.IsOnGround != lastStatus.IsOnGround) { groundStateChanged = Timestamps.Now; } }
protected override Task OnWillDisappear(ActionEventArgs <AppearancePayload> args) { this.flightConnector.AircraftStatusUpdated -= FlightConnector_AircraftStatusUpdated; status = null; return(Task.CompletedTask); }
public AircraftStatusBrief(AircraftStatus status) { Latitude = status.Latitude; Longitude = status.Longitude; Altitude = status.Altitude; IsOnGround = status.IsOnGround; }
/// <summary> /// Compares the race place (i.e. 1st, 2nd, 3rd, etc) /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns>-1 if a is before b, 0 if equal, 1 if b is before a</returns> private int PlaceCompare(AircraftAgent a, AircraftAgent b) { AircraftStatus statusA = aircraftStatuses[a]; AircraftStatus statusB = aircraftStatuses[b]; int checkPointA = statusA.checkpointIndex + (statusA.lap - 1) * aircraftArea.Checkpoints.Count; int checkPointB = statusB.checkpointIndex + (statusB.lap - 1) * aircraftArea.Checkpoints.Count; if (checkPointA == checkPointB) { // Compare distance to the next checkpoint Vector3 nextCheckpointPosition = GetAgentNextCheckpoint(a).position; int compare = Vector3.Distance(a.transform.position, nextCheckpointPosition) .CompareTo(Vector3.Distance(b.transform.position, nextCheckpointPosition)); return(compare); } else { // Compare number of checkpoints hit // The agent with more checkpoints is // ahead (lower place), so we flip the compare int compare = -1 * checkPointA.CompareTo(checkPointB); return(compare); } }
protected override async Task OnWillAppear(ActionEventArgs <AppearancePayload> args) { action = args.Action; status = null; setValues(args.Payload.Settings); this.flightConnector.AircraftStatusUpdated += FlightConnector_AircraftStatusUpdated; await UpdateImage(); }
protected override Task OnWillAppear(ActionEventArgs <AppearancePayload> args) { var settings = args.Payload.GetSettings <PresetToggleSettings>(); InitializeSettings(settings); status = null; this.flightConnector.AircraftStatusUpdated += FlightConnector_AircraftStatusUpdated; return(Task.CompletedTask); }
private async void FlightConnector_AircraftStatusUpdated(object sender, AircraftStatusUpdatedEventArgs e) { if (StreamDeck == null) { return; } var lastStatus = status; status = e.AircraftStatus; switch (action) { case "tech.flighttracker.streamdeck.master.activate": if (e.AircraftStatus.IsAutopilotOn != lastStatus?.IsAutopilotOn) { logger.LogInformation("Received AP update: {state}", e.AircraftStatus.IsAutopilotOn); await UpdateImage(); } break; case "tech.flighttracker.streamdeck.heading.activate": if (e.AircraftStatus.ApHeading != lastStatus?.ApHeading || e.AircraftStatus.IsApHdgOn != lastStatus?.IsApHdgOn) { logger.LogInformation("Received HDG update: {IsApHdgOn} {ApHeading}", e.AircraftStatus.IsApHdgOn, e.AircraftStatus.ApHeading); await UpdateImage(); } break; case "tech.flighttracker.streamdeck.nav.activate": if (e.AircraftStatus.IsApNavOn != lastStatus?.IsApNavOn) { logger.LogInformation("Received NAV update: {IsApNavOn}", e.AircraftStatus.IsApNavOn); await UpdateImage(); } break; case "tech.flighttracker.streamdeck.approach.activate": if (e.AircraftStatus.IsApAprOn != lastStatus?.IsApAprOn) { logger.LogInformation("Received APR update: {IsApAprOn}", e.AircraftStatus.IsApAprOn); await UpdateImage(); } break; case "tech.flighttracker.streamdeck.altitude.activate": if (e.AircraftStatus.ApAltitude != lastStatus?.ApAltitude || e.AircraftStatus.IsApAltOn != lastStatus?.IsApAltOn) { logger.LogInformation("Received ALT update: {IsApHdgOn} {ApHeading}", e.AircraftStatus.IsApAltOn, e.AircraftStatus.ApAltitude); await UpdateImage(); } break; } }
private void FixedUpdate() { if (GameManager.Instance.GameState == GameState.Playing) { //Update the place list every half second if (lastPlaceUpdate + .5f < Time.fixedTime) { lastPlaceUpdate = Time.fixedTime; if (sortedAircraftAgents == null) { //Get a copy of the list of agents for sorting sortedAircraftAgents = new List <AircraftAgent>(aircraftArea.AircraftAgents); } //Recalculate race places sortedAircraftAgents.Sort((a, b) => PlaceCompare(a, b)); for (int i = 0; i < sortedAircraftAgents.Count; i++) { aircraftStatuses[sortedAircraftAgents[i]].place = i + 1; } } //Update agent statuses foreach (AircraftAgent agent in aircraftArea.AircraftAgents) { AircraftStatus status = aircraftStatuses[agent]; //Update Agetn lap if (status.checkpointIndex != agent.NextCheckpointIndex) { status.checkpointIndex = agent.NextCheckpointIndex; status.timeRemaining = checkpointBonusTime; if (status.checkpointIndex == 0) { status.lap++; if (agent == FollowAgent && status.lap > numLaps) { GameManager.Instance.GameState = GameState.GameOver; } } } //Update agent time remaining status.timeRemaining = Mathf.Max(0f, status.timeRemaining - Time.fixedDeltaTime); if (status.timeRemaining == 0f) { aircraftArea.ResetAgentPosition(agent); status.timeRemaining = checkpointBonusTime; } } } }
private void InitializeUiElements() { _airplaneStateGrid = this.FindControl <Grid>("airplaneStateGrid"); _overlayGrid = this.FindControl <Grid>("overlayGrid"); _atcMessagesDataGrid = this.FindControl <DataGrid>("atcMessagesDataGrid"); _ipLabel = this.FindControl <TextBlock>("ipLabel"); _txtLandingRoll = this.FindControl <TextBlock>("txtLandingRoll"); _txtLandingRollLabel = this.FindControl <TextBlock>("txtLandingRollLabel"); _mainTabControl = this.FindControl <TabControl>("mainTabControl"); _expander = this.FindControl <Expander>("expander"); _TabItem_ATC = this.FindControl <TabItem>("TabItem_ATC"); _landingDetails = this.FindControl <LandingStats>("landingDetails"); _FMSControl = this.FindControl <FMS>("FMSControl"); _AttitudeIndicator = this.FindControl <AttitudeIndicator>("AttitudeIndicator"); _AircraftStateControl = this.FindControl <AircraftStatus>("AircraftStateControl"); _FpdControl = this.FindControl <FlightPlanDb>("FpdControl"); }
/// <summary> /// Starts a countdown at the beginning of the race /// </summary> /// <returns>yield return</returns> private IEnumerator StartRace() { //Show Countdown countdownUI.gameObject.SetActive(true); yield return(countdownUI.StartCountdown()); //Initialize agent status tracking aircraftStatuses = new Dictionary <AircraftAgent, AircraftStatus>(); foreach (AircraftAgent agent in aircraftArea.AircraftAgents) { AircraftStatus status = new AircraftStatus(); status.lap = 1; status.timeRemaining = checkpointBonusTime; aircraftStatuses.Add(agent, status); } //Begin Playing GameManager.Instance.GameState = GameState.Playing; }
private async void Hub_OnAircraftUpdated(string clientId, AircraftStatus status) { if (viewModel.IsTracking && viewModel.AircraftStatus != null && GpsHelper.CalculateDistance(status.Latitude, status.Longitude, viewModel.AircraftStatus.Latitude, viewModel.AircraftStatus.Longitude) < 10000) { try { var pref = await userPreferencesLoader.LoadAsync(); if (pref.ClientId != clientId) { await udpBroadcastLogic.SendTrafficAsync(status); } } catch (Exception ex) { logger.LogError(ex, "Cannot send network package!"); } } }
public async Task SendGpsAsync(AircraftStatus status) { if (udpClient != null) { await gpsDataSender.ExecuteAsync(async() => { var gpsData = Encoding.UTF8.GetBytes($"XGPSFlight Events,{status.Longitude:0.######},{status.Latitude:0.######},{status.Altitude * FeetToMeters:0.#)},{status.TrueHeading:0.#},{status.GroundSpeed * KnotsToMetersPerSecond:0.#}"); var sent = await udpClient.SendAsync(gpsData, gpsData.Length); logger.LogDebug($"Sent {sent}/{gpsData.Length} bytes for GPS."); }); } } public async Task SendAttitudeAsync(AircraftStatus status) { if (udpClient != null) { await attDataSender.ExecuteAsync(async() => { var statusData = Encoding.UTF8.GetBytes($"XATTFlight Events,{status.TrueHeading:0.#},{-status.Pitch:0.#},{-status.Bank:0.#}"); var sent = await udpClient.SendAsync(statusData, statusData.Length); logger.LogDebug($"Sent {sent}/{statusData.Length} bytes for ATT."); }); }
private async void FlightConnector_AircraftStatusUpdated(object sender, AircraftStatusUpdatedEventArgs e) { if (StreamDeck == null) { return; } var lastStatus = status; status = e.AircraftStatus; switch (settings?.Type) { case PresetFunction.Avionics: if (e.AircraftStatus.IsAvMasterOn != lastStatus?.IsAvMasterOn) { logger.LogInformation("Received AV Master update: {state}", e.AircraftStatus.IsAvMasterOn); await UpdateImage(); } break; case PresetFunction.ApMaster: if (e.AircraftStatus.IsAutopilotOn != lastStatus?.IsAutopilotOn) { logger.LogInformation("Received AP update: {state}", e.AircraftStatus.IsAutopilotOn); await UpdateImage(); } break; case PresetFunction.Heading: if (e.AircraftStatus.ApHeading != lastStatus?.ApHeading || e.AircraftStatus.IsApHdgOn != lastStatus?.IsApHdgOn) { logger.LogInformation("Received HDG update: {IsApHdgOn} {ApHeading}", e.AircraftStatus.IsApHdgOn, e.AircraftStatus.ApHeading); await UpdateImage(); } break; case PresetFunction.Nav: if (e.AircraftStatus.IsApNavOn != lastStatus?.IsApNavOn) { logger.LogInformation("Received NAV update: {IsApNavOn}", e.AircraftStatus.IsApNavOn); await UpdateImage(); } break; case PresetFunction.Altitude: if (e.AircraftStatus.ApAltitude != lastStatus?.ApAltitude || e.AircraftStatus.IsApAltOn != lastStatus?.IsApAltOn) { logger.LogInformation("Received ALT update: {IsApAltOn} {ApAltitude}", e.AircraftStatus.IsApAltOn, e.AircraftStatus.ApAltitude); await UpdateImage(); } break; case PresetFunction.VerticalSpeed: if (e.AircraftStatus.ApVs != lastStatus?.ApVs || e.AircraftStatus.IsApVsOn != lastStatus?.IsApVsOn) { logger.LogInformation("Received VS update: {IsApVsOn} {ApVerticalSpeed}", e.AircraftStatus.IsApVsOn, e.AircraftStatus.ApVs); await UpdateImage(); } break; case PresetFunction.FLC: if (e.AircraftStatus.ApAirspeed != lastStatus?.ApAirspeed || e.AircraftStatus.IsApFlcOn != lastStatus?.IsApFlcOn) { logger.LogInformation("Received FLC update: {IsApFlcOn}", e.AircraftStatus.IsApFlcOn); await UpdateImage(); } break; case PresetFunction.Approach: if (e.AircraftStatus.IsApAprOn != lastStatus?.IsApAprOn) { logger.LogInformation("Received APR update: {IsApAprOn}", e.AircraftStatus.IsApAprOn); await UpdateImage(); } break; } }
private async void FlightConnector_AircraftStatusUpdated(object sender, AircraftStatusUpdatedEventArgs e) { if (!isStarted) { return; } var status = e.AircraftStatus; DetectTakeOffLanding(status); lastStatus = status; await updateExecutor.ExecuteAsync(async() => { if (Math.Abs(status.Latitude) < 0.02 && Math.Abs(status.Longitude) < 0.02) { if (isStarted) { Debug.WriteLine(e.AircraftStatus.Latitude + " " + e.AircraftStatus.Longitude); Debug.WriteLine("Latitude less than .02, Longitude less than .02. Setting to Preparing."); SetPreparing(); } } else { try { string icao = lastICAO; string airport = lastAirport; await geocodeExecutor.ExecuteAsync(async() => { try { Debug.Write(e.AircraftStatus.Latitude + e.AircraftStatus.Longitude); var dataString = await httpClient.GetStringAsync($"http://iatageo.com/getCode/{e.AircraftStatus.Latitude.ToString(CultureInfo.InvariantCulture)}/{e.AircraftStatus.Longitude.ToString(CultureInfo.InvariantCulture)}"); var result = JsonConvert.DeserializeObject <IATAGeoResult>(dataString); icao = result.ICAO; airport = result.name; } catch (Exception ex) { Debug.WriteLine("HTTPRequestException, IATA-DATA: " + ex); } }); lastICAO = icao; lastAirport = airport; string country = null; if (!string.IsNullOrEmpty(icao)) { if (cachedAirports.TryGetValue(icao, out var airportData)) { country = airportData.country; } else { try { var dataString = await httpClient.GetStringAsync($"https://www.airport-data.com/api/ap_info.json?icao={icao}"); var result = JsonConvert.DeserializeObject <AirportDataResult>(dataString); cachedAirports.TryAdd(icao, result); country = result.country; } catch (Exception ex) { Debug.WriteLine("HTTPRequestException, AIRPORT-DATA: " + ex); } } } var tooltip = callsign; var details = string.Empty; if (!string.IsNullOrEmpty(airport)) { tooltip += " Near " + airport; } if (!string.IsNullOrEmpty(icao)) { details += $" Near {icao}"; tooltip += $" ({icao})"; } if (!string.IsNullOrEmpty(country)) { details += $", {country}"; tooltip += $" in {country}"; } discordRpcClient.SetPresence(new RichPresence { Details = details.Trim(), State = status.IsOnGround ? "Currently on the Ground" : $"Alt {Math.Round(status.Altitude)}ft, {Math.Round(status.IndicatedAirSpeed)}kt", Assets = new Assets { LargeImageKey = "icon_large", LargeImageText = tooltip.Trim() }, Timestamps = groundStateChanged }); } catch (Exception) { } } }); }
private async void FlightConnector_AircraftStatusUpdated(object sender, AircraftStatusUpdatedEventArgs e) { if (viewModel.IsTracking) { if (lastStatus?.IsOnGround == false && e.AircraftStatus.IsOnGround) { landed = true; } if (landed && (e.AircraftStatus.TouchdownNormalVelocity > 0 || !e.AircraftStatus.IsOnGround)) { landed = false; logger.LogInformation("Landing rate: {landingRate}. G-Force: {gforce}.", e.AircraftStatus.TouchdownNormalVelocity, e.AircraftStatus.GForce); lastStatusSent = DateTime.MinValue; if (viewModel.ShowLandingInfo) { flightConnector.Send($"Landing rate: {e.AircraftStatus.TouchdownNormalVelocity:0}fps. G-Force: {e.AircraftStatus.GForce:0.00}g."); } } e.AircraftStatus.Callsign = viewModel.Callsign; e.AircraftStatus.TransponderMode = viewModel.TransponderIdent ? TransponderMode.Ident : TransponderMode.ModeC; if (DateTime.Now - lastStatusSent > TimeSpan.FromMilliseconds(MinimumUpdatePeriod)) { if (hub?.ConnectionId != null) { route.Add(new AircraftStatusBrief(e.AircraftStatus)); lastStatusSent = DateTime.Now; await hub.SendAsync("UpdateAircraft", e.AircraftStatus); lastStatusSent = DateTime.Now; if (viewModel.TransponderIdent) { viewModel.TransponderIdent = false; } } var stopwatch = new Stopwatch(); stopwatch.Start(); var minDistance = 0d; Airport minAirport = null; foreach (var airport in airports.Values) { var distance = GpsHelper.CalculateDistance(e.AircraftStatus.Latitude, e.AircraftStatus.Longitude, airport.Latitude, airport.Longitude); if (minAirport == null || minDistance > distance) { minDistance = distance; minAirport = airport; } } if (minAirport != null) { viewModel.NearestAirport = minAirport; } //Debug.WriteLine($"Found closest airport in {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Stop(); } viewModel.AircraftStatus = e.AircraftStatus; try { if (viewModel.BroadcastUDP) { await udpBroadcastLogic.SendGpsAsync(e.AircraftStatus); await udpBroadcastLogic.SendAttitudeAsync(e.AircraftStatus); } } catch (Exception ex) { logger.LogError(ex, "Cannot send network package!"); } } lastStatus = e.AircraftStatus; }
public AircraftStatusUpdatedEventArgs(AircraftStatus aircraftStatus) { AircraftStatus = aircraftStatus; }
private async void FlightConnector_AircraftStatusUpdated(object sender, AircraftStatusUpdatedEventArgs e) { // NOTE: do not need to check for isConnected because this event is not triggered if simconnect is not connected if (!isStarted) { return; } var status = e.AircraftStatus; DetectTakeOffLanding(status); lastStatus = status; await updateExecutor.ExecuteAsync(async() => { if (Math.Abs(status.Latitude) < 0.02 && Math.Abs(status.Longitude) < 0.02) { // Aircraft is not loaded if (isStarted) { SetPreparing(); } } else { try { string icao = lastICAO; string airport = lastAirport; await geocodeExecutor.ExecuteAsync(async() => { try { var dataString = await httpClient.GetStringAsync($"http://iatageo.com/getCode/{e.AircraftStatus.Latitude.ToString(CultureInfo.InvariantCulture)}/{e.AircraftStatus.Longitude.ToString(CultureInfo.InvariantCulture)}"); var result = JsonConvert.DeserializeObject <IATAGeoResult>(dataString); icao = result.ICAO; airport = result.name; } catch (Exception ex) { logger.LogError(ex, $"Cannot get ICAO code of {status.Latitude} {status.Longitude}!"); } }); lastICAO = icao; lastAirport = airport; string country = null; if (!string.IsNullOrEmpty(icao)) { if (cachedAirports.TryGetValue(icao, out var airportData)) { country = airportData.country; } else { try { var dataString = await httpClient.GetStringAsync($"https://www.airport-data.com/api/ap_info.json?icao={icao}"); var result = JsonConvert.DeserializeObject <AirportDataResult>(dataString); cachedAirports.TryAdd(icao, result); country = result.country; } catch (Exception ex) { logger.LogError(ex, $"Cannot get airport information of {icao}!"); } } } var tooltip = callsign; var details = string.Empty; if (!string.IsNullOrEmpty(airport)) { tooltip += " near " + airport; } if (!string.IsNullOrEmpty(icao)) { details += $" near {icao}"; tooltip += $" ({icao})"; } if (!string.IsNullOrEmpty(country)) { details += $", {country}"; tooltip += $" in {country}"; } discordRpcClient.SetPresence(new RichPresence { Details = details.Trim(), State = status.IsOnGround ? "on the ground" : $"alt {Math.Round(status.Altitude)} ft", Assets = new Assets { LargeImageKey = "icon_large", LargeImageText = tooltip.Trim() }, Timestamps = groundStateChanged }); } catch (Exception ex) { logger.LogError(ex, "Cannot update rich present!"); } } }); }