BojanJurca / Esp32_oscilloscope

ESP32 oscilloscope - see the signals through Web browser the way ESP32 sees them
Creative Commons Zero v1.0 Universal
741 stars 84 forks source link

Request for barebone websocket server #6

Closed happytm closed 3 years ago

happytm commented 3 years ago

This is not an issue.

Thank you for comprehensive multi web server piece of software. I am enjoying testing it.

If time allows can you just create a repository with just websocket server for ESP32?

No FTP server, no HTTP server , no time related code. Just plain websocket server which can communicate with javascript client in web browser and may be display a graph from couple of variables like you show for freeheap and uptime on index page of your Esp32_web_ftp_telnet_server_template.

It should be barebone template where it is simple and people like me can understand and use it in their small project like home automation without complexity of all in one software.

Thank you.

BojanJurca commented 3 years ago

Hi. Sorry for late reply, I was taking vacations. I'll prepare something for you soon.

happytm commented 3 years ago

Thank you.

BojanJurca commented 3 years ago

/*

Demo1 - this is a minimum you need to do in order to make (only) web server (without websockets) to work

(other demos will follow)

*/

include

define HOSTNAME "MyESP32Server" // define the name of your ESP32 here

define MACHINETYPE "ESP32 NodeMCU" // describe your hardware here

// connect ESP32 in STAtion mode to your WiFi router ...

define DEFAULT_STA_SSID "YOUR_STA_SSID"

define DEFAULT_STA_PASSWORD "YOUR_STA_PASSWORD"

// ... but don't let ESP32 to set up its own A(ccess) P(oit)

define DEFAULT_AP_SSID ""

define DEFAULT_AP_PASSWORD ""

include "./servers/network.h"

include "./servers/webServer.hpp"

// Callback function that will handle all HTTP requests (since we do not have any file system mounted // to be able to pass .html and other files to client, this callback function is the only possibility // we have to respond to HTTP requests from clients (browsers)

