API Documentation
Loading...
Searching...
No Matches
HardwareCommandQueue.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Hardware
28File: HardwareCommandQueue
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "DLLInfo.h"
34#include <NDEVR/BaseValues.h>
35#include <NDEVR/String.h>
36#include <NDEVR/Dictionary.h>
37#include <NDEVR/RWLock.h>
38#include <NDEVR/Time.h>
39#include <NDEVR/TimeSpan.h>
40#include <NDEVR/Thread.h>
41#include <NDEVR/JSONNode.h>
42#include <NDEVR/ProgressInfo.h>
43#include <NDEVR/LogMessage.h>
44#include <NDEVR/Exception.h>
45namespace NDEVR
46{
47 enum class CommandSupport
48 {
52 };
53
70 template<class t_type>
72 {
73 public:
75 {
76 t_type command = t_type(0);
79 void clear()
80 {
81 command = t_type(0);
82 args.clear();
83 regex.clear();
84 }
85 };
92 bool hasPendingCommand(t_type command) const
93 {
94 return m_pending_commands.hasKey(command);
95 }
96 static const uint04 s_buffer_size = 256000;
97 void postCommand(t_type command, const String& args = String(), const String& regex = String())
98 {
100 if (allowMultipleCommandsInStream(command, args) || !m_pending_commands.hasKey(command))
101 {
102 m_ordered_commands.add({ command, args, regex });
103 if (!m_pending_commands.hasKey(command))
104 m_pending_commands[command] = 0;
105 m_pending_commands[command]++;
106 }
107 else
108 {
109 for (uint04 i = 0; i < m_ordered_commands.size(); i++)
110 {
111 if (m_ordered_commands[i].command == command)
112 {
113 m_ordered_commands[i].args = args;
114 m_ordered_commands[i].regex = regex;
115 }
116 }
117 }
118 }
119 void removeCommand(t_type command)
120 {
122 if (m_pending_commands.hasKey(command))
123 {
124 for (uint04 i = m_ordered_commands.size() - 1; !IsInvalid(i); i--)
125 {
126 if (m_ordered_commands[i].command == command)
127 {
128 m_ordered_commands.removeIndex(i);
129 }
130 }
131 m_pending_commands.erase(command);
132 }
133 }
134 void addCommandToFront(t_type command, const String& args = String(), const String& regex = String())
135 {
137 if (allowMultipleCommandsInStream(command, args) || !m_pending_commands.hasKey(command))
138 {
139 m_ordered_commands.add(0, { command, args, regex });
140 if (!m_pending_commands.hasKey(command))
141 m_pending_commands[command] = 0;
142 m_pending_commands[command]++;
143 }
144 else
145 {
146 for (uint04 i = 0; i < m_ordered_commands.size(); i++)
147 {
148 if (m_ordered_commands[i].command == command)
149 {
150 m_ordered_commands[i].args = args;
151 m_ordered_commands[i].regex = args;
152 if (i != 0)
153 m_ordered_commands.swapIndices(0, i);
154 }
155
156 }
157 }
158 }
159 virtual bool allowMultipleCommandsInStream(t_type command, const String& args) const
160 {
161 UNUSED(command);
162 UNUSED(args);
163 return false;
164 }
166 {
167 //WLock current_command_lock(&m_current_command);
168 if (m_current_command.command == t_type(0))
169 {
170 {
172 if (m_pending_block_command.command != t_type(0))
173 {
178 return true;
179 }
180 }
181 {
183 if (m_ordered_commands.size() > 0)
184 {
186 m_ordered_commands.removeIndex(0);
190 }
191 else
192 {
193 return false;
194 }
195 }
198 return true;
199 }
200 return false;
201 }
203 {
204 if (m_current_command.command != t_type(0))
205 {
206 //WLock lock(&m_current_command);
207 //if (m_current_command != t_type(0))
208 {
209 CommandRecord record;
211 record.end_time = Time::SystemTime();
213 m_records.add(record);
214 m_command_info[m_current_command.command].total_time += (record.end_time - record.start_time);
215 m_command_info[m_current_command.command].number_of_attempts++;
216#ifdef _DEBUG
217 m_command_info[m_current_command.command].average_time = m_command_info[m_current_command.command].total_time.elapsedSeconds() / m_command_info[m_current_command.command].number_of_attempts;
218#endif
221
222
223 }
224 }
225 }
226 virtual void retryCommand()
227 {
228 if (m_current_command.command != t_type(0))
229 {
230 const CommandQueueItem command = m_current_command;
232 addCommandToFront(command.command, command.args, command.regex);
233 }
234 }
235 virtual void cancelCommand()
236 {
237 if (m_current_command.command != t_type(0))
238 {
239 CommandRecord record;
241 record.end_time = Time::SystemTime();
243 m_records.add(record);
244 m_command_info[m_current_command.command].total_time += (record.end_time - record.start_time);
245 m_command_info[m_current_command.command].number_of_attempts++;
246#ifdef _DEBUG
247 m_command_info[m_current_command.command].average_time = m_command_info[m_current_command.command].total_time.elapsedSeconds() / m_command_info[m_current_command.command].number_of_attempts;
248#endif
251 }
252 }
253 virtual void onFailure(const t_type& command)
254 {
255 if (m_command_info[command].supports_command == CommandSupport::e_not_known)
256 m_command_info[command].supports_command = CommandSupport::e_not_supported;
257 m_command_info[command].number_of_failures++;
258 }
260 {
262 m_pending_commands.clear();
263 m_ordered_commands.clear();
264 WLock block_lock(&m_pending_block_command);
266 }
267 virtual void executeCommand(const t_type& command, const String& args) = 0;
268 void executeCommandBlocking(const t_type& command, const String& args = String())
269 {
270 bool finished = false;
271 for (;;)//wait to write pending command
272 {
273 {
274 WLock lock(&m_pending_block_command);//prevent new commands from being issued
275 if (m_pending_block_command.command == t_type(0))
276 {
279 finished = true;
280 }
281 }
282 if (finished)
283 break;
284 else
286 }
287 finished = false;
288 for (;;)//Wait for command to be executed
289 {
290 {
291 RLock lock(&m_pending_block_command);//prevent new commands from being issued
292 finished = m_pending_block_command.command != command;
293 }
294 if (finished)
295 break;
296 else
298 }
299 finished = false;
300 for (;;)//Wait for command execution to complete
301 {
302 {
303 //RLock lock(&m_current_command);//prevent new commands from being issued
304 finished = m_current_command.command != command;
305 }
306 if (finished)
307 break;
308 else
310 }
311 }
313 {
314 if (m_command_info.contains(command))
315 return m_command_info.get(command);
316 return CommandInformation();
317 }
318 virtual bool supportsCommand(t_type command) const
319 {
320 if (m_command_info.contains(command))
321 return m_command_info.get(command).supports_command != CommandSupport::e_not_supported;
322 return true;
323 }
324 void disableCommand(t_type command)
325 {
326 if (!m_command_info.contains(command))
327 {
328 m_command_info.add(command, CommandInformation());
329 }
330 for (uint04 i = 0; i < m_ordered_commands.size(); i++)
331 {
332 if (m_ordered_commands[i].command == command)
333 {
334 m_ordered_commands.removeIndex(i--);
335 m_pending_commands[command]--;
336 if (m_pending_commands[command] == 0)
337 m_pending_commands.erase(command);
338 }
339 }
340 m_command_info.get(command).supports_command = CommandSupport::e_not_supported;
341 }
342 void setSupport(t_type command, CommandSupport support)
343 {
344 m_command_info[command].supports_command = support;
345 }
346 void setSupported(t_type command, bool supported)
347 {
348 if (supported)
349 m_command_info[command].supports_command = CommandSupport::e_supported;
350 else
351 m_command_info[command].supports_command = CommandSupport::e_not_supported;
352 }
353 virtual void endCommandQueue()
354 {
355
356 }
358 {
360 return m_command_info.get(m_current_command.command).response_timeout;
361 return TimeSpan(0);
362 }
364 {
366 return m_command_info.get(m_current_command.command).tx_delay;
367 return TimeSpan(0);
368 }
370 {
372 return m_command_info.get(m_current_command.command).rx_delay;
373 return TimeSpan(0);
374 }
375 void setFromJSONInfo(const JSONNode& root, bool allow_command_override, ProgressInfo* log)
376 {
377 for (uint04 i = 0; i < Constant<uint04>::Invalid; i++)
378 {
379 t_type command = cast<t_type>(i);
381 if (display.size() == 0)
382 break;
383 try
384 {
386 if (m_command_info.contains(command))
387 {
388 info = m_command_info.get(command);
389 }
390 if (root.hasNode(display))
391 {
392 const JSONNode& node = root[display];
393 if (node.hasNode("Attempt Count"))
394 info.number_of_attempts = node["Attempt Count"].getAs<uint04>();
395 if (node.hasNode("Failure Count"))
396 info.number_of_failures = node["Failure Count"].getAs<uint04>();
397 if (node.hasNode("Total Response Time"))
398 info.total_time = TimeSpan(node["Total Response Time"].getAs<fltp08>());
399 if (allow_command_override)
400 {
401 if (node.hasNode("Supported"))
402 info.supports_command = node["Supported"].getAs<String>().getAs<CommandSupport>();
403 if (node.hasNode("Command"))
404 info.command = node["Command"].getAs<String>();
405 if (node.hasNode("Validation Regex"))
406 info.validation_regex = node["Validation Regex"].getAs<String>();
407 if (node.hasNode("Default Args"))
408 info.default_argument = node["Default Args"].getAs<String>();
409 if (node.hasNode("Transmission Delay"))
410 info.tx_delay = TimeSpan(node["Transmission Delay"].getAs<fltp08>());
411 if (node.hasNode("Receive Delay"))
412 info.rx_delay = TimeSpan(node["Receive Delay"].getAs<fltp08>());
413 if (node.hasNode("Response Timeout"))
414 info.response_timeout = TimeSpan(node["Response Timeout"].getAs<fltp08>());
415 }
416 }
417 m_command_info[command] = info;
418 }
419 catch (Exception& e)
420 {
421 if (log) log->addMessage(e.getMessage(), LogMessage::e_error);
422 }
423 }
424 }
425 JSONNode getCommandJSONInfo(bool only_supported) const
426 {
427 JSONNode root;
428 for (uint04 i = 0; i < Constant<uint04>::Invalid; i++)
429 {
430 t_type command = cast<t_type>(i);
431
433 if (display.size() == 0)
434 break;
436 if (m_command_info.contains(command))
437 {
438 info = m_command_info.get(command);
439 }
440 if (only_supported && info.supports_command == CommandSupport::e_not_supported)
441 continue;
442 JSONNode& node = root[display];
443 node["Command"] = info.command;
444 if (!only_supported)
445 node["Supported"] = String(info.supports_command);
446 node["Attempt Count"] = info.number_of_attempts;
447 node["Failure Count"] = info.number_of_failures;
448 node["Total Response Time"] = info.total_time.elapsedSeconds();
449 if (info.number_of_attempts > 0)
450 node["Average Response Time"] = info.total_time.elapsedSeconds() / info.number_of_attempts;
451 else
452 node["Average Response Time"] = 0;
453 node["Default Args"] = info.default_argument;
454 node["Transmission Delay"] = info.tx_delay;
455 node["Receive Delay"] = info.rx_delay;
456 node["Response Timeout"] = info.response_timeout;
457 node["Validation Regex"] = info.validation_regex;
458 }
459 return root;
460 }
461 String getCommandCSVInfo(bool only_supported, bool include_identity_info, char deliminator = ',') const
462 {
463 String del(deliminator);
464 String root;
465 root += "Command" + del;
466 if (!only_supported)
467 root += "Supported" + del;
468 root += "Attempt Count" + del;
469 root += "Failure Count" + del;
470 root += "Total Response Time" + del;
471 root += "Average Response Time" + del;
472 if (include_identity_info)
473 {
474 root += "Default Args" + del;
475 root += "Transmission Delay" + del;
476 root += "Receive Delay" + del;
477 root += "Response Timeout" + del;
478 root += "Validation Regex" + del;
479 }
480 for (uint04 i = 0; i < Constant<uint04>::Invalid; i++)
481 {
482 root.last() = '\n';
483 t_type command = cast<t_type>(i);
484
486 if (display.size() == 0)
487 break;
489 if (m_command_info.contains(command))
490 {
491 info = m_command_info.get(command);
492 }
493 if (only_supported && info.supports_command == CommandSupport::e_not_supported)
494 continue;
495 root += display + del;
496 if (!only_supported)
497 root += String(info.supports_command) + del;
498 root += String(info.number_of_attempts) + del;
499 root += String(info.number_of_failures) + del;
500 root += String(info.total_time.elapsedSeconds()) + del;
501 if (info.number_of_attempts > 0)
502 root += String(info.total_time.elapsedSeconds() / info.number_of_attempts) + del;
503 else
504 root += "0" + del;
505 if (include_identity_info)
506 {
507 root += info.default_argument + del;
508 root += String(info.tx_delay) + del;
509 root += String(info.rx_delay) + del;
510 root += String(info.response_timeout) + del;
511 root += info.validation_regex + del;
512 }
513 }
514 return root;
515 }
516 bool hasPending() const { return m_current_command.command != t_type(0) || m_pending_commands.size() > 0; };
517
518 t_type currentCommand() const { return m_current_command.command; }
519 const String& currentArgs() const { return m_current_command.args; }
520 const String& currentRegex() const { return m_current_command.regex; }
522 void setBufferOffset(uint04 buffer_offset) { m_buffer_offset = buffer_offset; }
523 protected:
532 };
534}
#define UNUSED(expr)
Definition BaseValues.hpp:406
#define HARDWARE_API
Definition DLLInfo.h:74
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:59
constexpr t_index_type size() const
Definition Buffer.hpp:1374
decltype(auto) last()
Definition Buffer.hpp:930
void clear()
Definition Buffer.hpp:557
A hash-based key-value store, useful for quick associative lookups.
Definition Dictionary.h:59
bool hasKey(const t_key &key) const
Definition Dictionary.h:64
uint04 size() const
Definition Dictionary.h:142
Definition Exception.hpp:52
virtual TranslatedString getMessage() const
Definition Exception.hpp:123
Definition HardwareCommandQueue.h:72
JSONNode getCommandJSONInfo(bool only_supported) const
Definition HardwareCommandQueue.h:425
CommandInformation commandInformation(t_type command)
Definition HardwareCommandQueue.h:312
CommandQueueItem m_pending_block_command
Definition HardwareCommandQueue.h:530
CommandQueueItem m_current_command
Definition HardwareCommandQueue.h:529
TimeSpan commandTimeout() const
Definition HardwareCommandQueue.h:357
void finishCommand()
Definition HardwareCommandQueue.h:202
void removeCommand(t_type command)
Definition HardwareCommandQueue.h:119
void disableCommand(t_type command)
Definition HardwareCommandQueue.h:324
Time m_current_command_start_time
Definition HardwareCommandQueue.h:528
virtual bool allowMultipleCommandsInStream(t_type command, const String &args) const
Definition HardwareCommandQueue.h:159
virtual bool supportsCommand(t_type command) const
Definition HardwareCommandQueue.h:318
void setFromJSONInfo(const JSONNode &root, bool allow_command_override, ProgressInfo *log)
Definition HardwareCommandQueue.h:375
bool popCommandAndExecute()
Definition HardwareCommandQueue.h:165
virtual void cancelCommand()
Definition HardwareCommandQueue.h:235
virtual void retryCommand()
Definition HardwareCommandQueue.h:226
uint04 bufferOffset() const
Definition HardwareCommandQueue.h:521
bool hasPendingCommand(t_type command) const
Definition HardwareCommandQueue.h:92
void executeCommandBlocking(const t_type &command, const String &args=String())
Definition HardwareCommandQueue.h:268
bool hasPending() const
Definition HardwareCommandQueue.h:516
uint04 m_buffer_offset
Definition HardwareCommandQueue.h:531
void postCommand(t_type command, const String &args=String(), const String &regex=String())
Definition HardwareCommandQueue.h:97
Dictionary< t_type, uint04 > m_pending_commands
Definition HardwareCommandQueue.h:525
const String & currentRegex() const
Definition HardwareCommandQueue.h:520
t_type currentCommand() const
Definition HardwareCommandQueue.h:518
void addCommandToFront(t_type command, const String &args=String(), const String &regex=String())
Definition HardwareCommandQueue.h:134
Buffer< CommandRecord > m_records
Definition HardwareCommandQueue.h:527
virtual void executeCommand(const t_type &command, const String &args)=0
TimeSpan rxDelay() const
Definition HardwareCommandQueue.h:369
virtual void endCommandQueue()
Definition HardwareCommandQueue.h:353
String getCommandCSVInfo(bool only_supported, bool include_identity_info, char deliminator=',') const
Definition HardwareCommandQueue.h:461
Dictionary< t_type, CommandInformation > m_command_info
Definition HardwareCommandQueue.h:524
void clearCommands()
Definition HardwareCommandQueue.h:259
void setSupported(t_type command, bool supported)
Definition HardwareCommandQueue.h:346
Buffer< CommandQueueItem > m_ordered_commands
Definition HardwareCommandQueue.h:526
virtual void onFailure(const t_type &command)
Definition HardwareCommandQueue.h:253
void setBufferOffset(uint04 buffer_offset)
Definition HardwareCommandQueue.h:522
void setSupport(t_type command, CommandSupport support)
Definition HardwareCommandQueue.h:342
static const uint04 s_buffer_size
Definition HardwareCommandQueue.h:96
TimeSpan txDelay() const
Definition HardwareCommandQueue.h:363
const String & currentArgs() const
Definition HardwareCommandQueue.h:519
JavaScript Object Notation or JSON is an open - standard file format that uses human - readable text ...
Definition JSONParser.h:60
decltype(auto) getAs() const
Definition JSONParser.h:201
bool hasNode(const String &child_node) const
Definition JSONParser.h:249
@ e_error
Definition LogMessage.h:53
A light-weight base class for Log that allows processes to update, without the need for.
Definition ProgressInfo.hpp:48
virtual bool addMessage(const LogMessage &message)=0
Used to lock a particular variable for reading. Any number of readers can be created when no write lo...
Definition RWLock.h:91
The core String class for the software.
Definition String.h:47
static TranslatedString DisplayString(const t_type &value)
Definition TranslatedString.h:54
Logic for reading or writing to a string or a user friendly, TranslatedString.
Definition StringStream.h:118
static void RequestSleep(const TimeSpan &interval)
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:54
static NDEVR_BASE_API Time SystemTime()
Retrieves the current system time.
Stores a time span, or difference between two times, with an optional start time.
Definition TimeSpan.h:46
constexpr fltp08 elapsedSeconds() const
Definition TimeSpan.h:111
NDEVR_BASE_API const String & englishTranslation() const
Used to lock a particular variable for writing. Only one write lock can be created when no read locks...
Definition RWLock.h:115
Definition ACIColor.h:37
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:177
float fltp04
Defines an alias representing a 4 byte floating-point number.
Definition BaseValues.hpp:125
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:94
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:379
CommandSupport
Definition HardwareCommandQueue.h:48
Definition HardwareCommandQueue.h:55
TimeSpan response_timeout
Definition HardwareCommandQueue.h:67
uint04 number_of_failures
Definition HardwareCommandQueue.h:64
CommandSupport supports_command
Definition HardwareCommandQueue.h:68
TimeSpan tx_delay
Definition HardwareCommandQueue.h:65
uint04 number_of_attempts
Definition HardwareCommandQueue.h:63
String default_argument
Definition HardwareCommandQueue.h:58
String validation_regex
Definition HardwareCommandQueue.h:57
TimeSpan total_time
Definition HardwareCommandQueue.h:59
String command
Definition HardwareCommandQueue.h:56
TimeSpan rx_delay
Definition HardwareCommandQueue.h:66
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved.
Definition BaseValues.hpp:230
Definition HardwareCommandQueue.h:75
t_type command
Definition HardwareCommandQueue.h:76
String regex
Definition HardwareCommandQueue.h:78
String args
Definition HardwareCommandQueue.h:77
void clear()
Definition HardwareCommandQueue.h:79
Definition HardwareCommandQueue.h:87
t_type command
Definition HardwareCommandQueue.h:90
Time start_time
Definition HardwareCommandQueue.h:88
Time end_time
Definition HardwareCommandQueue.h:89