Simple to use implementation of WebSockets for microcontrollers.
List of supported IDEs:
- Arduino
- Visual Studio Code with Platformio
- Microsoft Visual Studio with Visual Micro
List of supported MCUs:
- ATmega328P
- ATmega2560
- Renesas RA4M1 (ARM Cortex-M4)
- SAMD21 (ARM Cortex-M0+)
- STM32 (ARM Cortex-M)
- ESP8266
- ESP32-WROOM-32D
WebSocketServer compatible browsers:
- Chrome
- Edge
- Firefox
- Opera
The Autobahn|Testsuite reports for server and client
Some tests will never pass just because of memory lack in ATmega family.
- Development board (confirmed working, other boards may or may not work):
- Arduino Uno (ATmega328P)
- Arduino Pro Mini (ATmega328P)
- Arduino Mega2560
- Arduino Uno R4 Minima/WiFi (ARM Cortex-M4)
- Arduino Zero / SAMD21 M0 (ARM Cortex-M0)
- STM Nucleo-64 (ARM Cortex-M)
- WeMos D1 mini (ESP8266)
- NodeMCU v3 (ESP8266)
- ESPDUINO-32 (ESP32-WROOM-32D)
- Ethernet module or shield (confirmed working):
- Arduino Ethernet Shield (W5100)
- Arduino Ethernet Shield 2 (W5500)
- WizNet W5500 module
- ENC28j60
- Libraries:
- EthernetENC if you decide to use ENC28j60
Use Arduino Download Manager or follow this guide.
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 };
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 |
#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();
}
// 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;
});
// 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
#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();
}
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
simple-client.ino
example (without debug output, 128 bytes data buffer)
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%) |
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%) |
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%) |
...
- This project is licensed under the MIT License - see the LICENSE file for details
- arduino-base64 licensed under licensed under MIT License
- arduinolibs licensed under the MIT
- utf8_check licensed under the MIT