コード例 #1
0
        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);
            }
        }
コード例 #2
0
 private void DetectTakeOffLanding(AircraftStatus status)
 {
     if (lastStatus == null || status.IsOnGround != lastStatus.IsOnGround)
     {
         groundStateChanged = Timestamps.Now;
     }
 }
コード例 #3
0
        protected override Task OnWillDisappear(ActionEventArgs <AppearancePayload> args)
        {
            this.flightConnector.AircraftStatusUpdated -= FlightConnector_AircraftStatusUpdated;
            status = null;

            return(Task.CompletedTask);
        }
コード例 #4
0
 public AircraftStatusBrief(AircraftStatus status)
 {
     Latitude   = status.Latitude;
     Longitude  = status.Longitude;
     Altitude   = status.Altitude;
     IsOnGround = status.IsOnGround;
 }
コード例 #5
0
        /// <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);
            }
        }
コード例 #6
0
        protected override async Task OnWillAppear(ActionEventArgs <AppearancePayload> args)
        {
            action = args.Action;
            status = null;
            setValues(args.Payload.Settings);
            this.flightConnector.AircraftStatusUpdated += FlightConnector_AircraftStatusUpdated;

            await UpdateImage();
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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;
            }
        }
コード例 #9
0
        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;
                    }
                }
            }
        }
コード例 #10
0
 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");
 }
コード例 #11
0
        /// <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;
        }
コード例 #12
0
        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!");
                }
            }
        }
コード例 #13
0
        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.");
                });
            }
コード例 #14
0
        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;
            }
        }
コード例 #15
0
        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) { }
                }
            });
        }
コード例 #16
0
        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;
        }
コード例 #17
0
 public AircraftStatusUpdatedEventArgs(AircraftStatus aircraftStatus)
 {
     AircraftStatus = aircraftStatus;
 }
コード例 #18
0
        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!");
                    }
                }
            });
        }