Hi,
I'm working on a websocket server but I'm running into a problem I don't understand. I hope someone can enlighten me. My code is below.
-- I am running a websocket server on a Wiznet W5100s EVB Pico
-- Using Ethernet_Generic and WebSockets2_Generic libraries
-- A local HTML5/Javascript webpage makes a socket connection
-- Data is exchanged in JSON using the ArduinoJson library
Now this is what puzzles me:
-- Data sent from the webpage to the server is processed instantly after if (ws_client.available())
-- A connected potmeters value that is also read in the loop should also be sent to the client instantly
And that is not happening.
When there is no client connected, the read potmeter code (outside if (ws_client.available())
) runs at "loop speed". However, if a cliient is connected it is only run when a message is sent from the client to the server. For example, when the server receives a "ping".
I hope this explains the problem well enough for someone to let me know what is going on here.
Thanks in advance!
My code:
#include <Ethernet_Generic.h> // https://github.com/khoih-prog/Ethernet_Generic
#include <WebSockets2_Generic.h> // https://github.com/khoih-prog/WebSockets2_Generic
// JSON
#include <ArduinoJson.h>
// Serial debugging
#include <Streaming.h>
using namespace websockets2_generic;
#define SS_PIN 17
#define WEBSOCKETS_PORT 8080
byte mac[] = {0x00, 0x08, 0xDC, 0xAB, 0xCD, 0xEF};
IPAddress ip(192, 168, 1, 120);
IPAddress gateway(192, 168, 1, 1);
IPAddress DNSserver(0, 0, 0, 0);
IPAddress subnet(255,255,255,0);
// Websocket server
WebsocketsServer ws_server; // Create websocket server
WebsocketsClient ws_client; // Create global instance websocket client
bool ws_client_connected = false; // Boolean to determine is the websocket is active
// Keep Alive
unsigned long lastAlive = 0; // timestamp of last alive message from client
// JSON
StaticJsonDocument<128> jDocRx; // https://arduinojson.org/v6/assistant/#/step1 to determine size
StaticJsonDocument<128> jDocTx; // jDocRx for receiving, jDocTx for sending
// POTMETER
int potValue;
int previousPotvalue;
void initEthernet() // Initialize ethernet
{
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH);
Ethernet.init (SS_PIN);
}
// ==================================================================================================
// SETUP
void setup()
{
Serial.begin(115200);
initEthernet();
Ethernet.begin(mac, ip, gateway, DNSserver, subnet); // start ethernet, use Static IP
ws_server.listen(WEBSOCKETS_PORT);
}
// ==================================================================================================
// LOOP
void loop()
{
//======================
if(!ws_client_connected) // A new connection should only be accepted when there is no active connection
{
ws_client = ws_server.accept();
ws_client_connected = true; // A client is connected, set to true
lastAlive = millis(); // Timestamp the moment of connection as first alive
}
//==========================================================
if( ((millis() - lastAlive) > 5000) && ws_client_connected) // The client sends a ping every 2 seconds
{ // If no "alive" is received for 5 seconds &AND& ws_client_connected is true
ws_client.close(); // close the socket
ws_client_connected = false; // and set websocket connected to false
Serial << "connection closed: client inactive" << endl;
}
//========================
if (ws_client.available())
{
WebsocketsMessage msg = ws_client.readNonBlocking();
Serial << "Message received: " << msg.data() << endl;
deserializeJson(jDocRx, msg.data()); // Deserialize messagedata into jDocRx object
String id = jDocRx["id"]; // The messages contains an id to determine the kind of message and destination
if(id == "ping")
{
lastAlive = millis(); // Timestamp the last alive message from client
}
Serial << " inside ws_client.available() " << endl; // <<<<<<< THIS ONLY PRINTS AT WHEN A CLIENT SENDS DATA
} // end if ws_client.available()
Serial << " outside ws_client.available() " << endl; // <<<<<<< THIS ONLY PRINTS AT "LOOP SPEED" WHEN NO CLIENT IS CONNECTED
//========================
potValue = analogRead(A1);
if(abs(potValue - previousPotvalue) > 10){ // If the porvalue changes by more then 10,
previousPotvalue = potValue; // store the new value and
sendPotValue(potValue); // send the new value to the client
}
} // end loop
void sendPotValue(int potVal) // Function that sends potvalue to client
{
jDocTx["id"] = "pot";
jDocTx["val"] = potVal;
char buff[128];
size_t len = serializeJson(jDocTx, buff);
ws_client.send(buff, len);
}