diff --git a/README.md b/README.md
index a9f2995..6af1fc4 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ The default channels for the MobiFlight client are auto created on startup. Each
| 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.LVars.List``` | ```MF.LVars.List.Start```
```I_FCU_EFIS1_ARPT;I_ECAM_COND;...```
```MF.LVars.List.Cont```
```I_ASP2_INT_REC;I_ASP4_VOICE;...```
```MF.LVars.List.Cont```
```I_ASP2_PA_REC;I_ASP4_CAB_SEND;...```
```MF.LVars.List.End```|
| ```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``` |||
diff --git a/src/Sources/Code/Module.cpp b/src/Sources/Code/Module.cpp
index afe5a3e..84c87b5 100644
--- a/src/Sources/Code/Module.cpp
+++ b/src/Sources/Code/Module.cpp
@@ -44,19 +44,22 @@ uint16_t MOBIFLIGHT_MAX_VARS_PER_FRAME = 30;
// due to the maximum client-data-array-size (SIMCONNECT_CLIENTDATA_MAX_SIZE) of 8kB!
constexpr uint16_t MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN = 128;
+//declare struct Client
+struct Client;
+
// data struct for dynamically registered SimVars
struct SimVar {
int ID;
int Offset;
- std::string Name;
float Value;
+ struct Client * client;
};
struct StringSimVar {
int ID;
int Offset;
- std::string Name;
std::string Value;
+ struct Client * client;
};
// data struct for client accessing SimVars
@@ -81,12 +84,26 @@ 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;
+ //Runtime Rolling Client LVARS List Reading Index
+ uint16_t RollingLvarsListReadIndex = 0;
+};
+
+// Runtime Rolling CLient Data reading Index
+uint16_t RollingDataReadIndex = 0;
+
+//RPN code execution for reading values in every frame
+struct ReadRPNCode {
+ std::string Code;
+ //RetType: 0:float 1:integer 2:string
+ int RetType;
+ std::vector SimVars;
+ std::vector StringSimVars;
};
+std::vector RPNCodelist;
+
+
// The list of currently registered clients
std::vector RegisteredClients;
@@ -222,22 +239,38 @@ 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) {
- lVarList.clear();
+int ListLVars(Client* client) {
+ int i;
+ std::string buffer;
+ buffer.reserve(MOBIFLIGHT_MESSAGE_SIZE);
- for (int i = 0; i != 1000; i++) {
+ for (i = client->RollingLvarsListReadIndex; i < 10000; i++) {
const char * lVarName = get_name_of_named_variable(i);
- if (lVarName == NULLPTR) break;
- lVarList.push_back(std::string(lVarName));
+ if (lVarName == NULLPTR) {
+ break;
+ }
+ std::string str(lVarName);
+ // +1 means plus string seperator ';'
+ int buffer_size_next = buffer.size() + str.size() + 1;
+ if (buffer_size_next < MOBIFLIGHT_MESSAGE_SIZE - 1) {
+ lVarList.push_back(str);
+ buffer += str;
+ buffer += ";";
+ } else {
+ break;
+ }
}
+ client->RollingLvarsListReadIndex = i;
- std::sort(lVarList.begin(), lVarList.end());
-
- for (const auto& lVar : lVarList) {
- SendResponse(lVar.c_str(), client);
+ if (buffer.size() > 0) {
+ SendResponse(buffer.c_str(), client);
#if _DEBUG
- std::cout << "MobiFlight[" << client->Name.c_str() << "]: Available LVar > " << lVar.c_str() << std::endl;
+ std::cout << "MobiFlight[" << client->Name.c_str() << "]: Available LVar > " << buffer.c_str() << std::endl;
#endif
+ return buffer.size();
+ } else {
+ client->RollingLvarsListReadIndex = 0;
+ return 0;
}
}
@@ -255,10 +288,10 @@ void WriteSimVar(StringSimVar& simVar, Client* client)
);
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);
+ fprintf(stderr, "MobiFlight[%s]: Error on Setting String Client Data. %lu, SimVar: (String-ID: %ul)\n", client->Name.c_str(), hr, simVar.ID);
}
#if _DEBUG
- std::cout << "MobiFlight[" << client->Name.c_str() << "]: Written String-SimVar " << simVar.Name.c_str();
+ std::cout << "MobiFlight[" << client->Name.c_str() << "]: Written String-SimVar";
std::cout << " with String-ID " << simVar.ID << " has value " << simVar.Value.c_str() << std::endl;
#endif
}
@@ -276,27 +309,49 @@ void WriteSimVar(SimVar& simVar, Client* client) {
);
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);
+ fprintf(stderr, "MobiFlight[%s]: Error on Setting Client Data. %lu, SimVar: (ID: %u)", client->Name.c_str(), hr, simVar.ID);
}
#if _DEBUG
- std::cout << "MobiFlight[" << client->Name.c_str() << "]: Written SimVar " << simVar.Name.c_str();
+ std::cout << "MobiFlight[" << client->Name.c_str() << "]: Written SimVar";
std::cout << " with ID " << simVar.ID << " has value " << simVar.Value << std::endl;
#endif
}
+//check whether SimVar has already registered in SimVar list
+ReadRPNCode* IsDuplicatedSimVar(const std::string code) {
+ for (auto &rpn : RPNCodelist) {
+ if (rpn.Code == code) {
+ return &rpn;
+ }
+ }
+ return nullptr;
+}
+
// 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);
std::vector* StringSimVars = &(client->StringSimVars);
SimVar newSimVar;
+ ReadRPNCode* pdupRpn = IsDuplicatedSimVar(code);
HRESULT hr;
- newSimVar.Name = code;
newSimVar.ID = SimVars->size() + client->DataDefinitionIdSimVarsStart;
newSimVar.Offset = SimVars->size() * (sizeof(float));
newSimVar.Value = 0.0F;
+ newSimVar.client = client;
SimVars->push_back(newSimVar);
+ //duplicated SimVar
+ if (pdupRpn) {
+ pdupRpn->SimVars.push_back(newSimVar);
+ } else {
+ ReadRPNCode rpnCode;
+ rpnCode.Code = code;
+ rpnCode.RetType = 0;//hardcoded type id
+ rpnCode.SimVars.push_back(newSimVar);
+ RPNCodelist.push_back(rpnCode);
+ }
+
if (client->MaxClientDataDefinition < (SimVars->size() + StringSimVars->size())) {
hr = SimConnect_AddToClientDataDefinition(
g_hSimConnect,
@@ -307,11 +362,11 @@ void RegisterFloatSimVar(const std::string code, Client* client) {
);
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));
+ fprintf(stderr, "MobiFlight[%s]: Error on adding Client Data \"%s\" with ID: %u, Offset: %u and Size: %lu\n", client->Name.c_str(), code.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 << "MobiFlight[" << client->Name.c_str() << "]: Added SimVar > " << code.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;
@@ -324,7 +379,7 @@ void RegisterFloatSimVar(const std::string code, Client* client) {
newSimVar.Value = floatVal;
WriteSimVar(newSimVar, client);
#if _DEBUG
- std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterFloatSimVar > " << newSimVar.Name.c_str();
+ std::cout << "MobiFlight[" << client->Name.c_str() << "]: RegisterFloatSimVar > " << code.c_str();
std::cout << " ID [" << newSimVar.ID << "] : Offset(" << newSimVar.Offset << ") : Value(" << newSimVar.Value << ")" << std::endl;
#endif
}
@@ -334,14 +389,26 @@ void RegisterStringSimVar(const std::string code, Client* client) {
std::vector* SimVars = &(client->SimVars);
std::vector* StringSimVars = &(client->StringSimVars);
StringSimVar newStringSimVar;
+ ReadRPNCode* pdupRpn = IsDuplicatedSimVar(code);
HRESULT hr;
- newStringSimVar.Name = code;
newStringSimVar.ID = StringSimVars->size() + client->DataDefinitionIdStringVarsStart;
newStringSimVar.Offset = StringSimVars->size() * MOBIFLIGHT_STRING_SIMVAR_VALUE_MAX_LEN;
newStringSimVar.Value.empty();
+ newStringSimVar.client = client;
StringSimVars->push_back(newStringSimVar);
+ //duplicated SimVar
+ if (pdupRpn) {
+ pdupRpn->StringSimVars.push_back(newStringSimVar);
+ } else {
+ ReadRPNCode rpnCode;
+ rpnCode.Code = code;
+ rpnCode.RetType = 2;//hardcoded type id
+ rpnCode.StringSimVars.push_back(newStringSimVar);
+ RPNCodelist.push_back(rpnCode);
+ }
+
if (client->MaxClientDataDefinition < (SimVars->size() + StringSimVars->size())) {
hr = SimConnect_AddToClientDataDefinition(
g_hSimConnect,
@@ -352,11 +419,11 @@ void RegisterStringSimVar(const std::string code, Client* 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);
+ 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(), code.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 << "MobiFlight[" << client->Name.c_str() << "]: Added String-SimVar > " << code.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;
@@ -369,7 +436,7 @@ void RegisterStringSimVar(const std::string code, Client* client) {
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 << "MobiFlight[" << client->Name.c_str() << "]: RegisterStringSimVar > " << code.c_str();
std::cout << " ID [" << newStringSimVar.ID << "] : Offset(" << newStringSimVar.Offset << ") : Value(" << newStringSimVar.Value << ")" << std::endl;
#endif
}
@@ -391,66 +458,100 @@ void ClearSimVars(Client* client) {
WriteSimVar(simVar, client);
}
client->StringSimVars.clear();
+ // clear RNP code list
+ for (std::vector::iterator rit = RPNCodelist.begin(); rit != RPNCodelist.end();) {
+ for (std::vector::iterator it = (*rit).StringSimVars.begin(); it != (*rit).StringSimVars.end();) {
+ if ((*it).client == client) {
+ it = (*rit).StringSimVars.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ for (std::vector::iterator sit = (*rit).SimVars.begin(); sit != (*rit).SimVars.end();) {
+ if ((*sit).client == client) {
+ sit = (*rit).SimVars.erase(sit);
+ } else {
+ ++sit;
+ }
+ }
+ //remove empty RNP code
+ if ((*rit).StringSimVars.empty() && (*rit).SimVars.empty()) {
+ rit = RPNCodelist.erase(rit);
+ } else {
+ ++rit;
+ }
+ }
std::cout << "MobiFlight[" << client->Name.c_str() << "]: Cleared SimVar tracking." << std::endl;
- //client->RollingClientDataReadIndex = client->SimVars.begin();
- client->RollingClientDataReadIndex = 0;
+ //client->RollingDataReadIndex = client->SimVars.begin();
+ RollingDataReadIndex = 0;
}
+
// Read a single SimVar and send the current value to SimConnect Clients (overloaded for float SimVars)
-void ReadSimVar(SimVar &simVar, Client* client) {
+void ReadSimVarFloat(ReadRPNCode &rpn) {
FLOAT64 floatVal = 0;
- execute_calculator_code(std::string(simVar.Name).c_str(), &floatVal, nullptr, nullptr);
+ execute_calculator_code(rpn.Code.c_str(), &floatVal, nullptr, nullptr);
- if (simVar.Value == floatVal) return;
- simVar.Value = floatVal;
+ for (auto& simVar : rpn.SimVars) {
+ if ((simVar.Value > floatVal) && (simVar.Value - floatVal < 0.00001F)) {
+ continue;
+ } else if ((simVar.Value < floatVal) && (floatVal - simVar.Value < 0.00001F)) {
+ continue;
+ }
+ simVar.Value = floatVal;
- WriteSimVar(simVar, client);
+ WriteSimVar(simVar, simVar.client);
#if _DEBUG
- std::cout << "MobiFlight[" << client->Name.c_str() << "]: SimVar " << simVar.Name.c_str();
- std::cout << " with ID " << simVar.ID << " has value " << simVar.Value << std::endl;
+ std::cout << "MobiFlight[" << simVar.client->Name.c_str() << "]: SimVar " << rpn.Code.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) {
+void ReadSimVarString(ReadRPNCode &rpn) {
PCSTRINGZ charVal = nullptr;
- execute_calculator_code(std::string(simVar.Name).c_str(), nullptr, nullptr, &charVal);
+ execute_calculator_code(std::string(rpn.Code).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);
+ for (auto& simVar : rpn.StringSimVars) {
+ if (simVar.Value == stringVal) continue;
+ simVar.Value = stringVal;
+
+ WriteSimVar(simVar, 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;
+ std::cout << "MobiFlight[" << simVar.client->Name.c_str() << "]: StringSimVar " << rpn.Code.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 float SimVars)
+void ReadSimVar(ReadRPNCode &rpn) {
+ if (rpn.RetType == 0) {
+ ReadSimVarFloat(rpn);
+ } else if (rpn.RetType == 2) {
+ ReadSimVarString(rpn);
+ }
}
// Read all dynamically registered SimVars
void ReadSimVars() {
- for (auto& client : RegisteredClients) {
- std::vector* SimVars = &(client->SimVars);
- std::vector* StringSimVars = &(client->StringSimVars);
+ int totalSimVars = RPNCodelist.size();
+ int maxVarsPerFrame = (totalSimVars < MOBIFLIGHT_MAX_VARS_PER_FRAME) ? totalSimVars : MOBIFLIGHT_MAX_VARS_PER_FRAME;
- 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(RPNCodelist.at(RollingDataReadIndex));
- 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;
- }
+ RollingDataReadIndex++;
+ if (RollingDataReadIndex >= totalSimVars)
+ RollingDataReadIndex = 0;
}
}
@@ -544,8 +645,7 @@ Client* RegisterNewClient(const std::string clientName) {
newClient->DataDefinitionIDStringCommand = newClient->DataDefinitionIDStringResponse + 1;
newClient->SimVars = std::vector();
newClient->StringSimVars = std::vector();
- //newClient->RollingClientDataReadIndex = newClient->SimVars.begin();
- newClient->RollingClientDataReadIndex = 0;
+ RollingDataReadIndex = 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;
@@ -612,6 +712,7 @@ extern "C" MSFS_CALLBACK void module_init(void)
Client* client = RegisterNewClient(std::string(MOBIFLIGHT_CLIENT_DATA_NAME));
RegisterEvents();
ListLVars(client);
+ client->RollingLvarsListReadIndex = 0;
std::cout << "MobiFlight: Max Message size is " << MOBIFLIGHT_MESSAGE_SIZE << std::endl;
std::cout << "MobiFlight: Module Init Complete.Version: " << version << std::endl;
@@ -659,11 +760,15 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContex
}
else if (str == "MF.LVars.List") {
- SendResponse("MF.LVars.List.Start", client);
- ListLVars(client);
- SendResponse("MF.LVars.List.End", client);
+ if(client->RollingLvarsListReadIndex == 0) {
+ SendResponse("MF.LVars.List.Start", client);
+ }
+ if (ListLVars(client) > 0) {
+ SendResponse("MF.LVars.List.Cont", client);
+ } else {
+ SendResponse("MF.LVars.List.End", client);
+ }
break;
-
}
else if (str == "MF.Version.Get")
{