private void GetXplaneDataTimer_Tick(object sender, EventArgs e)
        {
            if (mXplaneConnector.LastReceive == DateTime.MinValue)
            {
                return;
            }

            if (mUserAircraftData.TransponderMode >= 2)
            {
                TransponderModeChanged?.Invoke(this, new ClientEventArgs <bool>(true));
            }
            else
            {
                TransponderModeChanged?.Invoke(this, new ClientEventArgs <bool>(false));
            }

            UserAircraftRadioStack radio = new UserAircraftRadioStack
            {
                ComAudioSelection = mRadioStackState.ComAudioSelection,
                Com1ActiveFreq    = mRadioStackState.Com1ActiveFreq,
                Com1StandbyFreq   = mRadioStackState.Com1StandbyFreq,
                Com1Power         = mRadioStackState.Com1Power,
                Com1Listening     = mRadioStackState.Com1Listening,
                Com2ActiveFreq    = mRadioStackState.Com2ActiveFreq,
                Com2StandbyFreq   = mRadioStackState.Com2StandbyFreq,
                Com2Power         = mRadioStackState.Com2Power,
                Com2Listening     = mRadioStackState.Com2Listening,
                Com1ForceRx       = mRadioStackState.Com1ForceRx,
                Com1ForceTx       = mRadioStackState.Com1ForceTx,
                Com2ForceRx       = mRadioStackState.Com2ForceRx,
                Com2ForceTx       = mRadioStackState.Com2ForceTx,
                AvionicsPower     = mRadioStackState.AvionicsPower
            };

            UserAircraftDataUpdated?.Invoke(this, new UserAircraftDataUpdatedEventArgs(mUserAircraftData));
            RadioStackStateChanged?.Invoke(this, new RadioStackStateChangedEventArgs(radio));

            if (mUserAircraftData.Latitude != 0.0 && mUserAircraftData.Longitude != 0.0)
            {
                mConnectionHeartbeats.Add(mXplaneConnector.LastReceive);
            }
        }
        public XplaneConnectionManager(IEventBroker broker, IAppConfig config, IFsdManger fsdManager) : base(broker)
        {
            DealerSocket visualDealerSocket = null;

            mVisualDealerSockets = null;
            mConfig     = config;
            mFsdManager = fsdManager;

            if (mConfig.VisualClientIPs.Count > 0)
            {
                foreach (string mIP in mConfig.VisualClientIPs)
                {
                    visualDealerSocket = new DealerSocket();
                    visualDealerSocket.Options.Identity     = Encoding.UTF8.GetBytes("CLIENT");
                    visualDealerSocket.Options.TcpKeepalive = true;
                    try
                    {
                        visualDealerSocket.Connect("tcp://" + mIP + ":" + mConfig.TcpPort);
                        if (mVisualDealerSockets == null)
                        {
                            mVisualDealerSockets = new List <DealerSocket>();
                        }
                        mVisualDealerSockets.Add(visualDealerSocket);
                    }
                    catch (AddressAlreadyInUseException)
                    {
                        NotificationPosted?.Invoke(this, new NotificationPostedEventArgs(NotificationType.Error, "Plugin port already in use. Please choose a different TCP port."));
                    }
                }
            }

            if (!string.IsNullOrEmpty(mConfig.SimClientIP))
            {
                mSimulatorIP = mConfig.SimClientIP;
            }

            mMessageQueue = new NetMQQueue <string>();
            mDealerSocket = new DealerSocket();
            mDealerSocket.Options.TcpKeepalive = true;
            mDealerSocket.Options.Identity     = Encoding.UTF8.GetBytes("CLIENT");
            mDealerSocket.ReceiveReady        += DealerSocket_ReceiveReady;
            try
            {
                mDealerSocket.Connect("tcp://" + mSimulatorIP + ":" + mConfig.TcpPort);
            }
            catch (AddressAlreadyInUseException)
            {
                NotificationPosted?.Invoke(this, new NotificationPostedEventArgs(NotificationType.Error, "Plugin port already in use. Please choose a different TCP port."));
            }
            mPoller = new NetMQPoller {
                mDealerSocket, mMessageQueue
            };
            if (!mPoller.IsRunning)
            {
                mPoller.RunAsync();
            }

            mMessageQueue.ReceiveReady += (s, e) =>
            {
                if (mMessageQueue.TryDequeue(out string msg, TimeSpan.FromMilliseconds(100)))
                {
                    if (mDealerSocket != null)
                    {
                        mDealerSocket.SendFrame(msg);
                    }
                    if (mVisualDealerSockets != null && mVisualDealerSockets.Count > 0)
                    {
                        foreach (DealerSocket socket in mVisualDealerSockets)
                        {
                            socket.SendFrame(msg);
                        }
                    }
                }
            };

            mXplaneConnector  = new XPlaneConnector.XPlaneConnector(mSimulatorIP);
            mUserAircraftData = new UserAircraftData();
            mRadioStackState  = new UserAircraftRadioStack();

            mGetXplaneDataTimer = new Timer
            {
                Interval = 10
            };
            mGetXplaneDataTimer.Tick += GetXplaneDataTimer_Tick;
            mGetXplaneDataTimer.Start();

            mConnectionTimer = new Timer
            {
                Interval = 50
            };
            mConnectionTimer.Tick += ConnectionTimer_Tick;
            mConnectionTimer.Start();

            mRetryConnectionTimer = new Timer
            {
                Interval = 1000
            };
            mRetryConnectionTimer.Tick += RetryConnectionTimer_Tick;
            mRetryConnectionTimer.Start();

            mWhosOnlineListRefresh = new Timer
            {
                Interval = 5000
            };
            mWhosOnlineListRefresh.Tick += WhosOnlineListRefresh_Tick;

            SetupSubscribers();

            if (!Directory.Exists(Path.Combine(mConfig.AppPath, "PluginLogs")))
            {
                Directory.CreateDirectory(Path.Combine(mConfig.AppPath, "PluginLogs"));
            }

            var directory = new DirectoryInfo(Path.Combine(mConfig.AppPath, "PluginLogs"));
            var query     = directory.GetFiles("*", SearchOption.AllDirectories);

            foreach (var file in query.OrderByDescending(file => file.CreationTime).Skip(10))
            {
                file.Delete();
            }

            mRawDataStream = new StreamWriter(Path.Combine(mConfig.AppPath, string.Format($"PluginLogs/PluginLog-{DateTime.UtcNow:yyyyMMddHHmmss}.log")), false);
        }