1
1
/*
2
- * commander.cpp
2
+ * Created on June 18 2020
3
3
*
4
- * Created on: Feb 5, 2022
5
- * Author: dani0
6
- */
4
+ * Copyright (c) 2020 - Daniel Hajnal
5
+
6
+ * This file is part of the Commander-API project.
7
+ * Modified 2022.02.06
8
+ */
7
9
8
10
#include " commander.hpp"
9
11
10
12
11
13
void Commander::attachTreeFunction ( API_t *API_tree_p, uint32_t API_tree_size_p ){
12
14
15
+ // Save parameters to internal variables.
13
16
API_tree = API_tree_p;
14
17
API_tree_size = API_tree_size_p;
15
18
16
19
}
17
20
18
- void Commander::attachDebugPort ( Serial *debugPort_p ){
19
-
20
- debugPort = debugPort_p;
21
-
22
- }
23
-
24
21
void Commander::init (){
25
22
23
+ // Generic conter variables.
26
24
uint32_t i;
27
25
uint32_t j;
28
26
27
+ // Temporary variable, used to flip elements.
29
28
API_t temp;
30
29
31
- if ( debugPort ){
32
-
33
- debugPort -> println ( " Rendezes elott:" );
34
- for ( i = 0 ; i < API_tree_size; i++ ){
35
-
36
- debugPort -> printf ( " %d. %s\r\n " , i, API_tree[ i ].name );
37
-
38
- }
39
- debugPort -> println ();
40
-
41
- }
42
-
43
- // Nev szerint sorba rendezzuk a parancsokat.
30
+ // Make the tree ordered by alphabet.
44
31
for ( i = 0 ; i < API_tree_size; i++ ){
45
32
46
33
for ( j = i + 1 ; j < API_tree_size; j++ ){
47
34
48
- // if( API_tree[ i ] > API_tree[ j ] ){
49
35
if ( strcmp ( API_tree[ i ].name , API_tree[ j ].name ) > 0 ){
50
36
51
37
temp = API_tree[ i ];
@@ -58,40 +44,18 @@ void Commander::init(){
58
44
59
45
}
60
46
61
- if ( debugPort ){
62
-
63
- debugPort -> println ( " Rendezes utan:" );
64
- for ( i = 0 ; i < API_tree_size; i++ ){
65
-
66
- debugPort -> printf ( " %d. %s\r\n " , i, API_tree[ i ].name );
67
-
68
- }
69
- debugPort -> println ();
70
-
71
- }
72
-
73
- // Elmentjuk a nevsorrend szerinti helyet a place valtozoba.
47
+ // Fill the place variable in the tree with
48
+ // correct alphabetical place.
74
49
for ( i = 0 ; i < API_tree_size; i++ ){
75
50
76
51
API_tree[ i ].place = i;
77
52
78
53
}
79
54
80
- // Optimalizaljuk a sorrendet.
81
- optimise_api_tree ();
82
-
83
- if ( debugPort ){
84
-
85
- debugPort -> println ( " Optimalizalas utan:" );
86
- for ( i = 0 ; i < API_tree_size; i++ ){
87
-
88
- debugPort -> printf ( " %d. %s\r\n " , i, API_tree[ i ].name );
89
-
90
- }
91
- debugPort -> println ();
92
-
93
- }
94
-
55
+ // Optimize the tree to make it balanced.
56
+ // It is necessary to speed up the command
57
+ // search phase.
58
+ optimize_api_tree ();
95
59
96
60
}
97
61
@@ -113,14 +77,13 @@ uint16_t Commander::find_api_index_by_place( uint16_t place ){
113
77
114
78
}
115
79
116
- // else return 0
117
80
return 0 ;
118
81
119
82
}
120
83
121
84
void Commander::swap_api_elements ( uint16_t index, uint16_t place ){
122
85
123
- // Buffer that will temporarly hold an element.
86
+ // Buffer that will temporary hold an element.
124
87
// This is required for a swap.
125
88
API_t buffer;
126
89
@@ -141,7 +104,7 @@ void Commander::swap_api_elements( uint16_t index, uint16_t place ){
141
104
142
105
}
143
106
144
- void Commander::optimise_api_tree (){
107
+ void Commander::optimize_api_tree (){
145
108
146
109
uint32_t i;
147
110
@@ -153,19 +116,19 @@ void Commander::optimise_api_tree(){
153
116
// Stores the previous elements address in the tree
154
117
API_t *prev;
155
118
156
- // It will store string compersation result
119
+ // It will store string comparison result
157
120
int32_t comp_res;
158
121
159
- // recursive optimiser need to initialise 'API_cntr' to 0
122
+ // recursive optimizer need to initialize elementCounter to 0
160
123
elementCounter = 0 ;
161
124
162
125
// recursively finds the order which is optimal for a balanced tree
163
- recursive_optimiser ( 0 , API_tree_size - 1 );
126
+ recursive_optimizer ( 0 , API_tree_size - 1 );
164
127
165
128
// The order is good, but the connection between the branches broken,
166
129
// because we swapped the API_tree array elements.
167
- // To fix this problem we have to reinitialise the tree, and use
168
- // 'add_interpreter_command' function again for all elements .
130
+ // To fix this problem we have to add elements from index 1 and
131
+ // place them in the binary tree .
169
132
for ( i = 1 ; i < API_tree_size; i++ ){
170
133
171
134
prev = &API_tree[ 0 ];
@@ -187,37 +150,36 @@ void Commander::optimise_api_tree(){
187
150
188
151
}
189
152
190
- // This function is used to order the elements in API_tree array to
191
- // get the fastest search speed
192
- // this function needs 'API_cntr' to be zeroed out before the first call
193
- void Commander::recursive_optimiser ( int32_t start_index, int32_t stop_index ){
153
+ void Commander::recursive_optimizer ( int32_t start_index, int32_t stop_index ){
194
154
195
- int32_t mid;
155
+ // The middle number between start and stop index
156
+ // will be stored in this variable.
157
+ int32_t mid;
196
158
197
- // End of recursive algorythm
198
- if ( start_index > stop_index ){
159
+ // Detect the end of recursion.
160
+ if ( start_index > stop_index ){
199
161
200
- return ;
162
+ return ;
201
163
202
- }
164
+ }
203
165
204
- // Find the middle of the intervall
205
- mid = ( start_index + stop_index ) / 2 ;
166
+ // Find the middle of the interval
167
+ mid = ( start_index + stop_index ) / 2 ;
206
168
207
- // Put the right element to it's place
208
- swap_api_elements ( elementCounter, mid );
209
- elementCounter++;
169
+ // Put the right element to it's place
170
+ swap_api_elements ( elementCounter, mid );
171
+ elementCounter++;
210
172
211
- // Do some recursion for the other intervalls
212
- recursive_optimiser ( start_index, mid - 1 );
213
- recursive_optimiser ( mid + 1 , stop_index );
173
+ // Do some recursion for the other intervals
174
+ recursive_optimizer ( start_index, mid - 1 );
175
+ recursive_optimizer ( mid + 1 , stop_index );
214
176
215
177
216
178
}
217
179
218
180
void Commander::executeCommand ( char *cmd ){
219
181
220
- // The begining of the argument list will be stored in this pointer
182
+ // The beginning of the argument list will be stored in this pointer
221
183
char *arg;
222
184
223
185
// This variable tracks the command name length
@@ -227,8 +189,13 @@ void Commander::executeCommand( char *cmd ){
227
189
// and the commands function won't be called.
228
190
uint8_t show_description = 0 ;
229
191
192
+ // Pointer to the selected command data.
230
193
API_t *commandData_ptr;
231
194
195
+ // Copy the command data to the internal buffer.
196
+ // It is necessary because we have to modify the content
197
+ // of it. If it is points to a const char array we will
198
+ // get a bus-fault error without a buffer.
232
199
strncpy ( tempBuff, cmd, COMMANDER_MAX_COMMAND_SIZE );
233
200
234
201
@@ -240,7 +207,7 @@ void Commander::executeCommand( char *cmd ){
240
207
// Reset the name counter before we start counting
241
208
cmd_name_cntr = 0 ;
242
209
243
- // Find the first space character or a string-end character.
210
+ // Find the first space, question mark or a string-end character.
244
211
// At this time count how long is the command name( in characters )
245
212
while ( ( *arg != ' \0 ' ) && ( *arg != ' ' ) && ( *arg != ' ?' ) ){
246
213
@@ -252,14 +219,6 @@ void Commander::executeCommand( char *cmd ){
252
219
// If a space character found we have to terminate the string there.
253
220
// It is important because strcmp function will search for string terminator
254
221
// character, and this way we can separate the command name from its arguments.
255
- // This method has a downside. If we pass a const char as command
256
- // to the execution function it will try to overwrite a character in it.
257
- // It is impossible if the input string is constant and it will result hard fault!
258
- // To prevent this we nead a buffer. This is why INTERPRETER_BUFFER_SIZE macro has
259
- // been created. If you want to pass const chars to your interpreter directly, you
260
- // have to define INTERPRETER_BUFFER_SIZE with a resonable size.
261
- // But if you can prove it, that there is no chace in your program to use const chars,
262
- // you can comment out INTERPRETER_BUFFER_SIZE macro. This can save some space in your RAM.
263
222
if ( *arg == ' ' ){
264
223
265
224
*arg = ' \0 ' ;
@@ -277,9 +236,10 @@ void Commander::executeCommand( char *cmd ){
277
236
278
237
}
279
238
280
- // Megnézzük, hogy a parancs létezik-e .
239
+ // Try to find the command datata .
281
240
commandData_ptr = (*this )[ tempBuff ];
282
241
242
+ // If it is not a NULL pointer, that means we have a mtach.
283
243
if ( commandData_ptr ){
284
244
285
245
// Because we have found the command in the API tree we have to choose
@@ -288,7 +248,6 @@ void Commander::executeCommand( char *cmd ){
288
248
if ( show_description ){
289
249
290
250
// Print the description text to the output channel.
291
-
292
251
response -> printf ( " %s: %s\r\n " , commandData_ptr -> name, commandData_ptr -> desc );
293
252
294
253
@@ -316,22 +275,69 @@ void Commander::executeCommand( char *cmd ){
316
275
317
276
void Commander::execute ( char *cmd ){
318
277
278
+ // Default execute handler, so the default response will be chosen.
319
279
response = &defaultResponse;
280
+
281
+ // Execute the command.
320
282
executeCommand ( cmd );
321
283
322
284
}
323
285
286
+ #ifdef COMMANDER_USE_SERIAL_RESPONSE
287
+
324
288
void Commander::execute ( char *cmd, Serial *resp ){
325
289
326
- serialResponse. select ( resp );
290
+ // Serial execute handler, so the Serial response will be chosen.
327
291
response = &serialResponse;
292
+
293
+ // Select the right Serial object in the response class.
294
+ serialResponse.select ( resp );
295
+
296
+ // Execute the command.
328
297
executeCommand ( cmd );
329
298
330
299
}
331
300
301
+ #endif
302
+
303
+ #ifdef COMMANDER_USE_ARDUINO_SERIAL_RESPONSE
304
+
305
+ void Commander::execute ( char *cmd, HardwareSerial *resp ){
306
+
307
+ // Arduino Serial execute handler, so the Arduino Serial response will be chosen.
308
+ response = &arduinoSerialResponse;
309
+
310
+ // Select the right HardwareSerial object in the response class.
311
+ arduinoSerialResponse.select ( resp );
312
+
313
+ // Execute the command.
314
+ executeCommand ( cmd );
315
+
316
+ }
317
+
318
+ #endif
319
+
320
+ #ifdef COMMANDER_USE_WIFI_CLIENT_RESPONSE
321
+
322
+ void Commander::execute ( char *cmd, WiFiClient *resp ){
323
+
324
+ // Arduino Serial execute handler, so the Arduino Serial response will be chosen.
325
+ response = &WiFiClientResponse;
326
+
327
+ // Select the right HardwareSerial object in the response class.
328
+ WiFiClientResponse.select ( resp );
329
+
330
+ // Execute the command.
331
+ executeCommand ( cmd );
332
+
333
+ }
334
+
335
+ #endif
336
+
332
337
Commander::API_t* Commander::operator [] ( int i ){
333
338
334
- if ( i < 0 ){
339
+ // Detect wrong addressing.
340
+ if ( ( i < 0 ) || ( i >= (int )API_tree_size ) ){
335
341
336
342
return NULL ;
337
343
@@ -376,6 +382,7 @@ Commander::API_t* Commander::operator [] ( char* name ){
376
382
377
383
}
378
384
385
+ // If we did not found the command we return NULL.
379
386
return NULL ;
380
387
381
388
}
@@ -385,4 +392,3 @@ Commander::API_t* Commander::operator [] ( const char* name ){
385
392
return (*this )[ (char *)name ];
386
393
387
394
}
388
-
0 commit comments