MQTT et DeepSleep

Bonjour à tous,

J'ai fabriqué un capteur de température et d'humidité, à base de NodeMCU et DHT22.
Je cherche à envoyer les données recueillies en MQTT sur un broker mosquitto (installé en local sur ma config jeedom).
Comme le tout fonctionne sur batterie, j'active le mode deepSleep à la fin de mon code.

Le code fonctionne parfaitement sans le mode deepSleep. Les messages sont biens reçus par le broker. En revanche, en mode deepSleep, le broker ne reçoit plus rien.

Hypothèse : la confirmation ne peut pas être réceptionné par le NodeMCU, vu que ce dernier est en mode deepSleep... Je ne sais pas si cela vient de là ?

Voici le code :

#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>
#include "DHT.h"
 
//replace with your network credentials
#define WIFI_SSID "SFR-5120"
#define WIFI_PASSWORD "WHITESPIRIT9"

 // Raspberry Pi Mosquitto MQTT Broker
#define MQTT_HOST IPAddress(192, 168, 0, 38)
#define MQTT_PORT 1883

//MQTT Topics
#define MQTT_PUB_TEMP "temp/salon"
#define MQTT_PUB_HUM  "hum/salon"

#define DHTPIN 13 
#define DHTTYPE DHT22 
DHT dht(DHTPIN, DHTTYPE);

float temp;
float hum;

#define DurationSleep 10 //SECONDES

AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;

WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;

unsigned long previousMillis = 0;   
const long interval = 5000;        

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void onWifiConnect(const WiFiEventStationModeGotIP& event) {
  Serial.println("Connected to Wi-Fi.");
  connectToMqtt();
}

void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
  Serial.println("Disconnected from Wi-Fi.");
  mqttReconnectTimer.detach(); 
  wifiReconnectTimer.once(2, connectToWifi);
}

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");

  if (WiFi.isConnected()) {
    mqttReconnectTimer.once(2, connectToMqtt);
  }
}

void onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  
  dht.begin();
  
  wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
  wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
  

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  
  connectToWifi();
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    hum = dht.readHumidity();
    temp = dht.readTemperature();
    
    if (isnan(temp) || isnan(hum)) {
      Serial.println(F("Failed to read from DHT sensor!"));
      return;
    }  
    
    // Publish an MQTT message on topic esp8266/dht/temperature
    uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());                            
    Serial.printf("Publishing on topic %s at QoS 1, packetId: %i", MQTT_PUB_TEMP, packetIdPub1);
    Serial.printf("Message: %.2f \n", temp);

    // Publish an MQTT message on topic esp8266/dht/humidity
    uint16_t packetIdPub2 = mqttClient.publish(MQTT_PUB_HUM, 1, true, String(hum).c_str());                            
    Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_HUM, packetIdPub2);
    Serial.printf("Message: %.2f \n", hum);
   
    ESP.deepSleep(DurationSleep*1000000);
  }
}

Quelqu'un a une idée ? :slight_smile:

Bonsoir

Hypothèse : la confirmation ne peut pas être réceptionné par le NodeMCU, vu que ce dernier est en mode deepSleep... Je ne sais pas si cela vient de là ?

une petite attente de qq secondes avant la mise en sommeil permettrait de tester l'hypothèse

Si pas OK je joins pour information un code qui a longtemps tourné pour publier vers le broker d'Adafruit (AIO). La carte est ici une carte à ESP32, la configuration du deepsleep est un peu différente des ESP8266 mais ça revient au même pour l'organisation d'ensemble du programme
A l'époque je cherchais à réduire le plus possible la durée d'une 'session', d'où le suivi de celle-ci
mqtt-vers-AIO_avec_sleep.ino (3.0 KB)

Il me semble d'un delay() bloque l'interception des messages MQTT

Il me semble d'un delay() bloque l'interception des messages MQTT

peut être mais pas certain, delay() sur ESP8266 n'est pas aussi bloquant que sur AVR, il rend la main a la pile WiFi

+de toutes façons delay() n'est pas la seule méthode pour temporiser, on peut faire ça avec millis()

Tu peux aussi coller la sortie sur le moniteur série ?
L'idéal étant de mettre en veille, lorsque tu as obtenue la confirmation de l'envoi de la requête.
Cela évite les temporisations hasardeuses

Bonjour,

J'ai également rencontré ce souci sur un sketch. Cette page m'avais aidé à résoudre le problème:

(Pour ma part, mon script contient un delay(500) après le WiFi.disconect.)

Bonne bidouilles.
A+

Merci pour vos retours.
Avec votre aide et un peu de bidouille, je publie ici le code fonctionnel pour les suivants :slight_smile:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

#define DURATION_SLEEP  300   //Duration sleep in seconds

// WiFi
const char *ssid = "SSID"; // Enter your WiFi name
const char *password = "PASSWD";  // Enter WiFi password

// MQTT Broker
const char *mqtt_broker = "192.168.0.38";  //Remplacer par l'IP local du broker
 
const char *topic_temp = "salon/temp";
const char *topic_hum = "salon/hum";
//const char *mqtt_username = "emqx";  //si utile
//const char *mqtt_password = "public";  //si utile
const int mqtt_port = 1883;

//DHT
#define DHTPIN 13 
#define DHTTYPE DHT22 
DHT dht(DHTPIN, DHTTYPE);
float temp;
char tempString[6];
float hum;
char humString[6];

WiFiClient espClient;
PubSubClient client(espClient);



// ----------------------------------------------- SETUP -------------------

void setup() {
  // Set software serial baud to 115200;
  Serial.begin(115200);
  // connecting to a WiFi network
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  
  Serial.println("Connected to the WiFi network");
  //connecting to a mqtt broker
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);
  while (!client.connected()) {
      String client_id = "esp8266-client-";
      client_id += String(WiFi.macAddress());
      Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
      if (client.connect(client_id.c_str())) {
          Serial.println("Public emqx mqtt broker connected");
      } else {
          Serial.print("failed with state ");
          Serial.print(client.state());
          delay(2000);
      }
  }



  dht.begin();
  

}

// ----------------------------------------- CALLBACK -----------------------------------------

void callback(char *topic, byte *payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
      Serial.print((char) payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
}

//-------------------------------------------------- LOOP -------------------------------
void loop() {
  client.loop();
  
  //TEMPERATURE
  temp = dht.readTemperature();
  dtostrf(temp, 2, 2, tempString);
  Serial.println(tempString);

  //HUMIDITE
  hum = dht.readHumidity();
  dtostrf(hum, 2, 2, humString);
  Serial.println(humString);
  

    // publish and subscribe
  // Version originale :   
  //client.publish(topic, "hello emqx");
    client.publish(topic_temp, tempString); 
    client.subscribe(topic_temp);
    client.publish(topic_hum, humString);  
    client.subscribe(topic_hum);
  delay(1000);

  //DEEPSLEEP
  WiFi.disconnect();
  client.disconnect();

  ESP.deepSleep(DURATION_SLEEP*1000000);
}

Merci pour le retour