knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.82k stars 1.47k forks source link

Getting regular disconnects #521

Open ebivan opened 5 years ago

ebivan commented 5 years ago

Hey there, i'm using pubsubclient to publish sensor values from a BME 280 sensor on an esp8266 board. Everything works fine, but I keep getting disconnects, I think I have messed up my code somewhere.

#include <Wire.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <ArduinoJson.h>

const char* ssid = "MY_ROUTER";
const char* password = "*************";
const char* mqtt_server = "192.168.1.120";
String clientId = "TPH-Wohnzimmer";
String willTopic = "wifimqtt/tph_wohnzimmer/state";
String willMessage = "offline";
const char* stateTopic = "wifimqtt/tph_wohnzimmer/state";
const char* messTopic = "wifimqtt/tph_wohnzimmer";

WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_BME280 bme; // I2C

long lastMsg = 0;
int value = 0;
static char temperatur[15];
static char feuchte[15];
static char druck[15];
float h, t, p, pin, dp;

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  IPAddress ip(192,168,1,130);
  IPAddress gateway(192,168,1,1);
  IPAddress subnet(255,255,255,0);
  WiFi.config(ip, gateway, subnet);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientId.c_str(),willTopic.c_str(),1,true,willMessage.c_str())) {
      Serial.println("connected");
      client.publish(stateTopic, "online", true);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  delay(10);
  Wire.begin(D3, D4); //(SDA, SCL)
  Wire.setClock(100000);

  WiFi.mode(WIFI_STA); 

  setup_wifi();

  client.setServer(mqtt_server, 1883);
  Serial.println(WiFi.localIP());
  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
      // weather monitoring
    bme.setSampling(Adafruit_BME280::MODE_FORCED,
                    Adafruit_BME280::SAMPLING_X1, // temperature
                    Adafruit_BME280::SAMPLING_X1, // pressure
                    Adafruit_BME280::SAMPLING_X1, // humidity
                    Adafruit_BME280::FILTER_OFF   );

    // suggested rate is 1/60Hz (1m)

}

void loop() {

    Serial.println("Getting Sensor Data... ");
    bme.takeForcedMeasurement();
    t = bme.readTemperature();
    p = bme.readPressure()/100.0F;
    h = bme.readHumidity();

    StaticJsonBuffer<300> JSONbuffer;
    JsonObject& JSONencoder = JSONbuffer.createObject();
    JSONencoder["temperature"] = t;
    JSONencoder["pressure"] = p;
    JSONencoder["humidity"] = h; 
    char JSONmessageBuffer[100];
    JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));

      if (!client.connected()) {
          reconnect();
      }
    client.loop();

    Serial.println("Publish message: ");    
    client.publish(messTopic, JSONmessageBuffer, true);

    Serial.print("Payload: ");
     Serial.println(t);
    Serial.println(p);
    Serial.println(h);

    //delay(100);
    //ESP.deepSleep(120e6); //120sek, 2min

   for (int i=0; i <= 11; i++){
      delay(4900);
      client.publish(stateTopic, "online", true);
      Serial.println(i);

   }

}

I thought either my Mosquitto server or pubsubclient would run into timeout, so I addes the last line to send an "online" message every 4.9 seconds but this didn't help. The sensor transmits data, and reconnects, so its kind of working, but its keeps getting disconnectet and reconnect every minute or so, which is bad because Home Assistant expects the "state" to be "online".

knolleary commented 5 years ago
  1. you may be calling client.loop() too quickly - try adding a delay(100) in your main loop
  2. By adding that for loop, you are publishing a message every 4.9 seconds 11 times - so roughly 55 seconds without calling client.loop() at all. This prevents the client from doing its keep-alive handling so the default keepalive timeout of 15 seconds will expire and disconnect the client.
aaron-neal commented 5 years ago

It is not conclusive, but I have had better longevity using:

if(client.state != MQTT_CONNECTED)

rather than:

if(!client.connected())

I say not conclusive, as my disconnects were few and far between (few hours) and haven't put in the time to investigate.

benbecke commented 1 year ago

Something new on that topic ? i have the same issue even when this is the one and only client connected to the broker.

Also tried delay, and the connection detection change..

Even this code brings up the reconnects

void loop() { // Read pin values and check for changes //if (!mqttClient.connected()) { if (mqttClient.state() != MQTT_CONNECTED) {
connectToMqtt(); } mqttClient.loop();

delay(100);
}

Broker logs that :

1678195174: Client MEGA2560_004 closed its connection. 1678195190: New connection from 192.168.1.4:49156 on port 1883. 1678195190: New client connected from 192.168.1.4:49156 as MEGA2560_004 (p2, c1, k15).