Skip to content

Commit b86eea2

Browse files
committed
Fixes #1, #4
1 parent 79927ea commit b86eea2

File tree

5 files changed

+826
-11
lines changed

5 files changed

+826
-11
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
/*
2+
* Created on April 24 2022
3+
*
4+
* Copyright (c) 2022 - Daniel Hajnal
5+
6+
* This file is part of the Commander-API project.
7+
* Modified 2022.04.24
8+
*
9+
* This is a simple example sketch that shows how
10+
* to use Commander-API library.
11+
*/
12+
13+
// Necessary includes
14+
#include "Commander-API.hpp"
15+
#include "Commander-IO.hpp"
16+
17+
// We have to create an object from Commander class.
18+
Commander commander;
19+
20+
// We have to create the prototypes functions for our commands.
21+
// The arguments has to be the same for all command functions.
22+
void cat_func( char *args, commandResponse *response );
23+
void dog_func( char *args, commandResponse *response );
24+
void sum_func( char *args, commandResponse *response );
25+
void led_func( char *args, commandResponse *response );
26+
27+
// To tell Commander how many commands we have, it is necessary
28+
// to create an array, that holds soma data that represents our
29+
// commands. The type of this array must be Commander::API_t.
30+
// To simplify the command registration, there is a macro called
31+
// apiElement. This macro helps to add command data to this array.
32+
// -The first argument is the name of the command. Commander will
33+
// search the commands by it's name.
34+
// -The second argument is the description for the command.
35+
// If you use the help command, or '?' character after the command
36+
// name, Commander will response with it's description.
37+
// -The third argument is the wrapper function, that has been defined
38+
// in the previous step.
39+
Commander::API_t API_tree[] = {
40+
apiElement( "cat", "Description for cat command.", cat_func ),
41+
apiElement( "dog", "Description for dog command.", dog_func ),
42+
apiElement( "led", "Toggle the buit-in LED.", led_func ),
43+
apiElement( "sum", "This function sums two number from the argument list.", sum_func )
44+
};
45+
46+
void setup() {
47+
48+
// Set the LED pin to output, and turn it off.
49+
pinMode( LED_BUILTIN, OUTPUT );
50+
digitalWrite( LED_BUILTIN, 0 );
51+
52+
// In this example we will use the Serial for communication,
53+
// so we have to initialize it.
54+
Serial.begin( 115200 );
55+
56+
// Step 1.
57+
Serial.println( "Step 1." );
58+
59+
// There is an option to attach a debug channel to Commander.
60+
// It can be handy to find any problems during the initialization
61+
// phase. In this example we will use Serial for this.
62+
commander.attachDebugChannel( &Serial );
63+
64+
// At start Commander des not know anything about our commands.
65+
// We have to attach the API_tree array from the previus steps
66+
// to Commander to work properly.
67+
commander.attachTree( API_tree );
68+
69+
// Step 2.
70+
Serial.println();
71+
Serial.println( "Step 2." );
72+
73+
// After we attached the API_tree, Commander has to initialise
74+
// itself for the fastes runtime possible. It creates a balanced
75+
// binary tree from the API_tree to boost the search speed.
76+
// This part uses some recursion, to make the code space small.
77+
// But recursion is a bit stack hungry, so please initialise
78+
// Commander at the beginning of your code to prevent stack-overlow.
79+
commander.init();
80+
81+
82+
// Example 1.
83+
Serial.println();
84+
Serial.println( "Example 1." );
85+
86+
// At this point Commander is initialised and functional, so lets try it.
87+
// To execute a command we have to use the execute command. Let's try
88+
// the led command. This command just toggles the built-in LED.
89+
commander.execute( "led" );
90+
91+
// Example 2.
92+
Serial.println();
93+
Serial.println( "Example 2." );
94+
95+
// The most helpful command is help. It prints out all of the available
96+
// commands.
97+
commander.execute( "help" );
98+
99+
// Example 3.
100+
Serial.println();
101+
Serial.println( "Example 3." );
102+
103+
// After the previous step we can see, that we did not see anything.
104+
// This is because we did not gave any response channel to the execute
105+
// function. Let's set Serial as response channel.
106+
commander.execute( "help", &Serial );
107+
108+
// Example 4.
109+
Serial.println();
110+
Serial.println( "Example 4." );
111+
112+
// To print the description data as well, we have to pass '-d' as argument
113+
// after the help command.
114+
commander.execute( "help -d", &Serial );
115+
116+
// Example 5.
117+
Serial.println();
118+
Serial.println( "Example 5." );
119+
// If we want to print out the description for only one command, we can
120+
// use the '?' operator after the command name.
121+
commander.execute( "led?", &Serial );
122+
123+
// Example 6.
124+
Serial.println();
125+
Serial.println( "Example 6." );
126+
// Now lets try the remaining functions.
127+
commander.execute( "cat", &Serial );
128+
commander.execute( "dog", &Serial );
129+
commander.execute( "sum", &Serial );
130+
131+
// Example 7.
132+
Serial.println();
133+
Serial.println( "Example 7." );
134+
// As we can see the cat and dog functions worked as expected,
135+
// but the sum function gave argument error. This happened
136+
// because we did not gave any arguments to that function.
137+
// Giving arguments to a command is very simple. You just have
138+
// to give an argument string after the command, separated by
139+
// a blank space. Commander will transfer the argument string
140+
// to the command's function. Lets try to sum 10 and 15.
141+
commander.execute( "sum 10 15", &Serial );
142+
143+
// Example 8.
144+
Serial.println();
145+
Serial.println( "Example 8." );
146+
// Now lets try to execute a command that does not exist,
147+
// and see what happens.
148+
commander.execute( "reboot", &Serial );
149+
150+
Serial.println();
151+
Serial.println( "Eaxmple session finished." );
152+
Serial.println( "Now you can play with commander as you like." );
153+
154+
}
155+
156+
// Continous example.
157+
// In the loop function there is a simple example to
158+
// read commands from Serial in runtime. You can use
159+
// the Serial monitor to try it. Set the line ending
160+
// to new-line and play with the commands.
161+
162+
// This is a buffer to hold the incoming command.
163+
char commandFromSerial[ 20 ];
164+
165+
// This variable tracks the location of the next free
166+
// space in the commandFromSerial buffer.
167+
uint8_t commandIndex = 0;
168+
169+
void loop() {
170+
171+
// Check if there is any data incoming.
172+
while( Serial.available() ){
173+
174+
// Read the next incoming character.
175+
char c = Serial.read();
176+
177+
// Every command from Serial is terminated with a new-line
178+
// character. If a new-line character arrives we have to
179+
// terminate the string in the commandFromSerial buffer,
180+
// and execute it. After execution we have to reset the
181+
// commandIndex counter to zero.
182+
if( c == '\n' ){
183+
184+
commandFromSerial[ commandIndex ] = '\0';
185+
commander.execute( commandFromSerial, &Serial );
186+
commandIndex = 0;
187+
188+
}
189+
190+
// If we have a carriage-return character we simply
191+
// ignore it.
192+
else if( c == '\r' ){
193+
continue;
194+
}
195+
196+
// Every other case we just put the data to the next
197+
// free space in the commandFromSerial buffer, increment
198+
// the commandIndex, and check if it want's to overflow.
199+
else{
200+
201+
commandFromSerial[ commandIndex ] = c;
202+
commandIndex++;
203+
if( commandIndex >= 20 ){
204+
commandIndex = 19;
205+
}
206+
207+
}
208+
209+
}
210+
211+
}
212+
213+
214+
/// This is an example function for the cat command
215+
void cat_func(char *args, commandResponse *response )
216+
{
217+
218+
response -> print("Hello from cat function!\r\n");
219+
220+
}
221+
222+
/// This is an example function for the dog command
223+
void dog_func(char *args, commandResponse *response )
224+
{
225+
226+
response -> print("Hello from dog function!\r\n");
227+
228+
}
229+
230+
/// This is an example function for the led command
231+
void led_func(char *args, commandResponse *response )
232+
{
233+
234+
digitalWrite( LED_BUILTIN, !digitalRead( LED_BUILTIN ) );
235+
236+
}
237+
238+
/// This is an example function for the sum command
239+
void sum_func(char *args, commandResponse *response )
240+
{
241+
242+
// These variables will hold the value of the
243+
// two numbers, that has to be summed.
244+
int a = 0;
245+
int b = 0;
246+
247+
// This variable will hold the result of the
248+
// argument parser.
249+
int argResult;
250+
251+
// This variable will hold the sum result.
252+
int sum = 0;
253+
254+
argResult = sscanf( args, "%d %d", &a, &b );
255+
256+
// We have to check that we parsed succesfully the two
257+
// numbers from the argument string.
258+
if( argResult != 2 ){
259+
260+
// If we could not parse two numbers, we have an argument problem.
261+
// We print out the problem to the response channel.
262+
response -> print( "Argument error! Two numbers required, separated with a blank space.\r\n" );
263+
264+
// Sadly we have to stop the command execution and return.
265+
return;
266+
267+
}
268+
269+
// Calculate the sum.
270+
sum = a + b;
271+
272+
// Print out the result.
273+
response -> printf( "%d + %d = %d\r\n", a, b, sum );
274+
275+
}

src/Commander-API.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ SOFTWARE.
3434

3535
#include "Commander-API.hpp"
3636

37+
const char *Commander::version = COMMANDER_API_VERSION;
3738

3839
void Commander::attachTreeFunction( API_t *API_tree_p, uint32_t API_tree_size_p ){
3940

src/Commander-API.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ SOFTWARE.
3535
#ifndef COMMANDER_API_SRC_COMMANDER_HPP_
3636
#define COMMANDER_API_SRC_COMMANDER_HPP_
3737

38+
#define COMMANDER_API_VERSION (const char*)"2.0.0"
39+
3840
#include "stdint.h"
3941
#include "string.h"
4042

@@ -77,6 +79,9 @@ class Commander{
7779

7880
public:
7981

82+
/// Library version string.
83+
static const char *version;
84+
8085
/// Structure for command data
8186
///
8287
/// Every command will get a structure like this.

0 commit comments

Comments
 (0)