Интерфейс командной строки во многих случаях является наиболее универсальным и удобным способом управления электроникой. С помощью такого интерфейса вы можете контролировать свои вещи через терминальное приложение, а также интегрировать его с вашим настольным/мобильным приложением.

В данном проекте описывается связь с ESP32 через Интернет с использованием интерфейса командной строки для сохранения сетевых учетных данных в энергонезависимой памяти и управления светодиодом.
В проекте мы используем несколько интересных инструментов:
- Библиотека SimpleCLI (https://github.com/spacehuhn/SimpleCLI) – для простого создания интерфейса командной строки. Вам не нужно мучиться с парсингом строк. Эта библиотека делает это (и многое другое) для вас в несколько строк.
- Библиотека настроек (https://github.com/espressif/arduino-esp32/blob/master/libraries/Preferences/src/Preferences.h) – самый элегантный способ взаимодействия с энергонезависимой / EEPROM / Flash-памятью во время выполнения из пользовательского кода. Мы используем эту библиотеку для хранения сетевых учетных данных в памяти и чтения их после включения, чтобы подключиться к сети.
- Husarnet (https://github.com/husarnet/arduino-esp32) – сеть виртуальной локальной сети, благодаря которой вы можете получить доступ к ESP32 как из локальной сети, так и через Интернет, без статического IP-адреса, настройки переадресации портов в маршрутизаторе и т. д. Вам даже не нужно запоминать IP-адрес вашей платы, но используйте вместо этого имена хостов.
Чтобы запустить проект, откройте Arduino IDE и выполните следующие действия.
Сначала установите пакет Husarnet для ESP32. Откройте File – Preferences (Файл - Настройки). В поле Additional Board Manager URLs (Дополнительные URL-адреса менеджера плат) добавьте эту ссылку: https://files.husarion.com/arduino/package_esp32_index.json. Откройте Tools - Board: ... - Boards Manager ... (Инструменты - Платы: ... - Менеджер плат …). Найдите esp32-husarnet и нажмите Install (Установить).
Теперь выберете плату ESP32. Откройте Tools – Board (Инструменты - Плата). Выберите ESP32 Dev Module в разделе «ESP32 Arduino (Husarnet)». Далее установите библиотеку SimpleCLI. Откройте Tools - Manage Libraries (Инструменты - Управление библиотеками). Найдите SimpleCLI и установите ее.
Запрограммируйте плату ESP32. Откройте проект ESP32_cli_eeprom.ino, загрузить проект на свою плату ESP32. После этого можно получить код присоединения Husarnet. Зарегистрируйтесь на https://app.husarnet.com/. Нажмите кнопку Create network, назовите ее (например, mynet) и нажмите кнопку Create. Нажмите кнопку Add element и перейдите на вкладку кода присоединения. Скопируйте свой код соединения, содержащий 22 символа XXXXXXXXXXXXXXXXXXXXXX, и сохраните его для дальнейшего использования.

Откройте последовательный монитор в Arduino IDE на скорости 115200 бод, также в настройках монитора установите Both NL & CR. Сохраните учетные данные сети Wi-Fi в энергонезависимой памяти ESP32, введя в последовательный монитор (XXXXX – название сети, YYYYY – пароль).
conwifi -ssid "<XXXXX>" -pass "<YYYYY>"Сохраните сетевые учетные данные Husarnet в энергонезависимой памяти ESP32, введя в монитор husarnet_join XXXXXXXXXXXXXXXXXXXXXX myesp32, где XXXXXXXXXXXXXXXXXXXXXX – код соединения HUSARNET.
Сбросьте ESP32. В последовательном мониторе вы должны увидеть, что ваша плата ESP32 пытается подключиться к сети Wi-Fi и Husarnet. Теперь установите Husarnet на свой компьютер с Linux и добавьте его в ту же сеть, что и ESP32. Для этого откройте терминал Linux и введите эту строку для установки Husarnet:
$ curl https://install.husarnet.com/install.sh | sudo bashПодключите ваш компьютер Linux к сети Husarnet, выполнив следующую команду:
$ sudo husarnet join XXXXXXXXXXXXXXXXXXXXXX mycomputer"Управляйте своим ESP32 через Интернет с помощью командной строки. Откройте терминал Linux и введите эту строку для подключения к ESP32:
$ socat - tcp:myesp32:8001Введите setled 1, чтобы включить светодиод, подключенный к линии ввода/вывода 16.

Код ESP32_cli_eeprom.ino:
#include <WiFi.h>
#include <Husarnet.h>
#include <SimpleCLI.h>
#include <Preferences.h>
const int CLI_PORT = 8001;
const int LED_PIN = 16;
HusarnetServer server(CLI_PORT);
Preferences preferences;
SimpleCLI cli;
Command conwifi;
Command husarnet_join;
Command setled;
void taskInternetCLI( void * parameter );
void conwifiCallback(cmd* c);
void husarnet_joinCallback(cmd* c);
void setledCallback(cmd* c);
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// Read Wi-Fi and Husarnet credentials from NVS memory
preferences.begin("my-app", false);
String ssid = preferences.getString("ssid");
String pass = preferences.getString("pass");
String hostname = preferences.getString("hostname");
String joincode = preferences.getString("joincode");
preferences.end();
// Configure a command line interface (CLI)
conwifi = cli.addCmd("conwifi", conwifiCallback);
conwifi.addArg("ssid");
conwifi.addArg("pass");
husarnet_join = cli.addCmd("husarnet_join", husarnet_joinCallback);
husarnet_join.addPosArg("joincode");
husarnet_join.addPosArg("hostname");
setled = cli.addCmd("setled", setledCallback);
setled.addPosArg("state");
// Connect to Wi-Fi
Serial.println("Connecting to Wi-Fi: ");
if (ssid != "") {
Serial.print("SSID:");
Serial.println(ssid);
Serial.print("PASS:");
Serial.println(pass);
WiFi.begin(ssid.c_str(), pass.c_str());
for (int j = 0; j < 10; j++) {
if (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (j == 9) {
Serial.printf("\r\nwrong Wi-Fi credentials. Going to commandline:\r\n");
Serial.println("ESP32 commandline");
Serial.print("# ");
return;
}
} else {
Serial.println("done");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
break;
}
}
} else {
Serial.println("no credentials in memory");
}
// Connect to Husarnet network
Serial.println("Connecting to Husarnet: ");
if (hostname != "") {
Serial.print("joincode:");
Serial.println(joincode);
Serial.print("hostname:");
Serial.println(hostname);
Husarnet.join(joincode.c_str(), hostname.c_str());
Husarnet.start();
xTaskCreate(
taskInternetCLI, /* Task function. */
"taskWifi", /* String with name of task. */
20000, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the task */
2, /* Priority of the task. */
NULL); /* Task handle. */
} else {
Serial.println("no credentials in memory");
}
Serial.println("ESP32 commandline");
Serial.print("# ");
}
String input;
void loop() {
// Check if user typed something into the serial monitor
if (Serial.available()) {
char c = Serial.read();
input += c;
if (c == '\r') {
cli.parse(input);
input = "";
} else {
Serial.print(c);
}
}
// Check for parsing errors
if (cli.errored()) {
// Get error out of queue
CommandError cmdError = cli.getError();
// Print the error
Serial.print("ERROR: ");
Serial.println(cmdError.toString());
// Print correct command structure
if (cmdError.hasCommand()) {
Serial.print("Did you mean \"");
Serial.print(cmdError.getCommand().toString());
Serial.println("\"?");
}
Serial.print("\r\n# ");
}
}
void conwifiCallback(cmd* c) {
Command cmd(c);
String ssid = cmd.getArg("ssid").getValue();
String pass = cmd.getArg("pass").getValue();
preferences.begin("my-app", false);
preferences.putString("ssid", ssid);
preferences.putString("pass", pass);
preferences.end();
Serial.println("\r\nWi-Fi credentials saved. Reset to connect.");
}
void husarnet_joinCallback(cmd* c) {
Command cmd(c);
String hostname = cmd.getArg("hostname").getValue();
String joincode = cmd.getArg("joincode").getValue();
preferences.begin("my-app", false);
preferences.putString("hostname", hostname);
preferences.putString("joincode", joincode);
preferences.end();
Serial.println("\r\nHusarnet credentials saved. Reset to connect.");
}
void setledCallback(cmd* c) {
Command cmd(c);
String state = cmd.getArg("state").getValue();
switch (state.toInt()) {
case 0:
digitalWrite(LED_PIN, LOW);
break;
case 1:
digitalWrite(LED_PIN, HIGH);
break;
}
Serial.println("\r\nHusarnet credentials saved. Reset to connect.");
}
void taskInternetCLI( void * parameter )
{
server.begin();
while (1) {
HusarnetClient client = server.available();
if (client) {
Serial.println("New Client.");
String currentLine = "";
Serial.printf("connected: %d\r\n", client.connected());
while (client.connected()) {
if (client.available()) {
char c = client.read();
currentLine += c;
if (c == '\n') {
cli.parse(currentLine);
currentLine = "";
client.println("ok");
}
}
}
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
} else {
delay(200);
}
}
}
© digitrode.ru