Andy B. Posted June 2 Report Posted June 2 Hi, I am having problems getting values from offsets. When checking for the connected state, FSUIPC says I am connected to flight simulator when trying to get a value from an offset. I wonder if it is my connection code, but not sure. Here is my ConnectionManager class. The main concern right now is the AutoConnect method. Any help is welcome. using DavyKager; using FSUIPC; using NAudio.SoundFont; using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; using tfm.Properties.Data.Navdata; namespace tfm.Utilities { /* * Manages the connection to FSUIPC and MSFS. All other processing of offsets * or data goes elsewhere. NOTE: only put connection related * code in this class. */ public static class ConnectionManager { private static Offset<uint> activityCounter = new Offset<uint>(0x337E); // Timer to manage the connection to MSFS. private static DispatcherTimer connectionTimer; // Timer to process FSUIPC and MSFS data. private static DispatcherTimer processTimer; private static bool connectedAnnounced = false; private static bool disconnectedAnnounced = false; // Logger facility to log connection status. private static readonly Logger logger = LogManager.GetCurrentClassLogger(); public static void AutoConnect() { // Start looking for MSFS. #region connectionTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; connectionTimer.Tick += async (s, e) => { // Open the connection. try { FSUIPCConnection.Open(); logger.Info("Connected to flight simulator (auto connect)."); // Automatically announce connected state. if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Connected."); connectedAnnounced = true; disconnectedAnnounced = false; } // Start processing data from MSFS. processTimer.Start(); // Stop trying to connect so the connection status is properly updated. connectionTimer.Stop(); } catch { if (tfm.Properties.Settings.Default.AnnounceConnectedState && !disconnectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Disconnected."); disconnectedAnnounced = true; connectedAnnounced = false; } } }; connectionTimer.Start(); #endregion // Start processing data. #region processTimer.Tick += (s, e) => { processTimer.Start(); try { FSUIPCConnection.Process(); var counter = activityCounter.Value; } catch (FSUIPCException ex) { /* * Since the connection to MSFS failed, stop the process timer and restart * the connection timer. We don't want to continue processing if * the connection is closed. We also don't want the connection timer running at * the same time as the process timer. It could cause connection problems, and needlessly fill the logs with endless loops of * errors. */ processTimer.Stop(); connectionTimer.Start(); logger.Warn($"Connection to MSFS closed: ({ex.FSUIPCErrorCode} - {ex.Message})."); } processTimer.Stop(); }; #endregion } public static void Connect() { processTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer.Tick += async (s, e) => { try { FSUIPCConnection.Process(); } catch (FSUIPCException ex) { logger.Warn($"Failed to connect - {ex.Message}."); } }; try { if (!FSUIPCConnection.IsOpen) { FSUIPCConnection.Open(); logger.Info("Connected to flight simulator (manual connection."); // Automatically announce connected state. if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Connected."); connectedAnnounced = true; disconnectedAnnounced = false; } // Start processing data from MSFS. processTimer.Start(); } else { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Already connected."); } } catch { if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Not able to connect."); disconnectedAnnounced = true; connectedAnnounced = false; } } } public static void Disconnect() { try { if (FSUIPCConnection.IsOpen) { FSUIPCConnection.Close(); if(tfm.Properties.Settings.Default.AnnounceConnectedState && !disconnectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Disconnected."); processTimer.Stop(); } } else { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Already disconnected."); } } catch { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Failed to disconnect."); } } } }
Paul Henty Posted June 2 Report Posted June 2 Hi Andy, The only thing that looks out of place to me is in the processTimer.Tick() function: At the start you have processTimer.start() and right at the end you have processTimer.Stop(). That's last line will mean the timer only ticks once and then stops. I've added comments below with !!!. // Start processing data. #region processTimer.Tick += (s, e) => { processTimer.Start(); // !!! Not required - it's already running. try { FSUIPCConnection.Process(); var counter = activityCounter.Value; } catch (FSUIPCException ex) { /* * Since the connection to MSFS failed, stop the process timer and restart * the connection timer. We don't want to continue processing if * the connection is closed. We also don't want the connection timer running at * the same time as the process timer. It could cause connection problems, and needlessly fill the logs with endless loops of * errors. */ processTimer.Stop(); connectionTimer.Start(); logger.Warn($"Connection to MSFS closed: ({ex.FSUIPCErrorCode} - {ex.Message})."); } processTimer.Stop(); // !!! This will stop the timer after the first tick. }; Paul
Andy B. Posted June 2 Author Report Posted June 2 Hi, Here is the method I am concerned with. I don't see any potential problems. What might be going wrong here? I am connected to flight simulator, but everything is returned as a 0. I don't see in this method where processTimer.start() is out of place. I have been trying to figure it out for a while though. public static void AutoConnect() { // Start looking for MSFS. #region connectionTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; connectionTimer.Tick += async (s, e) => { // Open the connection. try { FSUIPCConnection.Open(); logger.Info("Connected to flight simulator (auto connect)."); // Automatically announce connected state. if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Connected."); connectedAnnounced = true; disconnectedAnnounced = false; } // Stop trying to connect so the connection status is properly updated. connectionTimer.Stop(); // Start processing data from MSFS. processTimer.Start(); } catch { if (tfm.Properties.Settings.Default.AnnounceConnectedState && !disconnectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Disconnected."); disconnectedAnnounced = true; connectedAnnounced = false; } } }; connectionTimer.Start(); #endregion // Start processing data. #region processTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer.Tick += (s, e) => { try { FSUIPCConnection.Process(); } catch (FSUIPCException ex) { /* * Since the connection to MSFS failed, stop the process timer and restart * the connection timer. We don't want to continue processing if * the connection is closed. We also don't want the connection timer running at * the same time as the process timer. It could cause connection problems, and needlessly fill the logs with endless loops of * errors. */ processTimer.Stop(); connectionTimer.Start(); logger.Warn($"Connection to MSFS closed: ({ex.FSUIPCErrorCode} - {ex.Message})."); } }; #endregion }
Paul Henty Posted June 3 Report Posted June 3 I ran your code here and it works fine. I deleted the parts specific to your application that I don't have (mainly in the 'catch' statements). I was able to use it to display the player lon/lat on a WPF window. Whatever the problem on your side, it's not this class (unless it's the parts I had to delete). Maybe start with the code below and work your way up to see when it breaks. This works for me: public class ConnectionManager { public static DispatcherTimer connectionTimer; public static DispatcherTimer processTimer; public static void AutoConnect() { // Start looking for MSFS. connectionTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(50), }; connectionTimer.Tick += async (s, e) => { // Open the connection. try { FSUIPCConnection.Open(); // Stop trying to connect so the connection status is properly updated. connectionTimer.Stop(); // Start processing data from MSFS. processTimer.Start(); } catch { } }; connectionTimer.Start(); // Start processing data. processTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer.Tick += (s, e) => { try { FSUIPCConnection.Process(); } catch (FSUIPCException ex) { processTimer.Stop(); connectionTimer.Start(); } }; } } Paul
Andy B. Posted June 3 Author Report Posted June 3 Hi, I seem to be getting something by putting another timer in the window I wanted to show values in. Now, I have the PMDG 737 loaded with the PMDG offsets refresh data in the process timer. When trying to get the name of the aircraft, it tells me the connection isn't open, then crashes. On the other hand, pulling the activity counter at least gives me a static number, even though it should increas as the timer ticks. Who knows, back to the drawing board.
Andy B. Posted June 3 Author Report Posted June 3 Here is my window that I am trying to test the connection in. We are now back to the activity counter being 0 all the time and PMDG requests crash with fsuipc connection not open... strange, because we duplicated the workflow exactly from the previous edition of talking flight monitor. So, confused why it doesn't work now. Anyways, here is the window I am trying to use. At this point, it puts the value of the activity counter in the titlebar. using tfm.UI; using DavyKager; using FSUIPC; using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using tfm.Utilities; namespace tfm { public partial class MainWindow : Window { Offset<uint> activityCounter = new Offset<uint>(0x337E); private Offset<ushort> Com1Freq = new Offset<ushort>(0x034e); private readonly Logger logger = LogManager.GetCurrentClassLogger(); public MainWindow() { InitializeComponent(); SetupTFMMenu(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // Timer for reading offsets. #region var timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(300), }; timer.Tick += async (s, e) => { Dispatcher.BeginInvoke(() => { if (activityCounter.ValueChanged) { //Title = $" - Talking flight monitor {activityCounter.Value}"; } }); }; #endregion // If required, install default Navigraph database. #region using (var _dbContext = new tfm.Properties.Data.Navigraph.NavigraphContext()) { _dbContext.InstallDefaultDatabase(); } #endregion // If required, upgrade settings. #region "Upgrade settings" if (tfm.Properties.Settings.Default.SettingsRequiresUpgrade) { tfm.Properties.Settings.Default.Upgrade(); tfm.Properties.pmdg737_offsets.Default.Upgrade(); tfm.Properties.pmdg747_offsets.Default.Upgrade(); tfm.Properties.Weather.Default.Upgrade(); tfm.Properties.NavlogColumns.Default.Upgrade(); tfm.Properties.Settings.Default.SettingsRequiresUpgrade = false; // Disable vatsim mode for now. tfm.Properties.Settings.Default.VatsimMode = false; tfm.Properties.Settings.Default.Save(); tfm.Properties.pmdg737_offsets.Default.Save(); tfm.Properties.pmdg747_offsets.Default.Save(); tfm.Properties.Weather.Default.Save(); } #endregion // Start looking for MSFS. if (tfm.Properties.Settings.Default.AutoConnect) { connectMenuItem.IsEnabled = false; disconnectMenuItem.IsEnabled = false; ConnectionManager.AutoConnect(); } // Start audio services. AudioManager.SetupAudio(); // load airports database. AirportServices.LoadAirportsDatabase(); timer.Start(); Title = $"Talking flight monitor - {activityCounter.Value}"; LoadHomeScreen(); } public void SetupTFMMenu() { // Connection status. connectionStatusMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new ConnectionStatusUserControl(); }; // Runtime environment logs. runtimeEnvironmentMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new UI.Logs.RuntimeEnvironmentUserControl(); }; //Settings. settingsMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new UI.Settings.SettingsUserControl(); }; // Airports database. airportsDatabaseMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new UI.AirportsDatabaseUserControl(); }; } private void LoadHomeScreen() { switch (tfm.Properties.Settings.Default.HomeScreen) { case "Airports database": contentArea.Content = new UI.AirportsDatabaseUserControl(); break; case "Connection status": contentArea.Content = new UI.ConnectionStatusUserControl(); break; case "Runtime environment": contentArea.Content = new UI.Logs.RuntimeEnvironmentUserControl(); break; case "Settings": contentArea.Content = new UI.Settings.SettingsUserControl(); break; case "Empty": contentArea.Content = null; break; } } private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { // If in the airports database window. if (contentArea.Content is UI.AirportsDatabaseUserControl) { if (!AirportServices.MakeRunwaysProcess.HasExited) { e.Cancel = true; var result = await Task.Run(() => { return System.Windows.MessageBox.Show("Are you sure? TFM is still building the airports database. If you leave now, the build process will terminate. You will have to start the build process from the beginning the next time.", "Cancel airports database build process?", System.Windows.MessageBoxButton.YesNo); }); if (result == System.Windows.MessageBoxResult.Yes) { await Task.Run(() => { AirportServices.MakeRunwaysProcess.Kill(); }); e.Cancel = false; App.Current.Shutdown(); } else { e.Cancel = true; } } } } private void connectMenuItem_Click(object sender, RoutedEventArgs e) { ConnectionManager.Connect(); } private void disconnectMenuItem_Click(object sender, RoutedEventArgs e) { ConnectionManager.Disconnect(); } private void documentationMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://docs.talkingflightmonitor.com"); } private void supportMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://www.talkingflightmonitor.com/contact-us/"); } private void bugTrackerMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://bugtracker.talkingflightmonitor.com"); } private void websiteMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://www.talkingflightmonitor.com"); } } }
Andy B. Posted June 3 Author Report Posted June 3 Ok, it seems that taking out everything except the absolute requirements gives me the activity counter and the increasing count as time goes on :). Now my main problem is getting PMDG data. When I put an instance of the pmdg offsets.refresh method in the process timer, I always get a connection not open error. Remove the PMDG stuff and everything works as long as it isn't pulling pmdg data. For example, requesting the aircraft name fails because it is provided by PMDG. I do have the SDK section in the options file, and followed the preveious version of my connection code. Strange...
Andy B. Posted June 4 Author Report Posted June 4 I didn't know if you have seen this yet, but still haven't been able to figure out why fsuipc throws a connection not open when trying to get PMDG info. If anyone has any ideas, it would be greatly appreciated.
Paul Henty Posted June 4 Report Posted June 4 Are you using the PMDG_737_NGX_Offsets class from my DLL? I can't see any reference to it in the code you've provided. If it is, I would need to see the relevant bits of the code you create it and call RefreshData(). If you have your own class then I'll need to see a few of the offset declarations and how these get processed. Paul
Andy B. Posted June 4 Author Report Posted June 4 Here is my ConnectionManager class. Relevent code is in the AutoConnect method. Follows it is a main window that attempts to display the aircraft name in the title. using DavyKager; using FSUIPC; using NAudio.SoundFont; using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; using tfm.Properties.Data.Navdata; namespace tfm.Utilities { /* * Manages the connection to FSUIPC and MSFS. All other processing of offsets * or data goes elsewhere. NOTE: only put connection related * code in this class. */ public static class ConnectionManager { // Timer to manage the connection to MSFS. private static DispatcherTimer connectionTimer; // Timer to process FSUIPC and MSFS data. private static DispatcherTimer processTimer; private static bool connectedAnnounced = false; private static bool disconnectedAnnounced = false; // Logger facility to log connection status. private static readonly Logger logger = LogManager.GetCurrentClassLogger(); public static PMDG_737_NGX_Offsets offsets = new PMDG_737_NGX_Offsets(); public static void AutoConnect() { // Start looking for MSFS. #region connectionTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; connectionTimer.Tick += async (s, e) => { // Open the connection. try { FSUIPCConnection.Open(); logger.Info("Connected to flight simulator (auto connect)."); // Automatically announce connected state. if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Connected."); connectedAnnounced = true; disconnectedAnnounced = false; } // Stop trying to connect so the connection status is properly updated. connectionTimer.Stop(); // Start processing data from MSFS. processTimer.Start(); var test = offsets.MCP_Heading.Value; } catch { if (tfm.Properties.Settings.Default.AnnounceConnectedState && !disconnectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Disconnected."); disconnectedAnnounced = true; connectedAnnounced = false; } } }; connectionTimer.Start(); #endregion // Start processing data. #region processTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer.Tick += (s, e) => { try { FSUIPCConnection.Process(); if (tfm.Airplanes.Aircraft.AircraftName.Value.Contains("PMDG")) { offsets.RefreshData(); } } catch (FSUIPCException ex) { /* * Since the connection to MSFS failed, stop the process timer and restart * the connection timer. We don't want to continue processing if * the connection is closed. We also don't want the connection timer running at * the same time as the process timer. It could cause connection problems, and needlessly fill the logs with endless loops of * errors. */ processTimer.Stop(); connectionTimer.Start(); logger.Warn($"Connection to MSFS closed: ({ex.FSUIPCErrorCode} - {ex.Message})."); } }; #endregion } public static void Connect() { processTimer = new() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer.Tick += async (s, e) => { try { FSUIPCConnection.Process(); } catch (FSUIPCException ex) { logger.Warn($"Failed to connect - {ex.Message}."); } }; try { if (!FSUIPCConnection.IsOpen) { FSUIPCConnection.Open(); logger.Info("Connected to flight simulator (manual connection."); // Automatically announce connected state. if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Connected."); connectedAnnounced = true; disconnectedAnnounced = false; } // Start processing data from MSFS. processTimer.Start(); } else { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Already connected."); } } catch { if (tfm.Properties.Settings.Default.AnnounceConnectedState && !connectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Not able to connect."); disconnectedAnnounced = true; connectedAnnounced = false; } } } public static void Disconnect() { try { if (FSUIPCConnection.IsOpen) { FSUIPCConnection.Close(); if(tfm.Properties.Settings.Default.AnnounceConnectedState && !disconnectedAnnounced) { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Disconnected."); processTimer.Stop(); } } else { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Already disconnected."); } } catch { AudioManager.Output(useSAPI: tfm.Properties.Settings.Default.UseSAPIForAutoConnect, output: "Failed to disconnect."); } } } } Now, the main window class... using tfm.UI; using DavyKager; using FSUIPC; using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using tfm.Utilities; namespace tfm { public partial class MainWindow : Window { Offset<uint> activityCounter = new Offset<uint>(0x337E); private readonly Logger logger = LogManager.GetCurrentClassLogger(); private DispatcherTimer timer; private Offset<string> AircraftName = new Offset<string>(0x3d00, 255); public MainWindow() { InitializeComponent(); SetupTFMMenu(); timer = new() { Interval = TimeSpan.FromMilliseconds(300), }; timer.Tick += async (s, e) => { if (AircraftName.ValueChanged) { Title = $"Talking flight monitor {AircraftName.Value}"; } }; timer.Start(); } private async void Window_Loaded(object sender, RoutedEventArgs e) { // Load tolk. Tolk.Load(); // If required, install default Navigraph database. #region using (var _dbContext = new tfm.Properties.Data.Navigraph.NavigraphContext()) { _dbContext.InstallDefaultDatabase(); } #endregion // If required, upgrade settings. #region "Upgrade settings" if (tfm.Properties.Settings.Default.SettingsRequiresUpgrade) { tfm.Properties.Settings.Default.Upgrade(); tfm.Properties.pmdg737_offsets.Default.Upgrade(); tfm.Properties.pmdg747_offsets.Default.Upgrade(); tfm.Properties.Weather.Default.Upgrade(); tfm.Properties.NavlogColumns.Default.Upgrade(); tfm.Properties.Settings.Default.SettingsRequiresUpgrade = false; // Disable vatsim mode for now. tfm.Properties.Settings.Default.VatsimMode = false; tfm.Properties.Settings.Default.Save(); tfm.Properties.pmdg737_offsets.Default.Save(); tfm.Properties.pmdg747_offsets.Default.Save(); tfm.Properties.Weather.Default.Save(); } #endregion // Start looking for MSFS. if (tfm.Properties.Settings.Default.AutoConnect) { connectMenuItem.IsEnabled = false; disconnectMenuItem.IsEnabled = false; ConnectionManager.AutoConnect(); } // Start audio services. AudioManager.SetupAudio(); // load airports database. AirportServices.LoadAirportsDatabase(); LoadHomeScreen(); } public void SetupTFMMenu() { // Connection status. connectionStatusMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new ConnectionStatusUserControl(); }; // Runtime environment logs. runtimeEnvironmentMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new UI.Logs.RuntimeEnvironmentUserControl(); }; //Settings. settingsMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new UI.Settings.SettingsUserControl(); }; // Airports database. airportsDatabaseMenuItem.Click += (s, e) => { contentArea.Content = null; contentArea.Content = new UI.AirportsDatabaseUserControl(); }; } private void LoadHomeScreen() { switch (tfm.Properties.Settings.Default.HomeScreen) { case "Airports database": contentArea.Content = new UI.AirportsDatabaseUserControl(); break; case "Connection status": contentArea.Content = new UI.ConnectionStatusUserControl(); break; case "Runtime environment": contentArea.Content = new UI.Logs.RuntimeEnvironmentUserControl(); break; case "Settings": contentArea.Content = new UI.Settings.SettingsUserControl(); break; case "Empty": contentArea.Content = null; break; } } private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { // If in the airports database window. if (contentArea.Content is UI.AirportsDatabaseUserControl) { if (!AirportServices.MakeRunwaysProcess.HasExited) { e.Cancel = true; var result = await Task.Run(() => { return System.Windows.MessageBox.Show("Are you sure? TFM is still building the airports database. If you leave now, the build process will terminate. You will have to start the build process from the beginning the next time.", "Cancel airports database build process?", System.Windows.MessageBoxButton.YesNo); }); if (result == System.Windows.MessageBoxResult.Yes) { await Task.Run(() => { AirportServices.MakeRunwaysProcess.Kill(); }); e.Cancel = false; App.Current.Shutdown(); } else { e.Cancel = true; } } } } private void connectMenuItem_Click(object sender, RoutedEventArgs e) { ConnectionManager.Connect(); } private void disconnectMenuItem_Click(object sender, RoutedEventArgs e) { ConnectionManager.Disconnect(); } private void documentationMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://docs.talkingflightmonitor.com"); } private void supportMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://www.talkingflightmonitor.com/contact-us/"); } private void bugTrackerMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://bugtracker.talkingflightmonitor.com"); } private void websiteMenuItem_Click(object sender, RoutedEventArgs e) { UIHelper.OpenURL("https://www.talkingflightmonitor.com"); } } } Again, in the AutoConnect method, if I remove any reference to the offsets instance, the line var test = offsets.MCP_HEADING.Value, and the offsets.RefreshData() lines, everything works as expected.
Paul Henty Posted June 5 Report Posted June 5 Hi Andy, The problem is that you're instantiating the PMDG offsets before the connection is open. public static PMDG_737_NGX_Offsets offsets = new PMDG_737_NGX_Offsets(); public static PMDG_737_NGX_Offsets offsets = new PMDG_737_NGX_Offsets(); You can declare it at the class level, but you need to create it after the connection opens... Here's my cut-down class manager with the offsets added: public class ConnectionManager { public static DispatcherTimer connectionTimer; public static DispatcherTimer processTimer; public static PMDG_737_NGX_Offsets offsets; // !!! Declare but do not create yet public static void AutoConnect() { // Start looking for MSFS. connectionTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(50), }; connectionTimer.Tick += async (s, e) => { // Open the connection. try { FSUIPCConnection.Open(); offsets = new PMDG_737_NGX_Offsets(); // !!! Create the PMDG offsets after the connection is open. // Stop trying to connect so the connection status is properly updated. connectionTimer.Stop(); // Start processing data from MSFS. processTimer.Start(); } catch { } }; connectionTimer.Start(); // Start processing data. processTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(50), }; processTimer.Tick += (s, e) => { try { FSUIPCConnection.Process(); offsets.RefreshData(); } catch (FSUIPCException ex) { processTimer.Stop(); connectionTimer.Start(); } }; } } Paul
Andy B. Posted June 5 Author Report Posted June 5 I will try it and let you know how it works out. Thought I tried that before, but tried lots of different things.
Andy B. Posted June 5 Author Report Posted June 5 Ok, just tried your idea and it works... You are a life saver! I will work with this, but will come back if I have any other problems. 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now