v1.3.0.0
Structs.h
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#pragma once
21
22#include <string>
23#include <type_traits>
24#include <utility>
25
26#include <msclr/marshal.h>
27#include <msclr/marshal_cppstd.h>
28
29//#include "Enums_CLI.h"
30#include "client/WASimClient.h"
31
32using namespace System;
33using namespace System::Collections::Generic;
34using namespace System::Runtime::InteropServices;
35using namespace msclr::interop;
36
37// We need this to ignore the errors about "unknown" pragmas which actually work to suppress bogus Intellisense errors. Yeah.
38#pragma warning(disable:4068)
39
40/// WASimCommander::CLI::Structs namespace.
41/// CLI/.NET versions of WASimCommander API and Client data structures.
43{
44 using namespace WASimCommander::CLI::Enums;
45
46 // A fixed size char array... since "a member of a managed class cannot be a standard array"
47 // ... but apparently it's ok to have to make your own "standard array?" Strange and peculiar.
48 // This is used so we can memcpy between native and managed versions of the same packed structs.
49 // Originally found as "inline_array template written by Mark Hall and improved upon by Shaun Miller"
50 // on an archived blog by one of the CLR developers, Bran Bray:
51 // https://web.archive.org/web/20160126134209/http://blogs.msdn.com/b/branbray/archive/2005/07/20/441099.aspx
52 //
53 // Also the enable_if size check fails with a syntax error no matter what I try... but it's correct code.
54 // So don't try to make a zero size one, OK?
55 template<uint32_t SIZE /*, typename = std::enable_if_t<SIZE, uint32_t>*/ >
56 [Runtime::CompilerServices::UnsafeValueType]
57 [StructLayout(LayoutKind::Explicit, Size=(sizeof(Byte)*SIZE))]
58 public value struct char_array {
59 private:
60 [FieldOffset(0)]
61 Byte _item;
62
63 public:
64 char_array<SIZE>(String ^str) { fromManagedStr(str); }
65 char_array<SIZE>(const std::string &str) { fromStdStr(str); }
66 char_array<SIZE>(const char *str) : char_array<SIZE>(str, std::strlen(str)) {}
67 char_array<SIZE>(const char *str, const size_t len) {
68 clear();
69 const pin_ptr<Byte> ptr = &_item;
70 memcpy(ptr, str, min(SIZE, len));
71 }
72
73 void fromStdStr(const std::string &str) {
74 clear();
75 if (str.empty())
76 return;
77 const pin_ptr<Byte> ptr = &_item;
78 const uint32_t len = std::min<uint32_t>(SIZE-1, (uint32_t)str.size());
79 memcpy(ptr, str.data(), len);
80 //if (len < SIZE)
81 //memset(ptr + len, 0, (size_t)SIZE - len);
82 }
83
84 void fromManagedStr(String ^str) {
85 clear();
86 if (String::IsNullOrEmpty(str))
87 return;
88 const pin_ptr<Byte> ptr = &_item;
89 const array<Byte> ^strData = Text::Encoding::UTF8->GetBytes(str);
90 const pin_ptr<Byte> src = &strData[0];
91 const uint32_t len = std::min<uint32_t>(SIZE-1, strData->Length);
92 memcpy(ptr, src, len);
93 //if (len < SIZE)
94 //memset(ptr + len, 0, (size_t)SIZE - len);
95 }
96
97 void clear() {
98 const pin_ptr<Byte> ptr = &_item;
99 memset(ptr, 0, SIZE);
100 }
101
102 String ^ToString() override { return (String^)*this; }
103
104 operator String ^() {
105 const pin_ptr<Byte> ptr = &this->_item;
106 return gcnew String((const char *)ptr, 0, (int)std::strlen((const char *)ptr), Text::Encoding::UTF8);
107 //return gcnew String(*this, 0, (int)std::strlen(*this), Text::Encoding::UTF8);
108 }
109
110 operator std::string() {
111 const pin_ptr<Byte> ptr = &this->_item;
112 return std::string((const char *)ptr);
113 //return std::string(*this);
114 }
115
116 Byte% operator[](int index) {
117 return *((&_item)+index);
118 }
119
120 static operator interior_ptr<Byte>(char_array<SIZE>% ia) {
121 return &ia._item;
122 }
123
124 // These operators work but I'm not sure why... shouldn't pin_ptr go out of scope?
125 //operator Byte *() {
126 // pin_ptr<Byte> ptr = &_item;
127 // return ptr;
128 //}
129 //
130 //operator const char *() {
131 // pin_ptr<Byte> ptr = &_item;
132 // return reinterpret_cast<const char*>(ptr);
133 //}
134
135
136 };
137
138 /// <summary> Command data structure. The member contents depend on the command type as described in each command type of the `CommandId` enum documentation. \sa CommandId enum </summary>
139 /// For full documentation of each field see `WASimCommander::Command`.
140 [StructLayout(LayoutKind::Sequential, CharSet = CharSet::Ansi, Pack = 1)]
141 public ref struct Command sealed
142 {
143 public:
144 UInt32 token;
145 UInt32 uData;
146 double fData;
147 CommandId commandId;
148 char_array<STRSZ_CMD> sData;
149
150 Command() {}
151 explicit Command(CommandId id) : commandId(id) { }
152 explicit Command(CommandId id, uint32_t uData) : uData(uData), commandId(id) { }
153 explicit Command(CommandId id, uint32_t uData, double fData) : uData(uData), fData(fData), commandId(id) { }
154#pragma diag_suppress 144 // a value of type "System::String ^" cannot be used to initialize an entity of type "unsigned char" (sData is not a uchar... someone's confused)
155 explicit Command(CommandId id, uint32_t uData, String ^sData) : uData(uData), fData(0.0), commandId(id), sData{sData} { }
156 explicit Command(CommandId id, uint32_t uData, String ^sData, double fData) : uData(uData), fData(fData), commandId(id), sData{sData} { }
157 explicit Command(CommandId id, uint32_t uData, String ^sData, double fData, int32_t token) : token(token), uData(uData), fData(fData), commandId(id), sData{sData} { }
158#pragma diag_restore 144
159
160 void setStringData(String ^sData)
161 {
162 this->sData = char_array<STRSZ_CMD>(sData);
163 }
164
165 String ^ToString() override {
166 return String::Format("Command {{{0}; token: {1}; uData: {2}; fData: {3:F6}; sData: \"{4}\"}}", commandId, token, uData, fData, sData);
167 }
168
169 internal:
170 explicit Command(const WASimCommander::Command &from)
171 {
172 pin_ptr<UInt32> ptr = &this->token;
173 memcpy_s(ptr, Marshal::SizeOf(this), &from, sizeof(WASimCommander::Command));
174 }
175
176 inline operator WASimCommander::Command() {
178 pin_ptr<UInt32> ptr = &this->token;
179 memcpy_s(&cmd, sizeof(WASimCommander::Command), ptr, Marshal::SizeOf(this));
180 return cmd;
181 }
182 };
183
184
185 /// <summary> Log record structure. \sa WASimCommander:CommandId::Log command. </summary>
186 /// For full documentation of each field see `WASimCommander::LogRecord`.
187 [StructLayout(LayoutKind::Sequential, CharSet = CharSet::Ansi, Pack = 1)]
188 public ref struct LogRecord sealed
189 {
190 public:
191 UInt64 timestamp; // ms since epoch
192 LogLevel level;
193 char_array<STRSZ_LOG> message;
194
195 String ^ToString() override {
196 return String::Format("{0} [{1}] {2}", DateTimeOffset::FromUnixTimeMilliseconds(timestamp).LocalDateTime.ToString("MM/dd HH:mm:ss.fff"), level, (String ^)message);
197 }
198
199 internal:
200 explicit LogRecord(const WASimCommander::LogRecord &lr)
201 {
202 pin_ptr<UInt64> ptr = &this->timestamp;
203 memcpy_s(ptr, Marshal::SizeOf(this), &lr, sizeof(WASimCommander::LogRecord));
204 }
205 };
206
207
208 /// <summary> Structure for value update subscription requests. \sa WASimCommander:CommandId::Subscribe command. </summary>
209 /// For full documentation of each field see `WASimCommander::DataRequest`.
210 [StructLayout(LayoutKind::Sequential, CharSet = CharSet::Ansi, Pack = 1)]
211 public ref struct DataRequest
212 {
213 public:
214 UInt32 requestId {0};
215 UInt32 valueSize {0};
216 float deltaEpsilon {0.0f};
217 UInt32 interval {0};
218 UpdatePeriod period {UpdatePeriod::Never};
219 RequestType requestType {RequestType::None};
220 CalcResultType calcResultType {CalcResultType::None};
221 Byte simVarIndex {0};
222 SByte varTypePrefix {'L'};
223 char_array<STRSZ_REQ> nameOrCode;
224 char_array<STRSZ_UNIT> unitName;
225
226 /// <summary> Default constructor. Properties must be set to valid values, either later or inline, eg. `new DataRequest() { requestId: 1, requestType: RequestType::Named, ...}`. </summary>
228 /// <summary> Constructs a request for a named variable (`requestType = RequestType::Named`) with default update period on every `UpdatePeriod.Tick`. </summary>
229 explicit DataRequest(UInt32 requestId, Char variableType, String ^variableName, UInt32 valueSize) :
230 requestId(requestId), valueSize(valueSize), period(UpdatePeriod::Tick),
231 requestType(RequestType::Named), varTypePrefix((Byte)variableType), nameOrCode(variableName)
232 { }
233 /// <summary> Constructs a request for a named variable (`requestType = RequestType::Named`) with given update period, interval, and epsilon values. </summary>
234 explicit DataRequest(UInt32 requestId, Char variableType, String ^variableName, UInt32 valueSize, UpdatePeriod period, UInt32 interval, float deltaEpsilon) :
235 requestId(requestId), valueSize(valueSize), deltaEpsilon(deltaEpsilon), interval(interval), period(period),
236 requestType(RequestType::Named), varTypePrefix((Byte)variableType), nameOrCode(variableName)
237 { }
238 /// <summary> Constructs a request for a named Simulator Variable (`requestType = RequestType::Named` and `varTypePrefix = 'A'`) with default update period on every `UpdatePeriod.Tick`. </summary>
239 explicit DataRequest(UInt32 requestId, String ^simVarName, String ^unitName, Byte simVarIndex, UInt32 valueSize) :
240 requestId(requestId), valueSize(valueSize), period(UpdatePeriod::Tick),
241 requestType(RequestType::Named), simVarIndex(simVarIndex), varTypePrefix('A'), nameOrCode(simVarName), unitName(unitName)
242 { }
243 /// <summary> Constructs a request for a named Simulator Variable (`requestType = RequestType::Named` and `varTypePrefix = 'A'`) with given update period, interval, and epsilon values. </summary>
244 explicit DataRequest(UInt32 requestId, String ^simVarName, String ^unitName, Byte simVarIndex, UInt32 valueSize, UpdatePeriod period, UInt32 interval, float deltaEpsilon) :
245 requestId(requestId), valueSize(valueSize), deltaEpsilon(deltaEpsilon), interval(interval), period(period),
246 requestType(RequestType::Named), simVarIndex(simVarIndex), varTypePrefix('A'), nameOrCode(simVarName), unitName(unitName)
247 { }
248 /// <summary> Constructs a calculator code request (`requestType = RequestType::Calculated`) with default update period on every `UpdatePeriod.Tick`. </summary>
249 explicit DataRequest(UInt32 requestId, CalcResultType resultType, String ^calculatorCode, UInt32 valueSize) :
250 requestId(requestId), valueSize(valueSize), period(UpdatePeriod::Tick),
251 requestType(RequestType::Calculated), calcResultType(resultType), nameOrCode(calculatorCode)
252 { }
253 /// <summary> Constructs a calculator code request (`requestType = RequestType::Calculated`) with given update period, interval, and epsilon values.. </summary>
254 explicit DataRequest(UInt32 requestId, CalcResultType resultType, String ^calculatorCode, UInt32 valueSize, UpdatePeriod period, UInt32 interval, float deltaEpsilon) :
255 requestId(requestId), valueSize(valueSize), deltaEpsilon(deltaEpsilon), interval(interval), period(period),
256 requestType(RequestType::Calculated), calcResultType(resultType), nameOrCode(calculatorCode)
257 { }
258 /// <summary> Constructs a calculator code request (`requestType = RequestType::Calculated`) with default update period on every `UpdatePeriod.Tick`. </summary>
259 /// This overload, w/out a `valueSize` argument automatically determines the size based on the `resultType` argument:
260 /// - `CalcResultType::Double` = `WASimCommander::DATA_TYPE_DOUBLE`
261 /// - `CalcResultType::Integer` = `WASimCommander::DATA_TYPE_INT32`
262 /// - `CalcResultType::String` = 256
263 explicit DataRequest(UInt32 requestId, CalcResultType resultType, String ^calculatorCode) :
264 requestId(requestId), valueSize(calcResultToValueSize(resultType)), period(UpdatePeriod::Tick),
265 requestType(RequestType::Calculated), calcResultType(resultType), nameOrCode(calculatorCode)
266 { }
267 /// <summary> Constructs a calculator code request (`requestType = RequestType::Calculated`) with given update period, interval, and epsilon values.. </summary>
268 /// This overload, w/out a `valueSize` argument automatically determines the size based on the `resultType` argument:
269 /// - `CalcResultType::Double` = `WASimCommander::DATA_TYPE_DOUBLE`
270 /// - `CalcResultType::Integer` = `WASimCommander::DATA_TYPE_INT32`
271 /// - `CalcResultType::String` = 256
272 explicit DataRequest(UInt32 requestId, CalcResultType resultType, String ^calculatorCode, UpdatePeriod period, UInt32 interval, float deltaEpsilon) :
273 requestId(requestId), valueSize(calcResultToValueSize(resultType)), deltaEpsilon(deltaEpsilon), interval(interval), period(period),
274 requestType(RequestType::Calculated), calcResultType(resultType), nameOrCode(calculatorCode)
275 { }
276
277 /// <summary>Set the `nameOrCode` member using a `string` type value. </summary>
278 void setNameOrCode(String ^nameOrCode)
279 {
280 this->nameOrCode = char_array<STRSZ_REQ>(nameOrCode);
281 }
282
283 /// <summary>Set the `unitName` member using a `string` type value. </summary>
284 void setUnitName(String ^unitName)
285 {
286 this->unitName = char_array<STRSZ_UNIT>(unitName);
287 }
288
289 /// <summary>Serializes this `DataRequest` to a string for debugging purposes.</summary>
290 String ^ToString() override
291 {
292 String ^str = String::Format(
293 "DataRequest {{{0}; size: {1}; period: {2}; interval: {3}; deltaE: {4:F6}", requestId, valueSize, period, interval, deltaEpsilon
294 );
295 Text::StringBuilder sb(str);
296 if (requestType == RequestType::None)
297 return sb.Append("; type: None; }")->ToString();
298 if (requestType == RequestType::Named)
299 return sb.AppendFormat("; type: Named; name: \"{0}\"; unit: \"{1}\"; varType: '{2}'; varIndex: {3}}}", nameOrCode, unitName, varTypePrefix, simVarIndex)->ToString();
300 return sb.AppendFormat("; type: Calculated; code: \"{0}\"; resultType: {1}}}", nameOrCode, calcResultType)->ToString();
301 }
302
303 internal:
304 explicit DataRequest(const WASimCommander::DataRequest &dr)
305 {
306 pin_ptr<UInt32> ptr = &this->requestId;
307 memcpy_s(ptr, Marshal::SizeOf((DataRequest^)this), &dr, sizeof(WASimCommander::DataRequest));
308 }
309
310 inline operator WASimCommander::DataRequest()
311 {
312 WASimCommander::DataRequest dr(requestId);
313 pin_ptr<UInt32> ptr = &this->requestId;
314 memcpy_s(&dr, sizeof(WASimCommander::DataRequest), ptr, Marshal::SizeOf((DataRequest^)this));
315 return dr;
316 }
317
318 UInt32 calcResultToValueSize(CalcResultType type) {
319 return (type == CalcResultType::Double ? DATA_TYPE_DOUBLE : type == CalcResultType::Integer ? DATA_TYPE_INT32 : 256);
320 }
321 }; // DataRequest
322
323
324 /// <summary> `DataRequestRecord` inherits and extends `WASimCommander::CLI::Structs::DataRequest` with data pertinent for use by a data consumer/Client.
325 /// In particular, any value data sent from the server is stored here as a byte array in the `data` member (a byte array). </summary>
326 ///
327 /// `DataRequest` subscription results are delivered by `WASimClient` (via `OnDataReceived` event) using this `DataRequestRecord` structure.
328 /// WASimClient also holds a list of all data requests which have been added using `WASimClient::saveDataRequest()` method. These
329 /// requests are available for reference using `WASimClient::dataRequest()`, `WASimClient::dataRequests()`, and `WASimClient::dataRequestIdsList()` methods.
330 /// For full documentation of each field see `WASimCommander::Client::DataRequestRecord`.
331 ///
332 /// For assistance with converting the raw data to actual values, there are a couple `bool tryConvert(T)` templates which try to populate a value reference
333 /// (`out` parameter) of the desired type and returns true or false depending on if the conversion was valid. Validity is based only on the data array size vs.
334 /// the requested type size, so it will happily populate an Int32 with data representing a float value, since the type sizes match. **The user must know what data
335 /// type they are expecting.**
336 ///
337 /// One version of `tryConvert()` handles basic numeric types, and another is a special overload for returning Strings.
338 ///
339 /// There are also implicit conversion operators for all numeric types and String. If conversion fails, these return a default-constructed instance,
340 /// typically zero or an empty string.
341 ///
342 /// Also note that the size of the data array may or _may not_ be the same as the inherited `DataRequest::valueSize` member, since that may contain
343 /// special values for preset types. Always check the actual data array size (`data.Length`) if you need to know the storage requirements.
344 [StructLayout(LayoutKind::Sequential, CharSet = CharSet::Ansi, Pack = 1)]
345 public ref struct DataRequestRecord : public DataRequest
346 {
347 public:
348 time_t lastUpdate = 0; ///< Timestamp of last data update in ms since epoch.
349 array<Byte> ^data {}; ///< Value data array.
350
351
352 /// <summary> Tries to populate a value reference of the desired type `T` and returns true or false
353 /// depending on if the conversion was valid (meaning the size of requested type matches the data size). </summary>
354 /// If the conversion fails, result is default-initialized.
355 /// The requested type (`T`) must be a `value` type (not reference) and be default-constructible, (eg. numerics, chars), or fixed-size arrays of such types.
356 generic<typename T>
357#if !DOXYGEN
358 where T : value class, gcnew()
359#endif
360 inline bool tryConvert([Out] T %result)
361 {
362 if (data->Length == (int)sizeof(T)) {
363 pin_ptr<T> pr = &result;
364 pin_ptr<Byte> pd = &data[0];
365 memcpy_s(pr, sizeof(T), pd, data->Length);
366 return true;
367 }
368 result = T();
369 return false;
370 }
371
372 /// <summary> Overload for String type results. This will simply load whatever bytes are in the `data` array into a String, and only
373 /// returns `false` (and an empty String) if the data array is empty or starts with a null character byte (`0x00`). </summary>
374 inline bool tryConvert([Out] String ^ %result)
375 {
376 if (!data->Length || !data[0]) {
377 result = String::Empty;
378 return false;
379 }
380 pin_ptr<Byte> pd = &data[0];
381 result = gcnew String((const char *)pd);
382 return true;
383 }
384
385 /// \name Implicit conversion operators for various types.
386 /// \{
387 inline static operator double(DataRequestRecord ^dr) { return dr->toType<double>(); }
388 inline static operator float(DataRequestRecord ^dr) { return dr->toType<float>(); }
389 inline static operator int64_t(DataRequestRecord ^dr) { return dr->toType<int64_t>(); }
390 inline static operator uint64_t(DataRequestRecord ^dr) { return dr->toType<uint64_t>(); }
391 inline static operator int32_t(DataRequestRecord ^dr) { return dr->toType<int32_t>(); }
392 inline static operator uint32_t(DataRequestRecord ^dr) { return dr->toType<uint32_t>(); }
393 inline static operator int16_t(DataRequestRecord ^dr) { return dr->toType<int16_t>(); }
394 inline static operator uint16_t(DataRequestRecord ^dr) { return dr->toType<uint16_t>(); }
395 inline static operator int8_t(DataRequestRecord ^dr) { return dr->toType<int8_t>(); }
396 inline static operator uint8_t(DataRequestRecord ^dr) { return dr->toType<uint8_t>(); }
397 inline static operator String ^(DataRequestRecord ^dr) { return dr->toType<String ^>(); }
398 /// \}
399
400 // can't get generic to work
401 //generic<typename T> where T : value class, gcnew()
402 //inline static operator T(DataRequestRecord ^dr)
403 //{
404 // //return dr->toType<T>();
405 // T ret = T();
406 // dr->tryConvert(ret);
407 // return ret;
408 //}
409
410 /// <summary>Serializes this `DataRequestRecord` to string for debugging purposes.</summary>
411 /// To return the request's _value_ as a string, see `tryConvert()` or the `String ^()` operator. \sa DataRequest::ToString()
412 String ^ToString() override {
413 return String::Format(
414 "{0}; DataRequestRecord {{Last Update: {1}; Data: {2}}}",
416 DateTimeOffset::FromUnixTimeMilliseconds(lastUpdate).LocalDateTime.ToString("HH:mm:ss.fff"),
417 BitConverter::ToString(data)
418 );
419 }
420
421 internal:
423 DataRequest((WASimCommander::DataRequest)dr), lastUpdate{dr.lastUpdate}, data(gcnew array<Byte>((int)dr.data.size()))
424 {
425 Marshal::Copy(IntPtr((void*)dr.data.data()), data, 0, (int)dr.data.size());
426 }
427
428 template<typename T>
429 inline T toType()
430 {
431 T ret = T();
432 tryConvert(ret);
433 return ret;
434 }
435
436 };
437
438
439 /// <summary> Client Event data, delivered via callback. </summary>
440 /// For full documentation of each field see `WASimCommander::Client::ClientEvent`.
441 public ref struct ClientEvent sealed
442 {
443 public:
444 ClientEventType eventType;
445 ClientStatus status;
446 String ^ message {};
447
448 String ^ToString() override {
449 return String::Format("ClientEvent {{{0}; status: {1}; message: \"{2}\"}}", eventType, status, message);
450 }
451
452 internal:
454 eventType = (ClientEventType)n.eventType;
455 status = (ClientStatus)n.status;
456 message = gcnew String(n.message.c_str());
457 }
458 };
459
460
461 /// <summary> Structure for delivering list results, eg. of local variables sent from Server. </summary>
462 /// For full documentation of each field see `WASimCommander::Client::ListResult`.
463 public ref struct ListResult sealed
464 {
465 public:
466 using ListCollectionType = Dictionary<int, String^>;
467
468 LookupItemType listType;
469 HRESULT result;
470 ListCollectionType ^list;
471
472 String ^ToString() override {
473 Text::StringBuilder sb(String::Format("ListResult {{{0}; result: {1}; Values:\n", listType, result));
474 ListCollectionType::Enumerator en = list->GetEnumerator();
475 while (en.MoveNext())
476 sb.AppendFormat("{0,4} = {1}\n", en.Current.Key, en.Current.Value);
477 sb.Append("}");
478 return sb.ToString();
479 }
480
481 internal:
483 listType{(LookupItemType)r.listType}, result(r.result), list{gcnew ListCollectionType((int)r.list.size()) }
484 {
485#pragma diag_suppress 2242 // for list[] operator: expression must have pointer-to-object or handle-to-C++/CLI-array type but it has type "ListCollectionType ^" (um... isn't `list` a pointer?)
486 for (const auto &pr : r.list)
487 list[pr.first] = gcnew String(pr.second.c_str());
488#pragma diag_default 2242
489 }
490 };
491
492
493 /// <summary> Structure to hold data for registered (reusable) calculator events. Used to submit events with `WASimClient::registerEvent()`. </summary>
494 /// For full documentation of each field see `WASimCommander::Client::RegisteredEvent`.
495 public ref struct RegisteredEvent
496 {
497 public:
498 UInt32 eventId;
499 String ^ code { String::Empty };
500 String ^ name { String::Empty };
501
502 RegisteredEvent() {}
503 explicit RegisteredEvent(UInt32 eventId, String ^code) :
504 eventId{eventId}, code{code} { }
505 explicit RegisteredEvent(UInt32 eventId, String ^code, String ^name) :
506 eventId{eventId}, code{code}, name{name} { }
507
508 String ^ToString() override {
509 return String::Format("RegisteredEvent {{{0}; code: {1}; name: {2}}}", eventId, code, name);
510 }
511
512 internal:
514 eventId{ev.eventId}, code{gcnew String(ev.code.c_str())}, name{gcnew String(ev.name.c_str())} { }
515
517 marshal_context mc;
518 return WASimCommander::Client::RegisteredEvent (eventId, mc.marshal_as<std::string>(code), mc.marshal_as<std::string>(name));
519 }
520 };
521
522
523 /// <summary> Structure for using with `WASimClient::getVariable()` and `WASimClient::setVariable()` to specify information about the variable to set or get. Variables and Units can be specified by name or by numeric ID. </summary>
524 /// Only some variable types have an associated numeric ID ('A', 'L', 'T' types) and only some variable types accept a Unit specifier ('A', 'C', 'E', 'L' types). Using numeric IDs, if already known, is more efficient
525 /// on the server side since it saves the lookup step.
526 /// For full documentation of each field see `WASimCommander::Client::VariableRequest`.
527 public ref struct VariableRequest
528 {
529 public:
530 SByte variableType { 'L' };
531 String ^ variableName { String::Empty };
532 String ^ unitName { String::Empty };
533 int variableId { -1 };
534 int unitId { -1 };
535 Byte simVarIndex { 0 };
536 bool createLVar = false;
537
538 VariableRequest() {}
539 /// <summary> Construct a variable request for specified variable type ('A', 'L', etc) and variable name. </summary>
540 explicit VariableRequest(Char variableType, String ^variableName) :
541 variableType{(SByte)variableType}, variableName{variableName} { }
542 /// <summary> Construct a variable request for specified variable type ('A', 'L', etc) and numeric variable ID. </summary>
543 explicit VariableRequest(Char variableType, int variableId) :
544 variableType{(SByte)variableType}, variableId{variableId} { }
545 /// <summary> Construct a variable request for specified variable type ('A', 'L', etc), variable name, and with a named unit specifier. </summary>
546 explicit VariableRequest(Char variableType, String ^variableName, String ^unitName) :
547 variableType{(SByte)variableType}, variableName{variableName}, unitName{unitName} { }
548 /// <summary> Construct a variable request for specified variable type ('A', 'L', etc), numeric variable ID, and with a numeric unit ID specifier. </summary>
549 explicit VariableRequest(Char variableType, int variableId, int unitId) :
550 variableType{(SByte)variableType}, variableId{variableId}, unitId{unitId} { }
551 /// <summary> Construct a variable request for a Simulator variable ('A') with given name, named unit specifier, and index (use zero for non-indexed variables). </summary>
552 explicit VariableRequest(String ^simVariableName, String ^unitName, Byte simVarIndex) :
553 variableType{'A'}, variableName{simVariableName}, unitName{unitName} { }
554 /// <summary> Construct a variable request for a Simulator variable ('A') with given variable ID, numeric unit specifier, and index (use zero for non-indexed variables). </summary>
555 explicit VariableRequest(int simVariableId, int unitId, Byte simVarIndex) :
556 variableType{'A'}, variableId{simVariableId}, unitId{unitId} { }
557 /// <summary> Construct a variable request a Local variable ('L') with the specified name. </summary>
558 explicit VariableRequest(String ^localVariableName) :
559 variableType{'L'}, variableName{localVariableName} { }
560 /// <summary> Construct a variable request for a Local ('L') variable with the specified name. </summary>
561 /// `createVariable` will create the L var on the simulator if it doesn't exist yet (for "Get" as well as "Set" commands). An optional unit name can also be provided.
562 explicit VariableRequest(String ^localVariableName, bool createVariable) :
563 variableType{'L'}, variableName{localVariableName}, createLVar{createVariable} { }
564 /// <summary> Construct a variable request for a Local ('L') variable with the specified name. </summary>
565 /// `createVariable` will create the L var on the simulator if it doesn't exist yet (for "Get" as well as "Set" commands). An unit name can also be provided with this overload.
566 explicit VariableRequest(String ^localVariableName, bool createVariable, String ^unitName) :
567 variableType{'L'}, variableName{localVariableName}, unitName{unitName}, createLVar{createVariable} { }
568 /// <summary> Construct a variable request a Local variable ('L') with the specified numeric ID. </summary>
569 explicit VariableRequest(int localVariableId) :
570 variableType{'L'}, variableId{localVariableId} { }
571
572 String ^ToString() override {
573 return String::Format(
574 "VariableRequest {{{0}; variableName: \"{1}\"; unitName: \"{2}\"; variableId: {3}; unitId {4}; simVarIndex: {5}}}",
575 variableType, variableName, unitName, variableId, unitId, simVarIndex
576 );
577 }
578
579 internal:
581 {
582 marshal_context mc;
583 WASimCommander::Client::VariableRequest r((char)variableType, mc.marshal_as<std::string>(variableName), mc.marshal_as<std::string>(unitName), simVarIndex, createLVar);
584 r.variableId = variableId;
585 r.unitId = unitId;
586 return r;
587 }
588 };
589
590}
WASimCommander::CLI::Enums namespace. C++/CLI specific definitions only. See documentation for WASimC...
Definition: Enums.h:42
WASimCommander::CLI::Structs namespace. CLI/.NET versions of WASimCommander API and Client data struc...
Definition: Structs.h:43
HRESULT result
Execution result, one of: S_OK, E_FAIL, E_TIMEOUT
Definition: structs.h:46
WASimCommander::Enums::LookupItemType listType
the type of items being listed
Definition: structs.h:45
ClientEventType eventType
The type of event. See enum docs for details.
Definition: structs.h:33
std::string message
A short message about the event (eg. "Server Connected")
Definition: structs.h:35
listResult_t list
Mapping of numeric item IDs to name strings.
Definition: structs.h:47
ClientStatus status
Current status flag(s). See enum docs for details.
Definition: structs.h:34
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
@ String
Expect a string type result from execute_calculator_code().
WASimCommander main namespace. Defines constants and structs used in Client-Server interactions....
Definition: enums_impl.h:32
static const uint32_t DATA_TYPE_INT32
32-bit integer number (signed or unsigned)
static const uint32_t DATA_TYPE_DOUBLE
64-bit floating-point number
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
Structure for value update subscription requests.
Definition: Structs.h:212
DataRequest(UInt32 requestId, CalcResultType resultType, String ^ calculatorCode, UpdatePeriod period, UInt32 interval, float deltaEpsilon)
Constructs a calculator code request (requestType = RequestType::Calculated) with given update period...
Definition: Structs.h:272
DataRequest(UInt32 requestId, Char variableType, String ^ variableName, UInt32 valueSize)
Constructs a request for a named variable (requestType = RequestType::Named) with default update peri...
Definition: Structs.h:229
String ^ ToString() override
Serializes this DataRequest to a string for debugging purposes.
Definition: Structs.h:290
DataRequest(UInt32 requestId, CalcResultType resultType, String ^ calculatorCode)
Constructs a calculator code request (requestType = RequestType::Calculated) with default update peri...
Definition: Structs.h:263
DataRequest(UInt32 requestId, Char variableType, String ^ variableName, UInt32 valueSize, UpdatePeriod period, UInt32 interval, float deltaEpsilon)
Constructs a request for a named variable (requestType = RequestType::Named) with given update period...
Definition: Structs.h:234
void setUnitName(String ^ unitName)
Set the unitName member using a string type value.
Definition: Structs.h:284
DataRequest(UInt32 requestId, CalcResultType resultType, String ^ calculatorCode, UInt32 valueSize)
Constructs a calculator code request (requestType = RequestType::Calculated) with default update peri...
Definition: Structs.h:249
void setNameOrCode(String ^ nameOrCode)
Set the nameOrCode member using a string type value.
Definition: Structs.h:278
DataRequest(UInt32 requestId, CalcResultType resultType, String ^ calculatorCode, UInt32 valueSize, UpdatePeriod period, UInt32 interval, float deltaEpsilon)
Constructs a calculator code request (requestType = RequestType::Calculated) with given update period...
Definition: Structs.h:254
DataRequest()
Default constructor. Properties must be set to valid values, either later or inline,...
Definition: Structs.h:227
DataRequest(UInt32 requestId, String ^ simVarName, String ^ unitName, Byte simVarIndex, UInt32 valueSize, UpdatePeriod period, UInt32 interval, float deltaEpsilon)
Constructs a request for a named Simulator Variable (requestType = RequestType::Named and ‘varTypePre...
Definition: Structs.h:244
DataRequest(UInt32 requestId, String ^ simVarName, String ^ unitName, Byte simVarIndex, UInt32 valueSize)
Constructs a request for a named Simulator Variable (requestType = RequestType::Named and ‘varTypePre...
Definition: Structs.h:239
DataRequestRecord inherits and extends WASimCommander::CLI::Structs::DataRequest with data pertinent ...
Definition: Structs.h:346
array< Byte > ^ data
Value data array.
Definition: Structs.h:349
bool tryConvert([Out] T % result)
Tries to populate a value reference of the desired type T and returns true or false depending on if t...
Definition: Structs.h:360
time_t lastUpdate
Timestamp of last data update in ms since epoch.
Definition: Structs.h:348
String ^ ToString() override
Serializes this DataRequestRecord to string for debugging purposes.
Definition: Structs.h:412
bool tryConvert([Out] String ^ % result)
Overload for String type results. This will simply load whatever bytes are in the data array into a S...
Definition: Structs.h:374
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
VariableRequest(Char variableType, int variableId, int unitId)
Construct a variable request for specified variable type ('A', 'L', etc), numeric variable ID,...
Definition: Structs.h:549
VariableRequest(String ^ localVariableName)
Construct a variable request a Local variable ('L') with the specified name.
Definition: Structs.h:558
VariableRequest(String ^ simVariableName, String ^ unitName, Byte simVarIndex)
Construct a variable request for a Simulator variable ('A') with given name, named unit specifier,...
Definition: Structs.h:552
VariableRequest(int localVariableId)
Construct a variable request a Local variable ('L') with the specified numeric ID.
Definition: Structs.h:569
VariableRequest(Char variableType, int variableId)
Construct a variable request for specified variable type ('A', 'L', etc) and numeric variable ID.
Definition: Structs.h:543
VariableRequest(int simVariableId, int unitId, Byte simVarIndex)
Construct a variable request for a Simulator variable ('A') with given variable ID,...
Definition: Structs.h:555
VariableRequest(Char variableType, String ^ variableName)
Construct a variable request for specified variable type ('A', 'L', etc) and variable name.
Definition: Structs.h:540
VariableRequest(String ^ localVariableName, bool createVariable)
Construct a variable request for a Local ('L') variable with the specified name.
Definition: Structs.h:562
VariableRequest(Char variableType, String ^ variableName, String ^ unitName)
Construct a variable request for specified variable type ('A', 'L', etc), variable name,...
Definition: Structs.h:546
VariableRequest(String ^ localVariableName, bool createVariable, String ^ unitName)
Construct a variable request for a Local ('L') variable with the specified name.
Definition: Structs.h:566
DataRequestRecord inherits and extends WASimCommander::DataRequest with data pertinent for use by a d...
Definition: structs.h:70
std::vector< uint8_t > data
Value data array.
Definition: structs.h:72
Structure to hold data for registered (reusable) calculator events. Used to submit events with WASimC...
Definition: structs.h:150
std::string name
Optional custom name for this event. The name is for use with SimConnect_MapClientEventToSimEvent(id,...
Definition: structs.h:154
std::string code
The calculator code string to execute as the event action. The code is pre-compiled and stored on the...
Definition: structs.h:152
uint32_t eventId
A unique ID for this event. The ID can later be used to modify, trigger, or remove this event.
Definition: structs.h:151
Structure for using with WASimClient::getVariable() and WASimClient::setVariable() to specify informa...
Definition: structs.h:110
Command data structure. The member contents depend on the command type as described in each command t...
Structure for variable value subscription requests.
Log record structure.