/* Copyright (C) 2013 * swift Project Community / Contributors * * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, * including this file, may be copied, modified, propagated, or distributed except according to the terms * contained in the LICENSE file. */ #include "simconnectdatadefinition.h" #include "simconnectsymbols.h" #include "../fscommon/simulatorfscommonfunctions.h" #include "blackmisc/aviation/aircraftparts.h" #include "blackmisc/aviation/aircraftenginelist.h" #include "blackmisc/logmessage.h" #include using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackSimPlugin::FsCommon; namespace BlackSimPlugin { namespace FsxCommon { const QString &CSimConnectDefinitions::requestToString(Request request) { static const QString ownAircraft("RequestOwnAircraft"); static const QString title("RequestOwnAircraftTitle"); static const QString simEnv("RequestSimEnvironment"); static const QString sbData("RequestSbData"); static const QString facility("RequestFacility"); static const QString end(""); static const QString unknown("unknown"); switch (request) { case RequestOwnAircraft: return ownAircraft; case RequestOwnAircraftTitle: return title; case RequestSimEnvironment: return simEnv; case RequestSbData: return sbData; case RequestFacility: return facility; case RequestEndMarker: return end; default: break; } return unknown; } const QString &CSimConnectDefinitions::simObjectRequestToString(SimObjectRequest simObjectRequest) { static const QString baseId("base id"); static const QString add("add"); static const QString remove("remove"); static const QString lights("lights"); static const QString pos("position"); static const QString model("model"); static const QString misc("misc"); static const QString end(""); static const QString unknown("unknown"); switch (simObjectRequest) { case SimObjectBaseId: return baseId; case SimObjectAdd: return add; case SimObjectRemove: return remove; case SimObjectLights: return lights; case SimObjectPositionData: return pos; case SimObjectModel: return model; case SimObjectMisc: return misc; case SimObjectEndMarker: return end; default: break; } return unknown; } CSimConnectDefinitions::CSimConnectDefinitions() { } HRESULT CSimConnectDefinitions::initDataDefinitionsWhenConnected(const HANDLE hSimConnect) { HRESULT hr = s_ok(); hr += initOwnAircraft(hSimConnect); hr += initRemoteAircraft(hSimConnect); hr += initRemoteAircraftSimData(hSimConnect); hr += initSimulatorEnvironment(hSimConnect); hr += initSbDataArea(hSimConnect); return hr; } HRESULT CSimConnectDefinitions::initOwnAircraft(const HANDLE hSimConnect) { HRESULT hr = s_ok(); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE LATITUDE", "Degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE LONGITUDE", "Degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE ALTITUDE", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE ALT ABOVE GROUND", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PRESSURE ALTITUDE", "Meters"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "STATIC CG TO GROUND", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE HEADING DEGREES TRUE", "Degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE PITCH DEGREES", "Degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE BANK DEGREES", "Degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GROUND VELOCITY", "Knots"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GROUND ALTITUDE", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "SIM ON GROUND", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT STROBE", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT LANDING", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT TAXI", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT BEACON", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT NAV", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT LOGO", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "TRANSPONDER CODE:1", nullptr); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM ACTIVE FREQUENCY:1", "MHz"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM ACTIVE FREQUENCY:2", "MHz"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM STANDBY FREQUENCY:1", "MHz"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM STANDBY FREQUENCY:2", "MHz"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "FLAPS HANDLE PERCENT", "Percent Over 100"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "SPOILERS HANDLE POSITION", "Percent Over 100"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GEAR HANDLE POSITION", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "NUMBER OF ENGINES", "Number"); // Simconnect supports index 1 - 4 hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:1", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:2", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:3", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:4", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraftTitle, "TITLE", nullptr, SIMCONNECT_DATATYPE_STRING256); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: initOwnAircraft %1") << hr; } return hr; } HRESULT CSimConnectDefinitions::initRemoteAircraft(const HANDLE hSimConnect) { HRESULT hr = s_ok(); // Position hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSetPosition, "Initial Position", nullptr, SIMCONNECT_DATATYPE_INITPOSITION); // Hint: "Bool" and "Percent .." are units name // default data type is SIMCONNECT_DATATYPE_FLOAT64 -> double // Flaps hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "LEADING EDGE FLAPS LEFT PERCENT", "Percent Over 100"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "LEADING EDGE FLAPS RIGHT PERCENT", "Percent Over 100"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "TRAILING EDGE FLAPS LEFT PERCENT", "Percent Over 100"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "TRAILING EDGE FLAPS RIGHT PERCENT", "Percent Over 100"); // Gear & Spoiler hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GEAR HANDLE POSITION", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "SPOILERS HANDLE POSITION", "Percent Over 100"); // Engines hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:1", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:2", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:3", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:4", "Bool"); // Lights (other definition) hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraftTitle, "TITLE", nullptr, SIMCONNECT_DATATYPE_STRING256); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT STROBE", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT LANDING", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT TAXI", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT BEACON", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT NAV", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT LOGO", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT NAV", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT RECOGNITION", "Bool"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT CABIN", "Bool"); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: initRemoteAircraftSituation %1") << hr; } return hr; } HRESULT CSimConnectDefinitions::initRemoteAircraftSimData(const HANDLE hSimConnect) { HRESULT hr = s_ok(); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftGetPosition, "PLANE LATITUDE", "degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftGetPosition, "PLANE LONGITUDE", "degrees"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftGetPosition, "PLANE ALTITUDE", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftGetPosition, "GROUND ALTITUDE", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftGetPosition, "STATIC CG TO GROUND", "Feet"); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: initRemoteAircraftSimData DataRemoteAircraftGetPosition %1") << hr; } hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "STATIC CG TO GROUND", "Feet"); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "ATC TYPE", nullptr, SIMCONNECT_DATATYPE_STRING32); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "ATC MODEL", nullptr, SIMCONNECT_DATATYPE_STRING32); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "ATC ID", nullptr, SIMCONNECT_DATATYPE_STRING32); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "ATC AIRLINE", nullptr, SIMCONNECT_DATATYPE_STRING64); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "ATC FLIGHT NUMBER", nullptr, SIMCONNECT_DATATYPE_STRING8); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftModelData, "TITLE", nullptr, SIMCONNECT_DATATYPE_STRING256); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: initRemoteAircraftSimData DataRemoteAircraftModelData %1") << hr; } return hr; } HRESULT CSimConnectDefinitions::initSimulatorEnvironment(const HANDLE hSimConnect) { HRESULT hr = s_ok(); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataSimEnvironment, "ZULU TIME", "", SIMCONNECT_DATATYPE_INT32); hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataSimEnvironment, "LOCAL TIME", "", SIMCONNECT_DATATYPE_INT32); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: initSimulatorEnvironment %1") << hr; } return hr; } HRESULT CSimConnectDefinitions::initSbDataArea(const HANDLE hSimConnect) { HRESULT hr = s_ok(); const DWORD sbSize = sizeof(DataDefinitionClientAreaSb); // We need to know the client area 'name' and map it to a client ID hr += SimConnect_MapClientDataNameToID(hSimConnect, "SquawkBox Data", ClientAreaSquawkBox); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_MapClientDataNameToID %1") << hr; return hr; } // Mapping needs to be first hr += SimConnect_CreateClientData(hSimConnect, ClientAreaSquawkBox, sbSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_CreateClientData %1") << hr; return hr; } hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSb, 0, sbSize); hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbStandby, 17, 1); hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbIdent, 19, 1); hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbConnected, 1, 1); // network connected if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: SB data area data definitions %1") << hr; return hr; } // write a default client area so we are not suddenly squawking ident or so DataDefinitionClientAreaSb sbArea; sbArea.setDefaultValues(); hr += SimConnect_SetClientData(hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT, 0, sbSize, &sbArea); if (isFailure(hr)) { CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_SetClientData %1") << hr; } return hr; } DataDefinitionRemoteAircraftPartsWithoutLights::DataDefinitionRemoteAircraftPartsWithoutLights() { this->resetToInvalid(); } DataDefinitionRemoteAircraftPartsWithoutLights::DataDefinitionRemoteAircraftPartsWithoutLights(const CAircraftParts &parts) { this->initFromParts(parts); } bool DataDefinitionRemoteAircraftPartsWithoutLights::operator==(const DataDefinitionRemoteAircraftPartsWithoutLights &rhs) const { return std::tie(flapsLeadingEdgeLeftPercent, flapsLeadingEdgeRightPercent, flapsTrailingEdgeLeftPercent, flapsTrailingEdgeRightPercent, gearHandlePosition, spoilersHandlePosition, engine1Combustion, engine2Combustion, engine3Combustion, engine4Combustion) == std::tie(rhs.flapsLeadingEdgeLeftPercent, rhs.flapsLeadingEdgeRightPercent, rhs.flapsTrailingEdgeLeftPercent, rhs.flapsTrailingEdgeRightPercent, rhs.gearHandlePosition, rhs.spoilersHandlePosition, rhs.engine1Combustion, rhs.engine2Combustion, rhs.engine3Combustion, rhs.engine4Combustion); } void DataDefinitionRemoteAircraftPartsWithoutLights::setAllEngines(bool on) { engine1Combustion = on ? 1 : 0; engine2Combustion = on ? 1 : 0; engine3Combustion = on ? 1 : 0; engine4Combustion = on ? 1 : 0; } void DataDefinitionRemoteAircraftPartsWithoutLights::setEngine(int number1based, bool on) { double v = on ? 1.0 : 0.0; switch (number1based) { case 1: engine1Combustion = v; break; case 2: engine2Combustion = v; break; case 3: engine3Combustion = v; break; case 4: engine4Combustion = v; break; default: break; } } void DataDefinitionRemoteAircraftPartsWithoutLights::resetAllFlaps() { flapsLeadingEdgeLeftPercent = 0; flapsLeadingEdgeRightPercent = 0; flapsTrailingEdgeLeftPercent = 0; flapsTrailingEdgeRightPercent = 0; } void DataDefinitionRemoteAircraftPartsWithoutLights::resetSpoilers() { spoilersHandlePosition = 0; } void DataDefinitionRemoteAircraftPartsWithoutLights::resetToInvalid() { flapsLeadingEdgeLeftPercent = -1; flapsLeadingEdgeRightPercent = -1; flapsTrailingEdgeLeftPercent = -1; flapsTrailingEdgeRightPercent = -1; gearHandlePosition = -1; spoilersHandlePosition = -1; engine1Combustion = -1; engine2Combustion = -1; engine3Combustion = -1; engine4Combustion = -1; } void DataDefinitionRemoteAircraftPartsWithoutLights::initFromParts(const CAircraftParts &parts) { gearHandlePosition = parts.isGearDown() ? 1.0 : 0.0; flapsTrailingEdgeLeftPercent = flapsTrailingEdgeRightPercent = parts.getFlapsPercent() / 100.0; flapsLeadingEdgeLeftPercent = flapsLeadingEdgeRightPercent = parts.getFlapsPercent() * 0.2 / 100.0; spoilersHandlePosition = parts.isSpoilersOut() ? 1.0 : 0.0; this->setAllEngines(false); // init int e = 1; for (const CAircraftEngine &engine : parts.getEngines()) { this->setEngine(e++, engine.isOn()); } } CAircraftLights DataDefinitionRemoteAircraftLights::toLights() const { return CAircraftLights( dtb(lightStrobe), dtb(lightLanding), dtb(lightTaxi), dtb(lightBeacon), dtb(lightNav), dtb(lightLogo), dtb(lightRecognition), dtb(lightCabin)); } } // namespace } // namespace