From a63c40c8d72ffba69d4dbb3f9a1fb5d9997d9680 Mon Sep 17 00:00:00 2001 From: Sebastian M <86157512+DocMoebiuz@users.noreply.github.com> Date: Sat, 20 Aug 2022 13:44:16 +0200 Subject: [PATCH 1/8] Add MF.Config.MAX_VARS_PER_FRAME to limit number of variables read in each frame (#13) * reduce ReadSimVars() count to improve performance 1. use std::list instead of std::vector, for circular iteration 2. list max 5 SimVars reading in very frame 3. VimVars clean() needs update list iterator * too slow for feedback data use 12 for a while * Changed back to std::vector and added method to send command for changing it. * removed explicit DEFAULT value Co-authored-by: Wei Shuai --- .../mobiflight-event-module.xml | 2 +- src/Sources/Code/Module.cpp | 33 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/PackageDefinitions/mobiflight-event-module.xml b/src/PackageDefinitions/mobiflight-event-module.xml index f6b9e7b..91e6512 100644 --- a/src/PackageDefinitions/mobiflight-event-module.xml +++ b/src/PackageDefinitions/mobiflight-event-module.xml @@ -1,5 +1,5 @@ - + MISC Event Module diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp index 3d3ec59..d700b37 100644 --- a/src/Sources/Code/Module.cpp +++ b/src/Sources/Code/Module.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -10,7 +11,7 @@ #include "Module.h" HANDLE g_hSimConnect; -const char* version = "0.5.0"; +const char* version = "0.6.0"; const char* ClientName = "MobiFlightWasmModule"; const char* MobiFlightEventPrefix = "MobiFlight."; @@ -33,6 +34,10 @@ uint16_t SimVarOffset = 1000; // For each registered client can 10000 data definition ids are reserved uint16_t ClientDataDefinitionIdSimVarsRange = 10000; +// Maximum number of variables that are read from sim per frame, Default: 30 +// Can be set to different value via config command +uint16_t MOBIFLIGHT_MAX_VARS_PER_FRAME = 30; + // data struct for dynamically registered SimVars struct SimVar { int ID; @@ -58,6 +63,10 @@ struct Client { // This is an optimization to be able to re-use already defined data definition IDs & request IDs // after resetting registered SimVars uint16_t MaxClientDataDefinition = 0; + // Runtime Rolling CLient Data reading Index + //std::vector::iterator RollingClientDataReadIndex; + uint16_t RollingClientDataReadIndex; + }; // The list of currently registered clients @@ -272,6 +281,8 @@ void RegisterSimVar(const std::string code, Client* client) { void ClearSimVars(Client* client) { client->SimVars.clear(); fprintf(stderr, "MobiFlight: Cleared SimVar tracking."); + //client->RollingClientDataReadIndex = client->SimVars.begin(); + client->RollingClientDataReadIndex = 0; } // Read a single SimVar and send the current value to SimConnect Clients @@ -293,8 +304,14 @@ void ReadSimVar(SimVar &simVar, Client* client) { void ReadSimVars() { for (auto& client : RegisteredClients) { std::vector* SimVars = &(client->SimVars); - for (auto& value : *SimVars) { - ReadSimVar(value, client); + + int maxVarsPerFrame = SimVars->size() < MOBIFLIGHT_MAX_VARS_PER_FRAME ? SimVars->size() : MOBIFLIGHT_MAX_VARS_PER_FRAME; + + for (int i=0; i < maxVarsPerFrame; ++i) { + ReadSimVar(SimVars->at(client->RollingClientDataReadIndex), client); + client->RollingClientDataReadIndex++; + if (client->RollingClientDataReadIndex >= SimVars->size()) + client->RollingClientDataReadIndex = 0; } } } @@ -379,6 +396,8 @@ Client* RegisterNewClient(const std::string clientName) { newClient->DataDefinitionIDStringResponse = 2 * newClient->ID; // 500 Clients possible until offset 1000 is reached newClient->DataDefinitionIDStringCommand = newClient->DataDefinitionIDStringResponse + 1; newClient->SimVars = std::vector(); + //newClient->RollingClientDataReadIndex = newClient->SimVars.begin(); + newClient->RollingClientDataReadIndex = 0; newClient->DataDefinitionIdSimVarsStart = SimVarOffset + (newClient->ID * ClientDataDefinitionIdSimVarsRange); RegisteredClients.push_back(newClient); @@ -525,6 +544,14 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex SendNewClientResponse(client, newClient); fprintf(stderr, "MobiFlight: Received Client to register: %s.\n", str.c_str()); } + + if (m_str.get()->find("MF.Config.MAX_VARS_PER_FRAME.Set.") != std::string::npos) { + std::string prefix = "MF.Config.MAX_VARS_PER_FRAME.Set."; + str = m_str.get()->substr(prefix.length()); + uint16_t value = static_cast(std::stoi(str)); + MOBIFLIGHT_MAX_VARS_PER_FRAME = value; + fprintf(stderr, "MobiFlight: Set MF.Config.MAX_VARS_PER_FRAME to %u.\n", value); + } break; } From 89476c19ce846bd74f0ab7716cb91b1f63fe23aa Mon Sep 17 00:00:00 2001 From: Koseng <26673978+Koseng@users.noreply.github.com> Date: Wed, 29 Mar 2023 21:54:01 +0200 Subject: [PATCH 2/8] Version command and console messages (#16) --- README.md | 3 ++ src/Sources/Code/Module.cpp | 92 +++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index ccddd95..09f2b01 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,9 @@ The default channels for the MobiFlight client are auto created on startup. Each |```MF.SimVars.Clear``` ||| |```MF.SimVars.Set(5 (>L:MyVar))```||| |```MF.Clients.Add.ClientName```|```MF.Clients.Add.ClientName.Finished```|| +|```MF.Config.MAX_VARS_PER_FRAME.Set.30```||| +|```MF.Version.Get```|```MF.Version.0.6.0```|| + **MF.SimVars.Add.** The "SimVars.Add." command needs to be extended with a gauge calculator scipt for reading a variable, like shown in the table. Each added variable needs 4 reserved bytes to return its float value in the LVars channel. The bytes are allocated in the order of the LVars being added. The first variable starts at offset 0, the second at offset 4, the third at offset 8 and so on. To access each value, the external SimConnect clients needs a unique DataDefinitionId for each memory segment. It is recommended to start with ID 1000. diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp index d700b37..3540450 100644 --- a/src/Sources/Code/Module.cpp +++ b/src/Sources/Code/Module.cpp @@ -154,8 +154,13 @@ void RegisterEvents() { hr = SimConnect_AddClientEventToNotificationGroup(g_hSimConnect, MOBIFLIGHT_GROUP::DEFAULT, eventID, false); #if _DEBUG - if (hr != S_OK) fprintf(stderr, "MobiFlight: Error on registering Event %s with ID %u for code %s", eventName.c_str(), eventID, eventCommand.c_str()); - else fprintf(stderr, "MobiFlight: Success on registering Event %s with ID %u for code %s", eventName.c_str(), eventID, eventCommand.c_str()); + if (hr != S_OK) { + fprintf(stderr, "MobiFlight: Error on registering Event %s with ID %u for code %s", eventName.c_str(), eventID, eventCommand.c_str()); + } + else { + std::cout << "MobiFlight: Success on registering Event " << eventName.c_str(); + std::cout << " with ID " << eventID << " for code " << eventCommand.c_str() << std::endl; + } #endif eventID++; @@ -171,9 +176,9 @@ void LoadEventDefinitions() { int eventDefinition = CodeEvents.size(); LoadEventDefinitions(FileEventsUser); - fprintf(stderr, "MobiFlight: Loaded %u event defintions in total.", CodeEvents.size()); - fprintf(stderr, "MobiFlight: Loaded %u built-in event defintions.", eventDefinition); - fprintf(stderr, "MobiFlight: Loaded %u user event defintions.", CodeEvents.size() - eventDefinition); + std::cout << "MobiFlight: Loaded " << CodeEvents.size() << " event definitions in total." << std::endl; + std::cout << "MobiFlight: Loaded " << eventDefinition << " built-in event definitions." << std::endl; + std::cout << "MobiFlight: Loaded " << CodeEvents.size() - eventDefinition << " user event definitions." << std::endl; } void SendResponse(const char * message, Client* client) { @@ -193,7 +198,7 @@ void SendNewClientResponse(Client* client, Client* nc) { std::ostringstream oss; oss << "MF.Clients.Add." << nc->Name << ".Finished"; std::string data = oss.str(); - fprintf(stderr, "MobiFlight[%s]: SendNewClientData > %s", client->Name.c_str(), data.c_str()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: SendNewClientData > " << data.c_str() << std::endl; SendResponse(data.c_str(), client); } @@ -214,7 +219,7 @@ void ListLVars(Client* client) { for (const auto& lVar : lVarList) { SendResponse(lVar.c_str(), client); #if _DEBUG - fprintf(stderr, "MobiFlight[%s]: Available LVar > %s", client->Name.c_str(), lVar.c_str()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Available LVar > " << lVar.c_str() << std::endl; #endif } } @@ -233,7 +238,8 @@ void WriteSimVar(SimVar& simVar, Client* client) { fprintf(stderr, "MobiFlight[%s]: Error on Setting Client Data. %u, SimVar: %s (ID: %u)", client->Name.c_str(), hr, simVar.Name.c_str(), simVar.ID); } #if _DEBUG - fprintf(stderr, "MobiFlight[%s]: SimVar %s with ID %u has value %f", client->Name.c_str(),simVar.Name.c_str(), simVar.ID, simVar.Value); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: SimVar " << simVar.Name.c_str(); + std::cout << " with ID " << simVar.ID << " has value " << simVar.Value << std::endl; #endif } @@ -261,7 +267,7 @@ void RegisterSimVar(const std::string code, Client* client) { client->MaxClientDataDefinition = SimVars->size(); } #if _DEBUG - fprintf(stderr, "MobiFlight[%s]: RegisterSimVar SimVars Size: %d\n", client->Name.c_str(), SimVars->size()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterSimVar SimVars Size: " << SimVars->size() << std::endl; #endif FLOAT64 val; @@ -273,14 +279,15 @@ void RegisterSimVar(const std::string code, Client* client) { WriteSimVar(var1, client); #if _DEBUG - fprintf(stderr, "MobiFlight[%s]: RegisterSimVar > %s ID [%u] : Offset(%u) : Value(%f)", client->Name.c_str(), var1.Name.c_str(), var1.ID, var1.Offset, var1.Value); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterSimVar > " << var1.Name.c_str(); + std::cout << " ID [" << var1.ID << "] : Offset(" << var1.Offset << ") : Value(" << var1.Value << ")" << std::endl; #endif } // Clear the list of currently tracked SimVars void ClearSimVars(Client* client) { - client->SimVars.clear(); - fprintf(stderr, "MobiFlight: Cleared SimVar tracking."); + client->SimVars.clear(); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Cleared SimVar tracking." << std::endl; //client->RollingClientDataReadIndex = client->SimVars.begin(); client->RollingClientDataReadIndex = 0; } @@ -296,7 +303,8 @@ void ReadSimVar(SimVar &simVar, Client* client) { WriteSimVar(simVar, client); #if _DEBUG - fprintf(stderr, "MobiFlight[%s]: SimVar %s with ID %u has value %f", client->Name.c_str(), simVar.Name.c_str(), simVar.ID, simVar.Value); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: SimVar " << simVar.Name.c_str(); + std::cout << " with ID " << simVar.ID << " has value " << simVar.Value << std::endl; #endif } @@ -407,17 +415,17 @@ Client* RegisterNewClient(const std::string clientName) { } #if _DEBUG - fprintf(stderr, "MobiFlight: NewClient Name: %s\n", newClient->Name.c_str()); - fprintf(stderr, "MobiFlight: NewClient ID: %d\n", newClient->ID); - fprintf(stderr, "MobiFlight: NewClient DataAreaIDSimvar: %d\n", newClient->DataAreaIDSimvar); - fprintf(stderr, "MobiFlight: NewClient DataAreaIDResponse: %d\n", newClient->DataAreaIDResponse); - fprintf(stderr, "MobiFlight: NewClient DataAreaIDCommand: %d\n", newClient->DataAreaIDCommand); - fprintf(stderr, "MobiFlight: NewClient DataAreaNameSimVar: %s\n", newClient->DataAreaNameSimVar.c_str()); - fprintf(stderr, "MobiFlight: NewClient DataAreaNameResponse: %s\n", newClient->DataAreaNameResponse.c_str()); - fprintf(stderr, "MobiFlight: NewClient DataAreaNameCommand: %s\n", newClient->DataAreaNameCommand.c_str()); - fprintf(stderr, "MobiFlight: NewClient DataDefinitionIDStringResponse: %d\n", newClient->DataDefinitionIDStringResponse); - fprintf(stderr, "MobiFlight: NewClient DataDefinitionIDStringCommand: %d\n", newClient->DataDefinitionIDStringCommand); - fprintf(stderr, "MobiFlight: NewClient DataDefinitionIdSimVarsStart: %d\n", newClient->DataDefinitionIdSimVarsStart); + std::cout << "MobiFlight: NewClient Name: " << newClient->Name.c_str() << std::endl; + std::cout << "MobiFlight: NewClient ID: " << newClient->ID << std::endl; + std::cout << "MobiFlight: NewClient DataAreaIDSimvar: " << newClient->DataAreaIDSimvar << std::endl; + std::cout << "MobiFlight: NewClient DataAreaIDResponse: " << newClient->DataAreaIDResponse << std::endl; + std::cout << "MobiFlight: NewClient DataAreaIDCommand: " << newClient->DataAreaIDCommand << std::endl; + std::cout << "MobiFlight: NewClient DataAreaNameSimVar: " << newClient->DataAreaNameSimVar.c_str() << std::endl; + std::cout << "MobiFlight: NewClient DataAreaNameResponse: " << newClient->DataAreaNameResponse.c_str() << std::endl; + std::cout << "MobiFlight: NewClient DataAreaNameCommand: " << newClient->DataAreaNameCommand.c_str() << std::endl; + std::cout << "MobiFlight: NewClient DataDefinitionIDStringResponse: " << newClient->DataDefinitionIDStringResponse << std::endl; + std::cout << "MobiFlight: NewClient DataDefinitionIDStringCommand: " << newClient->DataDefinitionIDStringCommand << std::endl; + std::cout << "MobiFlight: NewClient DataDefinitionIdSimVarsStart: " << newClient->DataDefinitionIdSimVarsStart << std::endl; #endif return newClient; @@ -460,15 +468,13 @@ extern "C" MSFS_CALLBACK void module_init(void) Client* client = RegisterNewClient(std::string(MOBIFLIGHT_CLIENT_DATA_NAME)); RegisterEvents(); ListLVars(client); - - fprintf(stderr, "MobiFlight: Max Message size is %u", MOBIFLIGHT_MESSAGE_SIZE); - fprintf(stderr, "MobiFlight: Module Init Complete. Version: %s", version); - + + std::cout << "MobiFlight: Max Message size is " << MOBIFLIGHT_MESSAGE_SIZE << std::endl; + std::cout << "MobiFlight: Module Init Complete.Version: " << version << std::endl; } extern "C" MSFS_CALLBACK void module_deinit(void) { - if (!g_hSimConnect) return; HRESULT hr = SimConnect_Close(g_hSimConnect); @@ -477,7 +483,6 @@ extern "C" MSFS_CALLBACK void module_deinit(void) fprintf(stderr, "Could not close SimConnect connection.\n"); return; } - } void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext) @@ -495,33 +500,42 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex std::string str = std::string((char*)(&recv_data->dwData)); DWORD clientID = (DWORD)recv_data->dwRequestID; #if _DEBUG - fprintf(stderr, "MobiFlight: Received Command: %s\n", str.c_str()); - fprintf(stderr, "MobiFlight: Received ClientId: %ld\n", clientID); + std::cout << "MobiFlight: Received Command: " << str.c_str() << std::endl; + std::cout << "MobiFlight: Received ClientId: " << clientID << std::endl; #endif Client* client = RegisteredClients[clientID]; if (str == "MF.Ping") { SendResponse("MF.Pong", client); - fprintf(stderr, "MobiFlight[%s]: Received ping\n", client->Name.c_str()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received ping" << std::endl; } else if (str == "MF.SimVars.Clear") { ClearSimVars(client); break; - } else if (str == "MF.LVars.List") { + } + else if (str == "MF.LVars.List") { SendResponse("MF.LVars.List.Start", client); ListLVars(client); SendResponse("MF.LVars.List.End", client); break; + } + else if (str == "MF.Version.Get") + { + std::string v = "MF.Version." + std::string(version); + SendResponse(v.c_str(), client); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received get version" << std::endl; + break; + } // MF.SimVars.Set(5 (>L:MyVar)) else if (str.find("MF.SimVars.Set.") != std::string::npos) { std::string prefix = "MF.SimVars.Set."; str = str.substr(prefix.length()); #if _DEBUG - fprintf(stderr, "MobiFlight[%s]: Executing Code: %s\n", client->Name.c_str(), str.c_str()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Executing Code: " << str.c_str() << std::endl; #endif execute_calculator_code(str.c_str(), 0, nullptr, nullptr); break; @@ -533,7 +547,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex std::string prefix = "MF.SimVars.Add."; str = m_str.get()->substr(prefix.length()); RegisterSimVar(str, client); - fprintf(stderr, "MobiFlight[%s]: Received SimVar to register: %s.\n", client->Name.c_str(), str.c_str()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received SimVar to register: " << str.c_str() << std::endl; break; } @@ -542,7 +556,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex str= m_str.get()->substr(prefix.length()); Client* newClient = RegisterNewClient(str); SendNewClientResponse(client, newClient); - fprintf(stderr, "MobiFlight: Received Client to register: %s.\n", str.c_str()); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received Client to register: " << str.c_str() << std::endl; } if (m_str.get()->find("MF.Config.MAX_VARS_PER_FRAME.Set.") != std::string::npos) { @@ -550,7 +564,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex str = m_str.get()->substr(prefix.length()); uint16_t value = static_cast(std::stoi(str)); MOBIFLIGHT_MAX_VARS_PER_FRAME = value; - fprintf(stderr, "MobiFlight: Set MF.Config.MAX_VARS_PER_FRAME to %u.\n", value); + std::cout << "MobiFlight: Set MF.Config.MAX_VARS_PER_FRAME to " << value << std::endl; } break; } @@ -572,7 +586,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex int CodeEventId = eventID; std::string command = std::string(CodeEvents[CodeEventId].second); #if _DEBUG - fprintf(stderr, "execute %s\n", command.c_str()); + std::cout << "MobiFlight execute " << command.c_str() << std::endl; #endif execute_calculator_code(command.c_str(), nullptr, nullptr, nullptr); } From 45f1af47161e40b9c2875fc22c8b8da33b2b3267 Mon Sep 17 00:00:00 2001 From: Koseng <26673978+Koseng@users.noreply.github.com> Date: Wed, 2 Aug 2023 20:24:22 +0200 Subject: [PATCH 3/8] Fix Set Lvar command in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 09f2b01..6627032 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The default channels for the MobiFlight client are auto created on startup. Each | ```MF.LVars.List``` | ```MF.LVars.List.Start```
```A32NX_AUTOPILOT_1_ACTIVE```
```A32NX_AUTOPILOT_HEADING_SELECTED```
```...```
```MF.LVars.List.End```| | ```MF.SimVars.Add.(A:GROUND ALTITUDE,Meters)``` || ```1455.23``` | |```MF.SimVars.Clear``` ||| -|```MF.SimVars.Set(5 (>L:MyVar))```||| +|```MF.SimVars.Set.5 (>L:MyVar)```||| |```MF.Clients.Add.ClientName```|```MF.Clients.Add.ClientName.Finished```|| |```MF.Config.MAX_VARS_PER_FRAME.Set.30```||| |```MF.Version.Get```|```MF.Version.0.6.0```|| From 9e5bb6691c4ba83302ecd8d53c1e0cfcab005228 Mon Sep 17 00:00:00 2001 From: Koseng <26673978+Koseng@users.noreply.github.com> Date: Wed, 2 Aug 2023 20:53:37 +0200 Subject: [PATCH 4/8] Set version to 0.7.1 --- src/PackageDefinitions/mobiflight-event-module.xml | 2 +- src/Sources/Code/Module.cpp | 2 +- src/Sources/Code/StandaloneModule.vcxproj | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PackageDefinitions/mobiflight-event-module.xml b/src/PackageDefinitions/mobiflight-event-module.xml index 91e6512..14605b6 100644 --- a/src/PackageDefinitions/mobiflight-event-module.xml +++ b/src/PackageDefinitions/mobiflight-event-module.xml @@ -1,5 +1,5 @@ - + MISC Event Module diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp index 3540450..73e4f30 100644 --- a/src/Sources/Code/Module.cpp +++ b/src/Sources/Code/Module.cpp @@ -11,7 +11,7 @@ #include "Module.h" HANDLE g_hSimConnect; -const char* version = "0.6.0"; +const char* version = "0.7.1"; const char* ClientName = "MobiFlightWasmModule"; const char* MobiFlightEventPrefix = "MobiFlight."; diff --git a/src/Sources/Code/StandaloneModule.vcxproj b/src/Sources/Code/StandaloneModule.vcxproj index ec31ecd..04a0d88 100644 --- a/src/Sources/Code/StandaloneModule.vcxproj +++ b/src/Sources/Code/StandaloneModule.vcxproj @@ -49,6 +49,7 @@ true .wasm $(MSFS_IncludePath) + true false From 68eb4c53e745099c17cadaa5d323c26a98ec932b Mon Sep 17 00:00:00 2001 From: MiMaKes <65442551+MiMaKes@users.noreply.github.com> Date: Wed, 24 Jan 2024 18:14:50 +0100 Subject: [PATCH 5/8] Support String values (#19) * Fix for #8 - Added new client data zone for string data - SimConnect now properly loads the string data from the var - Data is properly stored in the new data zone * Improved functionality of string SimVars * Increased string data area size to maximum * write SimVar when string-value has changed * added some debug output * fixed some compiler warnings * Separated handling for "regular" float SimVars and "new" string SimVars * Added AddString command to readme * Review changes: * Refactoring RegisterSimVar function into two separate functions. One for floats, one for strings * Removing first WriteSimVar function call when registering a simvar * Removing unused variables --------- Co-authored-by: Roderick Griffioen --- README.md | 20 ++- src/Sources/Code/Module.cpp | 283 ++++++++++++++++++++++++++---------- 2 files changed, 221 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 6627032..a9f2995 100644 --- a/README.md +++ b/README.md @@ -21,23 +21,27 @@ The default channels for the MobiFlight client are auto created on startup. Each #### Communication protocol -| Command (string)| Responses (string) | LVars offset (float) | +| Command (string)| Responses (string) | LVars value (float/string) | | ----------- | ----------- | ---------| | ```MF.Ping```| ```MF.Pong```| | ```MF.LVars.List``` | ```MF.LVars.List.Start```
```A32NX_AUTOPILOT_1_ACTIVE```
```A32NX_AUTOPILOT_HEADING_SELECTED```
```...```
```MF.LVars.List.End```| -| ```MF.SimVars.Add.(A:GROUND ALTITUDE,Meters)``` || ```1455.23``` | -|```MF.SimVars.Clear``` ||| -|```MF.SimVars.Set.5 (>L:MyVar)```||| -|```MF.Clients.Add.ClientName```|```MF.Clients.Add.ClientName.Finished```|| -|```MF.Config.MAX_VARS_PER_FRAME.Set.30```||| -|```MF.Version.Get```|```MF.Version.0.6.0```|| +| ```MF.SimVars.Add.(A:GROUND ALTITUDE,Meters)``` || ```e.g. 1455.23 (float)``` | +| ```MF.SimVars.AddString.(A:GPS WP NEXT ID,String)``` || ```e.g. EDDS (string)``` | +| ```MF.SimVars.Clear``` ||| +| ```MF.SimVars.Set.5 (>L:MyVar)```||| +| ```MF.Clients.Add.ClientName```|```MF.Clients.Add.ClientName.Finished```|| +| ```MF.Config.MAX_VARS_PER_FRAME.Set.30```||| +| ```MF.Version.Get```|```MF.Version.0.6.0```|| **MF.SimVars.Add.** -The "SimVars.Add." command needs to be extended with a gauge calculator scipt for reading a variable, like shown in the table. Each added variable needs 4 reserved bytes to return its float value in the LVars channel. The bytes are allocated in the order of the LVars being added. The first variable starts at offset 0, the second at offset 4, the third at offset 8 and so on. To access each value, the external SimConnect clients needs a unique DataDefinitionId for each memory segment. It is recommended to start with ID 1000. +The "SimVars.Add." command needs to be extended with a gauge calculator script for reading a variable, like shown in the table. Each added variable needs 4 reserved bytes to return its float value in the LVars channel. The bytes are allocated in the order of the LVars being added. The first variable starts at offset 0, the second at offset 4, the third at offset 8 and so on. To access each value, the external SimConnect clients needs a unique DataDefinitionId for each memory segment. It is recommended to start with ID 1000. ![Lvars channels](doc/lvarsChannel.png) +**MF.SimVars.AddString.** +The "SimVars.AddString." command works similar to the "SimVars.Add." command but the string result of the gauge calculator script is used. The size of a single string can be up to 128 bytes, which allows handling a total of 64 string variables. The first variable starts at offset 0, the second at offset 128, the third at offset 256 and so on. To access each value, the external SimConnect clients needs a unique DataDefinitionId for each memory segment. It is recommended to start with ID 10000. + **MF.Clients.Add.** The default channels are reserved for communication with the MobiFlight client. But they can be used to request additional channels for other SimConnect clients as well. If another client wants to use the WASM module for variable access, it can register itself with the command ```MF.Clients.Add.MyClientName``` using the default command channel. The WASM module then creates the new shared memory channels "MyClientName.LVars", "MyClientName.Command", "MyClientName.Response" and informs the client with ```MF.Clients.Add.ClientName.Finished```. diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp index 73e4f30..a6c2857 100644 --- a/src/Sources/Code/Module.cpp +++ b/src/Sources/Code/Module.cpp @@ -22,22 +22,28 @@ std::vector> CodeEvents; const char* MOBIFLIGHT_CLIENT_DATA_NAME = "MobiFlight"; const char* CLIENT_DATA_NAME_POSTFIX_SIMVAR = ".LVars"; +const char* CLIENT_DATA_NAME_POSTFIX_STRINGVAR = ".StringVars"; const char* CLIENT_DATA_NAME_POSTFIX_COMMAND = ".Command"; const char* CLIENT_DATA_NAME_POSTFIX_RESPONSE = ".Response"; const int MOBIFLIGHT_MESSAGE_SIZE = 1024; -// This is an offset for the dynamically registered SimVars +// This is an offset for the dynamically registered SimVars // to avoid any conflicts with base IDs -uint16_t SimVarOffset = 1000; +constexpr uint16_t SIMVAR_OFFSET = 1000; // For each registered client can 10000 data definition ids are reserved -uint16_t ClientDataDefinitionIdSimVarsRange = 10000; +constexpr uint16_t CLIENT_DATA_DEF_ID_SIMVAR_RANGE = 10000; +constexpr uint16_t CLIENT_DATA_DEF_ID_STRINGVAR_RANGE = 10000; // Maximum number of variables that are read from sim per frame, Default: 30 // Can be set to different value via config command uint16_t MOBIFLIGHT_MAX_VARS_PER_FRAME = 30; +// Max length of a string variable. This will affect the maximum amount of string variables +// due to the maximum client-data-array-size (SIMCONNECT_CLIENTDATA_MAX_SIZE) of 8kB! +constexpr uint16_t MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN = 128; + // data struct for dynamically registered SimVars struct SimVar { int ID; @@ -46,6 +52,13 @@ struct SimVar { float Value; }; +struct StringSimVar { + int ID; + int Offset; + std::string Name; + std::string Value; +}; + // data struct for client accessing SimVars struct Client { int ID; @@ -53,20 +66,25 @@ struct Client { std::string DataAreaNameSimVar; std::string DataAreaNameResponse; std::string DataAreaNameCommand; + std::string DataAreaNameStringVar; SIMCONNECT_CLIENT_DATA_ID DataAreaIDSimvar; SIMCONNECT_CLIENT_DATA_ID DataAreaIDResponse; SIMCONNECT_CLIENT_DATA_ID DataAreaIDCommand; + SIMCONNECT_CLIENT_DATA_ID DataAreaIDStringSimVar; SIMCONNECT_CLIENT_DATA_DEFINITION_ID DataDefinitionIDStringResponse; SIMCONNECT_CLIENT_DATA_DEFINITION_ID DataDefinitionIDStringCommand; std::vector SimVars; + std::vector StringSimVars; + SIMCONNECT_CLIENT_DATA_DEFINITION_ID DataDefinitionIdSimVarsStart; + SIMCONNECT_CLIENT_DATA_DEFINITION_ID DataDefinitionIdStringVarsStart; // This is an optimization to be able to re-use already defined data definition IDs & request IDs - // after resetting registered SimVars + // after resetting registered SimVars uint16_t MaxClientDataDefinition = 0; // Runtime Rolling CLient Data reading Index //std::vector::iterator RollingClientDataReadIndex; uint16_t RollingClientDataReadIndex; - + }; // The list of currently registered clients @@ -154,12 +172,12 @@ void RegisterEvents() { hr = SimConnect_AddClientEventToNotificationGroup(g_hSimConnect, MOBIFLIGHT_GROUP::DEFAULT, eventID, false); #if _DEBUG - if (hr != S_OK) { - fprintf(stderr, "MobiFlight: Error on registering Event %s with ID %u for code %s", eventName.c_str(), eventID, eventCommand.c_str()); + if (hr != S_OK) { + fprintf(stderr, "MobiFlight: Error on registering Event %s with ID %lu for code %s", eventName.c_str(), eventID, eventCommand.c_str()); } else { std::cout << "MobiFlight: Success on registering Event " << eventName.c_str(); - std::cout << " with ID " << eventID << " for code " << eventCommand.c_str() << std::endl; + std::cout << " with ID " << eventID << " for code " << eventCommand.c_str() << std::endl; } #endif @@ -205,12 +223,11 @@ void SendNewClientResponse(Client* client, Client* nc) { // List all available LVars for the currently loaded flight // and send them to the SimConnect client void ListLVars(Client* client) { - int lVarId = 0; lVarList.clear(); for (int i = 0; i != 1000; i++) { const char * lVarName = get_name_of_named_variable(i); - if (lVarName == NULLPTR) break; + if (lVarName == NULLPTR) break; lVarList.push_back(std::string(lVarName)); } @@ -224,6 +241,29 @@ void ListLVars(Client* client) { } } +// Overloaded write function for string SimVars +void WriteSimVar(StringSimVar& simVar, Client* client) +{ + HRESULT hr = SimConnect_SetClientData( + g_hSimConnect, + client->DataAreaIDStringSimVar, + simVar.ID, + SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT, + 0, + MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN, + (void*)simVar.Value.c_str() + ); + + if (hr != S_OK) { + fprintf(stderr, "MobiFlight[%s]: Error on Setting String Client Data. %lu, SimVar: %s (String-ID: %ul)\n", client->Name.c_str(), hr, simVar.Name.c_str(), simVar.ID); + } +#if _DEBUG + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Written String-SimVar " << simVar.Name.c_str(); + std::cout << " with String-ID " << simVar.ID << " has value " << simVar.Value.c_str() << std::endl; +#endif +} + +// Overloaded write function for float SimVars void WriteSimVar(SimVar& simVar, Client* client) { HRESULT hr = SimConnect_SetClientData( g_hSimConnect, @@ -234,71 +274,123 @@ void WriteSimVar(SimVar& simVar, Client* client) { sizeof(simVar.Value), &simVar.Value ); - if (hr != S_OK) { - fprintf(stderr, "MobiFlight[%s]: Error on Setting Client Data. %u, SimVar: %s (ID: %u)", client->Name.c_str(), hr, simVar.Name.c_str(), simVar.ID); - } + + if (hr != S_OK) { + fprintf(stderr, "MobiFlight[%s]: Error on Setting Client Data. %lu, SimVar: %s (ID: %u)", client->Name.c_str(), hr, simVar.Name.c_str(), simVar.ID); + } #if _DEBUG - std::cout << "MobiFlight[" << client->Name.c_str() << "]: SimVar " << simVar.Name.c_str(); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Written SimVar " << simVar.Name.c_str(); std::cout << " with ID " << simVar.ID << " has value " << simVar.Value << std::endl; #endif } -// Register a single SimVar and send the current value to SimConnect Clients -void RegisterSimVar(const std::string code, Client* client) { +// Register a single Float-SimVar and send the current value to SimConnect Clients +void RegisterFloatSimVar(const std::string code, Client* client) { std::vector* SimVars = &(client->SimVars); - SimVar var1; - var1.Name = code; - var1.ID = SimVars->size() + client->DataDefinitionIdSimVarsStart; - var1.Offset = (SimVars->size()) * sizeof(float); - - SimVars->push_back(var1); + std::vector* StringSimVars = &(client->StringSimVars); + SimVar newSimVar; HRESULT hr; - if (client->MaxClientDataDefinition < SimVars->size()) - { + newSimVar.Name = code; + newSimVar.ID = SimVars->size() + client->DataDefinitionIdSimVarsStart; + newSimVar.Offset = SimVars->size() * (sizeof(float)); + newSimVar.Value = 0.0F; + SimVars->push_back(newSimVar); + + if (client->MaxClientDataDefinition < (SimVars->size() + StringSimVars->size())) { hr = SimConnect_AddToClientDataDefinition( g_hSimConnect, - var1.ID, - var1.Offset, + newSimVar.ID, + newSimVar.Offset, sizeof(float), 0 ); - client->MaxClientDataDefinition = SimVars->size(); + if (hr != S_OK) { + fprintf(stderr, "MobiFlight[%s]: Error on adding Client Data \"%s\" with ID: %u, Offset: %u and Size: %lu\n", client->Name.c_str(), newSimVar.Name.c_str(), newSimVar.ID, newSimVar.Offset, sizeof(float)); + } +#if _DEBUG + else { + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Added SimVar > " << newSimVar.Name.c_str(); + std::cout << " with ID: " << newSimVar.ID << ", Offset: " << newSimVar.Offset << " and Size: " << sizeof(float) << std::endl; + } + std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterFloatSimVar SimVars Size: " << SimVars->size() << std::endl; +#endif + client->MaxClientDataDefinition = (SimVars->size() + StringSimVars->size()); } + + FLOAT64 floatVal = 0; + execute_calculator_code(std::string(code).c_str(), &floatVal, nullptr, nullptr); + newSimVar.Value = floatVal; + WriteSimVar(newSimVar, client); #if _DEBUG - std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterSimVar SimVars Size: " << SimVars->size() << std::endl; + std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterFloatSimVar > " << newSimVar.Name.c_str(); + std::cout << " ID [" << newSimVar.ID << "] : Offset(" << newSimVar.Offset << ") : Value(" << newSimVar.Value << ")" << std::endl; #endif +} - FLOAT64 val; - WriteSimVar(var1, client); +// Register a single String-SimVar and send the current value to SimConnect Clients +void RegisterStringSimVar(const std::string code, Client* client) { + std::vector* SimVars = &(client->SimVars); + std::vector* StringSimVars = &(client->StringSimVars); + StringSimVar newStringSimVar; + HRESULT hr; - execute_calculator_code(std::string(code).c_str(), &val, NULL, NULL); - var1.Value = val; - - WriteSimVar(var1, client); + newStringSimVar.Name = code; + newStringSimVar.ID = StringSimVars->size() + client->DataDefinitionIdStringVarsStart; + newStringSimVar.Offset = StringSimVars->size() * MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN; + newStringSimVar.Value.empty(); + StringSimVars->push_back(newStringSimVar); + + if (client->MaxClientDataDefinition < (SimVars->size() + StringSimVars->size())) { + hr = SimConnect_AddToClientDataDefinition( + g_hSimConnect, + newStringSimVar.ID, + newStringSimVar.Offset, + MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN, + 0 + ); + if (hr != S_OK) { + fprintf(stderr, "MobiFlight[%s]: Error on adding Client Data \"%s\" with String-ID: %u, String-Offset: %u and Size: %u\n", client->Name.c_str(), newStringSimVar.Name.c_str(), newStringSimVar.ID, newStringSimVar.Offset, MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN); + } #if _DEBUG - std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterSimVar > " << var1.Name.c_str(); - std::cout << " ID [" << var1.ID << "] : Offset(" << var1.Offset << ") : Value(" << var1.Value << ")" << std::endl; + else { + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Added String-SimVar > " << newStringSimVar.Name.c_str(); + std::cout << " with String-ID: " << newStringSimVar.ID << ", String-Offset: " << newStringSimVar.Offset << " and Size: " << MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN << std::endl; + } + std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterStringSimVar StringSimVars Size: " << StringSimVars->size() << std::endl; +#endif + client->MaxClientDataDefinition = (SimVars->size() + StringSimVars->size()); + } + + PCSTRINGZ charVal = nullptr; + execute_calculator_code(std::string(code).c_str(), nullptr, nullptr, &charVal); + newStringSimVar.Value = std::string(charVal, strnlen(charVal, MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN)); + WriteSimVar(newStringSimVar, client); +#if _DEBUG + std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterStringSimVar > " << newStringSimVar.Name.c_str(); + std::cout << " ID [" << newStringSimVar.ID << "] : Offset(" << newStringSimVar.Offset << ") : Value(" << newStringSimVar.Value << ")" << std::endl; #endif } // Clear the list of currently tracked SimVars void ClearSimVars(Client* client) { - client->SimVars.clear(); + client->SimVars.clear(); + client->StringSimVars.clear(); std::cout << "MobiFlight[" << client->Name.c_str() << "]: Cleared SimVar tracking." << std::endl; //client->RollingClientDataReadIndex = client->SimVars.begin(); client->RollingClientDataReadIndex = 0; } -// Read a single SimVar and send the current value to SimConnect Clients +// Read a single SimVar and send the current value to SimConnect Clients (overloaded for float SimVars) void ReadSimVar(SimVar &simVar, Client* client) { - FLOAT64 val = 0; - execute_calculator_code(std::string(simVar.Name).c_str(), &val, NULL, NULL); - - if (simVar.Value == val) return; - simVar.Value = val; + FLOAT64 floatVal = 0; + + execute_calculator_code(std::string(simVar.Name).c_str(), &floatVal, nullptr, nullptr); + + if (simVar.Value == floatVal) return; + simVar.Value = floatVal; WriteSimVar(simVar, client); @@ -308,17 +400,41 @@ void ReadSimVar(SimVar &simVar, Client* client) { #endif } +// Read a single SimVar and send the current value to SimConnect Clients (overloaded for string SimVars) +void ReadSimVar(StringSimVar &simVar, Client* client) { + PCSTRINGZ charVal = nullptr; + + execute_calculator_code(std::string(simVar.Name).c_str(), nullptr, nullptr, &charVal); + std::string stringVal = std::string(charVal, strnlen(charVal, MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN)); + if (simVar.Value == stringVal) return; + simVar.Value = stringVal; + + WriteSimVar(simVar, client); + +#if _DEBUG + std::cout << "MobiFlight[" << client->Name.c_str() << "]: StringSimVar " << simVar.Name.c_str(); + std::cout << " with ID " << simVar.ID << " has value " << simVar.Value << std::endl; +#endif +} + // Read all dynamically registered SimVars void ReadSimVars() { for (auto& client : RegisteredClients) { std::vector* SimVars = &(client->SimVars); - - int maxVarsPerFrame = SimVars->size() < MOBIFLIGHT_MAX_VARS_PER_FRAME ? SimVars->size() : MOBIFLIGHT_MAX_VARS_PER_FRAME; - + std::vector* StringSimVars = &(client->StringSimVars); + + int totalSimVars = SimVars->size() + StringSimVars->size(); + int maxVarsPerFrame = (totalSimVars < MOBIFLIGHT_MAX_VARS_PER_FRAME) ? totalSimVars : MOBIFLIGHT_MAX_VARS_PER_FRAME; + for (int i=0; i < maxVarsPerFrame; ++i) { - ReadSimVar(SimVars->at(client->RollingClientDataReadIndex), client); + if(client->RollingClientDataReadIndex < SimVars->size() ) { + ReadSimVar(SimVars->at(client->RollingClientDataReadIndex), client); + } + else { + ReadSimVar(StringSimVars->at(client->RollingClientDataReadIndex - SimVars->size()), client); + } client->RollingClientDataReadIndex++; - if (client->RollingClientDataReadIndex >= SimVars->size()) + if (client->RollingClientDataReadIndex >= totalSimVars) client->RollingClientDataReadIndex = 0; } } @@ -331,25 +447,32 @@ void ReadSimVars() { void RegisterClientDataArea(Client* client) { HRESULT hr = SimConnect_MapClientDataNameToID(g_hSimConnect, client->DataAreaNameSimVar.c_str(), client->DataAreaIDSimvar); if (hr != S_OK) { - fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %u", hr); + fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %lu", hr); return; } SimConnect_CreateClientData(g_hSimConnect, client->DataAreaIDSimvar, 4096, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); hr = SimConnect_MapClientDataNameToID(g_hSimConnect, client->DataAreaNameResponse.c_str(), client->DataAreaIDResponse); if (hr != S_OK) { - fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %u", hr); + fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %lu", hr); return; } SimConnect_CreateClientData(g_hSimConnect, client->DataAreaIDResponse, MOBIFLIGHT_MESSAGE_SIZE, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); hr = SimConnect_MapClientDataNameToID(g_hSimConnect, client->DataAreaNameCommand.c_str(), client->DataAreaIDCommand); if (hr != S_OK) { - fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %u", hr); + fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %lu", hr); return; } SimConnect_CreateClientData(g_hSimConnect, client->DataAreaIDCommand, MOBIFLIGHT_MESSAGE_SIZE, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); + hr = SimConnect_MapClientDataNameToID(g_hSimConnect, client->DataAreaNameStringVar.c_str(), client->DataAreaIDStringSimVar); + if (hr != S_OK) { + fprintf(stderr, "MobiFlight: Error on creating Client Data Area. %lu", hr); + return; + } + SimConnect_CreateClientData(g_hSimConnect, client->DataAreaIDStringSimVar, SIMCONNECT_CLIENTDATA_MAX_SIZE, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); + DWORD dataAreaOffset = 0; hr = SimConnect_AddToClientDataDefinition( g_hSimConnect, @@ -395,18 +518,22 @@ Client* RegisterNewClient(const std::string clientName) { newClient = new Client(); newClient->Name = clientName; newClient->ID = RegisteredClients.size(); - newClient->DataAreaIDSimvar = 3 * newClient->ID; + newClient->DataAreaIDSimvar = 4 * newClient->ID; newClient->DataAreaIDCommand = newClient->DataAreaIDSimvar + 1; newClient->DataAreaIDResponse = newClient->DataAreaIDCommand + 1; + newClient->DataAreaIDStringSimVar = newClient->DataAreaIDResponse + 1; newClient->DataAreaNameSimVar = newClient->Name + std::string(CLIENT_DATA_NAME_POSTFIX_SIMVAR); newClient->DataAreaNameResponse = newClient->Name + std::string(CLIENT_DATA_NAME_POSTFIX_RESPONSE); newClient->DataAreaNameCommand = newClient->Name + std::string(CLIENT_DATA_NAME_POSTFIX_COMMAND); + newClient->DataAreaNameStringVar = newClient->Name + std::string(CLIENT_DATA_NAME_POSTFIX_STRINGVAR); newClient->DataDefinitionIDStringResponse = 2 * newClient->ID; // 500 Clients possible until offset 1000 is reached newClient->DataDefinitionIDStringCommand = newClient->DataDefinitionIDStringResponse + 1; newClient->SimVars = std::vector(); + newClient->StringSimVars = std::vector(); //newClient->RollingClientDataReadIndex = newClient->SimVars.begin(); newClient->RollingClientDataReadIndex = 0; - newClient->DataDefinitionIdSimVarsStart = SimVarOffset + (newClient->ID * ClientDataDefinitionIdSimVarsRange); + newClient->DataDefinitionIdSimVarsStart = SIMVAR_OFFSET + (newClient->ID * (CLIENT_DATA_DEF_ID_SIMVAR_RANGE + CLIENT_DATA_DEF_ID_STRINGVAR_RANGE)); + newClient->DataDefinitionIdStringVarsStart = newClient->DataDefinitionIdSimVarsStart + CLIENT_DATA_DEF_ID_SIMVAR_RANGE; RegisteredClients.push_back(newClient); @@ -420,19 +547,22 @@ Client* RegisterNewClient(const std::string clientName) { std::cout << "MobiFlight: NewClient DataAreaIDSimvar: " << newClient->DataAreaIDSimvar << std::endl; std::cout << "MobiFlight: NewClient DataAreaIDResponse: " << newClient->DataAreaIDResponse << std::endl; std::cout << "MobiFlight: NewClient DataAreaIDCommand: " << newClient->DataAreaIDCommand << std::endl; + std::cout << "MobiFlight: NewClient DataAreaIDStringSimVar: " << newClient->DataAreaIDStringSimVar << std::endl; std::cout << "MobiFlight: NewClient DataAreaNameSimVar: " << newClient->DataAreaNameSimVar.c_str() << std::endl; std::cout << "MobiFlight: NewClient DataAreaNameResponse: " << newClient->DataAreaNameResponse.c_str() << std::endl; std::cout << "MobiFlight: NewClient DataAreaNameCommand: " << newClient->DataAreaNameCommand.c_str() << std::endl; + std::cout << "MobiFlight: NewClient DataAreaNameStringVar: " << newClient->DataAreaNameStringVar.c_str() << std::endl; std::cout << "MobiFlight: NewClient DataDefinitionIDStringResponse: " << newClient->DataDefinitionIDStringResponse << std::endl; std::cout << "MobiFlight: NewClient DataDefinitionIDStringCommand: " << newClient->DataDefinitionIDStringCommand << std::endl; std::cout << "MobiFlight: NewClient DataDefinitionIdSimVarsStart: " << newClient->DataDefinitionIdSimVarsStart << std::endl; + std::cout << "MobiFlight: NewClient DataDefinitionIdStringVarsStart: " << newClient->DataDefinitionIdStringVarsStart << std::endl; #endif return newClient; } extern "C" MSFS_CALLBACK void module_init(void) -{ +{ g_hSimConnect = 0; HRESULT hr = SimConnect_Open(&g_hSimConnect, ClientName, (HWND) NULL, 0, 0, 0); if (hr != S_OK) @@ -440,7 +570,7 @@ extern "C" MSFS_CALLBACK void module_init(void) fprintf(stderr, "Could not open SimConnect connection.\n"); return; } - + hr = SimConnect_SubscribeToSystemEvent(g_hSimConnect, EVENT_FLIGHT_LOADED, "FlightLoaded"); if (hr != S_OK) { @@ -468,9 +598,9 @@ extern "C" MSFS_CALLBACK void module_init(void) Client* client = RegisterNewClient(std::string(MOBIFLIGHT_CLIENT_DATA_NAME)); RegisterEvents(); ListLVars(client); - + std::cout << "MobiFlight: Max Message size is " << MOBIFLIGHT_MESSAGE_SIZE << std::endl; - std::cout << "MobiFlight: Module Init Complete.Version: " << version << std::endl; + std::cout << "MobiFlight: Module Init Complete.Version: " << version << std::endl; } extern "C" MSFS_CALLBACK void module_deinit(void) @@ -491,7 +621,6 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex { case SIMCONNECT_RECV_ID_EVENT_FILENAME: { SIMCONNECT_RECV_EVENT_FILENAME* evt = (SIMCONNECT_RECV_EVENT_FILENAME*)pData; - int eventID = evt->uEventID; break; } @@ -503,18 +632,18 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex std::cout << "MobiFlight: Received Command: " << str.c_str() << std::endl; std::cout << "MobiFlight: Received ClientId: " << clientID << std::endl; #endif - + Client* client = RegisteredClients[clientID]; if (str == "MF.Ping") { SendResponse("MF.Pong", client); - std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received ping" << std::endl; + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received ping" << std::endl; } else if (str == "MF.SimVars.Clear") { ClearSimVars(client); break; - } + } else if (str == "MF.LVars.List") { SendResponse("MF.LVars.List.Start", client); ListLVars(client); @@ -526,7 +655,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex { std::string v = "MF.Version." + std::string(version); SendResponse(v.c_str(), client); - std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received get version" << std::endl; + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received get version" << std::endl; break; } @@ -535,19 +664,27 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex std::string prefix = "MF.SimVars.Set."; str = str.substr(prefix.length()); #if _DEBUG - std::cout << "MobiFlight[" << client->Name.c_str() << "]: Executing Code: " << str.c_str() << std::endl; + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Executing Code: " << str.c_str() << std::endl; #endif execute_calculator_code(str.c_str(), 0, nullptr, nullptr); break; } - + std::shared_ptr m_str = std::make_shared(str); - + if (m_str.get()->find("MF.SimVars.Add.") != std::string::npos) { std::string prefix = "MF.SimVars.Add."; str = m_str.get()->substr(prefix.length()); - RegisterSimVar(str, client); - std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received SimVar to register: " << str.c_str() << std::endl; + RegisterFloatSimVar(str, client); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received SimVar to register: " << str.c_str() << std::endl; + break; + } + + if (m_str.get()->find("MF.SimVars.AddString.") != std::string::npos) { + std::string prefix = "MF.SimVars.AddString."; + str = m_str.get()->substr(prefix.length()); + RegisterStringSimVar(str, client); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received StringSimVar to register: " << str.c_str() << std::endl; break; } @@ -556,7 +693,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex str= m_str.get()->substr(prefix.length()); Client* newClient = RegisterNewClient(str); SendNewClientResponse(client, newClient); - std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received Client to register: " << str.c_str() << std::endl; + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Received Client to register: " << str.c_str() << std::endl; } if (m_str.get()->find("MF.Config.MAX_VARS_PER_FRAME.Set.") != std::string::npos) { @@ -564,15 +701,13 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex str = m_str.get()->substr(prefix.length()); uint16_t value = static_cast(std::stoi(str)); MOBIFLIGHT_MAX_VARS_PER_FRAME = value; - std::cout << "MobiFlight: Set MF.Config.MAX_VARS_PER_FRAME to " << value << std::endl; + std::cout << "MobiFlight: Set MF.Config.MAX_VARS_PER_FRAME to " << value << std::endl; } break; } case SIMCONNECT_RECV_ID_EVENT_FRAME: { SIMCONNECT_RECV_EVENT* evt = (SIMCONNECT_RECV_EVENT*)pData; - int eventID = evt->uEventID; - ReadSimVars(); break; } @@ -586,14 +721,14 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex int CodeEventId = eventID; std::string command = std::string(CodeEvents[CodeEventId].second); #if _DEBUG - std::cout << "MobiFlight execute " << command.c_str() << std::endl; + std::cout << "MobiFlight execute " << command.c_str() << std::endl; #endif execute_calculator_code(command.c_str(), nullptr, nullptr, nullptr); - } + } else { fprintf(stderr, "MobiFlight: OOF! - EventID out of range:%u\n", eventID); } - + break; } default: From 1a82202c8473e7d056e98e642d9947ffb0624f80 Mon Sep 17 00:00:00 2001 From: DocMoebiuz Date: Fri, 26 Jan 2024 00:49:41 +0100 Subject: [PATCH 6/8] Compiled with 1.0.0 version --- src/MobiFlightEventModuleProject.xml | 4 +++- src/PackageDefinitions/mobiflight-event-module.xml | 2 +- src/Sources/Code/Module.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/MobiFlightEventModuleProject.xml b/src/MobiFlightEventModuleProject.xml index ba311d8..7d86cd9 100644 --- a/src/MobiFlightEventModuleProject.xml +++ b/src/MobiFlightEventModuleProject.xml @@ -1,9 +1,11 @@ - + . _PackageInt + _PublishingGroupInt PackageDefinitions\mobiflight-event-module.xml + diff --git a/src/PackageDefinitions/mobiflight-event-module.xml b/src/PackageDefinitions/mobiflight-event-module.xml index 14605b6..ccbfa62 100644 --- a/src/PackageDefinitions/mobiflight-event-module.xml +++ b/src/PackageDefinitions/mobiflight-event-module.xml @@ -1,5 +1,5 @@ - + MISC Event Module diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp index a6c2857..f68f2e4 100644 --- a/src/Sources/Code/Module.cpp +++ b/src/Sources/Code/Module.cpp @@ -11,7 +11,7 @@ #include "Module.h" HANDLE g_hSimConnect; -const char* version = "0.7.1"; +const char* version = "1.0.0"; const char* ClientName = "MobiFlightWasmModule"; const char* MobiFlightEventPrefix = "MobiFlight."; From b244a2680f0f7ea9e69667f3987079e4c1b9237c Mon Sep 17 00:00:00 2001 From: Sebastian M Date: Fri, 26 Jan 2024 00:58:06 +0100 Subject: [PATCH 7/8] Use the default mobiflight release.yml (#21) --- .github/release.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/release.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..391ccbe --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,26 @@ +changelog: + exclude: + labels: + - ignore-for-release-notes + categories: + - title: New Feature 🎉 + labels: + - feature + - title: Improvement ✨ + labels: + - enhancement + - title: Bug Fixes 🐛 + labels: + - bug + - title: Bug Fixes (BETA) 🐛 + labels: + - bug_beta + - title: Documentation 📚 + labels: + - documentation + - title: Development 💻 + labels: + - development + - title: Other Changes ⚡ + labels: + - "*" From cb4764a57baaf368cf0563ddf188e5e97f7c9530 Mon Sep 17 00:00:00 2001 From: Sebastian M Date: Sun, 11 Feb 2024 23:15:52 +0100 Subject: [PATCH 8/8] Fix clearing out values on clear. (#25) --- .../mobiflight-event-module.xml | 2 +- src/Sources/Code/Module.cpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/PackageDefinitions/mobiflight-event-module.xml b/src/PackageDefinitions/mobiflight-event-module.xml index ccbfa62..896e667 100644 --- a/src/PackageDefinitions/mobiflight-event-module.xml +++ b/src/PackageDefinitions/mobiflight-event-module.xml @@ -1,5 +1,5 @@ - + MISC Event Module diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp index f68f2e4..afe5a3e 100644 --- a/src/Sources/Code/Module.cpp +++ b/src/Sources/Code/Module.cpp @@ -11,7 +11,7 @@ #include "Module.h" HANDLE g_hSimConnect; -const char* version = "1.0.0"; +const char* version = "1.0.1"; const char* ClientName = "MobiFlightWasmModule"; const char* MobiFlightEventPrefix = "MobiFlight."; @@ -376,8 +376,22 @@ void RegisterStringSimVar(const std::string code, Client* client) { // Clear the list of currently tracked SimVars void ClearSimVars(Client* client) { + // We have to clear out the respective DataAreas + // of the SimVars and StringSimVars + // so that SimConnect sends data next time the + // WASM module is running again. + for (auto& simVar : client->SimVars) { + simVar.Value = 0; + WriteSimVar(simVar, client); + } client->SimVars.clear(); + + for (auto& simVar : client->StringSimVars) { + simVar.Value = ""; + WriteSimVar(simVar, client); + } client->StringSimVars.clear(); + std::cout << "MobiFlight[" << client->Name.c_str() << "]: Cleared SimVar tracking." << std::endl; //client->RollingClientDataReadIndex = client->SimVars.begin(); client->RollingClientDataReadIndex = 0;