This is my test:
// My First SimConnect App
#pragma warning(push, 3)
#include <Windows.h>
#include <SimConnect.h>
#pragma warning(pop)
#include <iostream>
constexpr DWORD DataReq{ 1 };
constexpr DWORD AircraftData{ 1 };
enum class Datum : DWORD {
NoId = 0,
Title,
IsUser,
AtcId,
AtcModel,
AircraftAGL,
Altitude
};
static HANDLE hSimConnect{ nullptr };
static bool connected{ false };
static void handleException(const SIMCONNECT_RECV_EXCEPTION& msg) {
const SIMCONNECT_EXCEPTION exc{ static_cast<SIMCONNECT_EXCEPTION>(msg.dwException) };
printf("Received an exception type %d:\n", (int)exc);
if (msg.dwSendID != SIMCONNECT_RECV_EXCEPTION::UNKNOWN_SENDID) {
printf("- Related to a message with SendID %d.\n", (int)msg.dwSendID);
}
if (msg.dwIndex != SIMCONNECT_RECV_EXCEPTION::UNKNOWN_INDEX) {
printf("- Regarding parameter %d.\n", (int)msg.dwIndex);
}
}
static void handle_messages(HANDLE hEvent)
{
while (connected && (::WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)) {
SIMCONNECT_RECV* pData{ nullptr };
DWORD cbData{ 0 };
HRESULT hr{ S_OK };
while (SUCCEEDED(hr = SimConnect_GetNextDispatch(hSimConnect, &pData, &cbData))) {
switch (pData->dwID) {
case SIMCONNECT_RECV_ID_EXCEPTION:
handleException(*((SIMCONNECT_RECV_EXCEPTION*)pData));
break;
case SIMCONNECT_RECV_ID_OPEN:
{
SIMCONNECT_RECV_OPEN* pOpen{ (SIMCONNECT_RECV_OPEN*)pData };
printf("Connected to '%s' version %d.%d (build %d.%d)\n",
pOpen->szApplicationName,
pOpen->dwApplicationVersionMajor,
pOpen->dwApplicationVersionMinor,
pOpen->dwApplicationBuildMajor,
pOpen->dwApplicationBuildMinor);
printf(" using SimConnect version %d.%d (build %d.%d)\n",
pOpen->dwSimConnectVersionMajor,
pOpen->dwSimConnectVersionMinor,
pOpen->dwSimConnectBuildMajor,
pOpen->dwSimConnectBuildMinor);
}
break;
case SIMCONNECT_RECV_ID_QUIT:
{
printf("Simulator is shutting down.\n");
connected = false;
}
break;
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA:
{
const SIMCONNECT_RECV_SIMOBJECT_DATA * msg{(const SIMCONNECT_RECV_SIMOBJECT_DATA*)pData};
unsigned dataSize{ cbData - (4 * 7) };
printf("Received SimObject data for request %d, object %d, defineId %d, entry %d out of %d, %d times 8 bytes of data, remaining message size %d bytes.\n",
msg->dwRequestID, msg->dwObjectID, msg->dwDefineID, msg->dwentrynumber, msg->dwoutof, msg->dwDefineCount, dataSize);
if ((msg->dwFlags & SIMCONNECT_DATA_REQUEST_FLAG_CHANGED) != 0) {
printf(" - Data is sent due to a change.\n");
}
if ((msg->dwFlags & SIMCONNECT_DATA_REQUEST_FLAG_TAGGED) != 0) {
printf(" - Data is in the TAGGED format.\n");
}
printf("Raw data:\n\n");
unsigned count{ 0 };
uint8_t* data = (uint8_t*)(&(msg->dwData));
while (count < dataSize) {
if ((count % 16) == 0) {
printf("0x%04x ", count);
}
printf(" 0x%02x", data[count]);
count += 1;
if ((count % 16) == 0) {
printf(" ");
for (unsigned p = count - 16; p < count; p++) {
printf("%c", ((data[p] < 0x20) || (data[p] > 0x7f)) ? '.' : ((char)(data[p])));
}
printf("\n");
}
}
if ((count % 16) != 0) {
while ((count % 16) != 0) {
printf(" ");
count++;
}
printf(" ");
for (unsigned p = count - 16; p < dataSize; p++) {
printf("%c", ((data[p] < 0x20) || (data[p] > 0x7f)) ? '.' : ((char)(data[p])));
}
printf("\n\n");
}
else {
printf("\n");
}
if (msg->dwRequestID != DataReq) {
printf("Ignoring data, not our request.\n\n");
}
else if (msg->dwDefineID != AircraftData) {
printf("Ignoring data, not AircraftData.\n\n");
}
else if ((msg->dwFlags & SIMCONNECT_DATA_REQUEST_FLAG_TAGGED) != 0) {
const uint8_t* ptr{ reinterpret_cast<const uint8_t*>(&(msg->dwData)) };
size_t i = 0;
while (i < dataSize) {
Datum id = static_cast<Datum>(*reinterpret_cast<const DWORD*>(&(ptr[i])));
//if (id == Datum::NoId) {
// break;
//}
i += sizeof(DWORD);
switch (id) {
case Datum::Title:
{
const char* s{ reinterpret_cast<const char*>(&(ptr[i])) };
printf("Aircraft title is '%s'.\n", s);
i += strlen(s) + 1;
if ((i % sizeof(DWORD)) != 0) {
i += (4 - (i % sizeof(DWORD)));
}
}
break;
case Datum::IsUser:
printf("This %s the user's aircraft.\n", (ptr[i] ? "IS" : "ISN'T"));
i += sizeof(DWORD);
break;
case Datum::AtcId:
{
const char* s{ reinterpret_cast<const char*>(&(ptr[i])) };
printf("Aircraft ATC Id is '%s'.\n", s);
i += strlen(s) + 1;
if ((i % sizeof(DWORD)) != 0) {
i += (4 - (i % sizeof(DWORD)));
}
}
break;
case Datum::AtcModel:
{
const char* s{ reinterpret_cast<const char*>(&(ptr[i])) };
printf("Aircraft ATC Model is '%s'.\n", s);
i += strlen(s) + 1;
if ((i % sizeof(DWORD)) != 0) {
i += (4 - (i % sizeof(DWORD)));
}
}
break;
case Datum::AircraftAGL:
{
int32_t aAGL = *reinterpret_cast<const uint32_t*>(&(ptr[i]));
printf("Aircraft is %d feet above ground level.\n", aAGL);
i += sizeof(int32_t);
}
break;
case Datum::Altitude:
{
int32_t alt = *reinterpret_cast<const uint32_t*>(&(ptr[i]));
if (alt == 0) {
printf("Aircraft is at sea level.\n");
}
else if (alt > 0) {
printf("Aircraft is %d feet above sea level.\n", alt);
}
else {
printf("Aircraft is %d feet below sea level.\n", -alt);
}
i += sizeof(int32_t);
}
break;
}
}
if (i < dataSize) {
printf("Skipping %d unused byte(s).\n", int(dataSize - i));
}
}
else {
printf("Data and stuff...\n\n");
}
}
break;
default:
printf("Ignoring message of type %d (length %d bytes)\n", pData->dwID, pData->dwSize);
break;
}
}
if (connected) {
Sleep(100);
}
}
}
static int testConnect()
{
HANDLE hEventHandle{ ::CreateEvent(NULL, FALSE, FALSE, NULL) };
if (hEventHandle == NULL) {
printf("Failed to create a Windows Event!\n");
return 1;
}
HRESULT hr = SimConnect_Open(&hSimConnect, "My First SimConnect App", nullptr, 0, hEventHandle, 0);
if (SUCCEEDED(hr)) {
std::cout << "Successfully connected to MSFS.\n";
SimConnect_AddToDataDefinition(hSimConnect, AircraftData, "TITLE", "", SIMCONNECT_DATATYPE_STRINGV, 0, static_cast<DWORD>(Datum::Title));
SimConnect_AddToDataDefinition(hSimConnect, AircraftData, "is user sim", "Bool", SIMCONNECT_DATATYPE_INT32, 0, static_cast<DWORD>(Datum::IsUser));
SimConnect_AddToDataDefinition(hSimConnect, AircraftData, "atc id", "", SIMCONNECT_DATATYPE_STRINGV, 0, static_cast<DWORD>(Datum::AtcId));
SimConnect_AddToDataDefinition(hSimConnect, AircraftData, "atc model", "", SIMCONNECT_DATATYPE_STRINGV, 0, static_cast<DWORD>(Datum::AtcModel));
SimConnect_AddToDataDefinition(hSimConnect, AircraftData, "aircraft agl", "feet", SIMCONNECT_DATATYPE_INT32, 0, static_cast<DWORD>(Datum::AircraftAGL));
SimConnect_AddToDataDefinition(hSimConnect, AircraftData, "plane altitude", "feet", SIMCONNECT_DATATYPE_INT32, 0, static_cast<DWORD>(Datum::Altitude));
SimConnect_RequestDataOnSimObject(hSimConnect, DataReq, AircraftData, SIMCONNECT_OBJECT_ID_USER_AIRCRAFT, SIMCONNECT_PERIOD_ONCE, SIMCONNECT_DATA_REQUEST_FLAG_TAGGED);
connected = true;
handle_messages(hEventHandle);
hr = SimConnect_Close(hSimConnect);
std::cout << "Disconnected from MSFS.\n";
}
else {
std::cerr << "Failed to connect to MSFS!\n";
}
return SUCCEEDED(hr);
}
int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[])
{
std::cout << "Welcome to my first SimConnect app.\n";
return testConnect();
}