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
arduino arduino-library esp32 esp8266 iot websockets

arduino-library-badge Build Status

Arduino Websockets

A library for writing modern websockets applications with Arduino (see prerequisites for supported platforms). This project is based on my project TinyWebsockets.

The library provides simple and easy interface for websockets work (Client and Server). See the basic-usage guide and the examples.

Please check out the TinyWebsockets Wiki for many more details!

Getting Started

This section should help you get started with the library. If you have any questions feel free to open an issue.

Prerequisites

Currently (version 0.5.*) the library only works with ESP8266, ESP32 and Teensy 4.1.

Installing

You can install the library from the Arduino IDE or using a release ZIP file from the Github release page. Detailed instructions can be found here.

Basic Usage

Client

Creating a client and connecting to a server:

WebsocketsClient client;
client.connect("ws://your-server-ip:port/uri");

Sending a message:

client.send("Hello Server!");

Waiting for messages:

client.onMessage([](WebsocketsMessage msg){
    Serial.println("Got Message: " + msg.data());
});

In order to keep receiving messages, you should:

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

Server

Creating a server and listening for connections:

WebsocketsServer server;
server.listen(8080);

Accepting connections:

WebsocketsClient client = server.accept();
// handle client as described before :)

Full Examples

Client

#include <ArduinoWebsockets.h>
#include <ESP8266WiFi.h>

const char* ssid = "ssid"; //Enter SSID
const char* password = "password"; //Enter Password
const char* websockets_server = "www.myserver.com:8080"; //server adress and port

using namespace websockets;

void onMessageCallback(WebsocketsMessage message) {
    Serial.print("Got Message: ");
    Serial.println(message.data());
}

void onEventsCallback(WebsocketsEvent event, String data) {
    if(event == WebsocketsEvent::ConnectionOpened) {
        Serial.println("Connnection Opened");
    } else if(event == WebsocketsEvent::ConnectionClosed) {
        Serial.println("Connnection Closed");
    } else if(event == WebsocketsEvent::GotPing) {
        Serial.println("Got a Ping!");
    } else if(event == WebsocketsEvent::GotPong) {
        Serial.println("Got a Pong!");
    }
}

WebsocketsClient client;
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);
    }

    // Setup Callbacks
    client.onMessage(onMessageCallback);
    client.onEvent(onEventsCallback);

    // Connect to server
    client.connect(websockets_server);

    // Send a message
    client.send("Hi Server!");
    // Send a ping
    client.ping();
}

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

Note: for ESP32 you only need to change to code that connects to WiFi (replace #include <ESP8266WiFi.h> with #include <WiFi.h>), everything else stays the same.

Server

#include <ArduinoWebsockets.h>
#include <ESP8266WiFi.h>

const char* ssid = "ssid"; //Enter SSID
const char* password = "password"; //Enter Password

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

  server.listen(80);
  Serial.print("Is server live? ");
  Serial.println(server.available());
}

void loop() {
  auto client = server.accept();
  if(client.available()) {
    auto msg = client.readBlocking();

    // log
    Serial.print("Got Message: ");
    Serial.println(msg.data());

    // return echo
    client.send("Echo: " + msg.data());

    // close the connection
    client.close();
  }

  delay(1000);
}

Note: for ESP32 you only need to change to code that connects to WiFi (replace #include <ESP8266WiFi.h> with #include <WiFi.h>), everything else stays the same.

Binary Data

For binary data it is recommended to use msg.rawData() which returns a std::string, or msg.c_str() which returns a const char*. The reason is that msg.data() returns an Arduino String, which is great for Serial printing and very basic memory handling but bad for most binary usages.

See issue #32 for further information.

SSL and WSS Support

No matter what board you are using, in order to use WSS (websockets over SSL) you need to use

client.connect("wss://your-secured-server-ip:port/uri");

The next sections describe board-specific code for using WSS with the library.

ESP8266

With the esp8266 there are multiple ways for using WSS. By default, ArduinoWebsockets does not validate the certificate chain. This can be set explicitly using:

client.setInsecure();

You can also use a SSL Fingerprint to validate the SSL connection, for example:

const char ssl_fingerprint[] PROGMEM = "D5 07 4D 79 B2 D2 53 D7 74 E6 1B 46 C5 86 4E FE AD 00 F1 98";

client.setFingerprint(ssl_fingerprint);

or you could use the setKnownKey() method to specify the public key of a certificate in order to validate the server you are connecting to.

PublicKey *publicKey = new PublicKey(public_key);
client.setKnownKey(publicKey);

or you can specify the Certificate Authority (CA) using setTrustAnchors method, as follows:

X509List *serverTrustedCA = new X509List(ca_cert);
client.setTrustAnchors(serverTrustedCA);

For client-side certificate validation, you can use RSA or EC certificates, using the method setClientRSACert or setClientECCert .

ESP32

With the esp32 you could either provide the full certificate, or provide no certificate. An example for setting CA Certificate:

const char ssl_ca_cert[] PROGMEM = \
    "-----BEGIN CERTIFICATE-----\n" \
    "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \
    "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
    "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \
    "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \
    "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \
    "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \
    "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \
    "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \
    "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \
    "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \
    "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \
    "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \
    "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \
    "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \
    "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \
    "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \
    "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \
    "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \
    "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \
    "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \
    "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \
    "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \
    "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \
    "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \
    "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \
    "-----END CERTIFICATE-----\n";

client.setCACert(ssl_ca_cert);

TEENSY 4.1

Currently WSS is not implemented.

Contributing

Contributions are welcomed! Please open issues if you have troubles while using the library or any queshtions on how to get started. Pull requests are welcomed, please open an issue first.

Contributors

Thanks for everyone who reported a bug, suggested a feature and contributed to the development of this library.

arnoson
⭐️ arnoson

ramdor
⭐️ ramdor

xgarb
⭐️ xgarb

matsujirushi
matsujirushi

bastienvans
bastienvans

johneakin
johneakin

lalten
lalten

adelin-mcbsoft
⭐️ adelin-mcbsoft

Jonty
⭐️ Jonty

Nufflee
Nufflee

mmcArg
mmcArg

JohnInWI
JohnInWI

logdog2709
logdog2709

elC0mpa
elC0mpa

oofnik
⭐️ oofnik

zastrixarundell
⭐️ zastrixarundell

elielmarcos
elielmarcos

Change Log