Skip to content

client.connected() return true when internet lost connection #8327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
6 tasks done
ruem2802 opened this issue Oct 1, 2021 · 6 comments
Closed
6 tasks done

client.connected() return true when internet lost connection #8327

ruem2802 opened this issue Oct 1, 2021 · 6 comments

Comments

@ruem2802
Copy link

ruem2802 commented Oct 1, 2021

----------------------------- Delete below -----------------------------

If your issue is a general question, starts similar to "How do I..", is related to 3rd party libs, or is related to hardware, please discuss at a community forum like esp8266.com.

INSTRUCTIONS

If you do not follow these instructions, your issue may be dismissed.

  1. Follow the checklist under Basic Infos and fill in the [ ] spaces with an X.
  2. Fill in all the fields under Platform and Settings in IDE marked with [ ] (pick the correct option for you in each case, delete the others).
  3. If you haven't already done so, test your issue against current master branch (aka latest git), because it may have been already fixed.
  4. Describe your problem.
  5. If you have a STACK DUMP decode it:

https://arduino-esp8266.readthedocs.io/en/latest/Troubleshooting/stack_dump.html

  1. Include a Minimal Complete Reproducible Example sketch that shows your issue. Do not include your entire project, or a huge piece of code.
  2. Include debug messages:

https://arduino-esp8266.readthedocs.io/en/latest/Troubleshooting/debugging.html

  1. Use markup (buttons above) and the Preview tab to check what the issue will look like.
  2. Delete these instructions from the above to the below marker lines before submitting this issue.

----------------------------- Delete above -----------------------------

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: [ESP-12|ESP-01|ESP-07|ESP8285 device|other]
  • Core Version: [latest git hash or date]
  • Development Env: [Arduino IDE|Platformio|Make|other]
  • Operating System: [Windows|Ubuntu|MacOS]

Settings in IDE

  • Module: [Generic ESP8266 Module|Wemos D1 mini r2|Nodemcu|other]
  • Flash Mode: [qio|dio|other]
  • Flash Size: [4MB/1MB]
  • lwip Variant: [v1.4|v2 Lower Memory|Higher Bandwidth]
  • Reset Method: [ck|nodemcu]
  • Flash Frequency: [40Mhz]
  • CPU Frequency: [80Mhz|160MHz]
  • Upload Using: [OTA|SERIAL]
  • Upload Speed: [115200|other] (serial upload only)

Problem Description

Detailed problem description goes here.

MCVE Sketch

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define BUTTON D1 
// WiFi
const char *ssid = "mousse"; // Enter your WiFi name
const char *password = "qweqweqwe";  // Enter WiFi password

// MQTT Broker
const char *mqtt_broker = "broker.emqx.io";
const char *topic = "esp8266/test";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
const int mqtt_port = 1883;
bool status_internet = true ;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  // Set software serial baud to 115200;
  Serial.begin(115200);
   pinMode(BUTTON, INPUT); // Button 1 as input
  // connecting to a WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  //connecting to a mqtt broker
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);
  while (!client.connected()) {
      status_internet  = fail;
      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(), mqtt_username, mqtt_password)) {
          status_internet  = true;
          Serial.println("Public emqx mqtt broker connected");
      } else {    
          Serial.print("failed with state ");
          Serial.print(client.state());
          delay(2000);
      }
  }
  // publish and subscribe
  client.publish(topic, "hello emqx");
  client.subscribe(topic);
}

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("-----------------------");
}

void check_input()
{
  if(digitalRead(BUTTON_1) client.publish("state button", 1);
  else client.publish("state button", 0);
}
void loop() {
  client.loop();
check_input();
}

Debug Messages

Debug messages go here

When internet lost connection client.connected() return true so I continue to publish -> Error

@mcspr
Copy link
Collaborator

mcspr commented Oct 1, 2021

This is not related to Core though? Example code you provided deals with PubSubClient, which is an external library and is not maintained in this repo. Check out the example code dealing with disconnections, and if that does not work please report to the PubSubClient repo instead:
https://github.com/knolleary/pubsubclient
https://github.com/knolleary/pubsubclient/blob/master/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino

@mcspr mcspr closed this as completed Oct 1, 2021
@ruem2802
Copy link
Author

ruem2802 commented Oct 1, 2021

@mcspr i checked pubsubclient.cpp, in function client.connected() they call core 's function: when lost connection (i unplug the network) -> function 's esp8266 (_client->connected) not return false state instantly
image

@mcspr
Copy link
Collaborator

mcspr commented Oct 2, 2021

Yes, but this does not happen immediately
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/client-class.html
https://www.arduino.cc/en/Reference/WiFiClientConnected

connected()
Whether or not the client is connected. Note that a client is considered connected if the connection has been closed but there is still unread data.

uint8_t WiFiClient::connected()
{
if (!_client || _client->state() == CLOSED)
return 0;
return _client->state() == ESTABLISHED || available();
}

_client->state() also does not change straight away when you hard-disconnect by unplugging the cable and thus wificlient will still think it is connected for a while (...at least 15min, iirc?). PubSubClient has an additional check for MQTT ping packets, see keepAlive (based on MQTT_KEEPALIVE) time checks at the top of the 'loop()'. It should notice that as there's no network activity and it will stop the underlying client in about 15seconds (default) and return 'false'.

@ruem2802
Copy link
Author

ruem2802 commented Oct 2, 2021

@mcspr Thank for support!!

@d-a-v
Copy link
Collaborator

d-a-v commented Oct 4, 2021

Regarding

connected()
Whether or not the client is connected. Note that a client is considered connected if the connection has been closed but there is still unread data.

While it is true that historically, ::connected() is true when ::available() is true, this assertion has been removed some time ago because it leaded to network issues.

Currently ::connected() is a synonym of Peer can still send us data in the future = the posix meaning or a connected tcp link. When it is false, no more new data can be received, but we can have unread data in the receive buffer, which ::available() is able to tell us.
This is described in our documentation and I can link to the history of this change on request (or update doc or whatever is needed to make things more clear).

@mcspr
Copy link
Collaborator

mcspr commented Oct 4, 2021

Currently ::connected() is a synonym of Peer can still send us data in the future = the posix meaning or a connected tcp link. When it is false, no more new data can be received, but we can have unread data in the receive buffer, which ::available() is able to tell us.
This is described in our documentation and I can link to the history of this change on request (or update doc or whatever is needed to make things more clear).

Then, should the notice be in the our client doc? 'git-blame' points to #4626, and there was at least one discussion related to the change at #6701 (which did not actually result in updating the docs... :/)

Something like

Whether or not the client is connected. Notice that a client is considered disconnected when the underlying connection is closed, even when there is still an unread data.

And replace the 'connected()' link with a html header link to the paragraph included in the wificlient class page

Also from cross-links, there's at least one patch to the pubsubclient that tweaks it's behaviour and uses ::available() before ::connected()
https://github.com/letscontrolit/ESPEasy/pull/2811/files
https://github.com/letscontrolit/ESPEasy/blob/mega/lib/pubsubclient/src/PubSubClient.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants