skaarj1989/mWebSockets

Arduino Uno R4 WiFi: ERR_CONNECTION_REFUSED with library examples

Closed this issue · 15 comments

I want to test Arduino Uno R4 WiFi as webserver using web sockets. Real noob, but did already manage to host an html page using WiFiServer on port 80, and viewing this page via Chrome at local IP 192.168.0.xxx (DHCP assigned). With the mWebSockets simple-server example (simplified/modified code below to avoid error messages) however, I only get the following serial output:

Connecting to mySSID connected Device IP: 192.168.0.xxx

But that is all that happens. When I then use Chrome to go to 192.168.0.xxx, I get a "ERR_CONNECTION_REFUSED" page.
Even though I am currently not interested in client functionality, also there the library chat-client example results in a "ERR_CONNECTION_REFUSED" error on the serial monitor.

Connecting to mySSID connected Device IP: 192.168.0.xxx Error in connection establishment: net::ERR_CONNECTION_REFUSED Connection failed!

CODE USED:

#include <WebSocketServer.h>
using namespace net;

#include <WiFiS3.h>             // include for Arduino Uno R4 WiFi
#  define _SERIAL Serial

constexpr char kSSID[]{"xxxx"};
constexpr char kPassword[]{"yyyy"};

constexpr uint16_t port = 3000;
WebSocketServer wss{port};

void setup()
{
  _SERIAL.begin(115200);
  delay(1000);

  _SERIAL.print(F("\nConnecting to "));
  _SERIAL.println(kSSID);

  WiFi.begin(kSSID, kPassword);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    _SERIAL.print(F("."));
  }

  _SERIAL.println(F(" connected"));
  _SERIAL.print(F("Device IP: "));
  _SERIAL.println(WiFi.localIP());

  wss.onConnection([](WebSocket &ws)
    {
      const auto protocol = ws.getProtocol();
      if (protocol)
      {
        _SERIAL.print(F("Client protocol: "));
        _SERIAL.println(protocol);
      }

      ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType,
                   const char *message, uint16_t length)
        {
          switch (dataType)
          {
            case WebSocket::DataType::TEXT:
              _SERIAL.print(F("Received: "));
              _SERIAL.println(message);
            break;
            case WebSocket::DataType::BINARY:
              _SERIAL.println(F("Received binary data"));
            break;
          }

          ws.send(dataType, message, length);
        }
      );

      ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *,
                 uint16_t)
        {
          _SERIAL.println(F("Disconnected"));
        }
      );

      _SERIAL.print(F("New client: "));
      _SERIAL.println(ws.getRemoteIP());

      const char message[]{"Hello from Arduino server!"};
      ws.send(WebSocket::DataType::TEXT, message, strlen(message));
    }
  );
  wss.begin();
}


void loop()
{
  wss.listen();
}

With WebSockets you can't just enter an IP address (of a server) in a browser.
Head into src/config.h and uncomment all the debugging defines.

Thank you for the quick reply. The following debugging defines in src/config.h are uncommented:

#define _DEBUG
#define _DUMP_HANDSHAKE
#define _DUMP_HEADER
#define _DUMP_FRAME_DATA

and I also changed
define NETWORK_CONTROLLER ETHERNET_CONTROLLER_W5X00 to define NETWORK_CONTROLLER NETWORK_CONTROLLER_WIFI in the same file so the Uno R4 board is handled correctly.

When uncommenting _SERIAL.setDebugOutput(true); in the example code, I get the following error: 'class UART' has no member named 'setDebugOutput'. When uncommenting WiFi.printDiag(_SERIAL);, I get 'class CWifi' has no member named 'printDiag'. Using Arduino IDE 2.2.1.

So far still only able to start WiFi connection, obtain local IP, but not able to get any of the 3 examples past the

Error in connection establishment: net::ERR_CONNECTION_REFUSED
Connection failed!

, although I am also not sure what I am supposed to see if they would be running OK? I would expect some of the const char message[] messages going back and forth over the serial monitor? Final goal is to display a live measurement value from the Arduino in a browser page and/or read back a buttonstate/field from web page to Arduino host. Any help greatly appreciated!

And to what server you're trying to connect? any of the example ones?

Basically, I am trying to replicate this (https://gitlab.com/MrDIYca/code-samples/-/blob/master/mrdiy_websocket_project_example.ino) but with your library for Uno R4. In the meantime, I made some progress, by adding code to the simple-server example, starting a WifiServer server(80) and an html page from the Arduino (code below).

char html_template[] PROGMEM = R"=====(
<html lang="en">
   <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>WebSocketServer TEST</title>
      <script>
        socket = new WebSocket("ws:/" + "/" + location.host + ":3000");
        socket.onopen = function(e) {  console.log("[socket] socket.onopen "); };
        socket.onerror = function(e) {  console.log("[socket] socket.onerror "); };
        socket.onmessage = function(e) {  
            console.log("[socket] " + e.data);
            document.getElementById("value_1").innerHTML = e.data;
        };
      </script>
   </head>
   <body style="max-width:400px;margin: auto;font-family:Arial, Helvetica, sans-serif;text-align:center">
      <div><h1><br />TEST VALUE</h1></div>
      <div><p id="value_1" style="font-size:100px;margin:0"></p></div>
   </body>
</html>
)=====";

