Particle publish permanently blocks when internet goes down

I am using the following code to send data every second.
System Thread is enabled.
If I power down the router, the program sometimes locks (unless rebooted) at Particle.publish() with solid cyan.
As in, it prints Before but not After on Serial

Serial.println("Before");
if (WiFi.ready() && Particle.connected())
{
    Particle.publish("name", data, PRIVATE , NO_ACK);
}
Serial.println("After");

At the same time to debug this I started listening for the setup button press events and set it to reboot the device when the button is pressed. And the event handler works even when the loop is stuck at Particle.publish.

I think you need to use PublishQueueAsyncRK if you want your program to keep running if there are brief outages.

This blocks the program permanently. As in After is never printed, even if I wait for several minutes. I was hoping the solid cyan would point to something.

And, PublishQueueAsyncRK also ends up with the same.

Did you change your particle publish to the queue one? publishQueue.publish?

I have an argon and a photon running with that and my code is not being locked when the internet goes away.

Yes I did.

Then you will probably need to wait for @rickkas7 to jump in here.

From memory, I recall that WiFi.ready() is not a sufficient test. Search the community for references to this. Check if you have an IP address as well (but only when WiFi is up).

Let us know how you went.

To expand on that, Particle.connected() should never be true without WiFi.ready() already being true.
So WiFi.ready() should not need to be checked when Particle.connected() is expected to be true too.

However, neither of the two are sufficient to tell whether the connection is currently - in this very moment - valid as short outages may not be caught by either of them.

Nevertheless, Particle.publish() should not (unless explicitly instructed via WITH_ACK) be blocking as it only hands off the delivery of the event to the system and won’t wait for it to actually happen.
Consequently I’d expect there is something else at play here.

So we need to learn some more about your circumstances

  • Which device OS version are you running?
  • What does "sometimes" exactly mean? How frequently?
  • What does the rest of your code do? (Since Serial.print() is printing asynchronously other things might interfere here too)
  • How are you listening to the button press?
2 Likes
  • I’ve tried v1.5.2 and latest v2 rc
  • I’ll have to find a way to run some long running test to find that out, but it’s pretty repeatable.
  • Just listening on Serial1 and sending to internet.
  • System.on(all_events, handle_all_the_events);

handle_all_the_events prints the events on Serial, and I don’t see any events at the moment the led turns solid cyan.

I guess this is the culprit.

Try populating a global string but printing it from loop().

That exactly is what I meant with this

Since it's probably the print statement in the callback function that causes the lock-up you won't see its output.

2 Likes

@brahma-dev To chime in on the good points made already, even with SYSTEM_THREAD(ENABLED); I would always check for WiFi.ready() on its own before checking Particle.connected() i.e. not in the same if statement. The other ripple in the space time continuum is your WiFi and how that is interacting with the WICED network stack. I have spent a lot of time trying to get the performance of the publish resilient to any WiFi condition and I still get cases where hangs occur. Happy path - works fine but turning off the WAP (out of range) when there are valid credentials or other cases do still seem to trip it up. The case I have still not solved is when the device is restarted with the WAP it has credentials for turned off. All seems OK and then at some point later a call using a shared resource (such as Serial or SPI) will stop.

Well spotted @ScruffR!

@brahma-dev, just checked what I do re Particle.publish(). I just check for Particle.connected().

Not sure how that makes a difference with C++ short circuiting boolean expressions tho' (unless you want different actions individual for combinatoric cases respectively).

AFAICT there is no difference between

  if (WiFi.ready()) 
    if (Particle.connected())
      doSomething();

and

  if (WiFi.ready() && Particle.connected()) 
    doSomething();

I'm even positive the machine code for both would look very similar.

BTW, the case ( false && true ) should never occur and should be considered a device OS bug if it ever happened.

That’s news to me - I bow to your vastly superior grasp of the C++ compiler workings. This possibly explains why I am seeing behaviour static code analysis would not highlight.

