I am trying to use the espAsychWebserver library which has support for websockets.
My client is google chrome browser. Using developer tools shows the error to be:
"WebSocket connection to 'ws://192.168.86.31/ws' failed"
on this line: Socket = new WebSocket('ws://' + window.location.hostname + '/ws');
which creates a the websocket on the client.
Wondering if anyone uses this library for web sockets and how do you set up the client to connect
I have tried appending :80 (for port 80) but get the same error.
With this library opening an additional port is not necessary for
websockets.
Here is my esp32 code:
#include <Arduino.h>
#include <WiFi.h> // needed to connect to WiFi
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
// #include <WebSocketsServer.h> // needed for instant communication between client and server through Websockets
#include <ArduinoJson.h> // needed for JSON encapsulation (send multiple variables with one string)
#include <FS.h>
#include <SPIFFS.h>
#include <string.h>
// void sendJson(String l_type, String l_value);
void sendJson(String l_type, String l_value, AsyncWebSocketClient *client);
// void webSocketEvent(byte num, WStype_t type, uint8_t *payload, size_t length);
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
// SSID and password of Wifi connection:
const char *ssid = "boulderhill";
const char *password = "wideflower594";
const char *l_type; // save & print key and value
int l_value;
// The String below "webpage" contains the complete HTML code that is sent to the client whenever someone connects to the webserver
// NOTE 27.08.2022: I updated in the webpage "slider.addEventListener('click', slider_changed);" to "slider.addEventListener('change', slider_changed);" -> the "change" did not work on my phone.
// String webpage = "<!DOCTYPE html><html><head><title>Page Title</title></head><body style='background-color: #EEEEEE;'><span style='color: #003366;'><h1>LED Controller</h1><form> <p>Select LED:</p> <div> <input type='radio' id='ID_LED_0' name='operation_mode'> <label for='ID_LED_0'>LED 0</label> <input type='radio' id='ID_LED_1' name='operation_mode'> <label for='ID_LED_1'>LED 1</label> <input type='radio' id='ID_LED_2' name='operation_mode'> <label for='ID_LED_2'>LED 2</label> </div></form><br>Set intensity level: <br><input type='range' min='1' max='100' value='50' class='slider' id='ID_LED_INTENSITY'>Value: <span id='ID_LED_INTENSITY_VALUE'>-</span><br></span></body><script>var led_0=document.getElementById('ID_LED_0');var led_1=document.getElementById('ID_LED_1');var led_2=document.getElementById('ID_LED_2');led_0.addEventListener('click', led_changed);led_1.addEventListener('click', led_changed);led_2.addEventListener('click', led_changed); var slider = document.getElementById('ID_LED_INTENSITY'); var output = document.getElementById('ID_LED_INTENSITY_VALUE'); slider.addEventListener('change', slider_changed); var Socket; function init() { console.log("creating Socket"); Socket = new WebSocket('ws://' + window.location.hostname + ':81/'); //url of esp32 + port =socket console.log("waiting for Socket ready") while{Socket.readyState != 1);Socket.onopen = function Socketopen(); Socket.onmessage = function(event) { //onmessage event occurs when a msg is rvd via event source processCommand(event); //runs processCommand(event) }; } function Socketopen(){console.log("Socket sucess opened");} function led_changed() {var l_LED_selected = 0;if(led_1.checked == true) { l_LED_selected = 1;} else if(led_2.checked == true) { l_LED_selected = 2;}console.log(l_LED_selected); var msg = { type: 'LED_selected', value: l_LED_selected};Socket.send(JSON.stringify(msg)); } function slider_changed () { var l_LED_intensity = slider.value;console.log(l_LED_intensity);var msg = { type: 'LED_intensity', value: l_LED_intensity};Socket.send(JSON.stringify(msg)); } function processCommand(event) {var obj = JSON.parse(event.data); var type = obj.type;if (type.localeCompare(\"LED_intensity\") == 0) { var l_LED_intensity = parseInt(obj.value); console.log(l_LED_intensity); slider.value = l_LED_intensity; output.innerHTML = l_LED_intensity;}else if(type.localeCompare(\"LED_selected\") == 0) { var l_LED_selected = parseInt(obj.value); console.log(l_LED_selected); if(l_LED_selected == 0) { led_0.checked = true; } else if (l_LED_selected == 1) { led_1.checked = true; } else if (l_LED_selected == 2) { led_2.checked = true; }} } window.onload = function(event) { init(); }</script></html>";
// Will be trying to add css,html & js using external files
// String webpage = "<!DOCTYPE html><html><head><title>Page Title</title><style>#box {background-color:#FFCC66;width:20%;height:100%; border: 1px solid black; padding-left: 5%;}#ID_LED_INTENSITY {position: relative;left:0px;padding:0px;}#leds {padding-bottom: 0px;}#range {padding-bottom:20px}#sokstate { margin-bottom:20px}</style><body style='background-color: #d000000;'><div id='box'><h1>LED Controller</h1><form> <p>Select LED:</p> <div id='leds'> <input type='radio' id='ID_LED_0' name='operation_mode'> <label for='ID_LED_0'>LED 0</label> <input type='radio' id='ID_LED_1' name='operation_mode'> <label for='ID_LED_1'>LED 1</label> <input type='radio' id='ID_LED_2' name='operation_mode'> <label for='ID_LED_2'>LED 2</label> </div></form><p style='position:relative right:30%'>intensity level:</p><div id='range'><p> <input type='range' min='1' max='100' value='50' class='slider' id='ID_LED_INTENSITY'><span > value:</span><span id='ID_LED_INTENSITY_VALUE'>-</span></p></div><div id='myrange'><p> <input type='range' min='1' max='100' value='25' class='slider' id='ID_PWM_INTENSITY'><span > value:</span><span id='ID_PWM_INTENSITY_VALUE'>-</span></p></div> <button id='sokstate' type='button' value='on'>close socket</button> </div></head></body><script> var Socket; document.getElementById('ID_LED_0').addEventListener('click', led_changed); document.getElementById('ID_LED_1').addEventListener('click', led_changed); document.getElementById('ID_LED_2').addEventListener('click', led_changed); var slider = document.getElementById('ID_LED_INTENSITY'); var output = document.getElementById('ID_LED_INTENSITY_VALUE'); slider.addEventListener('change', slider_changed); var myslider = document.getElementById('ID_PWM_INTENSITY'); var out = document.getElementById('ID_PWM_INTENSITY_VALUE'); myslider.addEventListener('change', myslider_changed); sokstate=document.getElementById('sokstate');sokstate.addEventListener('click', sokstate_cb);function sokstate_cb(){console.log(sokstate.value);console.log(sokstate.innerHTML);if(sokstate.value == 'on') { sokstate.value = 'off'; sokstate.innerHTML = 'open socket'; setTimeout(Socket.close(),1000);} else { setTimeout(init(),1000); sokstate.value = 'on'; sokstate.innerHTML = 'close socket'; } } function init() { Socket = new WebSocket('ws://' + window.location.hostname + ':81/'); Socket.onmessage = function(event) { processCommand(event); }; Socket.onopen = function(event){onOpen(event);};Socket.onerror = function(event){onError(event);}; } function onOpen(event){console.log('socket open for comms');}function onError(event){console.log('socket error even occurred');} function led_changed() {var l_LED_selected;if(document.getElementById('ID_LED_0').checked == true) { l_LED_selected = 0; console.log(l_LED_selected); var msg = { type: 'LED_selected', value: l_LED_selected}; Socket.send(JSON.stringify(msg)); } if(document.getElementById('ID_LED_1').checked == true) {l_LED_selected = 1;console.log(l_LED_selected); var msg = { type: 'LED_selected', value: l_LED_selected}; Socket.send(JSON.stringify(msg)); } if(document.getElementById('ID_LED_2').checked == true) {l_LED_selected = 2;console.log(l_LED_selected); var msg = {'state': {'reported':{'state': 0, 'rules':[ {'type': 'decode','value': 1975,'endTime': 0}, {'type': 1, 'connectedSensorId' : 'sensorId', 'threshold' : 1+0}]}}}; Socket.send(JSON.stringify(msg)); console.log('sent json doc'); console.log(l_LED_selected); var msg = { type: 'LED_selected', value: l_LED_selected}; Socket.send(JSON.stringify(msg)); }} function slider_changed () { var l_LED_intensity = slider.value;console.log(l_LED_intensity);var msg = { type: 'LED_intensity', value: l_LED_intensity};Socket.send(JSON.stringify(msg)); } function myslider_changed () { var l_PWM_intensity =myslider.value;console.log(l_PWM_intensity);var msg = { type: 'PWM_intensity', value: l_PWM_intensity};Socket.send(JSON.stringify(msg)); } function processCommand(event) {var obj = JSON.parse(event.data); var type = obj.type; if (type.localeCompare(`LED_intensity`) == 0) { var l_LED_intensity = parseInt(obj.value); console.log(l_LED_intensity); slider.value = l_LED_intensity; output.innerHTML = l_LED_intensity;}else if (type.localeCompare(`PWM_intensity`) == 0) { var l_PWM_intensity = parseInt(obj.value); console.log(l_PWM_intensity); myslider.value = l_PWM_intensity; out.innerHTML = l_PWM_intensity;}else if(type.localeCompare(`LED_selected`) == 0) { var l_LED_selected = parseInt(obj.value); console.log(l_LED_selected); if(l_LED_selected == 0) { document.getElementById('ID_LED_0').checked = true; } else if (l_LED_selected == 1) { document.getElementById('ID_LED_1').checked = true; } else if (l_LED_selected == 2) { document.getElementById('ID_LED_2').checked = true; }} } window.onload = function(event) { init(); } </script></html>";
int LED_selected = 0;
int LED_intensity = 50;
int PWM_intensity = 50;
// init PINs: assign any pin on ESP32
int led_pin_0 = 4;
int led_pin_1 = 0;
int led_pin_2 = 2; // On some ESP32 pin 2 is an internal LED, mine did not have one
// some standard stuff needed to do "analogwrite" on the ESP32 -> an ESP32 does not have "analogwrite" and uses ledcWrite instead
const int freq = 5000;
const int led_channels[] = {0, 1, 2};
const int resolution = 8;
const int myresolution = 10;
const int ledChannel = 4;
int ledPin = 16;
// Initialization of webserver and websocket
AsyncWebServer server(80); // the server uses port 80 (standard port for websites
AsyncWebSocket ws("/ws");
AsyncEventSource events("/events");
// WebSocketsServer webSocket = WebSocketsServer(81); // the websocket uses port 81 (standard port for websockets)
void notFound(AsyncWebServerRequest *request)
{
request->send(404, "text/plain", "Not found");
}
void setup()
{
Serial.begin(115200); // init serial port for debugging
// WiFi.mode(WIFI_STA);
// setup LED channels
ledcSetup(led_channels[0], freq, resolution);
ledcSetup(led_channels[1], freq, resolution);
ledcSetup(led_channels[2], freq, resolution);
// attach the channels to the led_pins to be controlled
ledcAttachPin(led_pin_0, led_channels[0]);
ledcAttachPin(led_pin_1, led_channels[1]);
ledcAttachPin(led_pin_2, led_channels[2]);
//-------------------- my pwm -----------------------------//
ledcSetup(ledChannel, (uint32_t)5000, myresolution);
ledcAttachPin(ledPin, ledChannel);
//-------------------led end ----------------------------//
if (!SPIFFS.begin())
{
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
WiFi.begin(ssid, password); // start WiFi interface
Serial.println("Establishing connection to WiFi with SSID: " + String(ssid)); // print SSID to the serial interface for debugging
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print(".");
}
Serial.print("Connected to network with IP address: ");
Serial.println(WiFi.localIP());
// send files on request
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(SPIFFS, "/index.html", "text/html"); });
server.on("/mystyle.css", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(SPIFFS, "/mystyle.css", "text/css"); });
server.on("/myjava.js", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(SPIFFS, "/myjava.js", "text/javascript"); });
server.begin(); // start server
// webSocket.begin(); // start websocket
// webSocket.onEvent(webSocketEvent); // define a callback function -> what does the ESP32 need to do when an event from the websocket is received? -> run function "webSocketEvent()"
ledcWrite(led_channels[LED_selected], map(LED_intensity, 0, 100, 0, 255)); // write initial state to LED selected
// getWebSocketVersion();
// size_t prev = millis();
}
void loop()
{
// server.handleClient(); // Needed for the webserver to handle all clients
ws.cleanupClients();
// webSocket.loop(); // Update function for the webSockets
}
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
{
switch (type)
{
case WS_EVT_DISCONNECT:
// Serial.println("Client " + String(client->id()) + " disconnected");
Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id());
break;
case WS_EVT_CONNECT: // if a client is connected, then type == WStype_CONNECTED
// Serial.println("Client " + String(client->id()) + " connected");
Serial.printf("ws[%s][%u] connect\n", server->url(), client->id());
client->printf("Hello Client %u :)", client->id());
sendJson("LED_intensity", String(LED_intensity), client); // send intensity & select to clients (one could send it just to the new client "num", but I left that out here
sendJson("LED_selected", String(LED_selected), client);
break;
case WS_EVT_DATA: // if a client has sent data,
// try to decipher the JSON string received
StaticJsonDocument<400> doc; // create JSON container
DeserializationError error = deserializeJson(doc, data);
if (error)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
else
{
l_type = doc["type"]; // save & print key and value
l_value = doc["value"];
Serial.println("Type: " + String(l_type));
Serial.println("Value: " + String(l_value));
if (String(l_type) == "PWM_intensity")
{
PWM_intensity = int(l_value);
sendJson("PWM_intensity", String(l_value), client);
ledcWrite(ledChannel, map(PWM_intensity, 0, 100, 0, 1023));
}
if (String(l_type) == "LED_intensity")
{
LED_intensity = int(l_value);
sendJson("LED_intensity", String(l_value), client);
ledcWrite(led_channels[LED_selected], map(LED_intensity, 0, 100, 0, 255));
}
// else if LED_select is changed -> switch on LED and switch off the rest
if (String(l_type) == "LED_selected")
{
LED_selected = int(l_value);
sendJson("LED_selected", String(l_value), client);
for (int i = 0; i < 3; i++)
{
if (i == LED_selected)
ledcWrite(led_channels[i], map(LED_intensity, 0, 100, 0, 255)); // switch on LED
else
ledcWrite(led_channels[i], 0); // switch off not-selected LEDs
}
}
Serial.println("");
break;
} // else
} // switch
}
// Simple function to send information to the web clients
void sendJson(String l_type, String l_value, AsyncWebSocketClient *client)
{
String jsonString = ""; // create a JSON string for sending data to the client
StaticJsonDocument<200> doc; // create JSON container
JsonObject object = doc.to<JsonObject>(); // create a JSON Object
object["type"] = l_type; // write data into the JSON object -> I used "type" to identify if LED_selected or LED_intensity is sent and "value" for the actual value
object["value"] = l_value;
serializeJson(doc, jsonString); // convert JSON object to string
client->printf("%s", jsonString);
// webSocket.broadcastTXT(jsonString); // send JSON string to all clients
}
Here is my javascript code:
var Socket;
document.getElementById('ID_LED_0').addEventListener('click', led_changed);
document.getElementById('ID_LED_1').addEventListener('click', led_changed);
document.getElementById('ID_LED_2').addEventListener('click', led_changed);
var slider = document.getElementById('ID_LED_INTENSITY');
var output = document.getElementById('ID_LED_INTENSITY_VALUE');
slider.addEventListener('change', slider_changed);
var myslider = document.getElementById('ID_PWM_INTENSITY');
var out = document.getElementById('ID_PWM_INTENSITY_VALUE');
myslider.addEventListener('change', myslider_changed);
sokstate = document.getElementById('sokstate');
sokstate.addEventListener('click', sokstate_cb);
function sokstate_cb() {
console.log(sokstate.value);
console.log(sokstate.innerHTML);
if (sokstate.value == 'on') {
sokstate.value = 'off';
sokstate.innerHTML = 'open socket';
setTimeout(Socket.close(), 1000);
}
else {
setTimeout(init(), 1000);
sokstate.value = 'on';
sokstate.innerHTML = 'close socket';
}
}
function init() {
/* Socket = new WebSocket('ws://192.168.86.31:80');*/
Socket = new WebSocket('ws://' + window.location.hostname) +'/ws';
Socket.onmessage = function (event) { processCommand(event); };
Socket.onopen = function (event) { onOpen(event); };
Socket.onerror = function (event) { onError(event); };
}
function onOpen(event) {
console.log('socket open for comms');
}
function onError(event) {
console.log('socket error even occurred');
}
function led_changed() {
var l_LED_selected;
if (document.getElementById('ID_LED_0').checked == true) {
l_LED_selected = 0;
console.log(l_LED_selected);
var msg = { type: 'LED_selected', value: l_LED_selected };
Socket.send(JSON.stringify(msg));
}
if (document.getElementById('ID_LED_1').checked == true) {
l_LED_selected = 1;
console.log(l_LED_selected);
var msg = { type: 'LED_selected', value: l_LED_selected };
Socket.send(JSON.stringify(msg));
}
if (document.getElementById('ID_LED_2').checked == true) {
l_LED_selected = 2;
console.log(l_LED_selected);
var msg = { type: 'LED_selected', value: l_LED_selected };
Socket.send(JSON.stringify(msg));
console.log('sent json doc');
console.log(l_LED_selected);
var msg = { type: 'LED_selected', value: l_LED_selected };
Socket.send(JSON.stringify(msg));
}
}
function slider_changed() {
var l_LED_intensity = slider.value;
console.log(l_LED_intensity);
var msg =
{
type: 'LED_intensity', value: l_LED_intensity
};
Socket.send(JSON.stringify(msg));
}
function myslider_changed() {
var l_PWM_intensity = myslider.value;
console.log(l_PWM_intensity);
var msg =
{ type: 'PWM_intensity', value: l_PWM_intensity };
Socket.send(JSON.stringify(msg));
}
function processCommand(event) {
console.log(event);
var obj = JSON.parse(event.data);
var type = obj.type;
if (type.localeCompare(`LED_intensity`) == 0) {
var l_LED_intensity = parseInt(obj.value);
console.log(l_LED_intensity);
slider.value = l_LED_intensity;
output.innerHTML = l_LED_intensity;
}
else if (type.localeCompare(`PWM_intensity`) == 0) {
var l_PWM_intensity = parseInt(obj.value);
console.log(l_PWM_intensity);
myslider.value = l_PWM_intensity;
out.innerHTML = l_PWM_intensity;
}
else if (type.localeCompare(`LED_selected`) == 0) {
var l_LED_selected = parseInt(obj.value);
console.log(l_LED_selected);
if (l_LED_selected == 0) {
document.getElementById('ID_LED_0').checked = true;
}
else if (l_LED_selected == 1) {
document.getElementById('ID_LED_1').checked = true;
}
else if (l_LED_selected == 2) {
document.getElementById('ID_LED_2').checked = true;
}
}
}
window.onload = function (event) {
init();
}