Skip to content

Commit c42e6aa

Browse files
committed
update examples and README
1 parent a1a24d5 commit c42e6aa

4 files changed

Lines changed: 183 additions & 31 deletions

File tree

README.md

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
# StaticSerialCommands
2-
3-
An Arduino library for parsing commands received over a serial port. Optimized for low dynamic memory usage, commands are stored in program memory. Typed arguments with strict input validation and friendly error messages. Commands can have subcommands.
2+
An Arduino library for parsing commands received over a serial port. Optimized for low dynamic memory usage, commands are stored in program memory.
3+
* Commands and arguments are separated by space.
4+
* A command must end with a new line or carriage return character.
5+
* Whitespaces are ignored when parsing a command.
6+
* Double quotation marks can be used to pass string argument with spaces.
7+
* Typed arguments with strict input validation.
8+
* Friendly error messages for invalid input.
9+
* Commands can have subcommands.
10+
* Methods to print out commands with syntax and description.
411

512
## Quickstart
6-
713
```cpp
814
#include "StaticSerialCommands.h"
915

@@ -25,18 +31,17 @@ void loop() {
2531
serialCommands.readSerial();
2632
}
2733
```
28-
2934
## Commands
30-
31-
COMMAND macro syntax:
35+
COMMAND macro is used to create Command object with data stored in program memory.
3236
```cpp
3337
COMMAND(function, command)
3438
COMMAND(function, command, subcommands)
3539
COMMAND(function, command, subcommands, description)
3640
COMMAND(function, command, arguments..., subcommands, description)
3741
```
3842
### Simple arguments
39-
Valid argument types: Int, Float, String
43+
Valid argument types: Int, Float, String \
44+
Maximum number of arguments is limited to 16.
4045
```cpp
4146
void cmd_hello(SerialCommands& sender, Args& args) {
4247
sender.getSerial().print(F("Hello "));
@@ -53,19 +58,17 @@ Command commands[] {
5358
// if string argument contains space it should be inside quotation marks
5459
// for example: name "Firstname Lastname"
5560
COMMAND(cmd_hello, "name", ArgType::String, nullptr, ""),
56-
COMMAND(cmd_multiply, "mul", ArgType::Int, ArgType::Int, nullptr, "multiplies two number"),
61+
COMMAND(cmd_multiply, "mul", ArgType::Int, ArgType::Int, nullptr, "multiply two numbers"),
5762
};
5863
```
59-
6064
### Custom arguments
61-
ARG macro syntax:
65+
ARG macro is used to specify command argument type, range (if type is numeric) and name.
6266
```cpp
6367
ARG(type)
6468
ARG(type, name)
6569
ARG(type, min, max)
6670
ARG(type, min, max, name)
6771
```
68-
6972
```cpp
7073
void cmd_led_on(SerialCommands& sender, Args& args) {
7174
auto pin = args[0].getInt();
@@ -90,15 +93,19 @@ Command commands[] {
9093
COMMAND(cmd_led_off, "off", ARG(ArgType::Int, 2, 13, "pin"), nullptr, "turn off the led on the given pin"),
9194
};
9295
```
96+
If you want to declare argument constraint into a variable, mark it as `constexpr`:
97+
```cpp
98+
constexpr auto argConstraint = ARG(ArgType::Int, 2, 13, "pin");
9399
94-
### Subcommands
95-
```
96-
help - list commands
97-
calc <int> - calculator
98-
calc <int> + <int> - add numbers
99-
calc <int> * <int> - multiply numbers
100+
Command commands[] {
101+
COMMAND(cmd_led_on, "on", argConstraint, nullptr, "turn on the led on the given pin"),
102+
COMMAND(cmd_led_off, "off", argConstraint, nullptr, "turn off the led on the given pin"),
103+
};
100104
```
101-
105+
### Subcommands
106+
An array of subcommands can only be passed to one command. \
107+
The sum of command arguments and subcommand arguments must be less than or equal to 16. \
108+
If the parent of subcommands has N arguments, the first N arguments of the subcommands will be the parent's arguments.
102109
```cpp
103110
void cmd_help(SerialCommands& sender, Args& args);
104111
void cmd_calc(SerialCommands& sender, Args& args);
@@ -124,14 +131,61 @@ void cmd_calc(SerialCommands& sender, Args& args) {
124131
}
125132

126133
void cmd_calc_add(SerialCommands& sender, Args& args) {
127-
float number1 = args[0].getInt();
128-
float number2 = args[1].getInt();
134+
auto number1 = args[0].getInt();
135+
auto number2 = args[1].getInt();
129136
sender.getSerial().println(number1 + number2);
130137
}
131138

