#include "include/_simconnect.h" SimConnect::SimConnect( HWND hWnd, std::function toLog, std::shared_ptr &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::gaconnector::websocket::data *data) { const std::lock_guard 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 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; } } }