Now I do get serial debugging output from the sketch, as follows:

[Line #0] GET / HTTP/1.1 
   ... etc etc.
[Line #13] 
New client: 192.168.0.xxx
TX FRAME : OPCODE=1, FIN=True, RSV=0, PAYLOAD-LEN=5, MASK=None
590.0  //--> this is the correct measurement value that I want to display
TX BYTES = 7
(below this, serial monitor keeps on printing dots)

and the html web page is correctly displaying the measurement value. It is however only displaying the initial value and is not changing/updating. Adding something like wss.broadcast(WebSocket::DataType::TEXT, message, strlen(message)); to the loop does not change this. What am I missing?

If I were you I would split WebServer and WebSocket server.
Start as small as possible and gradually expand your code.

To help you debug this I'm gonna need a minimal repro code.

I do not know how I can run / test the websocket without having a browser window that is actually showing me what is going on with the websocket. By combining the simple-server example with this example (https://gitlab.com/MrDIYca/code-samples/-/blob/master/mrdiy_websocket_project_example.ino) I now have the following code, which does show a value in the browser, but is not refreshing each loop, as I would like/expect. Maybe a problem with the different global/local/constant/variable uses of the variable "message" (as (const) char [])?

#include <WebSocketServer.h>
using namespace net;

#include <WiFiS3.h>             // include for Arduino Uno R4 WiFi

#  define _SERIAL Serial

constexpr char kSSID[]{"YOUR_SSID"};
constexpr char kPassword[]{"YOUR_PASS"};

WiFiServer server(80);  // server responds to clients (in this case - web browsers) on port 80, which is a standard port web browsers talk to web servers
String header;          // from example, see if can be replaced by char arrays (c-strings)
String output = "off";  // from example, see if can be replaced by char arrays (c-strings)

const byte timeoutTime = 2;                     // timeout time for client request in seconds, e.g. 2 s

constexpr uint16_t port = 3000;
WebSocketServer wss{port};

constexpr auto kBufferSize = 64;
char message[kBufferSize]{};

//Serial.setDebugOutput(true);


// html site code: ---------------------------------------------------
char html_template[] PROGMEM = R"=====(
<html lang="en">
   <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>WebSocketServer TEST</title>
      <script>
        socket = new WebSocket("ws:/" + "/" + location.host + ":3000");
        socket.onopen = function(e) {  console.log("[socket] socket.onopen "); };
        socket.onerror = function(e) {  console.log("[socket] socket.onerror "); };
        socket.onmessage = function(e) {  
            console.log("[socket] " + e.data);
            document.getElementById("value_1").innerHTML = e.data;
        };
      </script>
   </head>
   <body style="max-width:400px;margin: auto;font-family:Arial, Helvetica, sans-serif;text-align:center">
      <div><h1><br />TEST VALUE</h1></div>
      <div><p id="value_1" style="font-size:100px;margin:0"></p></div>
   </body>
</html>
)=====";

void webServer()
{
  WiFiClient client = server.available();   // Listen for incoming clients (client = e.g. web browser)
  if (client)
  { // If a new client connects,
    Serial.println(F(""));                  // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    uint32_t nowMil = millis();             // time since Arduino program was started (overflows after 50 days but no problem)
    uint32_t oldMil;
    oldMil = nowMil;
    while (client.connected() && nowMil - oldMil <= (timeoutTime * 1000))
    { // loop while the client's connected and no timeout has occurred
      nowMil = millis();
      if (client.available())
      { // if there's bytes to read from the client,

        // METADATA CONCERNING WEBSITE REQUEST *******************************
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n')                      // if the byte is a newline character
        {                    
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:

          // RESPONSE = WRITE TO WEBSITE *******************************
          if (currentLine.length() == 0)
          {
              // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
              // and a content-type so the client knows what's coming, then a blank line:
              client.println(F("HTTP/1.1 200 OK"));
              client.println(F("Content-type:text/html"));
              client.println(F("Connection: close"));
              client.println();
            
              // DISPLAY MAIN WEB PAGE
              //client.println(PAGE_MAIN);
              client.println(html_template);

              // The HTTP response ends with another blank line
              client.println();
            
            break;  // Break out of the while loop
          }
          else
          { // if you got a newline, then clear currentLine
            currentLine = "";
          } // end of else
        } // end of if byte = \n
        else if (c != '\r')
        {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        } // end of else if
      } // end of if client available
    } // end of while client connected
    
    header = "";  // Clear the header variable
    
    // Close the connection
    client.stop();
    Serial.println(F("Client disconnected."));
    Serial.println(F(""));
  }
} //_______________________________________________________________________________________


void setup()
{
  _SERIAL.begin(115200);
  delay(1000);

  _SERIAL.print(F("\nConnecting to "));
  _SERIAL.println(kSSID);

  WiFi.begin(kSSID, kPassword);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    _SERIAL.print(F("."));
  }

  _SERIAL.println(F(" connected"));
  _SERIAL.print(F("Device IP: "));
  _SERIAL.println(WiFi.localIP());

  wss.onConnection([](WebSocket &ws) {
    const auto protocol = ws.getProtocol();
    if (protocol) {
      _SERIAL.print(F("Client protocol: "));
      _SERIAL.println(protocol);
    }

    ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType,
                   const char *message, uint16_t length) {
      switch (dataType) {
      case WebSocket::DataType::TEXT:
        _SERIAL.print(F("Received: "));
        _SERIAL.println(message);
        break;
      case WebSocket::DataType::BINARY:
        _SERIAL.println(F("Received binary data"));
        break;
      }

      ws.send(dataType, message, length);
    });

    ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *,
                 uint16_t) { _SERIAL.println(F("Disconnected")); });

    _SERIAL.print(F("New client: "));
    _SERIAL.println(ws.getRemoteIP());

    // const char message[]{"Hello from Arduino server!"}; instead of fixed message: want to send variable test value
    ws.send(WebSocket::DataType::TEXT, message, strlen(message));
  });

  wss.begin();       // start the websocketserver
  
  server.begin();  // start the web server
}