132139
void cmd_calc_mul(SerialCommands& sender, Args& args) {
133-
float number1 = args[0].getInt();
134-
float number2 = args[1].getInt();
140+
auto number1 = args[0].getInt();
141+
auto number2 = args[1].getInt();
135142
sender.getSerial().println(number1 * number2);
136143
}
137144
```
145+
Result:
146+
```
147+
help - list commands
148+
calc <int> - calculator
149+
calc <int> + <int> - add numbers
150+
calc <int> * <int> - multiply numbers
151+
```
152+
## SerialCommands methods
153+
public methods of SerialCommands class:
154+
```cpp
155+
// read serial port and parse command when new line is received
156+
// if parsing is successful, command function will be called
157+
// if parsing is unsuccessful, error message will be printed
158+
void readSerial();
159+
160+
// get Serial object
161+
Stream& getSerial();
162+
163+
// print the command syntax
164+
void printCommand(const Command& command);
165+
166+
// print command description
167+
void printCommandDescription(const Command& command);
168+
169+
// list all commands but not their subcommands
170+
void listCommands();
171+
void listCommands(const Command* commands, uint16_t commandsCount);
172+
173+
// list all commands and their subcommands
174+
void listAllCommands();
175+
void listAllCommands(const Command* commands, uint16_t commandsCount);
176+
```
177+
## Custom buffer size
178+
Default buffer size is 64 bytes. \
179+
This buffer is used to store characters received over the serial port,
180+
and to read strings from program memory (command name, description and argument name). \
181+
The buffer must be large enough to:
182+
* receive the longest command
183+
* store the longest command name and the longest description.
184+
```cpp
185+
char buffer[128];
186+
SerialCommands serialCommands(
187+
Serial,
188+
commands, sizeof(commands) / sizeof(Command),
189+
buffer, sizeof(buffer)
190+
);
191+
```

examples/CommandsWithArguments/CommandsWithArguments.ino

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ void cmd_hello(SerialCommands& sender, Args& args) {
1919
}
2020

2121
void cmd_multiply(SerialCommands& sender, Args& args) {
22-
float number1 = args[0].getFloat();
23-
float number2 = args[1].getFloat();
22+
auto number1 = args[0].getFloat();
23+
auto number2 = args[1].getFloat();
2424
sender.getSerial().println(number1 * number2);
2525
}
2626

@@ -40,21 +40,41 @@ void cmd_led_off(SerialCommands& sender, Args& args) {
4040
sender.getSerial().println(F(" is off "));
4141
}
4242

43+
/*
44+
COMMAND macro is used to create Command object.
45+
It takes the following arguments:
46+
COMMAND(function, command)
47+
COMMAND(function, command, subcommands)
48+
COMMAND(function, command, subcommands, description)
49+
COMMAND(function, command, arguments..., subcommands, description)
50+
51+
ARG macro is used to specify argument type, range (if type is numeric) and name.
52+
It takes the following arguments:
53+
ARG(type)
54+
ARG(type, name)
55+
ARG(type, min, max)
56+
ARG(type, min, max, name)
57+
*/
58+
4359
Command commands[] {
4460
COMMAND(cmd_help, "help", NULL, "list commands"),
4561

4662
// if string argument contains space it should be inside quotation marks
47-
// for example: myname "Firstname Lastname"
48-
COMMAND(cmd_hello, "myname", ArgType::String, NULL, ""),
49-
COMMAND(cmd_multiply, "mul", ArgType::Float, ArgType::Float, NULL, "multiplies two number"),
63+
// for example: name "Firstname Lastname"
64+
COMMAND(cmd_hello, "name", ArgType::String, NULL, ""),
65+
COMMAND(cmd_multiply, "mul", ArgType::Float, ArgType::Float, NULL, "multiply two numbers"),
5066

51-
// set min and max value of argument
52-
// if the argument is out of range command does not run
67+
// argument should be an integer between 2 and 13
68+
// otherwise error message will be printed and command won't be executed
5369
COMMAND(cmd_led_on, "on", ARG(ArgType::Int, START_PIN, END_PIN, "pin"), NULL, "turn on the led on the given pin"),
5470
COMMAND(cmd_led_off, "off", ARG(ArgType::Int, START_PIN, END_PIN, "pin"), NULL, "turn off the led on the given pin"),
5571
};
5672

57-
SerialCommands serialCommands = SERIAL_COMMANDS(Serial, commands);
73+
SerialCommands serialCommands(Serial, commands, sizeof(commands) / sizeof(Command));
74+
75+
// if default buffer size (64) is too small pass a buffer through constructor
76+
// char buffer[128];
77+
// SerialCommands serialCommands(Serial, commands, sizeof(commands) / sizeof(Command), buffer, sizeof(buffer));
5878

5979
void setup() {
6080
Serial.begin(9600);

examples/SimpleCommands/SimpleCommands.ino

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Repository : https://github.com/naszly/Arduino-StaticSerialCommands
88

99
#define LED_PIN 13
1010

11+
void cmd_help(SerialCommands& sender, Args& args) {
12+
sender.listCommands();
13+
}
14+
1115
void cmd_led_on(SerialCommands& sender, Args& args) {
1216
digitalWrite(LED_PIN, HIGH);
1317
sender.getSerial().println(F("Led is on"));
@@ -19,16 +23,23 @@ void cmd_led_off(SerialCommands& sender, Args& args) {
1923
}
2024

2125
Command commands[] {
26+
COMMAND(cmd_help, "help"),
2227
COMMAND(cmd_led_on, "on"),
2328
COMMAND(cmd_led_off, "off"),
2429
};
2530

26-
SerialCommands serialCommands = SERIAL_COMMANDS(Serial, commands);
31+
SerialCommands serialCommands(Serial, commands, sizeof(commands) / sizeof(Command));
32+
33+
// if default buffer size (64) is too small pass a buffer through constructor
34+
// char buffer[128];
35+
// SerialCommands serialCommands(Serial, commands, sizeof(commands) / sizeof(Command), buffer, sizeof(buffer));
2736

2837
void setup() {
2938
Serial.begin(9600);
3039

3140
pinMode(LED_PIN, OUTPUT);
41+
42+
serialCommands.listCommands();
3243
}
3344

3445
void loop() {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*---------------------------------------------------------------------
2+
Author : naszly
3+
License : BSD
4+
Repository : https://github.com/naszly/Arduino-StaticSerialCommands
5+
-----------------------------------------------------------------------*/
6+
7+
#include <StaticSerialCommands.h>
8+
9+
void cmd_help(SerialCommands& sender, Args& args);
10+
void cmd_calc(SerialCommands& sender, Args& args);
11+
void cmd_calc_add(SerialCommands& sender, Args& args);
12+
void cmd_calc_mul(SerialCommands& sender, Args& args);
13+
14+
/*
15+
COMMAND macro is used to create Command object.
16+
It takes the following arguments:
17+
COMMAND(function, command)
18+
COMMAND(function, command, subcommands)
19+
COMMAND(function, command, subcommands, description)
20+
COMMAND(function, command, arguments..., subcommands, description)
21+
*/
22+
23+
Command subCommands[] {
24+
COMMAND(cmd_calc_add, "+", ArgType::Int, nullptr, "add numbers"),
25+
COMMAND(cmd_calc_mul, "*", ArgType::Int, nullptr, "multiply numbers"),
26+
};
27+
28+
Command commands[] {
29+
COMMAND(cmd_help, "help", nullptr, "list commands"),
30+
COMMAND(cmd_calc, "calc", ArgType::Int, subCommands, "calculator"),
31+
};
32+
33+
SerialCommands serialCommands(Serial, commands, sizeof(commands) / sizeof(Command));
34+
35+
// if default buffer size (64) is too small pass a buffer through constructor
36+
// char buffer[128];
37+
// SerialCommands serialCommands(Serial, commands, sizeof(commands) / sizeof(Command), buffer, sizeof(buffer));
38+
39+
void setup() {
40+
Serial.begin(9600);
41+
42+
serialCommands.listAllCommands();
43+
}
44+
45+
void loop() {
46+
serialCommands.readSerial();
47+
}
48+
49+
void cmd_help(SerialCommands& sender, Args& args) {
50+
sender.listAllCommands();
51+
}
52+
53+
void cmd_calc(SerialCommands& sender, Args& args) {
54+
sender.listAllCommands(subCommands, sizeof(subCommands) / sizeof(Command));
55+
}
56+
57+
void cmd_calc_add(SerialCommands& sender, Args& args) {
58+
auto number1 = args[0].getInt();
59+
auto number2 = args[1].getInt();
60+
sender.getSerial().println(number1 + number2);
61+
}
62+
63+
void cmd_calc_mul(SerialCommands& sender, Args& args) {
64+
auto number1 = args[0].getInt();
65+
auto number2 = args[1].getInt();
66+
sender.getSerial().println(number1 * number2);
67+
}

0 commit comments

Comments
 (0)