Write Bucket Cannot Read Socket When reconnecting

I am using the write_bucket function to send a timestamp and an analogue value to a data bucket every 2 mins. I have also written some code where I reconnect to wifi if it drops out (I need the wifi to be able to reconnect automatically for my project if it drops out and then becomes available after some time). The writing to thinger works as expected, then I disconnect and reconnect the wifi ( this also works well). Once reconnected to thinger, I can send the first data up to the bucket, but on the second or sometimes third set of data, I get a cannot read from socket message. It then disconnects from thinger and reconnects again so ends up sending every 6 minutes instead of 2 mins. I have traced the problem to it timing out during the Arduino readbytes function which is called via read() in ThingerClient.h, but I cannot understand why it is timing out when reading from stream.

Has anyone seen anything like this before that can help?

Hi,

the Thinger client library automatically reconnects to wifi and thinger when required. So, not sure why you need to code a wifi reconnect. Maybe it is interfering with the client library?.

Do you have a simple sketch that reproduces the issue?

Hi @alvarolb, Thanks for your reply, much appreciated.

I agree, that reconnection code could be causing problems. The reason I put this code in was in the event where the the router was switched off while I was sending data, and then I want the device to reconnect to the same network when it turns back on (similar to this post - Reconnect after internet failure) When I tested turning the router off and on again using the client library auto-reconnect, it didn’t reconnect. I’m assuming the built-in auto-reconnect only works if you go out of range and then come back into network range? Or maybe I’ve got that wrong and my code isn’t working as it should?

I’ll simplify the code I’m using and post it here as soon as I get a chance.

Hello,
I had similar problems.
But I identified that the source of the problem was the router/modem.
In my case it was the TP-LINK TL-MR3420 router
When I used my smartphone as a router, everything worked fine. The same happened when testing with other routers.

Try performing the following tests and post the log here:

First test:

  1. Connect the device to the router
  2. Turn off the router
  3. Wait for the device to identify the loss of connection with the router (maybe it takes 2 to 3 minutes)
  4. Reconnect the route
    Was the device able to connect?
    If possible, test with router and smartphone (with router function)

Second test:

  1. Connect the device to the router
  2. Just remove the internet cable from the router
  3. Wait for the device to identify the lack of internet connection
  4. Reconnect the internet cable to the router
    Was the device able to connect to the Thinger.io Server?
    If possible, test with the router and smartphone (with the router function. In this case, turn off and on the smartphone’s 3G/4G connection)

Also inform which device is using (ESP8266; ESP32…) the Arduino-Thinger library version and the Arduino IDE or Platformio version.

@George_Santiago Thanks very much for your suggestions - all very helpful. I tried both tests, but I removed my reconnection code so i was just using Thinger’s auto-reconnect - The first test I tried with a router and my smartphone (turning the connection off in both cases i.e the network SSID disappears) and the device was not able to connect.
Test 2, I unplugged the cable from my router and reconnected - the device reconnected automatically. I did the same with my smartphone hotspot i.e. I dropped the 4G data connection (but left the hotspot on) and again it reconnected correctly.

Conclusion is the Thinger autoconnect works well when the internet drops and then returns, but if a router/hotspot is restarted and the SSID disappears for a period of time, it cannot reconnect automatically to the device.

The code I added does allow it to reconnect if a router is restarted but as mentioned above, it doesn’t send the data reliably. Do you or @alvarolb have any ideas how a device could reconnect when a router is restarted as mine doesn’t seem to be reliable? See my code below:

#define THINGER_SERIAL_DEBUG

#include <ThingerMbed.h>
#include <ThingerMbedOTA.h>
#include <ThingerClient.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include "arduino_secrets.h" //supply your own

char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)

ThingerMbed thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
ThingerMbedOTA ota(thing);

int analogPin = A0;  
unsigned long millisLast = 0;

void thinger_reconnect()   {
	thing.stop();
	thing.handle();
	Serial.println("Restarting Thinger..");

	if (thing.is_connected()==1)
        {
          Serial.println("Thinger Reconnected");
          return;
        }
}


void setup() 
{

  Serial.begin(9600);
  // configure wifi network
  thing.add_wifi(SECRET_SSID, SECRET_PASS);
  delay(5000);

  thing["Timestamp"] >> [](pson &out){ 
    int force = analogRead(analogPin);
    out["Force (N)"] = force;
  };

 thing.start();

  while(WiFi.status()!=WL_CONNECTED || (thing.is_connected()==0) ) 
  {
    Serial.println("Waiting for Wifi connection...");
    delay(5000);
  }
}

