-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
146 lines (124 loc) · 6.46 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using System;
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.FlightSimulator.SimConnect;
namespace MSFSFlightDataDemo
{
internal class Program
{
static void Main(string[] args)
{
// Creating an instance of the SimVarRequester class to get things started
SimVarRequester svRequester = new SimVarRequester();
}
}
// The SimVarRequester contains all the functionality for opening communication to MSFS, requesting, receiving, and outputting simulation data
public class SimVarRequester
{
private SimConnect simConnect = null;
// These enumerations dont accomplish much, but their use is a requirement of the SimConnect SDK
enum DATA_REQUESTS
{
DataRequest
};
enum DEFINITIONS
{
SimPlaneDataStructure
};
const int WM_USER_SIMCONNECT = 0x0402; // This is some SDK defined constant necessary for connection
const int CX_RETRY_SECONDS = 5; // How long to wait to retry connection attempt after failure
const double DATA_POLLING_SECONDS = 0.5; // How often to request updated sim values freom MSFS
// This structure is used to instruct SimConnect how to package the data being sent in response to our requests
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SimPlaneDataStructure
{
public double plane_pitch;
public double plane_bank;
public double acceleration_z;
}
// This constructor initializes the connection to MSFS, configures the requests, and uses a System.Threading.Timer to poll MSFS for updated simulation data
public SimVarRequester()
{
Console.WriteLine("Attempting to connect to MSFS");
// Attempt connection to MSFS
// If connection is not successful, then pause and retry until success
while (simConnect == null)
{
try
{
simConnect = new SimConnect("MSFSFlightDataDemo Connection", IntPtr.Zero, WM_USER_SIMCONNECT, null, 0);
}
catch (Exception e)
{
Console.WriteLine("Unable to establish connection to MSFS");
Console.WriteLine("Error -> [{0}]", e.Message);
Console.WriteLine("Retrying in {0} second{1}", CX_RETRY_SECONDS, CX_RETRY_SECONDS == 1 ? "" : "s");
Thread.Sleep(CX_RETRY_SECONDS * 1000);
}
}
// Setting up event handlers for open, quit, and excetpions
simConnect.OnRecvOpen += new SimConnect.RecvOpenEventHandler(SimConnect_OnRecvOpen);
simConnect.OnRecvQuit += new SimConnect.RecvQuitEventHandler(SimConnect_OnRecvQuit);
simConnect.OnRecvException += new SimConnect.RecvExceptionEventHandler(SimConnect_OnRecvException);
// Create a profile for the type of simulations variables we are requesting
simConnect.AddToDataDefinition(DEFINITIONS.SimPlaneDataStructure, "Plane Pitch Degrees", "radians", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simConnect.AddToDataDefinition(DEFINITIONS.SimPlaneDataStructure, "Plane Bank Degrees", "radians", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simConnect.AddToDataDefinition(DEFINITIONS.SimPlaneDataStructure, "Acceleration Body Z", "feet per second squared", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
// Instruct SimConnect to use our SimPlaneDataStructure object to package our response data
simConnect.RegisterDataDefineStruct<SimPlaneDataStructure>(DEFINITIONS.SimPlaneDataStructure);
// Set up event handler for receiving responses to our requests
simConnect.OnRecvSimobjectDataBytype += new SimConnect.RecvSimobjectDataBytypeEventHandler(SimConnect_OnRecvSimobjectDataBytype);
// Create a timer that will issue simulation data requests to SimConnect at a defined interval
Timer timer = new Timer(this.OnTimerTick, null, 0, (long)(DATA_POLLING_SECONDS * 1000));
// Create an infinite loop to keep the console application open while the Timer is doing its job
while (true)
{
Thread.Sleep(1000);
}
}
void OnTimerTick(object state)
{
try
{
// Issue our request for the latest simulation data
simConnect.RequestDataOnSimObjectType(DATA_REQUESTS.DataRequest, DEFINITIONS.SimPlaneDataStructure, 0, SIMCONNECT_SIMOBJECT_TYPE.USER);
// Indicate that we are ready to receive a response to that request (silly that this is necessary)
simConnect.ReceiveMessage();
}
catch (Exception e)
{
Console.WriteLine("Unable to request data from MSFS");
Console.WriteLine("Error: {0}", e.Message);
}
}
// Handle connection open events
void SimConnect_OnRecvOpen(SimConnect sender, SIMCONNECT_RECV_OPEN data)
{
Console.WriteLine("Connection to MSFS established");
}
// Handle connection quit events
void SimConnect_OnRecvQuit(SimConnect sender, SIMCONNECT_RECV data)
{
if (simConnect != null)
{
simConnect.Dispose();
simConnect = null;
Console.WriteLine("Connection to MSFS has been closed");
}
}
// Handle connection exception events
void SimConnect_OnRecvException(SimConnect sender, SIMCONNECT_RECV_EXCEPTION data)
{
Console.WriteLine("Connection to MSFS has encountered an exception");
Console.WriteLine("Error: {0}", data.dwException);
}
// Handle request response events
void SimConnect_OnRecvSimobjectDataBytype(SimConnect sender, SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data)
{
// Isolate the requested simulation data from the response object and output the information
SimPlaneDataStructure currentSimData = (SimPlaneDataStructure)data.dwData[0];
Console.Write("\rPitch (rad):\t{0:N6}\tBank (rad):\t{1:N6}\tAccZ (f/s^2):\t{2:N6}\t\t", currentSimData.plane_pitch, currentSimData.plane_bank, currentSimData.acceleration_z);
}
}
}