gilmaimon / ArduinoWebsockets

A library for writing modern websockets applications with Arduino (ESP8266 and ESP32)
GNU General Public License v3.0
482 stars 97 forks source link

Disconnect from websocket server cannot reconnect #75

Closed andreapas79 closed 4 years ago

andreapas79 commented 4 years ago

Hi, really nice work, your library is really useful. My problem is this I have a WebSocket server with python and some clients with your WebSockets. Sometime after sending 100/200 messages, the client disconnect from the server and I cannot able to reconnect again...I must reset the client to work it again. Another question: how can I manage sending a message(for example sensor data) without interrupting listening, I tried with interrupts but restart the connection every time. Until now the only way I found, it's during GotPing event, some other ideas?

#include <ESP8266WiFi.h>
#include <Arduino_JSON.h>

//library By Gil Maimon https://github.com/gilmaimon/ArduinoWebsockets
#include <ArduinoWebsockets.h> 

const char* ssid = "ssid";
const char* password =  "password";
const char* websockets_server_host = "192.168.1.113"; //Enter server adress
const uint16_t websockets_server_port = 5000; // Enter server port

using namespace websockets;
JSONVar myObject;
WebsocketsClient client;

void(* Reboot)(void) = 0;

void onEventsCallback(WebsocketsEvent event, String data) {
    if(event == WebsocketsEvent::ConnectionOpened) {
        Serial.println("Connnection Opened");
    } else if(event == WebsocketsEvent::ConnectionClosed) {
        Serial.println("Connnection Closed");
        Reboot();
    } else if(event == WebsocketsEvent::GotPing) {
        myObject["action"] = WiFi.localIP().toString();
        myObject["tipo"] = "LED";
        myObject["valore"] = random(300);
        client.send(JSON.stringify(myObject));
        Serial.print(JSON.stringify(myObject));
        Serial.println("Got a Ping!");
    } else if(event == WebsocketsEvent::GotPong) {
        Serial.println("Got a Pong!");
    }
}

void connect_to_server(){
  bool connected = client.connect(websockets_server_host, websockets_server_port, "/");
  if(connected) {
    Serial.println("Connected!");
    myObject["action"] = WiFi.localIP().toString();
    myObject["tipo"] = "LED";
    myObject["valore"] = random(300);
    client.send(JSON.stringify(myObject));
    Serial.print(JSON.stringify(myObject));
  } else {
    Serial.println("Not Connected!");
  }

  // run callback when messages are received
  client.onMessage([&](WebsocketsMessage message) {
    Serial.print("Got Message: ");
    Serial.println(message.data());
  });
  client.onEvent(onEventsCallback);
}

void setup() {
    Serial.begin(115200);
    // Connect to wifi
    WiFi.begin(ssid, password);
    // Wait some time to connect to wifi
    for(int i = 0; i < 10 && WiFi.status() != WL_CONNECTED; i++) {
        Serial.print(".");
        delay(1000);
    }
    // Check if connected to wifi
    if(WiFi.status() != WL_CONNECTED) {
        Serial.println("No Wifi!");
        return;
    }

    Serial.println("Connected to Wifi, Connecting to server.");
    // try to connect to Websockets server
    connect_to_server();
}

void loop() {
   client.poll();  
}
gilmaimon commented 4 years ago

Hi, sorry for the long delay.

There are a few questions here, I'll try answering all of them.

Resetting the client

Currently, the client object will only work for one connection. Meaning you cannot use the same instance for connect(...) twice (for example, calling connect after the client disconnected once). The solution for that is doing:

WebsocketsClient client;
// ...
client = {}; // This will reset the client object

Sending and receiving simultaneously

The code for receiving websocket messages are executed in your loop (client.poll does the work). You can always do multiple stuff, for example:

// update interval is 10 seconds in this example
#define UPDATE_INTERVAL (1000 * 10)

int last_update_sent = 0;

void loop() {
   if (millis() - last_update_sent > UPDATE_INTERVAL) {
      client.send("here is an update");
      last_update_sent = millis();
   }
  // we execute poll anyways
  client.poll(); 
}

Client disconnects after sending 100/200 messages

This might be a bug, but it might also be a usage issue. Do you sleep between sending messages? If you won't give the firmware some time to do it's internal stuff (handle incoming and send outgoing tcp buffers) it might result in a disconnect. Unless you are doing some task that requires extremely short update intervals, just sleep in your loop and you'll be fine :)

Thanks. Gil.

gilmaimon commented 4 years ago

Closing for inactivity, hopefully I resolved your issues.