void loop() 
{

if (thing.is_connected()==0){  
    Serial.print("Thinger Connection Status: ");
    Serial.println(thing.is_connected());
    thinger_reconnect();
  }

if(millis()-millisLast > 120000) {
      millisLast+=120000; 
      thing.write_bucket("01234", "Timestamp", true);
      }
}

PIO version is Core 6.0.2 and Home 3.4.2; Device is Nano Connect RP2040; THinger lbrary is 2.21.1 and WifiNINA is 1.8.13

Hi @Tom_Whiting, can you test with an easier example like the following?

A few changes:

  • Removed your start calls to avoid using mbed tasks, just in case. We can enable it again if necesary.
  • Removed your network check and reconnect. It should be done automatically inside the library.
  • Ensure bucket is written before update latest timestamp.
  • Do not increase the last timestamp with a fixed value, just use the latest timestamp for a better accuracy.
#define THINGER_SERIAL_DEBUG

#include <ThingerMbed.h>
#include <ThingerMbedOTA.h>
#include <ThingerClient.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include "arduino_secrets.h" //supply your own

char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)

ThingerMbed thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
ThingerMbedOTA ota(thing);

int analogPin = A0;  
unsigned long last_ts = 0;

void setup() 
{

  Serial.begin(9600);

  // configure wifi network
  thing.add_wifi(SECRET_SSID, SECRET_PASS);

  thing["Timestamp"] >> [](pson &out){ 
    int force = analogRead(analogPin);
    out["Force (N)"] = force;
  };

}

void loop() 
{
  // it will handle everything: network reconnection and server disconnects
  thing.handle();

  // get current timestamp
  unsigned long current_ts = millis();

  // last tranmission is too old?
  if(current_ts-last_ts>=120000) {

      // only if bucket write is correct, update last tranmission
      if(thing.write_bucket("01234", "Timestamp", true)){
        last_ts = current_ts;
      }
  }
}

If it this does not work as expected, I will need to test better the Mbed and Portenta Integration.

Thanks very much for this @alvarolb. I tried your code and it works correctly prior to router restart which is great. This is the debug messages I’m getting before I restart the router/hotspot:

[THINGER] Authenticated
[THINGER] Writing bytes: 31 [OK]
[THINGER] Writing bytes: 2 [OK]
[THINGER] Available bytes: 2
[THINGER] Writing bytes: 32 [OK]
[THINGER] Writing bytes: 2 [OK]
[THINGER] Available bytes: 2
[THINGER] Writing bytes: 32 [OK]
[THINGER] Writing bytes: 2 [OK]
[THINGER] Available bytes: 2
[THINGER] Writing bytes: 31 [OK]
[THINGER] Writing bytes: 2 [OK]
[THINGER] Available bytes: 2
[THINGER] Writing bytes: 32 [OK]
[THINGER] Writing bytes: 2 [OK]

Then I restart the router/hotspot - it does reconnect after a while and will send a few timestamps, but then it seems to disconnect from wifi/Thinger and tries to reconnect again. Before it disconnects it shows the following debug (The Available bytes:2) serial debug seems to be missing, whereas it was showing prior to router restart.

[THINGER] Authenticated
[THINGER] Writing bytes: 2 [OK]
[THINGER] Writing bytes: 32 [OK]
[THINGER] Writing bytes: 2 [OK]
[THINGER] Writing bytes: 32 [OK]
[NETWORK] Starting connection...
[NETWORK] Connecting to network MyPublicWiFi
[NETWORK] Cannot connect!

In the second capture the device is missing the server keep alive(s) (no one available bytes are displayed) so it decides to reconnect again. Then, it realizes that the Wifi is also disconnected, and try to connect again. I suppose the Wifii reconnection never happens, is it?

@Tom_Whiting, update your library to Arduino-Thinger is 2.21.2
LINK: GitHub - thinger-io/Arduino-Library: IOTMP Arduino Library for connecting devices to thinger.io #IoT

thinger-io/Arduino-Library
CHANGELONG:
2.25.2

- Fix Compiling on WiFi devices without WiFi.begin() support after adding the WebConfig compatibility on ESP32.
- Fix PORTENTA H7 compiling issue: does not implement WiFi.begin(SSID).

Hi @alvarolb , Apologies, I think the connection I was using yesterday might have been a bit dodgy. I’m now trying your code on my home network. A similar thing is happening - Before I restart the router, the keep alive (Available bytes: 2 ) messages are showing periodically. After I restart and wifi/thinger reconnects, I am not getting the keep alive bytes showing (as in the post above), however now I’m on a better connection, the connection is staying and data is being sent every 60000ms (I changed it to every 1 minute to speed up testing) even thought he keep alive isn’t showing. I’ve now changed to writing data every 120000ms as per your code and it now works perfectly. I believe this might have something to do with me using a free Thinger account and so I can only send a minimum of every 1 minute to the bucket.