WiFiClient.cpp: 517 flush (): сбой на fd 48, errno: 11, «Больше нет процессов», что это значит?

esp32 wifi error

Здравствуйте, я написал этот скетч, который загружает показания датчика DHT22 на сервер phpMyAdmin в localHost, скетч работает нормально, данные загружаются на сервер каждые 5 минут, чем ESP засыпает, но каждый раз, когда код был выполнен, у меня есть распечатка этой ошибки в консоли, которую я не понимаю, что означает.

[  1937][E][WiFiClient.cpp:517] flush(): fail on fd 48, errno: 11, "No more processes"

здесь ниже моего скетча: скетч включает таймер каждые 5 минут, чтобы пробуждение esp считывало температуру и отправляло на сервер.

#include <Arduino.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>

// ДЛЯ датчика T
#define TsensorPin 4
#define DHTTYPE DHT22
DHT dht(TsensorPin, DHTTYPE);
String sensorName = "DHT22";
String sensorLocation = "Casa1";
float h;
float t;
float f;
float hif;
float hic;

// для подключения к Wi-Fi
const char* ssid     = "Captain Spiko";
const char* password = "123456789d";

// данные сервера
const char* serverName = "http://192.168.50.158/esp_web/post_esp.php";
String apiKeyValue = "123456789";

// для бодрствования и сна
#define uS_TO_S_FACTOR 1000000  
#define TIME_TO_SLEEP  300  
RTC_DATA_ATTR int bootCount = 0;

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void readTemperature(){
  
  h = dht.readHumidity();
  t = dht.readTemperature();
  f = dht.readTemperature(true); // в фа
  
  // Расчет теплового индекса в Фаренгейтах (по умолчанию)
  hif = dht.computeHeatIndex(f, h);
  // Расчет теплового индекса в градусах Цельсия (isFahreheit = false)
  hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

void activateSleep(){
  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush(); 
  esp_deep_sleep_start();
}

bool setupWifi(){
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  } 
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  if (WiFi.status() == WL_CONNECTED){
    return true;
  } else {
    return false;
  }



}

void postData(){
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
    http.begin(client, serverName);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    // Подготовьте данные вашего запроса HTTP POST
    String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
                          + "&location=" + sensorLocation + "&value1=" + String(h)
                          + "&value2=" + String(t) + "&value3=" + String(f) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
    int httpResponseCode = http.POST(httpRequestData);
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  }else {
    Serial.println("WiFi Disconnected");
  }
}

/// @краткая настройка
void setup() {
  
  Serial.begin(115200);
  delay(1000);
  ++bootCount; // tiene il conto dei перезапуск
  Serial.println("Boot number: " + String(bootCount));
  print_wakeup_reason();
  if (setupWifi() == true){
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);// устанавливаем следующее пробуждение через 30 секунд
    Serial.println(F("DHTxx test!"));
    dht.begin();
  };
  
  

}

/// @краткая функция цикла
void loop() {
  readTemperature();
  postData();
  activateSleep();
}

, 👍2

Обсуждение

на каком устройстве и в какой программе вы видите ошибку?, @jsotola

Я использую код VS с platformio, я вижу эту ошибку в серийной распечатке esp32, той, которая отправляет данные на сервер., @Damiano Miazzi

FD, вероятно, означает файловый дескриптор, а 48 — это число. Если это похоже на Linux, в основном все обрабатывается как файл: файлы, сокеты, процессы, ..., @Thomas Weller

Если setupWifi() == false, то dht.begin(); никогда не вызывается, но все равно входит в loop() и пытается считать температуры. Не уверен, что это хорошо или в конечном итоге приводит к неопределенному поведению., @Thomas Weller

Кроме того, я не понимаю, почему esp_sleep_enable_timer_wakeup() активируется только в том случае, если можно было подключиться к Wi-Fi. Если не удалось подключиться к Wi-Fi, вы все равно погрузитесь в глубокий сон. Но ты ведь не хочешь просыпаться через 30 секунд?, @Thomas Weller

if (WiFi.status() == WL_CONNECTED){ вернуть true; } еще {возвратите ложь; } — это карго-культовое программирование. Его можно упростить до return WiFi.status() == WL_CONNECTED. Аналогично для if (setupWifi() == true), что равно if (setupWifi()), @Thomas Weller


3 ответа


2

Я думаю, вы столкнулись с проблемой, описанной в разделе Проблемы Github для WifiClient.

Пользователь просмотрел это и обнаружил, что сообщение об ошибке не соответствует проблеме:

errno 11 (EAGAIN) возникает, когда вы начинаете читать (через функцию BSD recv) байты из потока с флагом MSG_DONTWAIT, а байтов для чтения нет. Строка ошибки ESP "Нет больше процессов" вводит в заблуждение. Это действительно "Данные недоступны, повторите попытку позже" или "Нет данных для обработки".

Похоже, что на сегодняшний день исправления для пакета еще нет, но другой пользователь опубликовал производный класс, который устраняет проблему:

Файл wifiFix.h:

#pragma once

class WiFiClientFixed : public WiFiClient {
public:
  void flush() override;
};

Файл wifiFix.cpp:

#include <WiFi.h>
#include <lwip/sockets.h>
#include "wifiFix.h"

#define WIFI_CLIENT_FLUSH_BUFFER_SIZE    (1024)

void WiFiClientFixed::flush() {
  int res;
  size_t a = available(), toRead = 0;
  if (!a) {
      return;//сбрасывать нечего
  }
  auto *buf = (uint8_t *) malloc(WIFI_CLIENT_FLUSH_BUFFER_SIZE);
  if (!buf) {
      return;//ошибка памяти
  }
  while (a) {
      // переопределить неработающий метод очистки WiFiClient, ссылка https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1237417915
      res = read(buf, min(a, (size_t)WIFI_CLIENT_FLUSH_BUFFER_SIZE));
      if (res < 0) {
          log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno));
          stop();
          break;
      }
      a -= res;
  }
  free(buf);
}

Файл main.cpp:

#include "wifiFix.h"
WiFiClient* wifi = new WiFiClientFixed();

Наконец, вместо http.begin(url); используйте http.begin(*wifi, url);

,

0

В Platformio.ini я изменил конфигурацию на "platform = [email protected]" с "platform = espressif32". Это решило эту проблему для меня

,

Как это решает проблему, я не получаю прямую окраску?, @Mike


0

Эта ошибка решена в Espressif Arduino Core 2.0.14, которая вышла в прошлом месяце. Если вы используете PlatformIO, добавьте это в свой файл Platformio.ini:

platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.05/platform-espressif32.zip

Это не из официальной ветки PlatformIO, а из Tasmota, надежного источника в сообществе PlatformIO. Посетите сайт GitHub: https://github.com/tasmota/platform-espressif32

,