available() not returning true
ramdor opened this issue · 8 comments
In version 0.3.1 and using the following code in a loop, after some random time (sometimes a long time) available() will return false, and bConnected will return true. Yet in the next loop around available is still false. The project in question is constantly sending and receiving websocket data until this problem occurs.
if(m_objWebsocketClient.available()) {
m_objWebsocketClient.poll();
} else {
bConnected = m_objWebsocketClient.connect(m_sTCI_server, port, "/");
}
@ramdor the way WebsocketsClient is currently designed it is not supposed to be reused. That means that connect should only be called once per object. That said, calling connect multiple time might work, it is just not tested or properly defined.
Can you elaborate on why you need to connect in a loop?
Also if you could share the full code that is relevant to the issue and the device you are using.
By the way, if you will re-create the object m_objWebsocketClient
every time you want to connect, the code should work fine (because then you will only call connect
once per instance):
if(m_objWebsocketClient.available()) {
m_objWebsocketClient.poll();
} else {
m_objWebsocketClient = websockets::WebsocketsClient();
bConnected = m_objWebsocketClient.connect(m_sTCI_server, port, "/");
}
But this is a temporary solution and the problem you are facing might indicate a bug in the library.
@gilmaimon I used it as a simple method to handle disconnection without going down the ping/pong/timeout route. I may try calling close() before the connect to see if this 'hides' the issue. Thanks for the info ref creating a new instance. I'll update when I have a moment to do some more checking into the issue.
It does however, seem to happen after quite a period of time (hours), and I am sending/receiving messages at around 4/5 per second. Quite honestly could be some issue in wifi stack causing a disconnect or some heap issue in the esp8266.
BTW: the lib is very nice, so easy to implement websockets. Fingers crossed we/I can resolve this issue. I didnt notice this in v0.2.odd, but cant be 100%.
@gilmaimon I used it as a simple method to handle disconnection without going down the ping/pong/timeout route. I may try calling close() before the connect to see if this 'hides' the issue. Thanks for the info ref creating a new instance. I'll update when I have a moment to do some more checking into the issue.
I understand now. You should know calling close
will not resolve the issue I think because once the connection was closed (either by some networking event or if close
was called) the client cannot be properly used again. So re-creating the instance is the best way to go about it. Altough, making the WebsocketsClient class re-usable can be an interesting feature.
BTW: the lib is very nice, so easy to implement websockets.
You made my day, making websockets easier on arduino was exactly my goal.
Fingers crossed we/I can resolve this issue. I didnt notice this in v0.2.odd, but cant be 100%.
Interesting. I did made some changes to the internal networking classes for esp32 (from version 0.2 to 0.3) but I believe I did not change anything in 0.3 that should affect your code.
I will have a more thorough look later today, please keep updating 👍
Well, I have done a bit of testing, and there does seem to be an issue somewhere. I tried .close() and like you said it would not help, which it didn't. Also tried re-creating the object, but for some reason, send would not work (did not receive message on the server side). Callbacks (msg + event) worked fine with the new created object.
So I decided to strip everything back, and just run it bare bones. Code below, sorry for the length and bad coding, lol. I have also included some serial debug output from it. If you notice there are some junk chars in the message, but it is the correct length. I checked heap remaining and that was fine. Test code to follow, then extract of serial output.
EDIT: I should mention, the string message from the ESP8266 (client) to the server is of the form :
rx_smeter:0,0;
and the reply received would be....
rx_smeter:0,0,<dbm>;
where dbm is -70odd in the serial data below.
EDIT2: If i restart the esp8266 it connects back up to the server no problem, so one would assume the server is ok.
//////////////////////////
// Test ArduinoWebsocket
// ramdor
////////////////////////
#define Sprintln(a) (Serial.println(a))
#define Sprint(a) (Serial.print(a))
#include <ESP8266WiFi.h>
#include <ArduinoWebsockets.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
using namespace websockets;
//-------------------------------------------
WebsocketsClient m_objWebsocketClient;
char m_sTCI_server[40] = "192.168.0.63";
char m_sTCI_port[6] = "40001";
//-------------------------------------------
void getSMeter(int nPeriodic, int nChan){
if(!m_objWebsocketClient.available()) return;
char sBuff[32];
sprintf(sBuff, "rx_smeter\:%d,%d\;",nPeriodic,nChan);
m_objWebsocketClient.send(sBuff);
}
//-------------------------------------------
void parseMessage(char *msg){
//Sprintln(msg);
}
//-------------------------------------------
void onMessageCallback(WebsocketsClient& client, WebsocketsMessage message) {
char buff[128];
if(message.isText()){
message.data().toCharArray(buff,128);
buff[127]='\0'; // justincase
Sprint(buff);
Sprint(" .... Len=");
Sprintln(message.data().length());
parseMessage(buff);
}
}
//-------------------------------------------
void onEventsCallback(WebsocketsClient& client, WebsocketsEvent event, String data) {
if(event == WebsocketsEvent::ConnectionOpened) {
Sprintln("Connnection Opened");
} else if(event == WebsocketsEvent::ConnectionClosed) {
Sprintln("Connnection Closed");
} else if(event == WebsocketsEvent::GotPing) {
Sprintln("Got a Ping!");
} else if(event == WebsocketsEvent::GotPong) {
Sprintln("Got a Pong!");
}
}
//-------------------------------------------
void wifiConnect(){
WiFiManager wifiManager;
wifiManager.setRemoveDuplicateAPs(false);
if (!wifiManager.autoConnect("ExpertSDR2AP","moomoo")) {
Sprintln("failed to connect and hit timeout");
ESP.reset();
delay(1000);
}
}
//-------------------------------------------
bool handleWebSocket(){
bool bConnected = true;
if(m_objWebsocketClient.available()) {
m_objWebsocketClient.poll();
}
else
{
Sprintln("trying to connect to web socket");
uint16_t uiPort = atoi(m_sTCI_port);
//with these uncommented, and the two in setup commented, getSMeter does not seem to send any data
//m_objWebsocketClient = WebsocketsClient();
//m_objWebsocketClient.onMessage(onMessageCallback);
//m_objWebsocketClient.onEvent(onEventsCallback);
bConnected = m_objWebsocketClient.connect(m_sTCI_server, uiPort, "/");
}
return bConnected;
}
//-------------------------------------------
void setup() {
system_update_cpu_freq(160);
WiFi.setOutputPower(20.5); // dBm
// comment these two out, and uncomment the section in handlewebsocket to try the new object approach
m_objWebsocketClient.onMessage(onMessageCallback);
m_objWebsocketClient.onEvent(onEventsCallback);
Serial.begin(115200);
}
//-------------------------------------------
void loop() {
yield(); // give some time over to let esp8266 do its stuff
if(WiFi.status() != WL_CONNECTED) {
wifiConnect();
return;
}
if(!handleWebSocket()) return;
// simple message to the service providing WS interface
getSMeter(0,0);
// With this 100 delay, all works ok
// but I assume it will show a problem after some XYZ time.
// If changed to 1 or taken out
// it will error very quickly, sub 30 seconds.
// Is it related to some websocket buffer overflow?
//delay(100);
}
Serial....
rx_smeter:0,0,-71; .... Len=18
rx_smeter:0,0,-71; .... Len=18
rx_smeter:0,0,-71; .... Len=18
rx_smeter:0,0,-71; .... Len=18
rx_smeter:0,0, @t⸮ .... Len=18
trying to connect to web socket
Connnection Opened
trying to connect to web socket
Connnection Opened
trying to connect to web socket
Connnection Opened
trying to connect to web socket
Connnection Opened
trying to connect to web socket
@ramdor I belive this is not an error in your setup (wifi/server/device) but an issue with the library. I will have a response (and hopefully an hotfix) very soon (hopefully < 1 hour)
@ramdor Ok, so I have a hotfix on its way to the IDE (version will be 0.3.2).
There are 2 errors that surfaced from your issue:
- There was no impl for proper copying and assigning (operator=)
- There is an error with the ESP8266 networking code.
The first issue, is what caused this problem:
with these uncommented, and the two in setup commented, getSMeter does not seem to send any data
The second is what caused the disconnection to begin with, and it is a problem with my esp8266 impl of networking. So, if I run the code on windows/linux (with my windows/linux tcp impl) everything runs fine.
So currently, in order to make your code work. This part:
// comment these two out, and uncomment the section in handlewebsocket to try the new object approach
m_objWebsocketClient.onMessage(onMessageCallback);
m_objWebsocketClient.onEvent(onEventsCallback);
Does not have to be commented, keep it as is.
This part:
//with these uncommented, and the two in setup commented, getSMeter does not seem to send any data
// (should not be commented)
m_objWebsocketClient = WebsocketsClient();
m_objWebsocketClient.onMessage(onMessageCallback);
m_objWebsocketClient.onEvent(onEventsCallback);
Should also not be commented. Now, every time a network error will occure, the client will fail, but the m_objWebsocketClient = WebsocketsClient();
part will work fine and will restart the client properly.
Regarding the networking error, this will take abit longer to fix but I am working on it.
Thank you very much for reporting this issue, please update once the new version (0.3.2) is available on the IDE (might take few hours)!
Ah brilliant. I patched direct with the zip, so using 0.3.2. I have converted over to the new object instantiation in the test bed, and it reconnects and gets messages, perfect !
Ok on the networking error. I let the testbed run, and as you expect it did get that error, however it reconnected ! Good luck with the networking fixes 👍
rx_smeter:0,0,-50; .... Len=18
rx_smeter:0,0,-50; .... Len=18
rx_smeter:0,0,-50; .... Len=18
rx_smeter:0,0,-50; .... Len=18
rx_smeter:0,0,-50; .... Len=18
rx_smeter:0,0, @D⸮ .... Len=18
trying to connect to web socket
Connnection Opened
device:SunSDR2; .... Len=15
receive_only:false; .... Len=19
trx_count:2; .... Len=12
channels_count:2; .... Len=17
.
.
<some stuff cut out>
.
.
audio_stop:1; .... Len=13
rx_smeter:0,0,-50; .... Len=18
rx_smeter:0,0,-50; .... Len=18