• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

espnow. Ошибка при использовании доставки сообщения

saharesp

New member
Разбирая пример Руи Сантоса с двумя модулями ESP8266 (управляющий и удаленный) c использованием espnow обратил внимание что в браузер выводится недостоверная информация об отправке сообщения на удаленный модуль ESP8266. Ошибка в том, что независимо, подключен удаленный модуль к питанию или нет в браузере получаю сообщение, что удаленный модуль включается или выключается. То есть часть кода отвечающая за вывод информации в браузер выполняется на стороне управляющего модуля. Решил привязать вывод информации к функции: esp_now_register_send_cb(OnDataSent), которая выдает состояние доставки сообщения на удаленный модуль. Все заработало. Но есть одно но... При первой отправке сообщения я получаю неправильное значение в окне браузера и переменная: string1_0 выдает неправильное значение в мониторе порта Arduino IDE, и следом выдает правильное значение. Дальше все работает корректно. Помогите исправить первое сообщение? Ниже на картинках эти сообщения в мониторе порта. Код примера:

#include <ESP8266WiFi.h>
#include <espnow.h>
// Вводим логин и пароль от роутера
const char *ssid = "SSID";
const char *password = "pass";
WiFiServer server(80);
String header;
uint8_t broadcastAddress1[] = {0xE8, 0xDB, 0x84, 0xA7, 0xB0, 0xC8};//14 плата
String string1_1;
int string1_0;
typedef struct test_struct {
int test1_int;
} ;
test_struct myData;
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
char macStr[18];
Serial.print("Отправлено к: ");
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.println (macStr);
Serial.println("Состояние доставки отправления: ");
if (esp_now_deinit() == 0)
{
if (sendStatus == 0) {
Serial.println("доставка сообщения успешно ");
Serial.print ("myData.test1_int = ");
Serial.println(myData.test1_int);
string1_0 = 1;
}
else
{
Serial.println("Сообщение не доставлено");
Serial.print ("myData.test1_int = ");
Serial.println(myData.test1_int);
string1_0 = 0;
}
Serial.print ("string1_0 = ");
Serial.println (string1_0);
Serial.println ("ESPNOW отключился");
}
else
{
Serial.print ("ESPNOW не отключился!");
}
//WiFi.printDiag(Serial);
}
unsigned long currentTime = millis();
unsigned long previousTime = 0;
const long timeoutTime = 2000;
void setup() {
delay(1000);
Serial.begin(115200);
Serial.println();
Serial.print("Configuring server...");
WiFi.softAP("SSID", "pass");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
Serial.println("HTTP server started");
WiFi.printDiag(Serial);
}
void loop() {
WiFiClient client = server.available();
if (client) {
Serial.println("New Client.");
String currentLine = "";
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
if (client.available()) {
char c = client.read();
Serial.write(c);
header += c;
if (c == '\n') {
if (currentLine.length() == 0) {
if (header.indexOf("GET /5/on") == 0) {
if (esp_now_init() == 0)
{
Serial.println("ESP-NOW подключился. . .");
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_register_send_cb(OnDataSent);
if (esp_now_add_peer(broadcastAddress1, ESP_NOW_ROLE_SLAVE, 1, NULL, 0) != 0)
{
Serial.println("Peer не добавлен!");
}
else
{
Serial.println("Peer добавлен!");
myData.test1_int = 0;
Serial.print ("Сообщение ");
Serial.print (myData.test1_int);
Serial.println (" подготовлено к отправке!");
// Отправляем сообщение через ESP-NOW
esp_now_send(broadcastAddress1, (uint8_t *)&myData, sizeof(myData));
Serial.println("GPIO 5 on");
Serial.print("string1_0 = ");
Serial.println(string1_0);
if (string1_0)
{
string1_1 = "выключен";
Serial.println("выключен");
}
else {
string1_1 = "нет связи";
Serial.println("нет связи");
}
}
} else
{
Serial.println("ESP-NOW не подключился. . .");
delay(1);
}
}
else if (header.indexOf("GET /5/off") == 0)
{
if (esp_now_init() == 0)
{
Serial.println("ESP-NOW подключился. . .");
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_register_send_cb(OnDataSent);
if (esp_now_add_peer(broadcastAddress1, ESP_NOW_ROLE_SLAVE, 1, NULL, 0) != 0)
{
Serial.println("Peer не добавлен!");
}
else
{
Serial.println("Peer добавлен!");
myData.test1_int = 1;
Serial.print ("Сообщение ");
Serial.print (myData.test1_int);
Serial.println (" подготовлено к отправке!");
esp_now_send(broadcastAddress1, (uint8_t *)&myData, sizeof(myData));
Serial.println("GPIO 5 off");
Serial.print("string1_0 = ");
Serial.println(string1_0);
if (string1_0)
{
string1_1 = "включен";
Serial.println("включен");
}
else {
string1_1 = "нет связи";
Serial.println("нет связи");
}
}
}
else {
Serial.println("ESP-NOW не подключился. . .");
delay(1);
}
}
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html; charset=utf-8");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
client.println("<body><h1>Свет в квартире</h1>");
client.println("<p>""Свет в ванне " + string1_1 + "</p>");
if (string1_1 == "включен") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">Выключить</button></a></p>");
}
else if (string1_1 == "выключен")
{
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">Включить</button></a></p>");
}
else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">Включить</button></a></p>");
}
client.println("</body></html>");
client.println();
break;
} else {
currentLine = "";
}
} else if (c != '\r') {
currentLine += c;
}
}
}
header = "";
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}

