Skip to content

Instantly share code, notes, and snippets.

@ClemRz
Last active July 6, 2017 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ClemRz/88b5ba77cd73a0035fd2fc6a843acb55 to your computer and use it in GitHub Desktop.
Save ClemRz/88b5ba77cd73a0035fd2fc6a843acb55 to your computer and use it in GitHub Desktop.
How to override a class in C++ in an Arduino environment

How to override a class in C++ in an Arduino environment

I was working on a custom firmware for ESP8266 using the famous Arduino library and I wanted to create a websocket server. I also wanted the EPS to serve the web page that acts as a websocket server (having the ESP in AP mode).

The awesome library ArduinoWebSockets is very easy to set up and make the ESP serve websockets connections on port 81. The thing is that when I was opening a browser at http://192.168.4.1:81 I had this message: "This is a Websocket server only!". Wow! This means that ESP is capable of returning a http message to the browser! This also means that the message could be tweaked to include the actual html page with the websocket JS client!

I looked at the library file WebSocketsServer.h and found that the method handleNonWebsocketConnection was the one sending this message. Also, this comment retained my atention: /* Note: can be override */ So I started to learn how I could override a C++ class inside the Arduino environment.

There are multiple examples of it on the Internet but none of them were showing how to override the constructor of a class!

Without further discussion, here is the magic.

overrides.h

In your Arduino IDE create a new tab named overrides.h containing the following code:

#ifndef _OVERRIDES_H
#define _OVERRIDES_H

class MyWebSocketsServer: public WebSocketsServer {
  public:
    MyWebSocketsServer(uint16_t port); // Declaration of the new constructor of my overriding class
    virtual void handleNonWebsocketConnection(WSclient_t * client);  // Declaration of the override of the virtual method
};

// This is how you override a virtual method:
void MyWebSocketsServer::handleNonWebsocketConnection(WSclient_t * client) {
  client->tcp->write("HTTP/1.1 200 OK\r\n"
          "Server: arduino-WebSocket-Server\r\n"
          "Content-Type: text/html\r\n"
          "Content-Length: 1099\r\n"
          "Connection: close\r\n"
          "\r\n"
          "<!DOCTYPE html><html><head><script>function sendRGB(){var n=parseInt(document.getElementById('r').value).toString(16),e=parseInt(document.getElementById('g').value).toString(16),o=parseInt(document.getElementById('b').value).toString(16);n.length<2&&(n='0'+n),e.length<2&&(e='0'+e),o.length<2&&(o='0'+o);var t='#'+n+e+o;console.log('RGB: '+t),connection.send(t)}var connection=new WebSocket('ws://192.168.4.1:81/',['arduino']);connection.onopen=function(){connection.send('Message from Browser to ESP8266 yay its Working!! '+new Date),connection.send('ping'),connection.send('Time: '+new Date)},connection.onerror=function(n){console.log('WebSocket Error ',n)},connection.onmessage=function(n){console.log('Server: ',n.data),connection.send('Time: '+new Date)};</script></head><body>LED Control:<br><br>R: <input id=\"r\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\"><br>G: <input id=\"g\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\"><br>B: <input id=\"b\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\"><br></body></html>");
}

// This is how you override a constructor, making a call to it's super class' constructor:
MyWebSocketsServer::MyWebSocketsServer(uint16_t port) : WebSocketsServer(port) {}

#endif  //_OVERRIDES_H

Easy hu!?

how to use it

Now in you main sketch, you have to include the ArduinoWebSockets library but also the override.h you just created. Next you will need to change the way you instaciate the WebSocketsServer class.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WebSocketsServer.h>
#include <Hash.h>
#include "overrides.h"

// Instead of instanciating original class:
// WebSocketsServer webSocket = WebSocketsServer(81);
// Instanciate your override:
MyWebSocketsServer _webSocket = MyWebSocketsServer(81);

void setup(void) {
  initAP(); // AP initialization
  initWebSocket(); // See ArduinoWebSockets' examples on how to initialize the server
}

void loop(void) {
  _webSocket.loop();
}

Et voilà!

Thanks for reading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment