Hello everyone,
I’ve been running my weather station on 0.4.7 for a little while now and have had some great success keeping it connected now that I am using a u.FL antenna (my record so far is over 1,000,000 seconds - a little over 11.5 days!). Still hasn’t hit -40ºC outside yet, but I’ll leave that test for later…
So I figured it was time to break things again and start playing around
I’ve been continually working to improve efficiency when working with Weather Underground, and thought to myself – the server seems to support keep-alive, since when I telnet into it I can keep sending push updates and so long as there are updates sent more often than 15s, the connection remains open. This got me to thinking … I’m using a really silly method of connect, println, delay, read, stop (disconnect). If the connection can be persistent, why don’t I just connect, println, delay, read, println, delay, read […] and use a single connection? So I gave it a try.
And for the most part, it works! BUT, there seems to be some weirdness going on. First, some code.
TCPClient client;
char WULastResp[512];
String WULastCmd; // Contains the last GET request sent to Wunderground
volatile bool wuSend;
void cbWUSend() {
wuSend = true;
}
Timer tWUSend(5000, cbWUSend);
void setup() {
tWUSend.start();
}
void loop() {
if(wuSend){
wuSend = false;
// Read the data returned from the ***LAST*** push! This grants us the maximum allowable delay (by *our* specifications).
if(client.available()){ // There's data to read!
int i = 0;
while (client.available())
{
char c = client.read();
if (i < 512)
WULastResp[i++] = c;
}
Particle.publish("WU-PushSuccess", String::format("Received response from WU: %s", WULastResp), 3600, PRIVATE);
}
else if(client.connected()) {
// WOAH! There's no data after our last push, but we are still "connected"?
// Looks like the connection stalled! Reconnect.
client.stop();
client.flush();
Particle.publish("WU-NoResponse", "WU never responded before next push! Forcing disconnection before pushing.", 3600, PRIVATE);
}
// Connect to WU.
// We will reach this point on two occasions:
// • when there was no data to be read, and the client was still "connected", so we forcefully reset it (above)
// • when there was no connection to begin with (initial start-up).
if(!client.connected()) // THIS IS WHERE SOMETHING ODD OCCURS
{
if (!client.connect(SERVER, 80))
{
Particle.publish("WU-ConnFailed", "Connection to WU Failed!", 3600, PRIVATE);
}
else {
Particle.publish("WU-ConnSuccess", "Connection to WU Succeeded!", 3600, PRIVATE);
}
}
// Now the client should be connected, either because we just connected above, or it
// was already connected when this loop started. But we just make sure…
if(client.connected()){
Particle.publish("WU-TryingPush", "Everything is connected, trying data push!", 3600, PRIVATE);
sendToWU(); // this calls client.println() after assembling a string to send, nothing more, nothing less.
}
else {
Particle.publish("WU-NotConnected", "Connection to WU didn't establish before push!", 3600, PRIVATE);
}
}
}
Let’s have an example now of what my event log looks like.
event: WU-ConnSuccess
data: {"data":"Connection to WU Succeeded!","ttl":"3600","published_at":"2015-11-28T05:09:59.391Z","coreid":""}
event: WU-TryingPush
data: {"data":"Everything is connected, trying data push!","ttl":"3600","published_at":"2015-11-28T05:09:59.470Z","coreid":""}
event: WU-PushSuccess
data: {"data":"Received response from WU: HTTP/1.0 200 OK\r\nContent-type: text/html\r\nDate: Sat, 28 Nov 2015 05:09:59 GMT\r\nContent-Length: 8\r\n\r\nsuccess\n","ttl":"3600","published_at":"2015-11-28T05:10:04.230Z","coreid":""}
event: WU-ConnSuccess
data: {"data":"Connection to WU Succeeded!","ttl":"3600","published_at":"2015-11-28T05:10:04.800Z","coreid":""}
event: WU-TryingPush
data: {"data":"Everything is connected, trying data push!","ttl":"3600","published_at":"2015-11-28T05:10:04.881Z","coreid":""}
event: WU-PushSuccess
data: {"data":"Received response from WU: HTTP/1.0 200 OK\r\nContent-type: text/html\r\nDate: Sat, 28 Nov 2015 05:10:04 GMT\r\nContent-Length: 8\r\n\r\nsuccess\n","ttl":"3600","published_at":"2015-11-28T05:10:09.228Z","coreid":""}
What I don’t understand is why it is reconnecting every time? I never call client.stop()
. I should only be seeing my WU-ConnSuccess event once, when the connection is opened, but instead, It looks like if(!client.connected())
is somehow indicating that there is no connection, when in fact there should be one - and another connection is made each time.
Is the connection automatically considered “disconnected” if there is no more data to read? That’s the only thing I can think of! Comments and suggestions appreciated! I know @mdma and others did a bunch of TCPClient bug-fixing work on 0.4.4, perhaps intimate knowledge of this system can help explain what’s going on here