Skip to content
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

WebSocket is already in CLOSING or CLOSED state. #6

Closed
xgarb opened this issue May 9, 2019 · 5 comments
Closed

WebSocket is already in CLOSING or CLOSED state. #6

xgarb opened this issue May 9, 2019 · 5 comments
Labels
usage queshtion Queshtions about using the library, its interface and so on

Comments

@xgarb
Copy link

xgarb commented May 9, 2019

I'm not sure I'm doing this right. I'm want to send a stream of co-ordinates from the browser and drive a servo based on them, I get one though and then the browser error shown in the subject line above. Code pasted below.

Maybe auto client = server.accept(); should be outside the loop?

#include <ArduinoWebsockets.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>

AsyncWebServer webserver(80);

using namespace websockets;
WebsocketsServer server;

void setup() {
  Serial.begin(115200);
  
  // Connect to wifi
  WiFi.begin(ssid, password);

  // Wait some time to connect to wifi
  for(int i = 0; i < 15 && WiFi.status() != WL_CONNECTED; i++) {
      Serial.print(".");
      delay(1000);
  }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());   //You can get IP address assigned to ESP
  
  webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html_gz, sizeof(index_html_gz));
    response->addHeader("Content-Encoding", "gzip");
    request->send(response);
  });
  
  webserver.begin();
  server.listen(83);
  Serial.print("Is server live? ");
  Serial.println(server.available());
}

void loop() {
  auto client = server.accept();
  if(client.available()) {
    Serial.println("client.available");
    auto msg = client.readBlocking();
	
    // log
    Serial.print("Got Message: ");
    Serial.println(msg.data());
  }
}
@gilmaimon
Copy link
Owner

Hi! Thank you for opening an issue.

What your code in loop does, is:

  1. accept a websockets connection
  2. read 1 message from the connection
  3. print that message

So, for every iteration of loop you accept a new connection. It is not completely sure what you are trying to do, but if I understand correctly you want to accept a connection and then print everything that is sent to you in that connection?
You can do this:

void loop() {
  auto client = server.accept();
  while(client.available()) {
    Serial.println("client.available");
    auto msg = client.readBlocking();
	
    // log
    Serial.print("Got Message: ");
    Serial.println(msg.data());
  }
}

Notice how I changed the if(client.available()) to while(client.available())! So now, while the client is connected, the code will print everything the client sends. If the client disconnects, it will exit the loop and will wait for the next client to connect. Is that more like what you want?

Few notes:

  • If the client will disconnect, readBlocking will return an empty message. You can check if a message is empty by using msg.isEmpty().
  • readBlocking will also return messages that are not data. For example pings, pongs, and close messages (those are all control messages in the websockets protocol). You can check if a message is text by using msg.isText().

You can get rid of those checks if you use the callback-based interface. It will look like this:

void handle_message(WebsocketsMessage msg) {
    // log
    Serial.print("Got Message: ");
    Serial.println(msg.data());
}

void loop() {
  auto client = server.accept();
  client.onMessage(handle_message);
  while(client.available()) {
     client.poll();
  }
}

This code accepts a connection, and while the connection is open, does polling. Polling is checking if there is anything new, and if there is, it will call the callback (in this case, I called it handle_message,

Gil.

@gilmaimon gilmaimon added the usage queshtion Queshtions about using the library, its interface and so on label May 9, 2019
@xgarb
Copy link
Author

xgarb commented May 10, 2019

Thanks for your detailed response. The final project is to add pan and tilt to an ESP32 based camera board. For this I need to send a 'stream' of jpgs from the camera to the browser and the browser to be able to send a 'stream' of co-ordinates (from a touch interface) to the ESP.

I've tried nearly every combination of async, sync http and websocket servers to get this working and the solution is always just around the corner!

Your code below worked perfectly the first time I tried

void handle_message(WebsocketsMessage msg) {
  // log
  Serial.print("Got Message: ");
  Serial.println(msg.data());
  int panValue = msg.data().toInt();
  ledcAnalogWrite(2, panValue + 90);
}

void loop() {
  auto client = server.accept();
  client.onMessage(handle_message);
  while (client.available()) {
    client.poll();
  }
}

I had the servo whizzing back and forth but now it stops after a bit with the same error but I think this is because the ESP32 has locked up. Maybe it's Wifi related that it worked better before. I should probably restrict the number of times coordinates are sent from the browser.

This code worked really well for streaming the camera data:

void loop() {
  auto client = server.accept();
  client.onMessage(handle_message);
  while (client.available()) {
      cam.run();
      client.sendBinary((const char*)cam.getfb(), (size_t)cam.getSize());
  }
}

I'll try again with it tomorrow. Here's my messy code if you want to try it: https://pastebin.com/cs0CSntM

@gilmaimon
Copy link
Owner

Interesting. You can try adding some delay between calls to poll. Also it is a very good idea to add delays between client.send.. calls. From previous experiances it seems like the esp32's internal buffer will overflow if you keep sending without any delay (so it does not finish actually sending the buffer before it overflows).

Also, if you want to see more info about the errors with the esp32, change the board to "ESP32 Dev Module" and change Core Debug Level to Error or if you really want to see everything, to Verbose.

Share the crash/fail logs here, it might help.

Also, where do you see the error "WebSocket is already in CLOSING or CLOSED state"? Is it in the browser that sends the data or in the esp32?

Gil.

@gilmaimon
Copy link
Owner

Is it working now?

@xgarb
Copy link
Author

xgarb commented May 19, 2019

I got distracted by another project. I'll get back to this one soon!

@xgarb xgarb closed this as completed May 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
usage queshtion Queshtions about using the library, its interface and so on
Projects
None yet
Development

No branches or pull requests

2 participants