NanoC6 OpenThread Arduino related example programs.
File -> Examples -> OpenThreadTools -> Board: M5NanoC6Tools -> USB CDC On Boot: EnabledTools -> Flash Size: 4MBTools -> Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)Tools -> Port
This example demonstrates how to create a basic Thread node.
#include "OThreadCLI.h"
#include "OThreadCLI_Util.h"
// The first device to start Thread will be the Leader
// Next devices will be Router or Child
void setup() {
Serial.begin(115200);
OThread.begin(); // AutoStart using Thread default settings
OThreadCLI.begin();
OThread.otPrintNetworkInformation(Serial); // Print Current Thread Network Information
}
void loop() {
Serial.print("Thread Node State: ");
Serial.println(OThread.otGetStringDeviceRole());
delay(5000);
}
This example demonstrates how to build a complete Thread network with two different types of nodes. The Leader Node will send a "Hello, M5Stack!" message to the Router Node.
#include "OThreadCLI.h"
#include "OThreadCLI_Util.h"
#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff"
#define CLI_NETWORK_CHANEL "dataset channel 24"
otInstance *aInstance = NULL;
bool udpInitialized = false;
void setup() {
Serial.begin(115200);
OThread.begin(false);
OThreadCLI.begin();
Serial.println();
Serial.println("Setting up OpenThread Node as Leader");
aInstance = esp_openthread_get_instance();
OThreadCLI.println("dataset init new");
OThreadCLI.println(CLI_NETWORK_KEY);
OThreadCLI.println(CLI_NETWORK_CHANEL);
OThreadCLI.println("dataset commit active");
OThreadCLI.println("ifconfig up");
OThreadCLI.println("thread start");
}
void loop() {
while (OThreadCLI.available()) {
Serial.write(OThreadCLI.read());
}
Serial.println("=============================================");
Serial.print("Thread Node State: ");
Serial.println(OThread.otGetStringDeviceRole());
if (OThread.otGetDeviceRole() == OT_ROLE_LEADER) {
const char *networkName = otThreadGetNetworkName(aInstance);
Serial.printf("Network Name: %s\r\n", networkName);
uint8_t channel = otLinkGetChannel(aInstance);
Serial.printf("Channel: %d\r\n", channel);
uint16_t panId = otLinkGetPanId(aInstance);
Serial.printf("PanID: 0x%04x\r\n", panId);
const otExtendedPanId *extPanId = otThreadGetExtendedPanId(aInstance);
Serial.printf("Extended PAN ID: ");
for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) {
Serial.printf("%02x", extPanId->m8[i]);
}
Serial.println();
otNetworkKey networkKey;
otThreadGetNetworkKey(aInstance, &networkKey);
Serial.printf("Network Key: ");
for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) {
Serial.printf("%02x", networkKey.m8[i]);
}
Serial.println();
char buf[OT_IP6_ADDRESS_STRING_SIZE];
const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance);
while (address != NULL) {
otIp6AddressToString(&address->mAddress, buf, sizeof(buf));
Serial.printf("IP Address: %s\r\n", buf);
address = address->mNext;
}
const otNetifMulticastAddress *mAddress = otIp6GetMulticastAddresses(aInstance);
while (mAddress != NULL) {
otIp6AddressToString(&mAddress->mAddress, buf, sizeof(buf));
printf("Multicast IP Address: %s\n", buf);
mAddress = mAddress->mNext;
}
if (!udpInitialized) {
Serial.println("\nInitializing UDP sender...");
OThreadCLI.println("udp open");
delay(100);
udpInitialized = true;
Serial.println("UDP initialized");
}
Serial.println("\nSending UDP message...");
OThreadCLI.println("udp send ff03::1 12345 \"Hello,M5Stack\"");
}
delay(5000);
}
#include "OThreadCLI.h"
#include "OThreadCLI_Util.h"
#define CLI_NETWORK_KEY "dataset networkkey 00112233445566778899aabbccddeeff"
#define CLI_NETWORK_CHANEL "dataset channel 24"
otInstance *aInstance = NULL;
bool udpInitialized = false;
void setup() {
Serial.begin(115200);
OThread.begin(false);
OThreadCLI.begin();
Serial.println();
Serial.println("Setting up OpenThread Node as Router/Child");
Serial.println("Make sure the Leader Node is already running");
aInstance = esp_openthread_get_instance();
OThreadCLI.println("dataset clear");
OThreadCLI.println(CLI_NETWORK_KEY);
OThreadCLI.println(CLI_NETWORK_CHANEL);
OThreadCLI.println("dataset commit active");
OThreadCLI.println("ifconfig up");
OThreadCLI.println("thread start");
}
void loop() {
while (OThreadCLI.available()) {
Serial.write(OThreadCLI.read());
}
Serial.println("=============================================");
Serial.print("Thread Node State: ");
Serial.println(OThread.otGetStringDeviceRole());
if (OThread.otGetDeviceRole() == OT_ROLE_CHILD || OThread.otGetDeviceRole() == OT_ROLE_ROUTER) {
const char *networkName = otThreadGetNetworkName(aInstance);
Serial.printf("Network Name: %s\r\n", networkName);
uint8_t channel = otLinkGetChannel(aInstance);
Serial.printf("Channel: %d\r\n", channel);
uint16_t panId = otLinkGetPanId(aInstance);
Serial.printf("PanID: 0x%04x\r\n", panId);
const otExtendedPanId *extPanId = otThreadGetExtendedPanId(aInstance);
Serial.printf("Extended PAN ID: ");
for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) {
Serial.printf("%02x", extPanId->m8[i]);
}
Serial.println();
otNetworkKey networkKey;
otThreadGetNetworkKey(aInstance, &networkKey);
Serial.printf("Network Key: ");
for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) {
Serial.printf("%02x", networkKey.m8[i]);
}
Serial.println();
char buf[OT_IP6_ADDRESS_STRING_SIZE];
const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance);
while (address != NULL) {
otIp6AddressToString(&address->mAddress, buf, sizeof(buf));
Serial.printf("IP Address: %s\r\n", buf);
address = address->mNext;
}
const otNetifMulticastAddress *mAddress = otIp6GetMulticastAddresses(aInstance);
while (mAddress != NULL) {
otIp6AddressToString(&mAddress->mAddress, buf, sizeof(buf));
printf("Multicast IP Address: %s\n", buf);
mAddress = mAddress->mNext;
}
if (!udpInitialized) {
Serial.println("\nInitializing UDP receiver...");
OThreadCLI.println("udp open");
delay(100);
OThreadCLI.println("udp bind :: 12345");
delay(100);
udpInitialized = true;
Serial.println("UDP listening on port 12345");
Serial.println("Waiting for messages...\n");
}
}
delay(5000);
}
This example demonstrates how to scan nearby Thread networks.
#include "OThreadCLI.h"
#include "OThreadCLI_Util.h"
void setup() {
Serial.begin(115200);
OThread.begin(true); // For scanning, AutoStart must be active, any setup
OThreadCLI.begin();
OThreadCLI.setTimeout(100); // Set a timeout for the CLI response
Serial.println();
Serial.println("This sketch will continuously scan the Thread Local Network and all devices IEEE 802.15.4 compatible");
}
void loop() {
Serial.println();
Serial.println("Scanning for nearby IEEE 802.15.4 devices:");
// 802.15.4 Scan just needs a previous OThreadCLI.begin()
if (!otPrintRespCLI("scan", Serial, 3000)) {
Serial.println("Scan Failed...");
}
delay(5000);
if (OThread.otGetDeviceRole() < OT_ROLE_CHILD) {
Serial.println();
Serial.println("This device has not started Thread yet, bypassing Discovery Scan");
return;
}
Serial.println();
Serial.println("Scanning MLE Discover:");
if (!otPrintRespCLI("discover", Serial, 3000)) {
Serial.println("Discover Failed...");
}
delay(5000);
}
This example provides a complete OpenThread CLI console.
#include "OThreadCLI.h"
void setup() {
Serial.begin(115200);
OThread.begin(false); // No AutoStart - fresh start
OThreadCLI.begin();
Serial.println("OpenThread CLI started - type 'help' for a list of commands.");
OThreadCLI.startConsole(Serial);
}
void loop() {}
This example demonstrates how to use callback functions to handle CLI responses.
#include "OThreadCLI.h"
// reads all the lines sent by CLI, one by one
// ignores some lines that are just a sequence of \r\n
void otReceivedLine() {
String line = "";
while (OThreadCLI.available() > 0) {
char ch = OThreadCLI.read();
if (ch != '\r' && ch != '\n') {
line += ch;
}
}
// ignores empty lines, usually EOL sequence
if (line.length() > 0) {
Serial.print("OpenThread CLI RESP===> ");
Serial.println(line.c_str());
}
}
void setup() {
Serial.begin(115200);
OThread.begin(); // AutoStart
OThreadCLI.begin();
OThreadCLI.onReceive(otReceivedLine);
}
void loop() {
// sends the "state" command to the CLI every second
// the onReceive() Callback Function will read and process the response
OThreadCLI.println("state");
delay(1000);
}