Skip to content

Commit 1aa6a1b

Browse files
committed
Add Arduino CLI library
1 parent c9c8ed4 commit 1aa6a1b

File tree

2 files changed

+229
-0
lines changed

2 files changed

+229
-0
lines changed

libraries/Cli/cli.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/* Cli library for Arduino */
2+
3+
#include "Arduino.h"
4+
#include "cli.h"
5+
#include <string.h>
6+
7+
8+
Cli::Cli(const char *_prompt, Print *pf) {
9+
_clear();
10+
prompt = _prompt;
11+
printfunc = pf;
12+
printfunc->write(prompt);
13+
}
14+
15+
// Clear the CLI buffer
16+
void Cli::_clear() {
17+
_cliBufferLength = 0;
18+
memset(_cliBuffer, 0, BUFFER_LENGTH);
19+
memset(_commandBuffer, 0, COMMAND_LENGTH);
20+
}
21+
22+
void Cli::addChar(char c) {
23+
if (c == 0xD || c == ';') {
24+
printfunc->print("\r\n");
25+
_parseAndRun();
26+
return;
27+
}
28+
if (c == 0x8) {
29+
if (_cliBufferLength > 0) {
30+
_cliBuffer[--_cliBufferLength] = '\0';
31+
printfunc->print("\010 \010");
32+
}
33+
return;
34+
}
35+
_cliBuffer[_cliBufferLength++] = c;
36+
if (_cliBufferLength >= BUFFER_LENGTH)
37+
_cliBufferLength = BUFFER_LENGTH-1;
38+
else
39+
printfunc->write(c);
40+
}
41+
42+
char Cli::_strncmp(const char *s1, const char *s2, char n) {
43+
const char *idx1 = s1;
44+
const char *idx2 = s2;
45+
char numindex = 0;
46+
47+
while (idx1 != 0 && idx2 != 0 && numindex < n) {
48+
if (*idx1 != *idx2)
49+
return 0;
50+
idx1++; idx2++; numindex++;
51+
}
52+
return 1;
53+
}
54+
55+
unsigned char Cli::_strlen(const char *s) {
56+
unsigned char len = 0;
57+
for ( ; *s != '\0' ; s++)
58+
len++;
59+
return len;
60+
}
61+
62+
char Cli::atoi(char *s) {
63+
char value = 0;
64+
int mult = 1;
65+
char *end = &s[_strlen(s)];
66+
while (end != s) {
67+
end--;
68+
if (*end > 0x39 || *end < 0x30) break;
69+
value += (*end - 0x30)*mult;
70+
mult *= 10;
71+
}
72+
if (*end == '-') {
73+
value *= -1;
74+
}
75+
return value;
76+
}
77+
78+
// Returns a pointer to the arguments on the command line.
79+
char *Cli::getArg() {
80+
char *ptr;
81+
ptr = _cliBuffer;
82+
while (*ptr != '\0' && *ptr != ' ')
83+
*ptr++;
84+
if (*ptr == ' ')
85+
*ptr++;
86+
return ptr;
87+
}
88+
89+
// Returns the nth arg on the command line (0 is the command).
90+
char *Cli::getArg(char n) {
91+
char *ptr;
92+
93+
ptr = _cliBuffer;
94+
for (char i = 0 ; i < _cliBufferLength ; i++) {
95+
if (n == 0) break;
96+
if (*ptr == '\0') break;
97+
if (*ptr == ' ') n--;
98+
*ptr++;
99+
}
100+
memset(_argBuffer, '\0', COMMAND_LENGTH);
101+
for (unsigned char i = 0 ; i < COMMAND_LENGTH ; i++) {
102+
_argBuffer[i] = *ptr++;
103+
if (*ptr == '\0' || *ptr == ' ') break;
104+
}
105+
return _argBuffer;
106+
}
107+
108+
void Cli::_help() {
109+
printfunc->println("Command help:");
110+
for (unsigned char i = 0 ; i < ncommands ; i++) {
111+
printfunc->write(' ');
112+
printfunc->write(commands[i].name);
113+
printfunc->write(" ");
114+
printfunc->println(commands[i].help);
115+
}
116+
printfunc->write(prompt);
117+
_clear();
118+
return;
119+
}
120+
121+
void Cli::_parseAndRun() {
122+
unsigned char i;
123+
if (_cliBufferLength == 0) {
124+
// Blank line
125+
printfunc->print(prompt);
126+
return;
127+
}
128+
if (_strlen(_cliBuffer) == 1 && _strncmp("?", _cliBuffer, 1)) {
129+
_help();
130+
return;
131+
}
132+
133+
for (i = 0 ; i < _cliBufferLength ; i++)
134+
if (_cliBuffer[i] != '\0' && _cliBuffer[i] != ' ')
135+
_commandBuffer[i] = _cliBuffer[i];
136+
else
137+
break;
138+
for (i = 0 ; i < ncommands ; i++) {
139+
Command c = commands[i];
140+
if (_strlen(_commandBuffer) == _strlen(c.name) &&
141+
_strncmp(_commandBuffer, c.name, _strlen(c.name))) {
142+
c.run();
143+
_clear();
144+
printfunc->print(prompt);
145+
return;
146+
}
147+
}
148+
149+
_clear();
150+
printfunc->println("Unknown command. '?' for help.");
151+
printfunc->print(prompt);
152+
}