Первое включение.pngВторое включение.png
 

aZholtikov

Active member
// Отправляем сообщение через ESP-NOW
esp_now_send(broadcastAddress1, (uint8_t *)&myData, sizeof(myData));
Serial.println("GPIO 5 on");
Serial.print("string1_0 = ");
Serial.println(string1_0);

Первый раз при выполнении этого кода string1_0=0 потому что еще не ни разу сработал OnDataSent, а при инициализации string1_0 равна 0. Время от отправки сообщения до получения подтверждения около 10 миллисекунд. Меняйте свой алгоритм программы.
 

aZholtikov

Active member
Вы удивитесь, но если выключите приемник после некоторого количества успешных передач, данные в мониторе порта передатчика тоже будут не такие (первый раз после отправки сообщения на выключенный передатчик) как ожидаются.
 

saharesp

New member
aZholtikov, спасибо за ответ. Я знаю, что после выключения приемника первые данные тоже будут не верные. Я как раз не понимаю как изменить алгоритм. С моей точки зрения код у меня собран правильно, все действия выполняются последовательно. Мой вопрос как раз и состоит в том, как мне изменить код.
 

aZholtikov

Active member
Не буду сильно вдаваться в детали. Попробуйте понять, почему помогло (вернее должно - не на чем проверить).
P.S. Решение представляет из себя "сильно ржавый быстрый костыль" только для решения конкретного вопроса... :) Писать блокирующий код крайне не рекомендуется...

1. Объявляете глобальную переменную
Код:
bool flag=false;
2. В первой строке функции OnDataSent добавляете
Код:
flag=true;
3. Здесь добавляете блокирующую задержку для ожидания статуса отправки и изменения значения string1_0 (как я писал время от отправки до получения статуса занимает около 10 миллисекунд).
Код:
// Отправляем сообщение через ESP-NOW
esp_now_send(broadcastAddress1, (uint8_t *)&myData, sizeof(myData));
while (flag==false)
{
}
flag=false;
Serial.println("GPIO 5 on");
Serial.print("string1_0 = ");
Serial.println(string1_0);
Ну как то так...
 

saharesp

New member
aZholtikov, к сожалению работает только в одном случае: если при первом запуске удаленное устройство выключено.
 

aZholtikov

Active member
Проверить не могу, так как в данный момент нет доступа к любым ESP.
Но я надеюсь посыл понятен? Между отправкой сообщения и получением статуса доставки/недоставки должно проходить некоторое время. Ставьте флаги по событиям и обрабатывайте их в loop.
 

saharesp

New member
Zholtikov, как Вы сказали сделал задержку. Но с помощью delay (500). И да, все заработало. В моем случае это корректное применение delay. Прикрепляю файл, там видно как изменился порядок выполнения кода. Спасибо за подсказку!
Включение.png
 
Сверху Снизу