String httpRequestHandler (String& httpRequest, httpServer::wwwSessionParameters *wsp) { // - must be reentrant! if (httpRequest.substring (0, 6) == "GET / ") { return String ("Example 01 - dynamic HTML page


") + (digitalRead (2) ? "Led is on." : "Led is off.") + String ("
"); }

return ""; // httpRequestHandler did not handle the request - tell httpServer to handle it internally (404, ...) by returning "" reply }

void setup () { Serial.begin (115200);

startNetworkAndInitializeItAtFirstCall (); // since we do not have any file system mounted this would only start WiFi // but won't initialize network configuration files

// start web server httpServer httpSrv = new httpServer (httpRequestHandler, // our HTTP callback function NULL, // no WS callback function 8 1024, // 8 KB stack size is usually enough, if httpRequestHandler or wsRequestHandler use more stack increase this value until server is stable (char *) "0.0.0.0", // start HTTP server on all available ip addresses 80, // HTTP port NULL); // no firewall callback function if (!httpSrv || (httpSrv && !httpSrv->started ())) Serial.println ("[httpServer] did not start."); }

void loop () {

}

BojanJurca commented 3 years ago

The function that is not displayed correctly looks like this:

image

BojanJurca commented 3 years ago

/*

Demo2 - this is a minimum you need to do in order to make (only) web server with websockets to work

(other demos will follow)

*/

include

define HOSTNAME "MyESP32Server" // define the name of your ESP32 here

define MACHINETYPE "ESP32 NodeMCU" // describe your hardware here

// connect ESP32 in STAtion mode to your WiFi router ...

define DEFAULT_STA_SSID "YOUR_STA_SSID"

define DEFAULT_STA_PASSWORD "YOUR_STA_PASSWORD"

// ... but don't let ESP32 to set up its own A(ccess) P(oit)

define DEFAULT_AP_SSID ""

define DEFAULT_AP_PASSWORD ""

include "./servers/network.h"

include "./servers/webServer.hpp"

// Callback function that will handle all HTTP requests (since we do not have any file system mounted // to be able to pass .html and other files to client, this callback function is the only possibility // we have to respond to HTTP requests from clients (browsers)

String httpRequestHandler (String& httpRequest, httpServer::wwwSessionParameters *wsp) { // - must be reentrant! if (httpRequest.substring (0, 6) == "GET / ") { return "\n" " \n" " RSSI

...
dBm\n" "\n" " \n" " \n" "\n"; }

return ""; // httpRequestHandler did not handle the request - tell httpServer to handle it internally (404, ...) by returning "" reply }

// Callback function that will handle all WS (websocket) requests - they are always called by web browser from HTML (responses or files - see above)

void wsRequestHandler (String& wsRequest, WebSocket webSocket) { // - must be reentrant! if (wsRequest.substring (0, 16) == "GET /streamRSSI ") { char c; do { delay (1000); int i = WiFi.RSSI (); c = (char) i; } while (webSocket->sendBinary ((byte ) &c, sizeof (c))); // send RSSI information as long as web browser is willing to receive it } }

void setup () { Serial.begin (115200);

startNetworkAndInitializeItAtFirstCall (); // since we do not have any file system mounted this would only start WiFi // but won't initialize network configuration files

// start web server httpServer httpSrv = new httpServer (httpRequestHandler, // our HTTP callback function wsRequestHandler, // our WS callback function 8 1024, // 8 KB stack size is usually enough, if httpRequestHandler or wsRequestHandler use more stack increase this value until server is stable (char *) "0.0.0.0", // start HTTP server on all available ip addresses 80, // HTTP port NULL); // no firewall callback function if (!httpSrv || (httpSrv && !httpSrv->started ())) Serial.println ("[httpServer] did not start."); }

void loop () {

}

BojanJurca commented 3 years ago

/*

Demo3 - mount FAT file system - it is easier to put HTML responses into files than into C variables or literals
        select Tools | Partition scheme | one of FAT partition sachems
      - we will also need FTP server in order to upload HTML file onto ESP32 FAT file system 

(other demos will follow)

*/

include

define HOSTNAME "MyESP32Server" // define the name of your ESP32 here

define MACHINETYPE "ESP32 NodeMCU" // describe your hardware here

// connect ESP32 in STAtion mode to your WiFi router ...

define DEFAULT_STA_SSID "YOUR_STA_SSID"

define DEFAULT_STA_PASSWORD "YOUR_STA_PASSWORD"

// ... but don't let ESP32 to set up its own A(ccess) P(oit)

define DEFAULT_AP_SSID ""

define DEFAULT_AP_PASSWORD ""

include "./servers/file_system.h"

include "./servers/network.h"

define USER_MANAGEMENT NO_USER_MANAGEMENT // although NO_USER_MANAGEMENT is selected we still need user_management.h - this is where

include "./servers/user_management.h" // web server will get its root directory from, whilest FTP server will accept whatever you type in

include "./servers/webServer.hpp"

include "./servers/ftpServer.hpp"

// httpRequestHandler HTTP callback function is no longer needed - web server can read its HTTP response from a HTML file

// Callback function that will handle all WS (websocket) requests - they are always called by web browser from HTML (responses or files - see above)

void wsRequestHandler (String& wsRequest, WebSocket webSocket) { // - must be reentrant! if (wsRequest.substring (0, 16) == "GET /streamRSSI ") { char c; do { delay (1000); int i = WiFi.RSSI (); c = (char) i; } while (webSocket->sendBinary ((byte ) &c, sizeof (c))); // send RSSI information as long as web browser is willing to receive it } }

void setup () { Serial.begin (115200);

// FFat.format (); // delete all files if you need to start from scratch mountFileSystem (true); // mount (and format if neccessary) file system

startNetworkAndInitializeItAtFirstCall (); // initialize network configuration files and start network

// start web server httpServer httpSrv = new httpServer (NULL, // no HTTP callback function wsRequestHandler, // our WS callback function 8 1024, // 8 KB stack size is usually enough, if httpRequestHandler or wsRequestHandler use more stack increase this value until server is stable (char *) "0.0.0.0", // start HTTP server on all available ip addresses 80, // HTTP port NULL); // no firewall callback function if (!httpSrv || (httpSrv && !httpSrv->started ())) Serial.println ("[httpServer] did not start.");

// start FTP server ftpServer *ftpSrv = new ftpServer ("0.0.0.0", // start FTP server on all available ip addresses 21, // controll connection FTP port NULL); // no firewall callback function if (!ftpSrv || (ftpSrv && !ftpSrv->started ())) Serial.println ("[ftpServer] did not start.");
}

void loop () {

}

After ESP32 starts you will have to FTP to it and upload index.html into /var/www/html directory (just type anything for username and password). index.html would look like this:

RSSI
...
dBm
BojanJurca commented 3 years ago

Some tags have disappeared - I'll just upload ZIP file. Demo3.zip

BojanJurca commented 3 years ago

Everything else is packing data into stream of bytes on the server side (ESP32) and parsing the same stream on the client side (javascript in web browser). Now suppose we want to stream samples from A/D converters on pins 36 and 39 each 1/10th of a second. Each sample fits into 16 bit unsigned integer. Therefore each 1/10th of a second ESP32 will push 2, 16 bit unsigned integers (4 bytes) into websocket which will be read by javascript in web browser and parsed into 2 16 bit unsigned integers.

/*

Demo4

*/

include

define HOSTNAME "MyESP32Server" // define the name of your ESP32 here

define MACHINETYPE "ESP32 NodeMCU" // describe your hardware here

// connect ESP32 in STA(tion) mode to your WiFi router ...

define DEFAULT_STA_SSID "YOUR_STA_SSID"

define DEFAULT_STA_PASSWORD "YOUR_STA_PASSWORD"

// ... but don't let ESP32 to set up its own A(ccess) P(oit)

define DEFAULT_AP_SSID ""

define DEFAULT_AP_PASSWORD ""

include "./servers/file_system.h"

include "./servers/network.h"

define USER_MANAGEMENT NO_USER_MANAGEMENT // although NO_USER_MANAGEMENT is selected we still need user_management.h - this is where

include "./servers/user_management.h" // web server will get its root directory from, whilest FTP server will accept whatever you type in

include "./servers/webServer.hpp"

include "./servers/ftpServer.hpp"

// httpRequestHandler HTTP callback function is no longer needed - web server can read its HTTP response from a HTML file

// Callback function that will handle all WS (websocket) requests - they are always called by web browser from HTML (responses or files - see above)

void wsRequestHandler (String& wsRequest, WebSocket webSocket) { // - must be reentrant! if (wsRequest.substring (0, 19) == "GET /streamSamples ") { uint16_t buffer [2]; do { delay (100); // 1/10 of a second buffer [0] = (int16_t) analogRead (36); buffer [1] = (int16_t) analogRead (39); } while (webSocket->sendBinary ((byte ) &buffer, sizeof (buffer))); // push 2, 16 bit unsigned integers (4 bytes) into websocket } }

void setup () { Serial.begin (115200);

// FFat.format (); // delete all files if you need to start from scratch mountFileSystem (true); // mount (and format if neccessary) file system

startNetworkAndInitializeItAtFirstCall (); // initialize network configuration files and start network

// start web server httpServer httpSrv = new httpServer (NULL, // no HTTP callback function wsRequestHandler, // our WS callback function 8 1024, // 8 KB stack size is usually enough, if httpRequestHandler or wsRequestHandler use more stack increase this value until server is stable (char *) "0.0.0.0", // start HTTP server on all available ip addresses 80, // HTTP port NULL); // no firewall callback function if (!httpSrv || (httpSrv && !httpSrv->started ())) Serial.println ("[httpServer] did not start.");

// start FTP server ftpServer *ftpSrv = new ftpServer ("0.0.0.0", // start FTP server on all available ip addresses 21, // controll connection FTP port NULL); // use firewall callback function for FTP server (replace with NULL if not needed) if (!ftpSrv || (ftpSrv && !ftpSrv->started ())) Serial.println ("[ftpServer] did not start.");
}

void loop () {

}

index.html could now look something like this:

pin 36
...
pin 39
...

Source files are attached in ZIP. Demo4.zip

happytm commented 3 years ago

Thank you for taking so much of your valuable time in order to explain in such a minute detail the concept of servers and the code which make it work. I am sure I will use demo4 for many of my wifi projects in future.

BojanJurca commented 3 years ago

Enjoy :)