-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThreadCli.ino
More file actions
114 lines (98 loc) · 3.52 KB
/
Copy pathThreadCli.ino
File metadata and controls
114 lines (98 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// ThreadCli - the full OpenThread command line on the serial monitor.
//
// Everything the official `ot-cli-ftd` can do, over USB serial: inspect and
// drive the stack interactively. Open the serial monitor at 115200 with
// "Newline" line ending and try:
//
// state -> leader / router / child / detached
// dataset active -> the network credentials in use
// ipaddr -> this node's IPv6 addresses
// neighbor table -> who we hear directly
// ping ff03::1 -> ping every node in the mesh
// udp / coap / scan / help -> there is a lot more
//
// The sketch pre-configures the same demo network as the other examples, so
// boards running FormNetwork / UdpBroadcast / CoapLamp will appear as
// neighbors. Comment out the setNetwork()/start() lines to drive
// commissioning entirely from the CLI (`dataset init new`, `ifconfig up`,
// `thread start`).
//
// The input loop accepts printable ASCII only - a cheap defense against
// line noise on marginal USB cables/clones.
#include <NiusThread.h>
#include <stdarg.h>
#include <stdio.h>
extern "C" {
#include <openthread/cli.h>
}
static const uint8_t kNetworkKey[16] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
};
// OpenThread CLI output -> Serial.
static int cliOutput(void *aContext, const char *aFormat, va_list aArguments) {
(void)aContext;
char buf[256];
int len = vsnprintf(buf, sizeof(buf), aFormat, aArguments);
if (len > 0) {
Serial.write(buf, min((size_t)len, sizeof(buf) - 1));
}
return len;
}
void setup() {
Serial.begin(115200);
while (!Serial && millis() < 5000) {}
Thread.begin();
Thread.setNetwork("ArduinoNRF", 25, 0xBEEF, kNetworkKey);
Thread.start();
otCliInit(Thread.instance(), cliOutput, NULL);
Serial.println();
Serial.println("OpenThread CLI ready - type 'help' for commands, 'state' for the role.");
Serial.print("> ");
}
void loop() {
static char line[256];
static size_t fill = 0;
static uint32_t lastCharMs = 0;
Thread.process();
// Replayed stale bytes (see the note up top) can leave an unterminated
// junk prefix in the line buffer, which would poison every following
// command. A real command arrives as one burst, so a partial line that
// has been idle for 2 s is junk - drop it.
if (fill > 0 && millis() - lastCharMs > 2000) {
fill = 0;
Serial.print("\r\n> ");
}
// Throttled + bounded input polling: on some clones every USB OUT fetch
// can replay stale bytes, and polling at loop rate makes that a storm
// that starves Thread.process(). 20 Hz polling is plenty for typed input.
static uint32_t lastPollMs = 0;
if (millis() - lastPollMs < 50) {
return;
}
lastPollMs = millis();
uint8_t budget = 64;
while (Serial.available() && budget-- > 0) {
char c = (char)Serial.read();
lastCharMs = millis();
if (c == '\r' || c == '\n') {
if (fill > 0) {
Serial.println(); // echo the line break
line[fill] = '\0';
otCliInputLine(line); // hand the command to OpenThread
fill = 0;
}
Serial.print("> ");
} else if (c == 0x7F || c == 0x08) { // backspace
if (fill > 0) {
fill--;
Serial.print("\b \b");
}
} else if (c >= 0x20 && c < 0x7F && fill < sizeof(line) - 1) {
// printable ASCII only - drops the binary noise some clone USB
// serial paths replay after a command
line[fill++] = c;
Serial.print(c); // echo
}
}
}