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:
+ - "*"
diff --git a/README.md b/README.md
index ccddd95..a9f2995 100644
--- a/README.md
+++ b/README.md
@@ -21,20 +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.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.

+**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/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 f6b9e7b..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 3d3ec59..afe5a3e 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 = "1.0.1";
const char* ClientName = "MobiFlightWasmModule";
const char* MobiFlightEventPrefix = "MobiFlight.";
@@ -21,17 +22,27 @@ 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 {
@@ -41,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;
@@ -48,16 +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
@@ -145,8 +172,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 %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;
+ }
#endif
eventID++;
@@ -162,9 +194,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) {
@@ -184,19 +216,18 @@ 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);
}
// 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));
}
@@ -205,11 +236,34 @@ 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
}
}
+// 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,
@@ -220,72 +274,160 @@ 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
- 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() << "]: 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
- fprintf(stderr, "MobiFlight[%s]: RegisterSimVar SimVars Size: %d\n", client->Name.c_str(), SimVars->size());
+ 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
+}
+
+// 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;
+
+ 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);
- FLOAT64 val;
- WriteSimVar(var1, client);
+ if (client->MaxClientDataDefinition < (SimVars->size() + StringSimVars->size())) {
+ hr = SimConnect_AddToClientDataDefinition(
+ g_hSimConnect,
+ newStringSimVar.ID,
+ newStringSimVar.Offset,
+ MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN,
+ 0
+ );
- execute_calculator_code(std::string(code).c_str(), &val, NULL, NULL);
- var1.Value = val;
-
- WriteSimVar(var1, client);
+ 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
+ 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
- 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() << "]: 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) {
+ // 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();
- fprintf(stderr, "MobiFlight: Cleared SimVar tracking.");
+
+ 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;
}
-// 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);
#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
+}
+
+// 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
}
@@ -293,8 +435,21 @@ void ReadSimVar(SimVar &simVar, Client* client) {
void ReadSimVars() {
for (auto& client : RegisteredClients) {
std::vector* SimVars = &(client->SimVars);
- for (auto& value : *SimVars) {
- ReadSimVar(value, client);
+ 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) {
+ 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 >= totalSimVars)
+ client->RollingClientDataReadIndex = 0;
}
}
}
@@ -306,25 +461,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,
@@ -370,16 +532,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->DataDefinitionIdSimVarsStart = SimVarOffset + (newClient->ID * ClientDataDefinitionIdSimVarsRange);
+ newClient->StringSimVars = std::vector();
+ //newClient->RollingClientDataReadIndex = newClient->SimVars.begin();
+ newClient->RollingClientDataReadIndex = 0;
+ 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);
@@ -388,24 +556,27 @@ 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 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)
@@ -413,7 +584,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)
{
@@ -442,14 +613,12 @@ extern "C" MSFS_CALLBACK void module_init(void)
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);
@@ -458,7 +627,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)
@@ -467,7 +635,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;
}
@@ -476,45 +643,62 @@ 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;
}
-
+
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);
- fprintf(stderr, "MobiFlight[%s]: Received SimVar to register: %s.\n", client->Name.c_str(), str.c_str());
+ 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;
}
@@ -523,15 +707,21 @@ 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) {
+ 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;
+ 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;
}
@@ -545,14 +735,14 @@ 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);
- }
+ }
else {
fprintf(stderr, "MobiFlight: OOF! - EventID out of range:%u\n", eventID);
}
-
+
break;
}
default:
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