460 lines
18 KiB
C++

#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;
}
}
}