v1.3.0.0
WASimClient_CLI.cpp
1/*
2This file is part of the WASimCommander project.
3https://github.com/mpaperno/WASimCommander
4
5COPYRIGHT: (c) Maxim Paperno; All Rights Reserved.
6
7This file may be used under the terms of either the GNU General Public License (GPL)
8or the GNU Lesser General Public License (LGPL), as published by the Free Software
9Foundation, either version 3 of the Licenses, or (at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16Copies of the GNU GPL and LGPL are included with this project
17and are available at <http://www.gnu.org/licenses/>.
18*/
19
20#include "WASimClient_CLI.h"
21
22using namespace WASimCommander::CLI;
23using namespace WASimCommander::CLI::Client;
24
25ref class WASimClient::Private
26{
27public:
28 // apparently we have to redeclare these w/out the std::function<> type :-/
29 using clientEventCallback_t = void(__stdcall *)(const WASimCommander::Client::ClientEvent &);
30 using listResultsCallback_t = void(__stdcall *)(const WASimCommander::Client::ListResult &);
31 using dataCallback_t = void(__stdcall *)(const WASimCommander::Client::DataRequestRecord &);
33 using commandCallback_t = void(__stdcall *)(const WASimCommander::Command &);
34
35 WASimClient ^q = nullptr;
37 [UnmanagedFunctionPointer(CallingConvention::StdCall)]
38 delegate void ClientEventCallback(const WASimCommander::Client::ClientEvent &);
39 [UnmanagedFunctionPointer(CallingConvention::StdCall)]
40 delegate void ListResultsCallback(const WASimCommander::Client::ListResult &);
41 [UnmanagedFunctionPointer(CallingConvention::StdCall)]
42 delegate void DataCallback(const WASimCommander::Client::DataRequestRecord &);
43 [UnmanagedFunctionPointer(CallingConvention::StdCall)]
44 delegate void LogCallback(const WASimCommander::LogRecord &, WASimCommander::Client::LogSource);
45 [UnmanagedFunctionPointer(CallingConvention::StdCall)]
46 delegate void CommandResultCallback(const WASimCommander::Command &);
47 [UnmanagedFunctionPointer(CallingConvention::StdCall)]
48 delegate void ResponseCallback(const WASimCommander::Command &);
49
50 [MarshalAs(UnmanagedType::FunctionPtr)]
51 ClientEventCallback ^clientEventCb;
52 [MarshalAs(UnmanagedType::FunctionPtr)]
53 ListResultsCallback ^listResultsCb;
54 [MarshalAs(UnmanagedType::FunctionPtr)]
55 DataCallback ^dataCb;
56 [MarshalAs(UnmanagedType::FunctionPtr)]
57 LogCallback ^logCb;
58 [MarshalAs(UnmanagedType::FunctionPtr)]
59 CommandResultCallback ^resultCb;
60 [MarshalAs(UnmanagedType::FunctionPtr)]
61 ResponseCallback ^responseCb;
62
63 ClientEventDelegate ^clientEventHandler;
64 ListResultsDelegate ^listResultsHandler;
65 DataDelegate ^dataHandler;
66 LogDelegate ^logHandler;
67 CommandResultDelegate ^resultHandler;
68 ResponseDelegate ^responseHandler;
69
71 q(q), client(c)
72 {
73 clientEventCb = gcnew ClientEventCallback(this, &Private::onClientEvent);
74 IntPtr pCb = Marshal::GetFunctionPointerForDelegate(clientEventCb);
75 client->setClientEventCallback(static_cast<clientEventCallback_t>(pCb.ToPointer()));
76
77 listResultsCb = gcnew ListResultsCallback(this, &Private::onListResult);
78 pCb = Marshal::GetFunctionPointerForDelegate(listResultsCb);
79 client->setListResultsCallback(static_cast<listResultsCallback_t>(pCb.ToPointer()));
80
81 dataCb = gcnew DataCallback(this, &Private::onDataResult);
82 pCb = Marshal::GetFunctionPointerForDelegate(dataCb);
83 client->setDataCallback(static_cast<dataCallback_t>(pCb.ToPointer()));
84
85 logCb = gcnew LogCallback(this, &Private::onLogRecord);
86 pCb = Marshal::GetFunctionPointerForDelegate(logCb);
87 client->setLogCallback(static_cast<logCallback_t>(pCb.ToPointer()));
88
89 resultCb = gcnew CommandResultCallback(this, &Private::onCommandResult);
90 pCb = Marshal::GetFunctionPointerForDelegate(resultCb);
91 client->setCommandResultCallback(static_cast<commandCallback_t>(pCb.ToPointer()));
92
93 responseCb = gcnew ResponseCallback(this, &Private::onServerResponse);
94 pCb = Marshal::GetFunctionPointerForDelegate(responseCb);
95 client->setResponseCallback(static_cast<commandCallback_t>(pCb.ToPointer()));
96 }
97
98 void onClientEvent(const WASimCommander::Client::ClientEvent &ev)
99 {
100 if (clientEventHandler)
101 clientEventHandler->Invoke(gcnew ClientEvent(ev));
102 }
103
104 void onListResult(const WASimCommander::Client::ListResult &lr)
105 {
106 if (listResultsHandler)
107 listResultsHandler->Invoke(gcnew ListResult(lr));
108 }
109
110 void onDataResult(const WASimCommander::Client::DataRequestRecord &ev)
111 {
112 if (dataHandler)
113 dataHandler->Invoke(gcnew DataRequestRecord(ev));
114 }
115
117 {
118 if (logHandler)
119 logHandler->Invoke(gcnew LogRecord(lr), (LogSource)s);
120 }
121
122 void onCommandResult(const WASimCommander::Command &cmd)
123 {
124 if (resultHandler)
125 resultHandler->Invoke(gcnew Command(cmd));
126 }
127
128 void onServerResponse(const WASimCommander::Command &cmd)
129 {
130 if (responseHandler)
131 responseHandler->Invoke(gcnew Command(cmd));
132 }
133
134 inline HR executeCalculatorCode(String ^ code, CalcResultType resultType, interior_ptr<double> pfResult, interior_ptr<String ^> psResult)
135 {
136 pin_ptr<double> pf = pfResult;
137 std::string s { };
138 const HRESULT hr = client->executeCalculatorCode(
139 marshal_as<std::string>(code),
141 pf, psResult ? &s : nullptr
142 );
143 if (psResult)
144 *psResult = marshal_as<String ^>(s);
145 return (HR)hr;
146 }
147
148 inline HR getVariable(VariableRequest ^var, interior_ptr<double> pfResult, interior_ptr<String ^> psResult)
149 {
150 pin_ptr<double> pf = pfResult;
151 std::string s { };
152 HR ret = (HR)client->getVariable(var, pf, psResult ? &s : nullptr);
153 if (psResult)
154 *psResult = marshal_as<String ^>(s);
155 return ret;
156 }
157
158 inline HR getOrCreateLocalVariable(String ^ name, interior_ptr<String ^> unit, double defaultValue, interior_ptr<double> pfResult)
159 {
160 pin_ptr<double> pf = pfResult;
161 if (unit)
162 return (HR)client->getOrCreateLocalVariable(marshal_as<std::string>(name), pf, defaultValue, marshal_as<std::string>((String ^)*unit));
163 return (HR)client->getOrCreateLocalVariable(marshal_as<std::string>(name), pf, defaultValue);
164 }
165
166 ~Private()
167 {
168 if (client) {
169 client->setListResultsCallback(nullptr);
170 client->setDataCallback(nullptr);
171 client->setCommandResultCallback(nullptr);
172 client->setResponseCallback(nullptr);
173 client->setClientEventCallback(nullptr);
174 client->setLogCallback(nullptr);
175 }
176
177 delete clientEventHandler;
178 delete listResultsHandler;
179 delete dataHandler;
180 delete logHandler;
181 delete resultHandler;
182 delete responseHandler;
183
184 delete clientEventCb;
185 delete listResultsCb;
186 delete dataCb;
187 delete logCb;
188 delete resultCb;
189 delete responseCb;
190 }
191
192};
193
194
195WASimClient::WASimClient(UInt32 clientId, String ^configFile) :
196 m_client( new WASimCommander::Client::WASimClient(clientId, marshal_as<std::string>(configFile))),
197 d { gcnew Private(this, m_client) }
198{}
199
200WASimClient::WASimClient(UInt32 clientId) : WASimClient(clientId, String::Empty)
201{ }
202
203WASimClient::~WASimClient()
204{
205 delete d;
206 d = nullptr;
207 this->!WASimClient();
208}
209
211{
212 if (m_client)
213 m_client->disconnectSimulator();
214 delete m_client;
215 m_client = nullptr;
216}
217
218inline HR WASimClient::executeCalculatorCode(String ^ code, CalcResultType resultType, double %pfResult) {
219 return d->executeCalculatorCode(code, resultType, &pfResult, nullptr);
220}
221
222inline HR WASimClient::executeCalculatorCode(String ^ code, CalcResultType resultType, String^ %psResult) {
223 return d->executeCalculatorCode(code, resultType, nullptr, &psResult);
224}
225
226inline HR WASimClient::executeCalculatorCode(String ^ code, CalcResultType resultType, double %pfResult, String^ %psResult) {
227 return d->executeCalculatorCode(code, resultType, &pfResult, &psResult);
228}
229
230inline HR WASimClient::getVariable(VariableRequest ^ var, double %pfResult) {
231 return d->getVariable(var, &pfResult, nullptr);
232}
233
234inline HR WASimClient::getVariable(VariableRequest ^ var, String^ %psResult) {
235 return d->getVariable(var, nullptr, &psResult);
236}
237
238inline HR WASimClient::getVariable(VariableRequest ^ var, double %pfResult, String^ %psResult) {
239 return d->getVariable(var, &pfResult, &psResult);
240}
241
242inline HR WASimClient::getOrCreateLocalVariable(String ^variableName, double defaultValue, double %pfResult) {
243 return d->getOrCreateLocalVariable(variableName, nullptr, defaultValue, &pfResult);
244}
245
246inline HR WASimClient::getOrCreateLocalVariable(String ^variableName, String ^unitName, double defaultValue, double %pfResult) {
247 return d->getOrCreateLocalVariable(variableName, &unitName, defaultValue, &pfResult);
248}
249
250inline array<DataRequestRecord^>^ WASimClient::dataRequests()
251{
252 const std::vector<WASimCommander::Client::DataRequestRecord> &res = m_client->dataRequests();
253 array<DataRequestRecord ^> ^ret = gcnew array<DataRequestRecord ^>((int)res.size());
254 int i = 0;
255 for (const auto &dr : res)
256 ret[i++] = gcnew DataRequestRecord(dr);
257 return ret;
258}
259
260inline array<UInt32>^ WASimClient::dataRequestIdsList()
261{
262 const std::vector<uint32_t> &res = m_client->dataRequestIdsList();
263 array<UInt32> ^ret = gcnew array<UInt32>((int)res.size());
264 if (res.size()) {
265 pin_ptr<UInt32> pp = &ret[0];
266 memcpy(pp, res.data(), res.size() * 4);
267 }
268 return ret;
269}
270
271inline array<RegisteredEvent^>^ WASimClient::registeredEvents()
272{
273 const std::vector<WASimCommander::Client::RegisteredEvent> &res = m_client->registeredEvents();
274 array<RegisteredEvent ^> ^ret = gcnew array<RegisteredEvent ^>((int)res.size());
275 int i = 0;
276 for (const auto &ev : res)
277 ret[i++] = gcnew RegisteredEvent(ev);
278 return ret;
279}
280
281#define DELEGATE_HANDLER(E, D, H) \
282 void WASimClient::E::add(D ^ h) { H += h; } \
283 void WASimClient::E::remove(D ^ h) { H -= h; }
284
285DELEGATE_HANDLER(OnClientEvent, ClientEventDelegate, d->clientEventHandler)
286DELEGATE_HANDLER(OnListResults, ListResultsDelegate, d->listResultsHandler)
287DELEGATE_HANDLER(OnDataReceived, DataDelegate, d->dataHandler)
288DELEGATE_HANDLER(OnLogRecordReceived, LogDelegate, d->logHandler)
289DELEGATE_HANDLER(OnCommandResult, CommandResultDelegate, d->resultHandler)
290DELEGATE_HANDLER(OnResponseReceived, ResponseDelegate, d->responseHandler)
291
292#undef DELEGATE_HANDLER
C+/CLI wrapper implementation of WASimCommander::Client::WASimClient. See documentation for the C++ c...
HR getVariable(VariableRequest ^ var, [Out] double % pfResult)
Get the value of a variable with a numeric result type. This is the most typical use case since most ...
array< UInt32 > ^ dataRequestIdsList()
See WASimClient::dataRequestIdsList().
HR getOrCreateLocalVariable(String ^ variableName, double defaultValue, [Out] double % pfResult)
array< DataRequestRecord ^> ^ dataRequests()
See WASimClient::dataRequests().
WASimClient(UInt32 clientId)
Construct a new client with the given ID. The ID must be unique among any other possible clients and ...
void disconnectSimulator()
See WASimClient::disconnectSimulator().
HR executeCalculatorCode(String^ code)
Execute calculator code without result
array< RegisteredEvent ^> ^ registeredEvents()
See WASimClient::registeredEvents().
WASimCommander Client implementation. Handles all aspects of communication with the WASimCommander Se...
Definition: WASimClient.h:85
void setDataCallback(dataCallback_t cb)
Sets a callback for value update data arriving from the server. Pass a nullptr value to remove a prev...
HRESULT executeCalculatorCode(const std::string &code, WASimCommander::Enums::CalcResultType resultType=WASimCommander::Enums::CalcResultType::None, double *pfResult=nullptr, std::string *psResult=nullptr) const
Run a string of MSFS Gauge API calculator code in RPN format, possibly with some kind of result expec...
HRESULT getOrCreateLocalVariable(const std::string &variableName, double *pfResult, double defaultValue=0.0, const std::string &unitName=std::string())
Gets the value of a local variable just like getLocalVariable() but will also create the variable on ...
HRESULT getVariable(const VariableRequest &variable, double *pfResult, std::string *psResult=nullptr)
Get a Variable value by name, with optional named unit type. This is primarily useful for local ('L')...
void setLogCallback(logCallback_t cb)
Sets a callback for logging activity, both from the server and the client itself. Pass a nullptr valu...
std::vector< DataRequestRecord > dataRequests() const
Returns a list of all data requests which have been added to the Client so far. (These are returned b...
void setCommandResultCallback(commandCallback_t cb)
Sets a callback for delivering command results returned by the server. Pass a nullptr value to remove...
std::vector< uint32_t > dataRequestIdsList() const
Returns a list of all DataRequest::requestIds which have been added to the Client so far.
void setListResultsCallback(listResultsCallback_t cb)
Sets a callback for list results arriving from the server. Pass a nullptr value to remove a previousl...
void setResponseCallback(commandCallback_t cb)
Sets a callback for delivering response commands sent to this client by the server module....
void setClientEventCallback(clientEventCallback_t cb)
Sets a callback for Client event updates which indicate status changes. Pass a nullptr value to remov...
std::vector< RegisteredEvent > registeredEvents() const
Returns a list of all registered events which have been added to the Client with registerEvent()....
WASimCommander::CLI::Client namespace. Implementation of the C++ WASimClient as a C++/CLI ....
HR
Method return status values; HRESULT "alias"
Definition: Enums.h:50
WASimCommander::CLI namespace. Container for implementation of the C++ WASimCommander API and WASimCl...
Definition: Enums.h:42
std::function< void __stdcall(const LogRecord &, LogSource)> logCallback_t
Callback function for log entries (from both Client and Server).
Definition: WASimClient.h:75
std::function< void __stdcall(const DataRequestRecord &)> dataCallback_t
Callback function for subscription result data.
Definition: WASimClient.h:74
std::function< void __stdcall(const ListResult &)> listResultsCallback_t
Callback function for delivering list results, eg. of local variables sent from Server.
Definition: WASimClient.h:73
std::function< void __stdcall(const Command &)> commandCallback_t
Callback function for commands sent from server.
Definition: WASimClient.h:76
LogSource
Log entry source, Client or Server.
Definition: enums_impl.h:74
std::function< void __stdcall(const ClientEvent &)> clientEventCallback_t
Callback function for Client events.
Definition: WASimClient.h:72
Client Event data, delivered via callback.
Definition: structs.h:32
Structure for delivering list results, eg. of local variables sent from Server.
Definition: structs.h:42
CalcResultType
The type of result that calculator code is expected to produce.
Definition: enums_impl.h:109
WASimCommander main namespace. Defines constants and structs used in Client-Server interactions....
Definition: enums_impl.h:32
Client Event data, delivered via callback.
Definition: Structs.h:442
Command data structure. The member contents depend on the command type as described in each command t...
Definition: Structs.h:142
DataRequestRecord inherits and extends WASimCommander::CLI::Structs::DataRequest with data pertinent ...
Definition: Structs.h:346
Structure for delivering list results, eg. of local variables sent from Server.
Definition: Structs.h:464
Structure to hold data for registered (reusable) calculator events. Used to submit events with WASimC...
Definition: Structs.h:496
Structure for using with WASimClient::getVariable() and WASimClient::setVariable() to specify informa...
Definition: Structs.h:528
DataRequestRecord inherits and extends WASimCommander::DataRequest with data pertinent for use by a d...
Definition: structs.h:70
Command data structure. The member contents depend on the command type as described in each command t...
Log record structure.