Given that calling Particle.connected() will block when the WiFi is not connected (due to bad credentials or WAP out of range) - how would you then suggest writing this to enforce a separation of the condition checks - by putting another statement between the if() s

Posting an example

            else if (WiFi.ready())                  //has expired but is WiFi AND Cloud connected AND opMode connected then auto renew the lease V416H
            {
                if (param.opMode == D_CONNECTED)
                {
                    if (Particle.connected())
                    {
                        result = true;
                        param.webAppLastLeaseUpdate = _now;
                        putParameters();
                    }
                }
            }

this would get concatenated to (x && y && z) {result = true;…}

Boolean evaluation with short circuiting works from left to right evaluating one combinatoric expression at a time. As soon one expression in an AND operation false (or true in an OR) the rest of the entire expression will be skipped (nested operations will be treated accordingly).

Hence

  if (x) 
    if (y)
      if (z) 
        result = true;

and

  if (x && y && z) 
    result = true

will only execute y and z if all the expressions before already rendered true.

When you write your own functions bool x(), bool y() and bool z() which log their being called respectively you can easily test that.

1 Like

So just the order matters!

Correct!

However, as so often in life: There is one catch (although that won’t apply for the examples above)
Boolean short-circuiting may not happen (be possible) for expressions with objects that overload || or && operator.

1 Like

Does that also mean I can’t use Serial1.write at the same time as Particle.publish ?
I removed all Serial output but still end up with solid cyan when I kill the WiFi; with the reboot on button press still functional.

I also tried the blocking version of Particle.publish and that also ends up with same solid cyan.

Hi,
let's back to the track :slight_smile:

I'm publishing from my Photon for years with no problem at all !!!
but I just checking for Particle.connected() something like this:

if (Particle.connected()) Particle.publish("All_data", status, 60, PRIVATE); 

and the status is formatted like this:

snprintf(status, sizeof(status),"{\"sensor_data\": %s, \"extender_data\": %s, \"FIRMWARE_CLASS\": \"%s\", \"Ver\": %f, \"wifi_name\": \"%s\", \"wifi_sig_str\": %d }"
,msg
,msg2
,FIRMWARE_CLASS
,FIRMWARE_VERSION
, WiFi.SSID()
,(int8_t)WiFi.RSSI()); 

all of this is in function

void publishStatus()

then I call this

publishStatus();

within the loop every 2 sec

#define DEBUG_INTERVAL_SECS 2

int n = 0;

unsigned long interval = 0;

void publishStatus(){
    
     snprintf(status, sizeof(status),"{\"sensor_data\": %s, \"extender_data\": %s, \"FIRMWARE_CLASS\": \"%s\", \"Ver\": %f, \"wifi_name\": \"%s\", \"wifi_sig_str\": %d }",msg, msg2, FIRMWARE_CLASS, FIRMWARE_VERSION, WiFi.SSID(), (int8_t)WiFi.RSSI());   
     
     if (Particle.connected()) Particle.publish("All_data", status, 60, PRIVATE);
    
}

void setup(){

some setup stuff .....
  ....
  ....


}


void loop(){

if (millis() - interval > 1000) {
     interval = millis();

  some other stuff .....
  ....
  ....

 n++;
    if (n > DEBUG_INTERVAL_SECS ){
        n = 0;
        
        publishStatus();
    }

  some other stuff .....
  ....
  ....
  }
}

So as @ScruffR mentioned we will need to see your code to determinate what's going on

I would have posted it already if it was possible.
But as far as I can go. The loop reads around 500+ bytes from Serial1, packages it to a string and sends it to the internet.

I have tried both blocking and non blocking Particle.publish and in both cases it fails the same way.

If I understand it correctly, Serial1 should not affect the blocking version of Particle.publish.

I was also listening for out_of_memory events but they don’t happen when the led goes solid cyan.

Perhaps someone can point me to things that can affect the blocking version of Particle.publish when system thread is enabled.