|
1 |
| -# Commander API |
2 |
| -**Version V0.2A** |
| 1 | +@mainpage Commander-API library |
| 2 | +**Version V2.0.0** |
3 | 3 |
|
4 |
| -Commander-API is a simple to use interpreter library and you can easily use it to process character based commands and link them to a specified function. It is designed mainly to work with low memory capacity devices, for example, __small ARM or AVR devices or some embedded stuff__. The library shows an Arduino implementation and it can be found in the Arduino folder in the repository. The source files are located in the src folder. |
| 4 | +Commander-API is a simple to use parser library and you can easily use it to process character based commands and link them to a specified function. It is designed mainly to work with low memory capacity devices, for example, __small ARM or AVR processors__. |
5 | 5 |
|
6 |
| -# Doxygen documentation |
| 6 | +## Changes in V2 |
7 | 7 |
|
8 |
| -The project has a Doxygen generated documentation. It can be found in Doc/html/index.html. |
9 |
| -The theme that used with the documentation can be found [here](https://jothepro.github.io/doxygen-awesome-css/) |
| 8 | +Version 2.X is a more refined version of the original Commander-API. The original was working well, but it was a bit flimsy when you had to work with a huge API list. |
| 9 | +It halso caused Hardfault when the API tree was not created correctly. Besides that if you wanted to add a new command, you had to change the header and the source |
| 10 | +file as well. The biggest problem was, that it was a C-API, so no overloading, no C++ magic. |
10 | 11 |
|
11 |
| -# Arduino installation |
12 |
| - |
13 |
| -__1.__ |
14 |
| - |
15 |
| -Download this library as a .zip, or clone it. |
16 |
| - |
17 |
| -__2.__ |
18 |
| - |
19 |
| -Create a new sketch in Arduino IDE and open its folder. |
20 |
| - |
21 |
| -__3.__ |
22 |
| - |
23 |
| - |
24 |
| -Now copy interpreter.c and interpreter.h files from src folder in this repository, to your sketch folder. |
25 |
| - |
26 |
| -__4.__ |
27 |
| - |
28 |
| -Because Arduino uses C++ not C, you have to rename the interpreter.c file to interpreter.cpp, |
29 |
| -and the interpreter.h file to interpreter.hpp. My recommendation is to use a text editor for |
30 |
| -this step like [Atom](https://atom.io/) or [Notepad++](https://notepad-plus-plus.org/downloads/). |
31 |
| - |
32 |
| -__5.__ |
33 |
| - |
34 |
| -If Arduino IDE is opened __save all your work,__ then restart Arduino IDE. |
35 |
| - |
36 |
| -__6.__ |
37 |
| - |
38 |
| - |
39 |
| -Now you should see the interpreter.cpp and interpreter.hpp files on the top bar. |
40 |
| -Than you just include interpreter.hpp as usual. |
41 |
| - |
42 |
| -Congratulations you successfully added the library to your sketch. |
43 |
| - |
44 |
| -# Usage with Arduino |
45 |
| - |
46 |
| -**Basic example** |
47 |
| - |
48 |
| -__1.__ |
49 |
| - |
50 |
| -The first thing you have to do is to add the library files to your project. |
51 |
| -It is discussed in the Arduino installation page how to do. |
52 |
| - |
53 |
| -__2.__ |
54 |
| - |
55 |
| -The next thing you have to do is to include the library at the beginning of your program. |
56 |
| - |
57 |
| -Code: |
58 |
| -``` |
59 |
| -#include "interpreter.hpp" |
60 |
| -``` |
61 |
| - |
62 |
| -__3.__ |
63 |
| - |
64 |
| -Now, you have to create at leas 3 commands, and add them to the interpreter. To do that, first you have to open |
65 |
| -the interpreter.cpp file. Locate the next comment: |
66 |
| - |
67 |
| -``` |
68 |
| -// +---- Create instruction data for the API ----+ |
69 |
| -// | | |
70 |
| -// | This is where you have to add | |
71 |
| -// | your commands! | |
72 |
| -// | | |
73 |
| -// +-----------------------------------------------+ |
74 |
| -``` |
75 |
| - |
76 |
| -By default in the code, there are 4 commands created as an example, below this comment. |
77 |
| - |
78 |
| -``` |
79 |
| -create_command_data(stop, "This command can be used to stop something.\r\nargs:\td - generic number\r\n\tc - someting else"); |
80 |
| -create_command_data(start, "This command can be used to start something.\r\nargs:\td - generic number\r\n\tc - someting else"); |
81 |
| -create_command_data(left, "This command can be used to make someting turn left.\r\nargs:\td - generic number\r\n\tc - someting else"); |
82 |
| -create_command_data(right, "This command can be used to make someting turn right.\r\nargs:\td - generic number\r\n\tc - someting else"); |
83 |
| -``` |
84 |
| - |
85 |
| -You can modify these of course. How you can create a new one is shown in the next step. |
86 |
| - |
87 |
| -__4.__ |
88 |
| - |
89 |
| -If you want to create a new command, firstly you have to create its data. To do that you have to use create_command_data macro. |
90 |
| -The syntax is: |
91 |
| - |
92 |
| -``` |
93 |
| -create_command_data( name_of_the_command, description_of_this_command ); |
94 |
| -``` |
95 |
| - |
96 |
| -Example: |
97 |
| -``` |
98 |
| -create_command_data( reset, "description of reset command" ); |
99 |
| -``` |
100 |
| - |
101 |
| -__Note that the name of the command should not have " characters before and after like a regular string!__ |
102 |
| -The name also can't start with a number, and you can't use any special characters in it like: ?!,:-...etc.. |
103 |
| - |
104 |
| -__5.__ |
105 |
| - |
106 |
| -In step 3, and 4 you only created the data for the commands. In this step you have to add these data to the interpreter. |
107 |
| -To do that you have to find the following text int the implementation of init_interpreter function: |
108 |
| - |
109 |
| -``` |
110 |
| -// +---- Match instruction to it's function ----+ |
111 |
| -// | | |
112 |
| -// | This is where you have to match | |
113 |
| -// | every instruction name to it's | |
114 |
| -// | function. | |
115 |
| -// | | |
116 |
| -// +-----------------------------------------------+ |
117 |
| -``` |
118 |
| - |
119 |
| -By default in the code, there are 4 commands added as an example, below this comment. |
120 |
| - |
121 |
| -``` |
122 |
| -add_command(stop, stop_func); |
123 |
| -add_command(start, start_func); |
124 |
| -add_command(left, left_func); |
125 |
| -add_command(right, right_func); |
126 |
| -``` |
127 |
| - |
128 |
| -You can modify these of course. How you can create a new one is shown in the next step. |
129 |
| - |
130 |
| -__6.__ |
131 |
| - |
132 |
| -To add the created data to the interpreter you have to use add_command macro. |
133 |
| -The syntax is: |
134 |
| -``` |
135 |
| -add_command( name_of_the_command, function_for_this_command ); |
136 |
| -``` |
137 |
| - |
138 |
| -Example: |
139 |
| -``` |
140 |
| -add_command( reset, reset_func ); |
141 |
| -``` |
142 |
| - |
143 |
| -__Not that the name of the command has to match exactly with the name in step 3 and 4!__ |
144 |
| - |
145 |
| -__7.__ |
146 |
| - |
147 |
| -Now you have to create the function that will be executed when the command arrives to the interpreter. |
148 |
| -The name of this function has to be exactly the same as the function name( 2nd argument ) in step 5, and 6. |
149 |
| - |
150 |
| -Example: |
151 |
| -``` |
152 |
| -// This is an example function for the reset command |
153 |
| -void reset_func(char *args, int(*resp_fn)(const char*, ...)) |
154 |
| -{ |
155 |
| -
|
156 |
| - int test_arg1; |
157 |
| - int test_arg2; |
158 |
| - int arg_read_result; |
159 |
| -
|
160 |
| - Serial.println( "Reset function called" ); |
161 |
| -
|
162 |
| - // Do the actual code somewhere here. |
163 |
| -
|
164 |
| - // If you want to use the response channel, |
165 |
| - // This is how to do it correctly. |
166 |
| - // Always check the response function channel! |
167 |
| - // If it's a NULL pointer you can't use it, |
168 |
| - // because it will crash your porgram! |
169 |
| - if( resp_fn != NULL ){ |
170 |
| -
|
171 |
| - resp_fn( "Wow! Magic!!!!\r\n" ); |
172 |
| -
|
173 |
| - } |
174 |
| -
|
175 |
| - // If you have arguments you have to process it like a sscanf |
176 |
| - arg_read_result = sscanf( args, "%d %d", test_arg1, test_arg2 ); |
177 |
| -
|
178 |
| - // You should check that if the argument read was successfully |
179 |
| - // sscanf should return exactly the same number as how many arguments |
180 |
| - // you have added. |
181 |
| - if( arg_read_result == 2 ){ |
182 |
| -
|
183 |
| - // Arguments processed, no error. |
184 |
| -
|
185 |
| - } |
186 |
| -
|
187 |
| - else{ |
188 |
| -
|
189 |
| - // Some of the arguments has an error. |
190 |
| - // Maybe a Type-O. |
191 |
| -
|
192 |
| - } |
193 |
| -
|
194 |
| -} |
195 |
| -``` |
196 |
| - |
197 |
| -The example above is quite complex, but it shows all of the futures that a command function has. |
198 |
| -You don't have to use all of it if you doesn't need that specific function. |
199 |
| -The only restriction is that the function type has to be the same. |
200 |
| - |
201 |
| -You can write these functions driectly in interpreter.cpp file, or you can create a header and |
202 |
| -an implementation file for your command functions and include that in interpreter.hpp. |
203 |
| - |
204 |
| -Example: |
205 |
| -``` |
206 |
| -void name_of_the_function(char *args, int(*resp_fn)(const char*, ...)); |
207 |
| -``` |
208 |
| - |
209 |
| -I know that it is not pretty, but in practice you just copy and rename it. |
210 |
| - |
211 |
| -__8.__ |
212 |
| - |
213 |
| -The next thing is to count how many commands you have. __This number has to be exact!__ |
214 |
| -You have to open interpreter.hpp file, then search for the NUM_OF_API_FUNCS definition. |
215 |
| -Give this macro the correct number of commands. |
216 |
| - |
217 |
| -__9.__ |
218 |
| - |
219 |
| -The library has an option called ARDUINO_PLATFORM in interpreter.hpp. If you use |
220 |
| -Arduino IDE you have to uncomment this define. |
221 |
| - |
222 |
| -__10.__ |
223 |
| - |
224 |
| -Now the basic configuration of the library is finished, so you just have to use it in your code. |
225 |
| -The interpreter has to be initialized. To initialise the interpreter the safest practise is, |
226 |
| -to initialise it as soon as possible. The reason for this is because the library uses some recursive |
227 |
| -functions to build a binary tree from the commands. It needs a relatively high amount of stack |
228 |
| -compared a simple initialisation function. After the initialisation this stack memory will be |
229 |
| -freed up. In Arduino environment basically you have to init Serial first, then, |
230 |
| -init the interpreter in the beginning of the setup function. |
231 |
| - |
232 |
| -Code: |
233 |
| -``` |
234 |
| -init_interpreter(); |
235 |
| -``` |
236 |
| - |
237 |
| -__10.__ |
238 |
| - |
239 |
| -Now you just have to use the execute function every time you want to execute a command. |
240 |
| -The 3 examples in the Arduino folder in the repository shows 3 detailed example to use |
241 |
| -and understand this library. |
242 |
| - |
243 |
| -__Congratulations, you have made your first project with Commander API :)__ |
244 |
| - |
245 |
| -# The importance of response function |
246 |
| - |
247 |
| - |
248 |
| - |
249 |
| -Imagine a system that has a various number of channels to communicate with. |
250 |
| -For example a Linux system, which has its shell redirected to SSH, Serial, GUI... |
251 |
| -If a command arrives in one of the supported channels, you want to generate |
252 |
| -the response to that channel. For example if a command arrives from Serial, |
253 |
| -you want to generate the answer and the messages from the command to Serial as well, |
254 |
| -not to any other channels. This is why response function is used. |
255 |
| -The Commander API handles everything you just have to create a valid response |
256 |
| -function to it. The advanced demo shows how to add a response function correctly. |
257 |
| -If you don't use a response function, please use NULL as argument. In this case the |
258 |
| -error messages will be redirected to INTERPRETER_PRINTF definition. |
259 |
| - |
260 |
| -# Print the description |
261 |
| - |
262 |
| - |
263 |
| - |
264 |
| -To print the description you just have to add a question mark to the end of the command. |
265 |
| - |
266 |
| -# When and how to use a buffer? |
267 |
| - |
268 |
| -Commander API designed to work mainly on embedded devices. In these devices usually you work |
269 |
| -from RAM. If you work from RAM you have an option to modify the contant of the command that |
270 |
| -has given to the execute function. There are two cases when you __MUST__ have to use a buffer: |
271 |
| - |
272 |
| -__1.__ When you want to use the execute function with constant data. In this case the Commander |
273 |
| -API will try to overwrite this data, while executing the command. Why is it work like this is |
274 |
| -explained in the source file. In this case it will cause Hard Fault, because the software will |
275 |
| -try to modify the content of the FLASH( or program ) memory. This is restricted. |
276 |
| - |
277 |
| -__2.__ When you don't want to modify the data. In my opinion it is very rare. In most cases |
278 |
| -you just collect the command string until a terminator character and pass it to the interpreter. |
279 |
| -If you need the command string after the execute function use a buffer. |
280 |
| - |
281 |
| -How to setup buffered mode: |
282 |
| - |
283 |
| -__1.__ |
284 |
| - |
285 |
| -Open interpreter.hpp and find INTERPRETER_BUFFER_SIZE definition. |
286 |
| - |
287 |
| -__2.__ |
288 |
| - |
289 |
| -If it is commented, uncomment it. |
290 |
| -You have to decide how large buffer you need. If it is too large than you will waste RAM. |
291 |
| -If it is too short, than you can't interpret large commands correctly. |
292 |
| - |
293 |
| -If you __does not need a buffer__, than you __MUST uncomment__ INTERPRETER_BUFFER_SIZE! |
294 |
| - |
295 |
| -# Arduino printf function |
296 |
| - |
297 |
| -The arduino_printf function is implemented by compatibility reasons. Commander API requires |
298 |
| -a printf like function as a communication channel. This function acts like a printf function, |
299 |
| -but it is redirected to serial. If you need more channels like TCP |
300 |
| -or bluetooth you have to implement a printf like functions for those channels as well. |
| 12 | +The new version is designed from ground up and the main motivation was to make it as reliable as the original, but make it much simpler to use. |
301 | 13 |
|
| 14 | +__Key changes:__ |
| 15 | +* Full C++ API |
| 16 | +* Arduino compatible without any modifications |
| 17 | +* Platform-IO compatibility( still in progress ) |
| 18 | +* Simpler usage |
| 19 | +* Better example |
| 20 | +* Low memory consumption to make it compatible with lower end devices like Arduino UNO, Nano... |
| 21 | +* Response function overload. Thanks to C++ the response function can be anything like Serial, WiFiClient... |
302 | 22 |
|
303 | 23 | ## Contributing
|
304 | 24 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
305 | 25 |
|
306 | 26 | Please make sure to update tests as appropriate.
|
307 | 27 |
|
308 | 28 | ## Donation
|
309 |
| -If this project help you reduce time to develop, you can give me a cup of coffee :) |
| 29 | +If this project help you reduce time to develop, you can give me a cup of coffee :coffee: :coffee: :coffee: |
310 | 30 |
|
311 | 31 | [](https://www.paypal.com/donate?hosted_button_id=YFGZD78H6K2CS)
|
312 | 32 |
|
313 | 33 | ## License & copyright
|
314 | 34 | © Daniel Hajnal
|
315 |
| -Licensed under the MIT License |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | +Licensed under the MIT License |
0 commit comments