skaarj1989 / mWebSockets

WebSockets for microcontrollers
https://skaarj1989.github.io/mWebSockets/autobahn-testsuite/servers/
MIT License
106 stars 22 forks source link
arduino arduino-uno arduino-zero arm-cortex client cpp11 enc28j60 esp32 esp8266 ethernet-shield mega2560 nucleo platformio rfc6455 samd21 server stm32 w5100 w5500 websockets

μWebSockets

arduino-library-badge Build Status CodeFactor Grade GitHub

Simple to use implementation of WebSockets for microcontrollers.

List of supported IDEs:

List of supported MCUs:

WebSocketServer compatible browsers:

The Autobahn|Testsuite reports for server and client
Some tests will never pass just because of memory lack in ATmega family.

Table of contents

Requirements

Installation

Use Arduino Download Manager or follow this guide.

config.h

Change the following definition if you use a different network controller:

...

#define NETWORK_CONTROLLER ETHERNET_CONTROLLER_W5X00
ETHERNET_CONTROLLER_W5X00
ETHERNET_CONTROLLER_ENC28J60
NETWORK_CONTROLLER_WIFI

ETHERNET_CONTROLLER_W5X00 stands for the official Arduino Ethernet library.

Uncomment these if you want additional information on the serial monitor:

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

Increase the following value if you expect big data frames (or decrease for devices with a small amount of memory).

constexpr uint16_t kBufferMaxSize{ 256 };

Physical connection

If you have a WeMos D1 in the size of Arduino Uno simply attaching a shield does not work. You have to wire the ICSP on an Ethernet Shield to proper pins.

Ethernet Shield
(W5100/W5500)
Arduino
Pro Mini
WeMos D1
(ICSP) MISO PIN 12 D12 / MISO
(ICSP) MOSI PIN 11 D11 / MOSI
(ICSP) SCK PIN 13 D13 / SCK
(SS) PIN 10 PIN 10 D10 / SS
W5500 /
ENC28j60
Arduino Uno /
Pro Mini
Arduino
Mega2560
MISO PIN 12 PIN 50
MOSI PIN 11 PIN 51
SCS PIN 10 PIN 53
SCLK PIN 13 PIN 52

Usage examples

Server

#include <WebSocketServer.h>
using namespace net;

WebSocketServer server{3000};

void setup() {
  // Ethernet/WiFi initialization goes here ...
  // ...

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

    ws.onClose([](WebSocket &ws, const WebSocket::CloseCode code,
                 const char *reason, uint16_t length) {
      // ...
    });
    ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType,
                   const char *message, uint16_t length) {
      // ...
    });
  });

  server.begin();
}

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

Verify clients

// verifyClient callback is called for every header during handshake
// (except for those required by protocol, like "Connection", "Upgrade" etc.)
server.begin([](const IPAddress &ip, const char *header, const char *value) {
  // verify ip ...

  // verify "Origin" header:
  if (strcmp_P(header, (PGM_P)F("Origin")) == 0)
    if (strcmp_P(value, (PGM_P)F("file://")) == 0) return false;

  return true;
});

Subprotocol negotiation

// If you won't pass callback for `protocolHandler` then server will use the
// first requested subprotocol if any
wss.begin(nullptr, [](const char *protocols) {
  // iterate csv protocols and return the one that is supported by your server
  // or nullptr to ignore
});

// You can check client protocol in other callbacks
wss.onConnection([](WebSocket &ws) {
  const auto protocol = ws.getProtocol();
  // ...
  }
});

Node.js server examples here

Client

#include <WebSocketClient.h>
using namespace net;

WebSocketClient client;

void setup() {
  // Ethernet/WiFi initialization goes here ...
  // ...

  client.onOpen([](WebSocket &ws) {
    const char message[]{ "Hello from Arduino client!" };
    ws.send(WebSocket::DataType::TEXT, message, strlen(message));
  });
  client.onClose([](WebSocket &ws, const WebSocket::CloseCode code,
                   const char *reason, uint16_t length) {
    // ...
  });
  client.onMessage([](WebSocket &ws, const WebSocket::DataType dataType,
                     const char *message, uint16_t length) {
    // ...
  });

  client.open("echo.websocket.org", 80);
}

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

Chat

Node.js server on Raspberry Pi (/node.js/chat.js)

Browser client (/node.js/chat-client.htm)

Arduino Uno client (/examples/chat/chat.ino)

More examples here

Approx memory usage

simple-client.ino example (without debug output, 128 bytes data buffer)

Ethernet.h (W5100 and W5500)

Board Program space Dynamic memory
Arduino Uno 24 648 bytes (76%) 829 bytes (40%)
Arduino Mega2560 25 640 bytes (10%) 857 bytes (10%)
Arduino Pro Mini 24 648 bytes (80%) 829 bytes (40%)
Arduino Zero 30 596 bytes (11%) 3 056 bytes (9%)
Arduino Uno R4 Minima 63 860 bytes (24%) 3 620 bytes (11%)

EthernetENC.h (ENC28j60)

Board Program space Dynamic memory
Arduino Uno 31 062 bytes (96%) 1 406 bytes (68%)
Arduino Mega2560 32 074 bytes (12%) 1 406 bytes (17%)
Arduino Pro Mini 31 062 bytes (101%) 1 406 bytes (68%)
Arduino Zero 36 796 bytes (14%) 3 684 bytes (11%)

WiFi

Board Program space Dynamic memory
Generic ESP8266 286 328 bytes (29%) 27 356 bytes (33%)
WeMos D1 mini 286 328 bytes (27%) 27 356 bytes (33%)
NodeMCU 286 328 bytes (27%) 27 356 bytes (33%)
Arduino Uno R4 WiFi 57 596 bytes (21%) 4 492 bytes (13%)

Known issues

...

License