Start on SimConnect

This commit is contained in:
2022-10-03 02:05:06 +02:00
parent 997586b8aa
commit 23db85c2a5
22 changed files with 1209 additions and 116 deletions
+6
View File
@@ -6,6 +6,7 @@ enable_language(RC)
add_executable(germanairlinesva_esp WIN32
${socket}
resources/resources-${BIT}.rc
simconnect.cpp
main.cpp
)
@@ -23,6 +24,11 @@ target_compile_definitions(germanairlinesva_esp PRIVATE
BIT="${BIT}"
IBM
)
if (MSFS)
target_compile_definitions(germanairlinesva_esp PRIVATE
MSFS
)
endif()
target_compile_options(germanairlinesva_esp PRIVATE
-Wall
+20 -6
View File
@@ -1,20 +1,34 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_ESP_MAIN_H
#define GERMANAIRLINESVA_GACONNECTOR_ESP_MAIN_H
#include "constants.h"
#include "windows.h"
#include "SimConnect.h"
#include <atomic>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <queue>
#include <string>
#include "websocket.h"
#include <shlobj.h>
#include <stdlib.h>
#include <windows.h>
#include "config/config.hpp"
#include "constants.h"
#include "logbook/logbook.hpp"
#include "recording/recording.hpp"
#include "simconnect.h"
#include "simdata/simDatabase.hpp"
WINBOOL addNotifyIcon(HWND hWnd);
WINBOOL removeNotifyIcon(HWND hWnd);
WINBOOL createMenu(HWND hWnd);
void end(HWND hwnd);
void serverWorker();
void recordingWorker();
void toLog(const std::string &message);
#endif
+125
View File
@@ -0,0 +1,125 @@
#ifndef GERMANAIRLINESVA_GACONNECTOR_ESP_SIMCONNECT_H
#define GERMANAIRLINESVA_GACONNECTOR_ESP_SIMCONNECT_H
#include <cmath>
#include <functional>
#include <string>
#include "websocket.h"
#include <windows.h>
#include "SimConnect.h"
#include "config/config.hpp"
#include "constants.h"
#pragma pack(push)
#pragma pack(1)
struct data {
double parkingBrake; // BRAKE PARKING INDICATOR
double onGround; // SIM ON GROUND
double emptyWeight; // EMPTY WEIGHT
double currentWeight; // TOTAL WEIGHT
double fuel; // FUEL TOTAL QUANTITY WEIGHT
double headingTrue; // PLANE HEADING DEGREES TRUE
double headingMagnetic; // PLANE HEADING DEGREES Magnetic
double groundSpeed; // GROUND VELOCITY
double indicatedAirspeed; // AIRSPEED INDICATED
double barberPoleSpeed; // AIRSPEED BARBER POLE
double verticalVelocity; // VELOCITY WORLD Y
double verticalSpeed; // VERTICAL SPEED
double altitude; // PLANE ALTITUDE
double altitudeAGL; // PLANE ALT ABOVE GROUND
double latitude; // PLANE LATITUDE
double longitude; // PLANE LONGITUDE
double elapsedTime; // ABSOLUTE TIME
double fuelFlowEng1; // ENG FUEL FLOW PPH:1
double fuelFlowEng2; // ENG FUEL FLOW PPH:2
double fuelFlowEng3; // ENG FUEL FLOW PPH:3
double fuelFlowEng4; // ENG FUEL FLOW PPH:4
int brakePos;
int brakeParkPos;
int brakeLeftPos;
double timeZulu; // ZULU TIME IN SECONDS
double gForce; // G FORCE IN G
};
struct Port {
double headingTrue; // PLANE HEADING DEGREES TRUE
double latitude; // PLANE LATITUDE
double longitude; // PLANE LONGITUDE
};
#pragma pack(pop)
enum DEFINITIONS {
D_DATA,
D_PORT,
};
enum REQUESTS {
R_DATA,
R_ACFT,
R_DIALOG,
R_PORT,
};
enum EVENTS {
E_PAUSE,
E_STATUS,
E_TEXT,
E_TIMEMIN,
E_TIMEHRS,
E_TIMESEC,
};
enum GROUPS {
G_TIME,
};
class SimConnect
{
private:
HANDLE simConnect;
bool connectedToSim;
char version;
std::string aircraftPath;
bool pausedMenu;
bool paused;
std::mutex mutex;
struct germanairlinesva::websocket::data simData;
std::shared_ptr<germanairlinesva::file::config::Config> configuration;
std::function<void(const std::string)> toLog;
void handleOpen(SIMCONNECT_RECV_OPEN *data);
void handleSystemEvent(SIMCONNECT_RECV_SYSTEM_STATE *state);
void handleEvent(SIMCONNECT_RECV_EVENT *event);
void handleData(SIMCONNECT_RECV_SIMOBJECT_DATA *data);
public:
SimConnect(
HWND hWnd,
std::function<void(const std::string)> toLog,
std::shared_ptr<germanairlinesva::file::config::Config> &configuration);
~SimConnect();
bool isConnected() const;
const std::string getVersion() const;
void getData(struct germanairlinesva::websocket::data *data);
void getStates() const;
void handleMessage();
};
#endif
+241 -44
View File
@@ -1,6 +1,22 @@
#include "include/main.h"
bool connectedToSim = false;
std::mutex mutex;
std::queue<std::function<void()>> &messageQueue()
{
static std::queue<std::function<void()>> _messageQueue;
return _messageQueue;
}
std::thread serverThread;
std::thread recordingThread;
std::atomic<bool> wantsExit;
std::shared_ptr<germanairlinesva::file::config::Config> configuration;
std::unique_ptr<germanairlinesva::file::simdata::SimDatabase> database;
std::unique_ptr<germanairlinesva::websocket::Websocket> connector;
std::unique_ptr<SimConnect> simConnect;
struct germanairlinesva::websocket::data toSend;
germanairlinesva::file::recording::Recording p;
// The Window Procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -8,58 +24,34 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
static UINT s_uTaskbarRestart;
switch (msg) {
case WM_CREATE:
case WM_CREATE: {
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
break;
}
case WM_CLOSE: {
toLog("Close");
DestroyWindow(hWnd);
break;
}
case WM_DESTROY: {
toLog("Destroy");
removeNotifyIcon(hWnd);
UnregisterClass(WINDOW_CLASS, GetModuleHandle(NULL));
PostQuitMessage(0);
end(hWnd);
break;
}
case TRAY_MESSAGE: {
switch (lParam) {
case WM_RBUTTONUP:
case WM_CONTEXTMENU: {
const int IDM_EXIT = 100;
POINT pt;
GetCursorPos(&pt);
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, "Version: " BIT);
if (connectedToSim) {
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, "Connected to Sim");
}
AppendMenu(hMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hMenu, MF_STRING, IDM_EXIT, "Exit");
SetForegroundWindow(hWnd);
WINBOOL cmd = TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_LEFTBUTTON |
TPM_BOTTOMALIGN | TPM_RETURNCMD,
pt.x,
pt.y,
0,
hWnd,
NULL);
if (cmd == IDM_EXIT) {
PostMessage(hWnd, WM_CLOSE, 0, NULL);
}
DestroyMenu(hMenu);
createMenu(hWnd);
break;
}
}
break;
}
case SIMCONNECT_MESSAGE: {
if (simConnect != nullptr && simConnect->isConnected()) {
simConnect->handleMessage();
}
break;
}
default: {
if (msg == s_uTaskbarRestart) {
addNotifyIcon(hWnd);
@@ -77,13 +69,13 @@ int WINAPI WinMain(HINSTANCE hInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HANDLE simConnect;
HRESULT hr;
WNDCLASS wc;
ZeroMemory(&wc, sizeof(WNDCLASS));
HWND hWnd;
MSG msg;
wantsExit.store(false);
// Exit if already running
hWnd = FindWindow(WINDOW_CLASS, WINDOW_CLASS);
if (hWnd != NULL) {
@@ -132,12 +124,98 @@ int WINAPI WinMain(HINSTANCE hInstance,
// Never show window
// ShowWindow(hWnd, SHOW_OPENWINDOW);
hr = SimConnect_Open(&simConnect, "GAConnector", hWnd, NULL, NULL, NULL);
if (hr == E_FAIL) {
toLog("SimConnect_Open failed");
} else {
connectedToSim = true;
configuration = std::make_unique<germanairlinesva::file::config::Config>();
toLog("Config loaded");
connector = std::make_unique<germanairlinesva::websocket::Websocket>(
"wss://ws.hofmannnet.myhome-server.de:8000",
configuration->getUser(),
toLog);
toLog("WebSocket started");
#ifndef MSFS
PWSTR folder;
HRESULT result = SHGetKnownFolderPath(FOLDERID_RoamingAppData,
KF_FLAG_DEFAULT,
NULL,
&folder);
if (SUCCEEDED(result)) {
size_t origsize = wcslen(folder) + 1;
size_t convertedChars = 0;
char *nstring = new char[origsize * 2];
wcstombs_s(&convertedChars, nstring, origsize * 2, folder, _TRUNCATE);
std::string path(nstring);
path.append("\\Microsoft\\FSX\\scenery.cfg");
toLog(path);
delete[] nstring;
CoTaskMemFree(folder);
char hash[2 * MD5LEN + 1] = "";
if (germanairlinesva::util::generateMD5(path.c_str(), hash, toLog) == 0) {
database = std::make_unique<germanairlinesva::file::simdata::SimDatabase>(
FSX_VERSION,
hash,
configuration,
toLog);
}
toLog("Readback test of sim database using EDDF");
auto ap = (*database)["EDDF"];
for (const auto &it : ap.first) {
toLog(" " + it.to_string());
}
for (const auto &it : ap.second) {
toLog(" " + it.to_string());
}
toLog("Readback test of sim database using XXXX");
auto ap2 = (*database)["XXXX"];
ap2.first.size() == 0 ? toLog(" SUCCESS") : toLog(" ERROR");
}
#endif
toLog("Logbook Test");
germanairlinesva::file::logbook::Logbook logbook;
logbook.addEntry("08.09.2022",
"F",
"1000",
"L049",
"D-ALFA",
"John F. Kennedy International Aiport / EDDF",
"A1",
"14L",
"Gander International Airport / CYQX",
"10",
"03",
"10:00",
"10:20",
"13:20",
"13:30",
210.5,
20.1,
5012.4156,
8.87,
5041.3856,
7.1,
971.14,
2.41,
980.65,
-165.23,
1,
1.2012,
"2022-09-08_VGA1000",
5.5,
1);
logbook.toFile();
// Open SimConnect
simConnect = std::make_unique<SimConnect>(hWnd, toLog, configuration);
// Thread for sending data to websocket
serverThread = std::thread(&serverWorker);
recordingThread = std::thread(&recordingWorker);
toLog("Workers started");
// The Message Loop
while (GetMessage(&msg, NULL, 0, 0) > 0) {
@@ -146,8 +224,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
}
// Exit
SimConnect_Close(&simConnect);
toLog("Bye");
toLog("Connector stopped");
return msg.wParam;
}
#pragma clang diagnostic pop
@@ -193,6 +270,126 @@ WINBOOL removeNotifyIcon(HWND hWnd)
return Shell_NotifyIcon(NIM_DELETE, &niData);
}
WINBOOL createMenu(HWND hWnd)
{
const int IDM_EXIT = 100;
POINT pt;
GetCursorPos(&pt);
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, "Version: " BIT " Bit");
if (simConnect->isConnected()) {
std::string version("Connected to Sim: ");
version.append(simConnect->getVersion());
AppendMenu(hMenu, MF_STRING | MF_GRAYED, NULL, version.c_str());
}
AppendMenu(hMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hMenu, MF_STRING, IDM_EXIT, "Exit");
SetForegroundWindow(hWnd);
WINBOOL cmd = TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_LEFTBUTTON |
TPM_BOTTOMALIGN | TPM_RETURNCMD,
pt.x,
pt.y,
0,
hWnd,
NULL);
if (cmd == IDM_EXIT) {
PostMessage(hWnd, WM_CLOSE, 0, NULL);
}
return DestroyMenu(hMenu);
}
void end(HWND hWnd)
{
removeNotifyIcon(hWnd);
UnregisterClass(WINDOW_CLASS, GetModuleHandle(NULL));
/* End threads */
wantsExit = true;
serverThread.join();
recordingThread.join();
p.toFile("flight.rec");
// End SimConnect
delete simConnect.release();
PostQuitMessage(0);
}
void serverWorker()
{
germanairlinesva::util::setThreadName("GAServerWorker");
while (!wantsExit) {
simConnect->getStates();
struct germanairlinesva::websocket::data *copy =
new germanairlinesva::websocket::data();
{
const std::lock_guard<std::mutex> lock(mutex);
simConnect->getData(copy);
}
connector->sendData(*copy);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
toLog("Server thread stopped");
}
void recordingWorker()
{
germanairlinesva::util::setThreadName("GARecordingWorker");
germanairlinesva::file::recording::RecordingEntry lastPath;
std::uint32_t segment = 0;
auto ap = (*database)["EDDF"];
auto rwys = ap.second;
while (!wantsExit) {
struct germanairlinesva::websocket::data *copy =
new germanairlinesva::websocket::data();
{
const std::lock_guard<std::mutex> lock(mutex);
simConnect->getData(copy);
}
germanairlinesva::file::recording::RecordingEntry currentPath(
segment,
static_cast<std::uint16_t>(copy->alt),
static_cast<std::uint16_t>(copy->gs),
{copy->lat, copy->lon});
if (strcmp(copy->path, "") != 0 && !copy->pause &&
lastPath != currentPath) {
p.addEntry(currentPath);
lastPath = currentPath;
for (const auto &it : rwys) {
if (it.containsPoint({copy->lat, copy->lon})) {
toLog("On Runway: " + it.to_string());
}
}
}
segment++;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
toLog("Recording thread stopped");
}
void toLog(const std::string &message)
{
std::time_t utc = std::time(nullptr);
+459
View File
@@ -0,0 +1,459 @@
#include "include/simconnect.h"
SimConnect::SimConnect(
HWND hWnd,
std::function<void(const std::string)> toLog,
std::shared_ptr<germanairlinesva::file::config::Config> &configuration)
: configuration(configuration), toLog(std::move(toLog))
{
HRESULT hr = SimConnect_Open(&this->simConnect,
"GAConnector",
hWnd,
SIMCONNECT_MESSAGE,
NULL,
NULL);
if (!SUCCEEDED(hr)) {
this->toLog("SimConnect_Open: Failed");
} else {
this->connectedToSim = true;
this->toLog("SimConnect_Close: Connection opened");
// Setup SimConnect
SimConnect_SubscribeToSystemEvent(simConnect, EVENTS::E_PAUSE, "Pause");
SimConnect_SubscribeToSystemEvent(simConnect, EVENTS::E_STATUS, "Sim");
SimConnect_MapClientEventToSimEvent(simConnect,
EVENTS::E_TIMESEC,
"CLOCK_SECONDS_ZERO");
SimConnect_AddClientEventToNotificationGroup(simConnect,
GROUPS::G_TIME,
EVENTS::E_TIMESEC,
false);
SimConnect_SetNotificationGroupPriority(simConnect,
GROUPS::G_TIME,
SIMCONNECT_GROUP_PRIORITY_HIGHEST);
SimConnect_MapClientEventToSimEvent(simConnect,
EVENTS::E_TIMEMIN,
"ZULU_MINUTES_SET");
SimConnect_AddClientEventToNotificationGroup(simConnect,
GROUPS::G_TIME,
EVENTS::E_TIMEMIN,
false);
SimConnect_SetNotificationGroupPriority(simConnect,
GROUPS::G_TIME,
SIMCONNECT_GROUP_PRIORITY_HIGHEST);
SimConnect_MapClientEventToSimEvent(simConnect,
EVENTS::E_TIMEHRS,
"ZULU_HOURS_SET");
SimConnect_AddClientEventToNotificationGroup(simConnect,
GROUPS::G_TIME,
EVENTS::E_TIMEHRS,
false);
SimConnect_SetNotificationGroupPriority(simConnect,
GROUPS::G_TIME,
SIMCONNECT_GROUP_PRIORITY_HIGHEST);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"BRAKE PARKING INDICATOR",
"BOOL",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"SIM ON GROUND",
"BOOL",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"EMPTY WEIGHT",
"KILOGRAMS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"TOTAL WEIGHT",
"KILOGRAMS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"FUEL TOTAL QUANTITY WEIGHT",
"KILOGRAMS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"PLANE HEADING DEGREES TRUE",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"PLANE HEADING DEGREES MAGNETIC",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"GROUND VELOCITY",
"KNOTS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"AIRSPEED INDICATED",
"KNOTS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"AIRSPEED BARBER POLE",
"KNOTS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"VELOCITY WORLD Y",
"FEET/MINUTE",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"VERTICAL SPEED",
"FEET/MINUTE",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"PLANE ALTITUDE",
"FEET",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"PLANE ALT ABOVE GROUND",
"FEET",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"PLANE LATITUDE",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"PLANE LONGITUDE",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"ABSOLUTE TIME",
"SECONDS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:1",
"KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:2",
"KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:3",
"KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"ENG FUEL FLOW PPH:4",
"KILOGRAMS PER SECOND",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"BRAKE INDICATOR",
"POSITION",
SIMCONNECT_DATATYPE_INT32,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"BRAKE PARKING POSITION",
"POSITION",
SIMCONNECT_DATATYPE_INT32,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"BRAKE LEFT POSITION",
"POSITION",
SIMCONNECT_DATATYPE_INT32,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"ZULU TIME",
"SECONDS",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_DATA,
"G FORCE",
"GForce",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_PORT,
"PLANE HEADING DEGREES TRUE",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_PORT,
"PLANE LATITUDE",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_AddToDataDefinition(simConnect,
DEFINITIONS::D_PORT,
"PLANE LONGITUDE",
"DEGREES",
SIMCONNECT_DATATYPE_FLOAT64,
0,
SIMCONNECT_UNUSED);
SimConnect_RequestDataOnSimObject(simConnect,
REQUESTS::R_DATA,
DEFINITIONS::D_DATA,
SIMCONNECT_OBJECT_ID_USER,
SIMCONNECT_PERIOD_SIM_FRAME,
SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT,
0,
0,
0);
}
}
SimConnect::~SimConnect()
{
if (this->connectedToSim) {
HRESULT hr = SimConnect_Close(this->simConnect);
if (!SUCCEEDED(hr)) {
this->toLog("SimConnect_Close: Failed");
} else {
this->connectedToSim = true;
this->toLog("SimConnect_Close: Connection closed");
}
}
}
void SimConnect::getStates() const
{
SimConnect_RequestSystemState(this->simConnect,
REQUESTS::R_ACFT,
"AircraftLoaded");
SimConnect_RequestSystemState(this->simConnect, REQUESTS::R_DIALOG, "DIALOG");
}
bool SimConnect::isConnected() const { return this->connectedToSim; }
const std::string SimConnect::getVersion() const
{
switch (this->version) {
case MSFS_VERSION:
return "MSFS";
case FSX_VERSION:
return "FSX";
case P3D5_VERSION:
return "P3D5";
case P3D4_VERSION:
return "P3D4";
break;
case P3D3_VERSION:
return "P3D3";
default:
return "Unknown";
}
}
void SimConnect::getData(struct germanairlinesva::websocket::data *data)
{
const std::lock_guard<std::mutex> lock(this->mutex);
memcpy(data, &this->simData, sizeof(this->simData));
}
void SimConnect::handleMessage()
{
SIMCONNECT_RECV *pData;
DWORD cbData;
HRESULT hr = SimConnect_GetNextDispatch(this->simConnect, &pData, &cbData);
if (SUCCEEDED(hr)) {
switch (pData->dwID) {
case SIMCONNECT_RECV_ID_OPEN: {
this->handleOpen((SIMCONNECT_RECV_OPEN *)pData);
break;
}
case SIMCONNECT_RECV_ID_EVENT: {
this->handleEvent((SIMCONNECT_RECV_EVENT *)pData);
break;
}
case SIMCONNECT_RECV_ID_SYSTEM_STATE: {
this->handleSystemEvent((SIMCONNECT_RECV_SYSTEM_STATE *)pData);
break;
}
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: {
this->handleData((SIMCONNECT_RECV_SIMOBJECT_DATA *)pData);
break;
}
default:
break;
}
}
}
void SimConnect::handleOpen(SIMCONNECT_RECV_OPEN *data)
{
switch (data->dwSimConnectVersionMajor) {
case MSFS_VERSION:
this->version = MSFS_VERSION;
break;
default:
break;
case FSX_VERSION:
switch (data->dwSimConnectBuildMajor) {
case FSXRTM_SUBVERSION:
case FSSXSP1_SUBVERRSION:
break;
case FSXSP2_SUBVERSION:
case FSXACC_SUBVERSION:
case FSXGOLD_SUBVERSION:
this->version = FSX_VERSION;
break;
case FSXSE_SUBVERSION:
if (configuration->getFSXSEPath().length() > 0) {
this->version = FSXSE_VERSION;
} else {
this->version = FSX_VERSION;
}
break;
}
break;
case P3D5_VERSION:
this->version = P3D5_VERSION;
break;
case P3D4_VERSION:
this->version = P3D4_VERSION;
break;
case P3D3_VERSION:
this->version = P3D3_VERSION;
break;
}
}
void SimConnect::handleSystemEvent(SIMCONNECT_RECV_SYSTEM_STATE *state)
{
switch (state->dwRequestID) {
case REQUESTS::R_ACFT:
this->aircraftPath = state->szString;
break;
case REQUESTS::R_DIALOG:
this->pausedMenu = state->dwInteger != 0;
break;
}
}
void SimConnect::handleEvent(SIMCONNECT_RECV_EVENT *event)
{
switch (event->uEventID) {
case EVENTS::E_PAUSE:
this->paused = event->dwData != 0;
break;
case EVENTS::E_STATUS:
this->toLog("SimConnect Status " + std::to_string(event->dwData));
break;
}
}
void SimConnect::handleData(SIMCONNECT_RECV_SIMOBJECT_DATA *data)
{
switch (data->dwRequestID) {
case REQUESTS::R_DATA: {
const std::lock_guard<std::mutex> lock(this->mutex);
struct data *_data = (struct data *)&data->dwData;
this->simData.pause = this->paused || this->pausedMenu;
this->simData.pBrake = _data->parkingBrake != 0 || _data->brakePos;
this->simData.onGrnd = _data->onGround != 0;
this->simData.totFuelKg = _data->fuel;
this->simData.truHdg = _data->headingTrue;
this->simData.alt = _data->altitude;
this->simData.gs = _data->groundSpeed;
this->simData.ias = _data->indicatedAirspeed;
this->simData.vs =
abs(_data->verticalVelocity - _data->verticalSpeed) > 200
? _data->verticalSpeed
: _data->verticalVelocity;
this->simData.lat = _data->latitude;
this->simData.lon = _data->longitude;
this->simData.ff[0] = _data->fuelFlowEng1;
this->simData.ff[1] = _data->fuelFlowEng2;
this->simData.ff[2] = _data->fuelFlowEng3;
this->simData.ff[3] = _data->fuelFlowEng4;
this->simData.maxSpd = _data->barberPoleSpeed;
strcpy(this->simData.path, this->aircraftPath.c_str());
this->simData.uptime = _data->elapsedTime;
this->simData.magHeading = _data->headingMagnetic;
this->simData.payloadKg =
_data->currentWeight - _data->emptyWeight - _data->fuel;
this->simData.totalWeightKg = _data->currentWeight;
}
}
}