// Aircraft data and mode mapping via config file in aircraft folder #include "stdafx.h" // Things for execution bool quit = 0; HANDLE hSimConnect = NULL; char *throttleQuadrantCFG; initialization init; uint8_t numEngines = 0; // Event to catch beginning static enum EVENT_ID { EVENT_SIM_START, REQUEST_SYSTEM_STATE, }; // Definitions for levers, dynamically added to SimConnect static enum DATA_DEFINE_ID { DEFINITION_AC_DATA, DEFINITION_LEVER_ONE, DEFINITION_LEVER_TWO, DEFINITION_LEVER_THREE, DEFINITION_LEVER_FOUR, }; // Request ID static enum REQUEST_ID { AC_DATA_REQUEST, }; // Struct for ac data struct aircraftData { double numEngines; double lowerThrottleLimit; }; // Structs for levers struct engineJustThrottle { double throttlePercent; }; struct engineThrottleAndPropeller { double throttlePercent; double propellerPercent; }; struct engineThrottleAndMixture { double throttlePercent; double mixturePercent; }; struct engineAll { double throttlePercent; double propellerPrecent; double mixturePercent; }; //TESTING PURPOSE engineJustThrottle tc; char *trimwhitespace(char *str) { char *end; // Trim leading space while (isspace((unsigned char)*str)) str++; if (*str == 0) // All spaces? return str; // Trim trailing space end = str + strlen(str) - 1; while (end > str && isspace((unsigned char)*end)) end--; // Write new null terminator *(end + 1) = 0; return str; } char *readLine(FILE *file) { if (file == NULL) { printf("\nError: file pointer is null."); exit(1); } int maximumLineLength = 128; char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength); if (lineBuffer == NULL) { printf("\nError allocating memory for line buffer."); exit(1); } char ch = getc(file); int count = 0; while ((ch != '\n') && (ch != EOF)) { if (count == maximumLineLength) { maximumLineLength += 128; lineBuffer = (char *)realloc(lineBuffer, maximumLineLength); if (lineBuffer == NULL) { printf("\nError reallocating space for line buffer."); exit(1); } } lineBuffer[count] = ch; count++; ch = getc(file); } lineBuffer[count] = '\0'; if (count > 0) return lineBuffer; else return NULL ; } void setupDefinitions() { printf("\nSetting up..."); HRESULT hr; hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_ONE); hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_TWO); hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_THREE); hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_FOUR); FILE *fp = fopen(throttleQuadrantCFG, "r"); char * line = NULL; uint8_t numEngines = 0; bool hasPropeller = false; bool hasMixture = false; if (fp == NULL) { printf("\nThe application cannot run without a valid tq.cfg."); exit(EXIT_FAILURE); } while ((line = readLine(fp)) != NULL) { // Parse char *assign = strstr(line, "="); char *id = (char *)calloc(13, 1); memcpy(id, line, ((long)assign - (long)line)); if (strcmp(trimwhitespace(id), "numModes") == 0) init.numModes = atoi(assign + 1); else if (strcmp(trimwhitespace(id), "hasPropeller") == 0) hasPropeller = atoi(assign + 1); else if (strcmp(trimwhitespace(id), "hasMixture") == 0) hasMixture = atoi(assign + 1); else if (strcmp(trimwhitespace(id), "mode1") == 0) strcpy(init.modes[0], strrev(assign + 1)); else if (strcmp(trimwhitespace(id), "mode2") == 0) strcpy(init.modes[1], strrev(assign + 1)); else if (strcmp(trimwhitespace(id), "mode3") == 0) strcpy(init.modes[2], strrev(assign + 1)); free(line); free(id); } fclose(fp); fp = fopen("dump.hex", "wb"); /*DEBUG*/fwrite(&init, 1, sizeof(initialization), fp); fclose(fp); // Setup Data definitions if (!hasPropeller && !hasMixture) { switch (numEngines) { case 1: hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); break; case 2: hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:2", "percent"); break; case 3: hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:2", "percent"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:3", "percent"); break; case 4: hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:2", "percent"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:3", "percent"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:4", "percent"); break; default: break; } } } // SimConnect callback void CALLBACK MyDispatchProcTC(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext) { HRESULT hr; switch (pData->dwID) { case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: { SIMCONNECT_RECV_SIMOBJECT_DATA *data = (SIMCONNECT_RECV_SIMOBJECT_DATA *)pData; switch (data->dwRequestID) { case AC_DATA_REQUEST: { printf("\Aircraft data retrieved"); init.maxRev = (int8_t)((aircraftData *)&data->dwData)->lowerThrottleLimit; numEngines = (uint8_t)((aircraftData *)&data->dwData)->numEngines; setupDefinitions(); break; } default: break; } break; } case SIMCONNECT_RECV_ID_SYSTEM_STATE: { SIMCONNECT_RECV_SYSTEM_STATE *state = (SIMCONNECT_RECV_SYSTEM_STATE *)pData; switch (state->dwRequestID) { // Receive loaded aircraft name, set path to tq.cfg case REQUEST_SYSTEM_STATE: { char *path = strrev(strstr(strrev(state->szString), "\\")); throttleQuadrantCFG = (char *)calloc(strlen(path) + 6, 1); strcpy(throttleQuadrantCFG, path); strcat(throttleQuadrantCFG, "tq.cfg"); printf("\n%s loaded.", throttleQuadrantCFG); printf("\nRetrieving aicraft data..."); hr = SimConnect_RequestDataOnSimObject(hSimConnect, AC_DATA_REQUEST, DEFINITION_AC_DATA, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_ONCE); break; } default: break; } break; } case SIMCONNECT_RECV_ID_EVENT: { SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT *)pData; switch (evt->uEventID) { case EVENT_SIM_START: { // Send this request to get the user aircraft id printf("\n\nRequesting loaded AC path..."); hr = SimConnect_RequestSystemState(hSimConnect, REQUEST_SYSTEM_STATE, "AircraftLoaded"); } break; default: break; } break; } case SIMCONNECT_RECV_ID_QUIT: { quit = 1; break; } default: break; } } void testThrottleControl() { HRESULT hr; if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Throttle Control", NULL, 0, 0, 0))) { printf("\nConnected to Flight Simulator!"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AC_DATA, "NUMBER OF ENGINES", "number"); hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AC_DATA, "THROTTLE LOWER LIMIT", "percent"); // Set up a data definition for the throttle control //hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_LEVER_ONE, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(tc), &tc); // Request a simulation started event hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SIM_START, "SimStart"); while (0 == quit) { SimConnect_CallDispatch(hSimConnect, MyDispatchProcTC, NULL); Sleep(1); } hr = SimConnect_Close(hSimConnect); } } int __cdecl _tmain(int argc, _TCHAR* argv[]) { testThrottleControl(); return 0; }