libraries/Cli/cli.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Command line library for Arduino.
3+
*
4+
* This simple library allows you to add a CLI interface to your project.
5+
*/
6+
7+
#ifndef cli_h
8+
#define cli_h
9+
10+
#include "Arduino.h"
11+
#include <avr/pgmspace.h>
12+
13+
#define COMMAND_LENGTH 10
14+
#define BUFFER_LENGTH 64
15+
16+
typedef void (*CommandProc)();
17+
18+
19+
/*
20+
* This defines a single command.
21+
*/
22+
struct Command {
23+
// The name of the command, what the user types to run it.
24+
const char *name;
25+
// Help text associated with the command.
26+
const char *help;
27+
// The function to run when the command is run.
28+
CommandProc run;
29+
};
30+
31+
/*
32+
* The main CLI definition.
33+
*/
34+
class Cli
35+
{
36+
public:
37+
/* Constructor. Args: the prompt string and a printer pointer */
38+
Cli(const char *, Print *);
39+
/* Adds an incoming character, e.g from serial port. */
40+
void addChar(char c);
41+
/* Used by the command's function to get the command argument at position n */
42+
char *getArg(char n);
43+
/* Fetch a pointer to the start of the command's arguments. */
44+
char *getArg();
45+
/* Converts the given string to a signed char. */
46+
char atoi(char *);
47+
/* The printable function */
48+
Print *printfunc;
49+
/* The valid commands in this cli. */
50+
Command *commands;
51+
/* Number of commands */
52+
char ncommands;
53+
54+
private:
55+
/* The prompt to display. */
56+
const char *prompt;
57+
/* Clear the cli buffer */
58+
void _clear();
59+
/* Buffer holding text at the prompt */
60+
char _cliBuffer[BUFFER_LENGTH];
61+
unsigned char _cliBufferLength;
62+
/* Contains first word on the cli */
63+
char _commandBuffer[COMMAND_LENGTH];
64+
/* Contains all other words on the cli */
65+
char _argBuffer[COMMAND_LENGTH];
66+
/* Lightweight utility functions */
67+
// Length of the string.
68+
unsigned char _strlen(const char *);
69+
// Whether the two strings match.
70+
char _strncmp(const char *, const char *, char);
71+
// When enter is pressed, run the command.
72+
void _parseAndRun();
73+
// Display help.
74+
void _help(void);
75+
};
76+
77+
#endif

0 commit comments

Comments
 (0)