1075 lines
57 KiB
C++
1075 lines
57 KiB
C++
#include "load-manager.h"
|
|
|
|
// Data
|
|
UserData_t* UserData;
|
|
GSXData_t* GSXData;
|
|
paxPayloadData_t* livePaxPayloadData;
|
|
paxPayloadData_t* targetPaxPayloadData;
|
|
fPayloadData_t* liveFPayloadData;
|
|
fPayloadData_t* targetFPayloadData;
|
|
FuelData_t* liveFuelData;
|
|
UserOptions_t* UserOptions;
|
|
bool AircraftLoaded;
|
|
|
|
// Operational
|
|
bool commBusCallbackRegistered;
|
|
HANDLE simConnect;
|
|
FILE* logFile;
|
|
MODULE_VAR tick18 = { TICK18 };
|
|
|
|
// Init
|
|
extern "C" MSFS_CALLBACK void module_init(void) {
|
|
log(stdout, "Starting init.\n");
|
|
|
|
logFile = fopen("\\work\\log.txt", "w");
|
|
if (logFile == NULL)
|
|
{
|
|
log(stderr, "Error creating logfile.\n");
|
|
}
|
|
|
|
log(stdout, "Logfile created.\n");
|
|
log(stdout, "Version" VERSION_STRING"startup.\n");
|
|
|
|
UserData = new UserData_t();
|
|
GSXData = new GSXData_t();
|
|
livePaxPayloadData = new paxPayloadData_t();
|
|
targetPaxPayloadData = new paxPayloadData_t();
|
|
liveFPayloadData = new fPayloadData_t();
|
|
targetFPayloadData = new fPayloadData_t();
|
|
liveFuelData = new FuelData_t();
|
|
UserOptions = new UserOptions_t();
|
|
// defaults
|
|
UserOptions->paxWeightKG = 86;
|
|
UserOptions->paxWeightLBS = 190;
|
|
UserOptions->bagWeightKG = 23;
|
|
UserOptions->bagWeightLBS = 50;
|
|
|
|
targetFPayloadData->CGTarget = targetPaxPayloadData->CGTarget = 21;
|
|
|
|
#pragma region SimConnect
|
|
|
|
// SimConnect open
|
|
HRESULT hr;
|
|
hr = SimConnect_Open(&simConnect, "KHOFMANN TFDi MD-11 Load Manager", nullptr, 0, 0, 0);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not open SimConnect connection, terminating.\n");
|
|
return;
|
|
}
|
|
// SimConnect Empty Weight data definition
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_EMPTY_WEIGHT, "EMPTY WEIGHT", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add EMPTY WEIGHT to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
// SimConnect Pax/F Weight data definition
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:1", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:1 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:1", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:1 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:2", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:2 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:2", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:2 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:3", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:3 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:3", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:3 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:4", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:4 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:4", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:4 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:5", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:5 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:5", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:5 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:6", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:6 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:6", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:6 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:7", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:7 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:7", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:7 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:8", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:8 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:8", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:8 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:9", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:9 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:9", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:9 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:10", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:10 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:10", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:10 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:11", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:11 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:11", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:11 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:12", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:12 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:12", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:12 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:13", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:13 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:13", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:13 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:14", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:14 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:14", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:14 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:15", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:15 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_F, "PAYLOAD STATION WEIGHT:15", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:15 to F data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:16", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:16 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:17", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:17 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:18", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:18 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:19", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:19 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:20", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:20 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_PAYLOAD_PAX, "PAYLOAD STATION WEIGHT:21", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add PAYLOAD STATION WEIGHT:21 to PAX data definition, terminating.\n");
|
|
return;
|
|
}
|
|
// SimConnect Fuel data definition
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL WEIGHT PER GALLON", "pounds", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL WEIGHT PER GALLON to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK LEFT MAIN QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK LEFT MAIN QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK RIGHT MAIN QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK RIGHT MAIN QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK CENTER QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK CENTER QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK CENTER2 QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK CENTER2 QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK CENTER3 QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK CENTER3 QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK LEFT TIP QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK LEFT TIP QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK RIGHT TIP QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK RIGHT TIP QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK EXTERNAL1 QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK EXTERNAL1 QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK LEFT AUX QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK LEFT AUX QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_FUEL, "FUEL TANK RIGHT AUX QUANTITY", "gallons", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add FUEL TANK RIGHT AUX QUANTITY to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
// GSX LVars
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_BOARDING_STATE", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:FSDT_GSX_BOARDING_STATE to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_DEBOARDING_STATE", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:FSDT_GSX_DEBOARDING_STATE to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_NUMPASSENGERS_BOARDING_TOTAL", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:FSDT_GSX_NUMPASSENGERS_BOARDING_TOTAL to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_NUMPASSENGERS_DEBOARDING_TOTAL", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:FSDT_GSX_NUMPASSENGERS_DEBOARDING_TOTAL to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_BOARDING_CARGO_PERCENT", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:FSDT_GSX_BOARDING_CARGO_PERCENT to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_DEBOARDING_CARGO_PERCENT", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:FSDT_GSX_DEBOARDING_CARGO_PERCENT to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
// User LVars
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_USER_DATA, "L:MD11_EFB_IS_CARGO", "bool", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:MD11_EFB_IS_CARGO to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_USER_DATA, "L:MD11_OPT_ER", "bool", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:MD11_OPT_ER to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_USER_DATA, "L:MD11_EFB_OPTIONS_GENERAL", "number", SIMCONNECT_DATATYPE_FLOAT64);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not add L:MD11_EFB_OPTIONS_GENERAL to data definition, terminating.\n");
|
|
return;
|
|
}
|
|
|
|
log(stdout, "Data definitions created.\n");
|
|
|
|
// SimConnect Requests
|
|
hr = SimConnect_RequestDataOnSimObject(simConnect, DATA_REQUEST_EMPTY_WEIGHT, DATA_DEFINITION_EMPTY_WEIGHT, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not request empty weight, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_RequestDataOnSimObject(simConnect, DATA_REQUEST_PAYLOAD_PAX, DATA_DEFINITION_PAYLOAD_PAX, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not request payload pax, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_RequestDataOnSimObject(simConnect, DATA_REQUEST_PAYLOAD_F, DATA_DEFINITION_PAYLOAD_F, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not request payload f, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_RequestDataOnSimObject(simConnect, DATA_REQUEST_FUEL, DATA_DEFINITION_FUEL, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not request fuel, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_RequestDataOnSimObject(simConnect, DATA_REQUEST_GSX, DATA_DEFINITION_GSX, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not request GSX, terminating.\n");
|
|
return;
|
|
}
|
|
hr = SimConnect_RequestDataOnSimObject(simConnect, DATA_REQUEST_USER_DATA, DATA_DEFINITION_USER_DATA, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not request user data, terminating.\n");
|
|
return;
|
|
}
|
|
|
|
log(stdout, "Requests created.\n");
|
|
|
|
hr = SimConnect_CallDispatch(simConnect, MyDispatchProc, nullptr);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Could not set dispatch proc, terminating.\n");
|
|
return;
|
|
}
|
|
|
|
log(stdout, "Callback created.\n");
|
|
|
|
#pragma endregion
|
|
|
|
// CommBus
|
|
if (!fsCommBusRegister(COMM_BUS_UPDATE_TARGET_EVENT, commBusUpdateTargetCallback)) {
|
|
log(stderr, "Could not register CommBus, terminating.\n");
|
|
return;
|
|
}
|
|
else {
|
|
log(stdout, "CommBus registered.\n");
|
|
}
|
|
|
|
// Options
|
|
FILE* optionsFile = fopen("\\work\\options.json", "rb");
|
|
if (optionsFile != NULL) {
|
|
char readBuffer[256];
|
|
rapidjson::FileReadStream is(optionsFile, readBuffer, sizeof(readBuffer));
|
|
rapidjson::Document optionsDoc;
|
|
optionsDoc.ParseStream(is);
|
|
if (optionsDoc.HasMember("GSXSync")) UserOptions->GSXSync = optionsDoc["GSXSync"].GetBool();
|
|
if (optionsDoc.HasMember("paxWeightKG")) UserOptions->paxWeightKG = optionsDoc["paxWeightKG"].GetDouble();
|
|
if (optionsDoc.HasMember("bagWeightKG")) UserOptions->bagWeightKG = optionsDoc["bagWeightKG"].GetDouble();
|
|
if (optionsDoc.HasMember("paxWeightLBS")) UserOptions->paxWeightLBS = optionsDoc["paxWeightLBS"].GetDouble();
|
|
if (optionsDoc.HasMember("bagWeightLBS")) UserOptions->bagWeightLBS = optionsDoc["bagWeightLBS"].GetDouble();
|
|
fclose(optionsFile);
|
|
|
|
log(stdout, "Options loaded.\n");
|
|
}
|
|
else {
|
|
log(stdout, "Options file not present, skip.\n");
|
|
}
|
|
|
|
log(stdout, "Initialized.\n");
|
|
}
|
|
|
|
// Deinit
|
|
extern "C" MSFS_CALLBACK void module_deinit(void) {
|
|
HRESULT hr;
|
|
hr = SimConnect_Close(simConnect);
|
|
if (hr != S_OK) {
|
|
log(stderr, "Failed to close SimConnect.\n");
|
|
}
|
|
|
|
log(stdout, "SimConnect closed.\n");
|
|
|
|
delete UserData;
|
|
delete GSXData;
|
|
delete livePaxPayloadData;
|
|
delete targetPaxPayloadData;
|
|
delete liveFPayloadData;
|
|
delete targetFPayloadData;
|
|
delete liveFuelData;
|
|
delete UserOptions;
|
|
|
|
log(stdout, "Global memory released.\n");
|
|
|
|
fsCommBusUnregister(COMM_BUS_UPDATE_TARGET_EVENT, commBusUpdateTargetCallback);
|
|
|
|
log(stdout, "CommBus unregistered.\n");
|
|
|
|
// Options
|
|
rapidjson::Document optionsDoc;
|
|
rapidjson::Document::AllocatorType& allocator = optionsDoc.GetAllocator();
|
|
optionsDoc.SetObject();
|
|
optionsDoc.AddMember("GSXSync", UserOptions->GSXSync, allocator);
|
|
optionsDoc.AddMember("paxWeightKG", UserOptions->paxWeightKG, allocator);
|
|
optionsDoc.AddMember("bagWeightKG", UserOptions->bagWeightKG, allocator);
|
|
optionsDoc.AddMember("paxWeightLBS", UserOptions->paxWeightLBS, allocator);
|
|
optionsDoc.AddMember("bagWeightLBS", UserOptions->bagWeightLBS, allocator);
|
|
FILE* optionsFile = fopen("\\work\\options.json", "wb");
|
|
if (optionsFile != NULL) {
|
|
char writeBuffer[256];
|
|
rapidjson::FileWriteStream os(optionsFile, writeBuffer, sizeof(writeBuffer));
|
|
rapidjson::Writer<rapidjson::FileWriteStream> writer(os);
|
|
optionsDoc.Accept(writer);
|
|
fclose(optionsFile);
|
|
|
|
log(stdout, "Options written.\n");
|
|
}
|
|
else {
|
|
log(stdout, "Filed to open options file for write, skip.\n");
|
|
}
|
|
|
|
log(stdout, "Deinitialized.\n");
|
|
}
|
|
|
|
// Main loop
|
|
extern "C" MSFS_CALLBACK bool Load_Manager_gauge_callback(FsContext ctx, int service_id, void* pData) {
|
|
switch (service_id) {
|
|
case PANEL_SERVICE_PRE_UPDATE: {
|
|
lookup_var(&tick18);
|
|
if (fmod(tick18.var_value.n, 3) == 0) sendData();
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// CommBus
|
|
void commBusUpdateTargetCallback(const char* args, unsigned int size, void* ctx) {
|
|
int hr = receiveData(args);
|
|
log(stdout, "Target update request exited with: %d.\n", (void*)hr);
|
|
}
|
|
|
|
#pragma region JSON data handling
|
|
|
|
// JSON receive
|
|
int receiveData(const char* buf) {
|
|
if (liveFPayloadData == nullptr || livePaxPayloadData == nullptr || targetFPayloadData == nullptr || targetPaxPayloadData == nullptr ||
|
|
liveFuelData == nullptr || UserData == nullptr) return 0;
|
|
|
|
rapidjson::Document document;
|
|
document.Parse(buf);
|
|
if (document.HasParseError()) return document.GetParseError();
|
|
|
|
if (document.HasMember("mode")) {
|
|
int mode = document["mode"].GetUint();
|
|
switch(mode) {
|
|
// SB Entry
|
|
case 0: {
|
|
if (UserData->isCargo) {
|
|
if(document.HasMember("CGTarget"))
|
|
targetFPayloadData->CGTarget = document["CGTarget"].GetDouble();
|
|
|
|
if (document.HasMember("plannedZFW"))
|
|
targetFPayloadData->sbPlanned.ZFW = document["plannedZFW"].GetDouble();
|
|
if (document.HasMember("plannedGW"))
|
|
targetFPayloadData->sbPlanned.GW = document["plannedGW"].GetDouble();
|
|
|
|
if (document.HasMember("cargo"))
|
|
targetFPayloadData->sbPlanned.cargo = document["cargo"].GetInt();
|
|
|
|
distribute(targetFPayloadData, liveFuelData, targetFPayloadData->sbPlanned.cargo, UserData);
|
|
}
|
|
else {
|
|
if (document.HasMember("CGTarget"))
|
|
targetPaxPayloadData->CGTarget = document["CGTarget"].GetDouble();
|
|
|
|
if (document.HasMember("plannedZFW"))
|
|
targetPaxPayloadData->sbPlanned.ZFW = document["plannedZFW"].GetDouble();
|
|
if (document.HasMember("plannedGW"))
|
|
targetPaxPayloadData->sbPlanned.GW = document["plannedGW"].GetDouble();
|
|
|
|
if (document.HasMember("numPax"))
|
|
targetPaxPayloadData->sbPlanned.pax = document["numPax"].GetInt();
|
|
if (document.HasMember("cargo"))
|
|
targetPaxPayloadData->sbPlanned.cargo = document["cargo"].GetInt();
|
|
|
|
distribute(targetPaxPayloadData, liveFuelData, targetPaxPayloadData->sbPlanned.pax, targetPaxPayloadData->sbPlanned.cargo, UserData, UserOptions);
|
|
}
|
|
break;
|
|
}
|
|
// ZFW Entry
|
|
case 1: {
|
|
if (!document.HasMember("ZFWTarget") || !document.HasMember("CGTarget")) return -1;
|
|
double ZFWTarget = document["ZFWTarget"].GetDouble();
|
|
double CGTarget = document["CGTarget"].GetDouble();
|
|
|
|
if (UserData->isCargo) {
|
|
targetFPayloadData->CGTarget = CGTarget;
|
|
distribute(targetFPayloadData, liveFuelData, ZFWTarget, UserData);
|
|
}
|
|
else {
|
|
targetPaxPayloadData->CGTarget = CGTarget;
|
|
distribute(targetPaxPayloadData, liveFuelData, ZFWTarget, UserData, UserOptions);
|
|
}
|
|
break;
|
|
}
|
|
// Station Entry
|
|
case 2: {
|
|
if (UserData->isCargo) {
|
|
if (!document.HasMember("upper1") || !document.HasMember("upper2") ||
|
|
!document.HasMember("upper3") || !document.HasMember("upper4") ||
|
|
!document.HasMember("lowerForward") || !document.HasMember("lowerRear")) return -1;
|
|
targetFPayloadData->stations.upper1 = document["upper1"].GetInt();
|
|
targetFPayloadData->stations.upper2 = document["upper2"].GetInt();
|
|
targetFPayloadData->stations.upper3 = document["upper3"].GetInt();
|
|
targetFPayloadData->stations.upper4 = document["upper4"].GetInt();
|
|
targetFPayloadData->lowerForward = document["lowerForward"].GetDouble();
|
|
targetFPayloadData->lowerRear = document["lowerRear"].GetDouble();
|
|
|
|
generatePayload(targetFPayloadData, UserData->isImperial);
|
|
}
|
|
else {
|
|
if (!document.HasMember("business1") || !document.HasMember("business2") ||
|
|
!document.HasMember("economy1") || !document.HasMember("economy2") ||
|
|
!document.HasMember("forwardCargo") || !document.HasMember("rearCargo")) return -1;
|
|
targetPaxPayloadData->paxCount.business1 = document["business1"].GetInt();
|
|
targetPaxPayloadData->paxCount.business2 = document["business2"].GetInt();
|
|
targetPaxPayloadData->paxCount.economy1 = document["economy1"].GetInt();
|
|
targetPaxPayloadData->paxCount.economy2 = document["economy2"].GetInt();
|
|
targetPaxPayloadData->forwardCargo = document["forwardCargo"].GetDouble();
|
|
targetPaxPayloadData->rearCargo = document["rearCargo"].GetDouble();
|
|
|
|
generatePayload(targetPaxPayloadData, UserData->isImperial, UserOptions);
|
|
}
|
|
break;
|
|
}
|
|
// Trigger load
|
|
case 3: {
|
|
if (UserData->isCargo) {
|
|
load(targetFPayloadData, simConnect, UserData->isImperial);
|
|
}
|
|
else {
|
|
load(targetPaxPayloadData, simConnect, UserData->isImperial);
|
|
}
|
|
|
|
AircraftLoaded = true;
|
|
|
|
break;
|
|
}
|
|
// Trigger unload
|
|
case 4: {
|
|
if (UserData->isCargo) {
|
|
unloadF(simConnect, UserData->isER);
|
|
}
|
|
else {
|
|
unload(simConnect, UserData->isER);
|
|
}
|
|
|
|
AircraftLoaded = false;
|
|
|
|
break;
|
|
}
|
|
// Option set
|
|
case 5: {
|
|
if (document.HasMember("GSXSync")) {
|
|
UserOptions->GSXSync = document["GSXSync"].GetBool();
|
|
}
|
|
if (document.HasMember("paxWeight")) {
|
|
if (UserData->isImperial) UserOptions->paxWeightLBS = document["paxWeight"].GetInt();
|
|
else UserOptions->paxWeightKG = document["paxWeight"].GetInt();
|
|
}
|
|
if (document.HasMember("bagWeight")) {
|
|
if (UserData->isImperial) UserOptions->bagWeightLBS = document["bagWeight"].GetInt();
|
|
else UserOptions->bagWeightKG = document["bagWeight"].GetInt();
|
|
}
|
|
|
|
rapidjson::Document optionsDoc;
|
|
rapidjson::Document::AllocatorType& allocator = optionsDoc.GetAllocator();
|
|
optionsDoc.SetObject();
|
|
optionsDoc.AddMember("GSXSync", UserOptions->GSXSync, allocator);
|
|
optionsDoc.AddMember("paxWeightKG", UserOptions->paxWeightKG, allocator);
|
|
optionsDoc.AddMember("bagWeightKG", UserOptions->bagWeightKG, allocator);
|
|
optionsDoc.AddMember("paxWeightLBS", UserOptions->paxWeightLBS, allocator);
|
|
optionsDoc.AddMember("bagWeightLBS", UserOptions->bagWeightLBS, allocator);
|
|
FILE* optionsFile = fopen("\\work\\options.json", "wb");
|
|
if (optionsFile != NULL) {
|
|
char writeBuffer[256];
|
|
rapidjson::FileWriteStream os(optionsFile, writeBuffer, sizeof(writeBuffer));
|
|
rapidjson::Writer<rapidjson::FileWriteStream> writer(os);
|
|
optionsDoc.Accept(writer);
|
|
fclose(optionsFile);
|
|
|
|
log(stdout, "Options written.\n");
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
sendData();
|
|
}
|
|
else return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// JSON send
|
|
void sendData () {
|
|
if (liveFPayloadData == nullptr || livePaxPayloadData == nullptr || targetFPayloadData == nullptr || targetPaxPayloadData == nullptr ||
|
|
liveFuelData == nullptr || UserData == nullptr || GSXData == nullptr) return;
|
|
|
|
rapidjson::Document document;
|
|
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
|
|
document.SetObject();
|
|
|
|
rapidjson::Value livePayload;
|
|
livePayload.SetObject();
|
|
rapidjson::Value targetPayload;
|
|
targetPayload.SetObject();
|
|
rapidjson::Value GSX;
|
|
GSX.SetObject();
|
|
rapidjson::Value userData;
|
|
userData.SetObject();
|
|
rapidjson::Value limits;
|
|
limits.SetObject();
|
|
rapidjson::Value options;
|
|
options.SetObject();
|
|
rapidjson::Value sbPlanned;
|
|
sbPlanned.SetObject();
|
|
|
|
rapidjson::StringBuffer strbuf;
|
|
rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
|
|
|
|
#pragma region Live Payload
|
|
|
|
// OEW (empty + aux tank wgts)
|
|
livePayload.AddMember("empty",
|
|
FROM_POUNDS(UserData->isImperial, UserData->isCargo ? liveFPayloadData->empty : livePaxPayloadData->empty) +
|
|
FROM_POUNDS(UserData->isImperial, UserData->isCargo ? liveFPayloadData->leftAux : livePaxPayloadData->leftAux) +
|
|
FROM_POUNDS(UserData->isImperial, UserData->isCargo ? liveFPayloadData->rightAux : livePaxPayloadData->rightAux),
|
|
allocator);
|
|
// Cargo only
|
|
if (UserData->isCargo) {
|
|
livePayload.AddMember("crew",
|
|
FROM_POUNDS(UserData->isImperial, liveFPayloadData->pilot) +
|
|
FROM_POUNDS(UserData->isImperial, liveFPayloadData->firstOfficer) +
|
|
FROM_POUNDS(UserData->isImperial, liveFPayloadData->engineer),
|
|
allocator);
|
|
livePayload.AddMember("upper1", FROM_POUNDS(UserData->isImperial, liveFPayloadData->upper1Left + liveFPayloadData->upper1Right), allocator);
|
|
livePayload.AddMember("upper2", FROM_POUNDS(UserData->isImperial, liveFPayloadData->upper2Left + liveFPayloadData->upper2Right), allocator);
|
|
livePayload.AddMember("upper3", FROM_POUNDS(UserData->isImperial, liveFPayloadData->upper3Left + liveFPayloadData->upper3Right), allocator);
|
|
livePayload.AddMember("upper4", FROM_POUNDS(UserData->isImperial, liveFPayloadData->upper4Left + liveFPayloadData->upper4Right), allocator);
|
|
livePayload.AddMember("lowerForward", FROM_POUNDS(UserData->isImperial, liveFPayloadData->lowerForward), allocator);
|
|
livePayload.AddMember("lowerRear", FROM_POUNDS(UserData->isImperial, liveFPayloadData->lowerRear), allocator);
|
|
livePayload.AddMember("total", FROM_POUNDS(UserData->isImperial, liveFPayloadData->total), allocator);
|
|
// CGs
|
|
calculateCGs(liveFPayloadData, liveFuelData, &liveFPayloadData->ZFWCG, &liveFPayloadData->TOCG, true);
|
|
livePayload.AddMember("ZFWCG", liveFPayloadData->ZFWCG, allocator);
|
|
livePayload.AddMember("TOCG", liveFPayloadData->TOCG, allocator);
|
|
}
|
|
// Pax only (converted to passengers)
|
|
else {
|
|
livePayload.AddMember("crew",
|
|
FROM_POUNDS(UserData->isImperial, livePaxPayloadData->pilot) + FROM_POUNDS(UserData->isImperial, livePaxPayloadData->firstOfficer) +
|
|
FROM_POUNDS(UserData->isImperial, livePaxPayloadData->engineer) + FROM_POUNDS(UserData->isImperial, livePaxPayloadData->cabinCrewFront) +
|
|
FROM_POUNDS(UserData->isImperial, livePaxPayloadData->cabinCrewRear),
|
|
allocator);
|
|
livePayload.AddMember("business1",
|
|
(short)round((livePaxPayloadData->business1Left + livePaxPayloadData->business1Center +
|
|
livePaxPayloadData->business1Right) / PAX_WEIGHT(true, UserOptions)),
|
|
allocator);
|
|
livePayload.AddMember("business2",
|
|
(short)round((livePaxPayloadData->business2Left + livePaxPayloadData->business2Center +
|
|
livePaxPayloadData->business2Right) / PAX_WEIGHT(true, UserOptions)),
|
|
allocator);
|
|
livePayload.AddMember("economy1",
|
|
(short)round((livePaxPayloadData->economy1Left + livePaxPayloadData->economy1Center +
|
|
livePaxPayloadData->economy1Right) / PAX_WEIGHT(true, UserOptions)),
|
|
allocator);
|
|
livePayload.AddMember("economy2",
|
|
(short)round((livePaxPayloadData->economy2Left + livePaxPayloadData->economy2Center +
|
|
livePaxPayloadData->economy2Right) / PAX_WEIGHT(true, UserOptions)),
|
|
allocator);
|
|
livePayload.AddMember("forwardCargo", FROM_POUNDS(UserData->isImperial, livePaxPayloadData->forwardCargo), allocator);
|
|
livePayload.AddMember("rearCargo", FROM_POUNDS(UserData->isImperial, livePaxPayloadData->rearCargo), allocator);
|
|
livePayload.AddMember("total", FROM_POUNDS(UserData->isImperial, livePaxPayloadData->total), allocator);
|
|
// CGs
|
|
calculateCGs(livePaxPayloadData, liveFuelData, &livePaxPayloadData->ZFWCG, &livePaxPayloadData->TOCG, true);
|
|
livePayload.AddMember("ZFWCG",livePaxPayloadData->ZFWCG, allocator);
|
|
livePayload.AddMember("TOCG", livePaxPayloadData->TOCG, allocator);
|
|
}
|
|
// Fuel
|
|
livePayload.AddMember("fuel", FROM_POUNDS(UserData->isImperial, liveFuelData->total), allocator);
|
|
#pragma endregion
|
|
|
|
#pragma region Target Payload
|
|
|
|
// OEW (empty + aux tank wgts)
|
|
targetPayload.AddMember("empty",
|
|
(UserData->isCargo ? targetFPayloadData->empty : targetPaxPayloadData->empty)+
|
|
(UserData->isCargo ? targetFPayloadData->leftAux : targetPaxPayloadData->leftAux) +
|
|
(UserData->isCargo ? targetFPayloadData->rightAux : targetPaxPayloadData->rightAux),
|
|
allocator);
|
|
// Cargo only
|
|
if (UserData->isCargo) {
|
|
targetPayload.AddMember("crew", targetFPayloadData->pilot + targetFPayloadData->firstOfficer + targetFPayloadData->engineer, allocator);
|
|
targetPayload.AddMember("upper1", targetFPayloadData->upper1Left + targetFPayloadData->upper1Right, allocator);
|
|
targetPayload.AddMember("upper2", targetFPayloadData->upper2Left + targetFPayloadData->upper2Right, allocator);
|
|
targetPayload.AddMember("upper3", targetFPayloadData->upper3Left + targetFPayloadData->upper3Right, allocator);
|
|
targetPayload.AddMember("upper4", targetFPayloadData->upper4Left + targetFPayloadData->upper4Right, allocator);
|
|
targetPayload.AddMember("lowerForward", targetFPayloadData->lowerForward, allocator);
|
|
targetPayload.AddMember("lowerRear", targetFPayloadData->lowerRear, allocator);
|
|
targetPayload.AddMember("total", targetFPayloadData->total, allocator);
|
|
targetPayload.AddMember("CGTarget", targetFPayloadData->CGTarget, allocator);
|
|
// CGs
|
|
calculateCGs(targetFPayloadData, liveFuelData, &targetFPayloadData->ZFWCG, &targetFPayloadData->TOCG, UserData->isImperial);
|
|
targetPayload.AddMember("ZFWCG", targetFPayloadData->ZFWCG, allocator);
|
|
targetPayload.AddMember("TOCG", targetFPayloadData->TOCG, allocator);
|
|
}
|
|
// Pax only (converted to passengers)
|
|
else {
|
|
targetPayload.AddMember("crew",
|
|
targetPaxPayloadData->pilot + targetPaxPayloadData->firstOfficer + targetPaxPayloadData->engineer +
|
|
targetPaxPayloadData->cabinCrewFront + targetPaxPayloadData->cabinCrewRear,
|
|
allocator);
|
|
targetPayload.AddMember("business1", targetPaxPayloadData->paxCount.business1, allocator);
|
|
targetPayload.AddMember("business2", targetPaxPayloadData->paxCount.business2, allocator);
|
|
targetPayload.AddMember("economy1", targetPaxPayloadData->paxCount.economy1, allocator);
|
|
targetPayload.AddMember("economy2", targetPaxPayloadData->paxCount.economy2, allocator);
|
|
targetPayload.AddMember("forwardCargo", targetPaxPayloadData->forwardCargo, allocator);
|
|
targetPayload.AddMember("rearCargo", targetPaxPayloadData->rearCargo, allocator);
|
|
targetPayload.AddMember("total", targetPaxPayloadData->total, allocator);
|
|
targetPayload.AddMember("CGTarget", targetPaxPayloadData->CGTarget, allocator);
|
|
// CGs
|
|
calculateCGs(targetPaxPayloadData, liveFuelData, &targetPaxPayloadData->ZFWCG, &targetPaxPayloadData->TOCG, UserData->isImperial);
|
|
targetPayload.AddMember("ZFWCG", targetPaxPayloadData->ZFWCG, allocator);
|
|
targetPayload.AddMember("TOCG", targetPaxPayloadData->TOCG, allocator);
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
// GSX
|
|
GSX.AddMember("boardingState", GSXData->boardingState, allocator);
|
|
GSX.AddMember("deboardingState", GSXData->deboardingState, allocator);
|
|
|
|
// User Data
|
|
userData.AddMember<bool>("isCargo", UserData->isCargo, allocator);
|
|
userData.AddMember<bool>("isER", UserData->isER, allocator);
|
|
userData.AddMember<bool>("isImperial", UserData->isImperial, allocator);
|
|
|
|
// Limits
|
|
limits.AddMember("minCG", MIN_CG, allocator);
|
|
limits.AddMember("maxCG", MAX_CG, allocator);
|
|
limits.AddMember("maxFuel", UserData->isER ? MAX_FUEL_ER(UserData->isImperial) : MAX_FUEL(UserData->isImperial), allocator);
|
|
limits.AddMember("maxTOW", UserData->isER ? MAX_TOW_ER(UserData->isImperial) : MAX_TOW(UserData->isImperial), allocator);
|
|
// Cargo Only
|
|
if (UserData->isCargo) {
|
|
limits.AddMember("upper1", MAX_UPPER_CARGO(UserData->isImperial), allocator);
|
|
limits.AddMember("upper2", MAX_UPPER_CARGO(UserData->isImperial), allocator);
|
|
limits.AddMember("upper3", MAX_UPPER_CARGO(UserData->isImperial), allocator);
|
|
limits.AddMember("upper4", MAX_UPPER_CARGO(UserData->isImperial), allocator);
|
|
limits.AddMember("lowerForward", MAX_FRONT_CARGO(UserData->isImperial), allocator);
|
|
limits.AddMember("lowerRear", MAX_REAR_CARGO(UserData->isImperial, UserData->isER), allocator);
|
|
limits.AddMember("maxZFW", MAX_F_ZFW(UserData->isImperial), allocator);
|
|
limits.AddMember("minZFW", targetFPayloadData->empty + targetFPayloadData->leftAux + targetFPayloadData->rightAux, allocator);
|
|
}
|
|
// Pax only
|
|
else {
|
|
limits.AddMember("business1", MAX_BUSINESS_1, allocator);
|
|
limits.AddMember("business2", MAX_BUSINESS_2, allocator);
|
|
limits.AddMember("economy1", MAX_ECONOMY_1, allocator);
|
|
limits.AddMember("economy2", MAX_ECONOMY_2, allocator);
|
|
limits.AddMember("forwardCargo", MAX_FRONT_CARGO(UserData->isImperial), allocator);
|
|
limits.AddMember("rearCargo", MAX_REAR_CARGO(UserData->isImperial, UserData->isER), allocator);
|
|
limits.AddMember("maxZFW", MAX_PAX_ZFW(UserData->isImperial), allocator);
|
|
limits.AddMember("minZFW", targetPaxPayloadData->empty + targetPaxPayloadData->leftAux + targetPaxPayloadData->rightAux, allocator);
|
|
}
|
|
|
|
// Options
|
|
options.AddMember("GSXSync", UserOptions->GSXSync, allocator);
|
|
options.AddMember("paxWeight", UserData->isImperial ? UserOptions->paxWeightLBS : UserOptions->paxWeightKG, allocator);
|
|
options.AddMember("bagWeight", UserData->isImperial ? UserOptions->bagWeightLBS : UserOptions->bagWeightKG, allocator);
|
|
|
|
// SB Planned
|
|
sbPlanned.AddMember("ZFW", UserData->isCargo ? targetFPayloadData->sbPlanned.ZFW: targetPaxPayloadData->sbPlanned.ZFW, allocator);
|
|
sbPlanned.AddMember("GW", UserData->isCargo ? targetFPayloadData->sbPlanned.GW : targetPaxPayloadData->sbPlanned.GW, allocator);
|
|
sbPlanned.AddMember("cargo", UserData->isCargo ? targetFPayloadData->sbPlanned.cargo : targetPaxPayloadData->sbPlanned.cargo, allocator);
|
|
if (!UserData->isCargo) {
|
|
sbPlanned.AddMember("pax", targetPaxPayloadData->sbPlanned.pax, allocator);
|
|
}
|
|
|
|
// Construct document
|
|
document.AddMember("livePayload", livePayload.Move(), allocator);
|
|
document.AddMember("targetPayload", targetPayload.Move(), allocator);
|
|
document.AddMember("GSX", GSX.Move(), allocator);
|
|
document.AddMember("userData", userData.Move(), allocator);
|
|
document.AddMember("limits", limits.Move(), allocator);
|
|
document.AddMember("options", options.Move(), allocator);
|
|
document.AddMember("sbPlanned", sbPlanned.Move(), allocator);
|
|
document.AddMember("loaded", AircraftLoaded, allocator);
|
|
|
|
// Write to CommBus
|
|
document.Accept(writer);
|
|
|
|
fsCommBusCall(COMM_BUS_LIVE_DATA_EVENT, strbuf.GetString(), strbuf.GetSize(), FsCommBusBroadcast_JS);
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
// Logfile
|
|
void log(FILE* file, const char* format, void* optionalElement)
|
|
{
|
|
if (logFile != NULL)
|
|
{
|
|
time_t rawtime;
|
|
time(&rawtime);
|
|
|
|
char* _new = (char*)calloc(strlen(format) + 24 + 1, sizeof(char));
|
|
if (_new == NULL) {
|
|
fprintf(stderr, MODULE_NAME"Failed to allocate string for log.\n");
|
|
return;
|
|
}
|
|
|
|
strftime(_new, 24, "%FT%TZ | ", gmtime(&rawtime));
|
|
strncat(_new, format, strlen(format));
|
|
fprintf(logFile, _new, optionalElement);
|
|
fflush(logFile);
|
|
free(_new);
|
|
}
|
|
|
|
char* _new = (char*)calloc(strlen(format) + strlen(MODULE_NAME) + 1, sizeof(char));
|
|
if (_new == NULL) {
|
|
fprintf(stderr, MODULE_NAME"Failed to allocate string for interal console.\n");
|
|
return;
|
|
}
|
|
|
|
strncpy(_new, MODULE_NAME, strlen(MODULE_NAME));
|
|
strncat(_new, format, strlen(format));
|
|
fprintf(file, _new, optionalElement);
|
|
free(_new);
|
|
}
|
|
|
|
// SimConnect
|
|
void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext) {
|
|
switch (pData->dwID) {
|
|
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: {
|
|
SIMCONNECT_RECV_SIMOBJECT_DATA* pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
|
|
switch (pObjData->dwRequestID) {
|
|
case DATA_REQUEST_EMPTY_WEIGHT: {
|
|
liveFPayloadData->empty = livePaxPayloadData->empty = *((double*)&pObjData->dwData);
|
|
|
|
break;
|
|
}
|
|
case DATA_REQUEST_PAYLOAD_F: {
|
|
fPayloadData_t* data = (fPayloadData_t*)&pObjData->dwData;
|
|
data->empty = liveFPayloadData->empty;
|
|
memcpy(liveFPayloadData, data, sizeof(fPayloadData_t));
|
|
liveFPayloadData->total = liveFPayloadData->empty + liveFPayloadData->pilot + liveFPayloadData->firstOfficer +
|
|
liveFPayloadData->engineer + liveFPayloadData->upper1Left + liveFPayloadData->upper1Right +
|
|
liveFPayloadData->upper2Left + liveFPayloadData->upper2Right + liveFPayloadData->upper3Left +
|
|
liveFPayloadData->upper3Right + liveFPayloadData->upper4Left + liveFPayloadData->upper4Right +
|
|
liveFPayloadData->lowerForward + liveFPayloadData->lowerRear + liveFPayloadData->leftAux +
|
|
liveFPayloadData->rightAux;
|
|
|
|
break;
|
|
}
|
|
case DATA_REQUEST_PAYLOAD_PAX: {
|
|
paxPayloadData_t* data = (paxPayloadData_t*)&pObjData->dwData;
|
|
data->empty = livePaxPayloadData->empty;
|
|
memcpy(livePaxPayloadData, data, sizeof(paxPayloadData_t));
|
|
livePaxPayloadData->total = livePaxPayloadData->empty + livePaxPayloadData->pilot + livePaxPayloadData->firstOfficer +
|
|
livePaxPayloadData->engineer + livePaxPayloadData->cabinCrewFront + livePaxPayloadData->business1Left +
|
|
livePaxPayloadData->business1Center + livePaxPayloadData->business1Right + livePaxPayloadData->business2Left +
|
|
livePaxPayloadData->business2Center + livePaxPayloadData->business2Right + livePaxPayloadData->economy1Left +
|
|
livePaxPayloadData->economy1Center + livePaxPayloadData->economy1Right + livePaxPayloadData->economy2Left +
|
|
livePaxPayloadData->economy2Center + livePaxPayloadData->economy2Right + livePaxPayloadData->cabinCrewRear +
|
|
livePaxPayloadData->forwardCargo + livePaxPayloadData->rearCargo + livePaxPayloadData->leftAux +
|
|
livePaxPayloadData->rightAux;
|
|
|
|
break;
|
|
}
|
|
case DATA_REQUEST_FUEL: {
|
|
FuelData_t* data = (FuelData_t*)&pObjData->dwData;
|
|
liveFuelData->main1 = data->main1 * data->poundsPerGallon;
|
|
liveFuelData->main3 = data->main3 * data->poundsPerGallon;
|
|
liveFuelData->main2 = data->main2 * data->poundsPerGallon;
|
|
liveFuelData->upperAux = data->upperAux * data->poundsPerGallon;
|
|
liveFuelData->lowerAux = data->lowerAux * data->poundsPerGallon;
|
|
liveFuelData->main1Tip = data->main1Tip * data->poundsPerGallon;
|
|
liveFuelData->main3Tip = data->main3Tip * data->poundsPerGallon;
|
|
liveFuelData->tail = data->tail * data->poundsPerGallon;
|
|
liveFuelData->forwardAux1 = data->forwardAux1 * data->poundsPerGallon;
|
|
liveFuelData->forwardAux2 = data->forwardAux2 * data->poundsPerGallon;
|
|
liveFuelData->total = liveFuelData->main1 + liveFuelData->main3 + liveFuelData->main2 + liveFuelData->upperAux +
|
|
liveFuelData->lowerAux + liveFuelData->main1Tip + liveFuelData->main3Tip + liveFuelData->tail +
|
|
liveFuelData->forwardAux1 + liveFuelData->forwardAux2;
|
|
|
|
break;
|
|
}
|
|
case DATA_REQUEST_GSX: {
|
|
GSXData_t* data = (GSXData_t*)&pObjData->dwData;
|
|
memcpy(GSXData, data, sizeof(GSXData_t));
|
|
|
|
if (UserOptions->GSXSync) {
|
|
if (GSXData->boardingState == GSX_SERVICE_ACTIVE) {
|
|
double cargoBoarded = GSXData->cargoBoarded;
|
|
if (UserData->isCargo) {
|
|
fPayloadData_t localPayload = {};
|
|
memcpy(&localPayload, targetFPayloadData, sizeof(localPayload));
|
|
|
|
localPayload.stations.upper1 = targetFPayloadData->stations.upper1 * (cargoBoarded / 100);
|
|
localPayload.stations.upper2 = targetFPayloadData->stations.upper2 * (cargoBoarded / 100);
|
|
localPayload.stations.upper3 = targetFPayloadData->stations.upper3 * (cargoBoarded / 100);
|
|
localPayload.stations.upper4 = targetFPayloadData->stations.upper4 * (cargoBoarded / 100);
|
|
localPayload.lowerForward = targetFPayloadData->lowerForward * (cargoBoarded / 100);
|
|
localPayload.lowerRear = targetFPayloadData->lowerRear * (cargoBoarded / 100);
|
|
|
|
generatePayload(&localPayload, UserData->isImperial);
|
|
load(&localPayload, simConnect, UserData->isImperial);
|
|
}
|
|
else {
|
|
double passengersBoarded = GSXData->passengersBoarded;
|
|
paxPayloadData_t localPayload = {};
|
|
memcpy(&localPayload, targetPaxPayloadData, sizeof(localPayload));
|
|
|
|
localPayload.paxCount.business1 = min(targetPaxPayloadData->paxCount.business1, passengersBoarded);
|
|
passengersBoarded -= localPayload.paxCount.business1;
|
|
localPayload.paxCount.business2 = min(targetPaxPayloadData->paxCount.business2, passengersBoarded);
|
|
passengersBoarded -= localPayload.paxCount.business2;
|
|
localPayload.paxCount.economy1 = min(targetPaxPayloadData->paxCount.economy1, passengersBoarded);
|
|
passengersBoarded -= localPayload.paxCount.economy1;
|
|
localPayload.paxCount.economy2 = min(targetPaxPayloadData->paxCount.economy2, passengersBoarded);
|
|
passengersBoarded -= localPayload.paxCount.economy2;
|
|
localPayload.forwardCargo = targetPaxPayloadData->forwardCargo * (cargoBoarded / 100);
|
|
localPayload.rearCargo = targetPaxPayloadData->rearCargo * (cargoBoarded / 100);
|
|
|
|
generatePayload(&localPayload, UserData->isImperial, UserOptions);
|
|
load(&localPayload, simConnect, UserData->isImperial);
|
|
}
|
|
}
|
|
if (GSXData->deboardingState == GSX_SERVICE_ACTIVE) {
|
|
double cargoDeboarded = GSXData->cargoDeboarded;
|
|
if (UserData->isCargo) {
|
|
fPayloadData_t localPayload = {};
|
|
memcpy(&localPayload, targetFPayloadData, sizeof(localPayload));
|
|
|
|
localPayload.stations.upper1 -= targetFPayloadData->stations.upper1 * (cargoDeboarded / 100);
|
|
localPayload.stations.upper2 -= targetFPayloadData->stations.upper2 * (cargoDeboarded / 100);
|
|
localPayload.stations.upper3 -= targetFPayloadData->stations.upper3 * (cargoDeboarded / 100);
|
|
localPayload.stations.upper4 -= targetFPayloadData->stations.upper4 * (cargoDeboarded / 100);
|
|
localPayload.lowerForward -= targetFPayloadData->lowerForward * (cargoDeboarded / 100);
|
|
localPayload.lowerRear -= targetFPayloadData->lowerRear * (cargoDeboarded / 100);
|
|
|
|
generatePayload(&localPayload, UserData->isImperial);
|
|
load(&localPayload, simConnect, UserData->isImperial);
|
|
}
|
|
else {
|
|
double passengersDeboarded = GSXData->passengersDeboarded;
|
|
paxPayloadData_t localPayload = {};
|
|
memcpy(&localPayload, targetPaxPayloadData, sizeof(localPayload));
|
|
|
|
localPayload.paxCount.business1 -= min(targetPaxPayloadData->paxCount.business1, passengersDeboarded);
|
|
passengersDeboarded -= targetPaxPayloadData->paxCount.business1 - localPayload.paxCount.business1;
|
|
localPayload.paxCount.business2 -= min(targetPaxPayloadData->paxCount.business2, passengersDeboarded);
|
|
passengersDeboarded -= targetPaxPayloadData->paxCount.business2 - localPayload.paxCount.business2;
|
|
localPayload.paxCount.economy1 -= min(targetPaxPayloadData->paxCount.economy1, passengersDeboarded);
|
|
passengersDeboarded -= targetPaxPayloadData->paxCount.economy1 - localPayload.paxCount.economy1;
|
|
localPayload.paxCount.economy2 -= min(targetPaxPayloadData->paxCount.economy2, passengersDeboarded);
|
|
passengersDeboarded -= targetPaxPayloadData->paxCount.economy2 - localPayload.paxCount.economy2;
|
|
localPayload.forwardCargo -= targetPaxPayloadData->forwardCargo * (cargoDeboarded / 100);
|
|
localPayload.rearCargo -= targetPaxPayloadData->rearCargo * (cargoDeboarded / 100);
|
|
|
|
generatePayload(&localPayload, UserData->isImperial, UserOptions);
|
|
load(&localPayload, simConnect, UserData->isImperial);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case DATA_REQUEST_USER_DATA: {
|
|
UserData_t* data = (UserData_t*)&pObjData->dwData;
|
|
data->isImperial = ((long)data->isImperial) & 1;
|
|
memcpy(UserData, data, sizeof(UserData_t));
|
|
|
|
// Update static weights
|
|
// Shared part 1
|
|
targetFPayloadData->empty = targetPaxPayloadData->empty = FROM_POUNDS(UserData->isImperial, liveFPayloadData->empty);
|
|
targetFPayloadData->pilot = targetPaxPayloadData->pilot = targetFPayloadData->firstOfficer = targetPaxPayloadData->firstOfficer =
|
|
targetFPayloadData->engineer = targetPaxPayloadData->engineer = PILOT_WEIGHT(UserData->isImperial);
|
|
// Shared part 2
|
|
targetFPayloadData->leftAux = targetPaxPayloadData->leftAux = targetFPayloadData->rightAux = targetPaxPayloadData->rightAux =
|
|
UserData->isER ? AUX_WEIGHT(UserData->isImperial) : 0;
|
|
// Pax only fixed weights
|
|
if (!UserData->isCargo) {
|
|
targetPaxPayloadData->cabinCrewFront = FRONT_CREW_WEIGHT(UserData->isImperial);
|
|
targetPaxPayloadData->cabinCrewRear = REAR_CREW_WEIGHT(UserData->isImperial);
|
|
}
|
|
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SIMCONNECT_RECV_ID_EXCEPTION:
|
|
{
|
|
SIMCONNECT_RECV_EXCEPTION* pEx = (SIMCONNECT_RECV_EXCEPTION*)pData;
|
|
log(stderr, "SimConnect Exception: %i\n", &pEx->dwException);
|
|
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
} |