void loop()
{
    
    uint16_t val1 = analogRead(0); // measurement value to be displayed
    char valbuf[8];
    dtostrf(val1, 1, 1, valbuf);
    memset(message, 0, sizeof(message));
    strcat(message, valbuf);
    strcat(message, "\0");

    /*
    Serial.print(message); // to show that measured value is changing
    Serial.print(F(" ")); // to show that measured value is changing
    */

    if (WiFi.status() == WL_CONNECTED || WiFi.status() == WL_AP_CONNECTED)  // if connected to WiFi (or as access point),
    {
      webServer();                      // run webserver
      
      wss.listen();
      wss.broadcast(WebSocket::DataType::TEXT, message, strlen(message));
    }

  //delay(100);
}

You can move the html file to your PC (thats what I do).

Looks like the WebSocketServer closes a connection for some reason.
Investigating ...

Works fine without webServer() in the main loop function.

Could you please elaborate on how to test the websocket with a local html file? Comment out the webServer() in the main loop, save the hmtl page locally as .html (in sketch folder?) and then what? How to run the code and see the updated measurement value?

Well ... just open the html file in your browser.
And update the following line to the actual IP/port:

socket = new WebSocket("ws:/" + "/" + location.host + ":3000");

OK, that is indeed working, thank you very much for your time! So now I need to get working on the webServer function and make sure that it does not interfere with the webserversocket or close it prematurely?

Hi, I use the lastest code of auther orderFDW in this post for UNO R4 in Arduino IDE.
I modified the file in \libraries\mWebSockets\src\base64, the file "Base64.cpp", i modified this (to solve problem of some error)
#include <avr\pgmspace.h>
with
#if (defined(AVR))
#include <avr\pgmspace.h>
#else
#include <pgmspace.h>
#endif

then, compile the code, almost is fine, but some error like this
WARNING: library mWebSockets claims to run on avr, esp8266, esp32, sam, samd, stm32 architecture(s) and may be incompatible with your current board which runs on renesas_uno architecture(s).
In file included from C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/utility.h:3:0,
from C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/WebSocket.h:5,
from C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/WebSocketServer.h:5,
from C:\Users\baank\OneDrive\Documents\Arduino\UNOR4_web_socket\UNOR4_web_socket.ino:1:
C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/platform.h:33:4: error: #error "Unsupported platform"

error "Unsupported platform"

^~~~~

exit status 1

Compilation error: exit status 1

Coulde you please guide me how to do next? I really want to run web socket in UNO R4 wifi. Please help, thanks.

Hi again,
in config.h file, when i change #define NETWORK_CONTROLLER ETHERNET_CONTROLLER_W5X00 ---> #define NETWORK_CONTROLLER NETWORK_CONTROLLER_WIFI
It will have error after compiling:
WARNING: library mWebSockets claims to run on avr, esp8266, esp32, sam, samd, stm32 architecture(s) and may be incompatible with your current board which runs on renesas_uno architecture(s).
In file included from C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/utility.h:3:0,
from C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/WebSocket.h:5,
from C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/WebSocketServer.h:5,
from C:\Users\baank\OneDrive\Documents\Arduino\UNOR4_web_socket\UNOR4_web_socket.ino:1:
C:\Users\baank\OneDrive\Documents\Arduino\libraries\mWebSockets\src/platform.h:33:4: error: #error "Unsupported platform"

error "Unsupported platform"

^~~~~

Multiple libraries were found for "WiFi.h"
Used: C:\Users\baank\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\libraries\WiFiS3
Not used: C:\Users\baank\OneDrive\Documents\Arduino\libraries\WiFiEspAT
Not used: C:\Users\baank\OneDrive\Documents\Arduino\libraries\WiFiNINA
exit status 1

Compilation error: exit status 1

@fumikrobot Use master branch.
Do not hesitate to create your own issue (your problem is outside of the scope of this one).

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.