Correct way to call Cloud Fucntions when using MANUAL mode with SYSTEM_THREAD(ENABLED) (DeviceOS 1.4.0)

Hi all,

I had some questions about the correct, or “best” way to use cloud functions when using manual mode with system threading enabled.

We’ve been using almost identical code on all of our devices for quite a while now, running on 1.2.1. The devices are deployed in a variety of locations and are reliably connecting with good up-time.

We’ve deployed the most recent couple units with 1.4.0. We tested this device OS with the same code for weeks before deploying and everything worked perfectly. However now that the units are in the field, we are experiencing random outages and disconnects. During testing, units had and RSSI of -100 and in the field they have a RSSI of -75. We’ve never seen behavior like this on our older units running deviceOS prior to 1.4.0, even at the same location.

Our current theory is that a combination of the deviceOS update to 1.4.0, our code, and less then ideal cellular network conditions at the location are contributing to the errors.

I wanted to get some feedback from the community on our void setup() code and cloud functions, and see if what we’re doing is correct or if there are better ways.

#include "VariousLibraries.h"

#define PARTICLE_USING_DEPRECATED_API // to not require Particle.publish() scope (PUBLIC/PRIVATE)

SYSTEM_MODE(MANUAL);

SYSTEM_THREAD(ENABLED);

void setup() {

   Serial.begin(9600);

   if (Particle.connected() == false) {
        Particle.connect();
    }

    delay(5000);    // allow time to connect

    //Sync time
    Particle.syncTime();
    int beginningTime = millis();
    while (Time.year() == 1999 && (millis() - beginningTime) < 5000);
    if (Time.year() == 1999) {
        System.reset();
    }
   
}

These devices are essentially data loggers, so we do want them to enter the void loop() even if we aren’t connected to the cloud so they can start recording data (data is saved to an SD card).

Yes, the above code isn’t complete. But this question is intended to be broad in scope. What is the correct way to write void setup() in 1.4.0? What is the correct way to call Particle.connect()? and Particle.syncTime()?

Thanks,

Colby

1 Like

After Particle.connect() it's usually advisable to wait a bit longer that merely five seconds and instead of using delay() a better approach would look like this

  Particle.connect();
  if (waitFor(Particle.connected, 60000)) {
    // connection established within 60 seconds
    // procede
  }
  else {
    // no connection 
    // act appropriatly depending on your use case
  } 

Also Particle.function(), Particle.variable() and Particle.subscribe() can and should be registered as soon as possible - in MANUAL mode that can even be before connecting.

I'd advise agains using that.
PUBLIC is the default when scope is omitted and that may cause unexpected behaviour effects if someone should happen to send an event of the same name. Even chosing an "obscure" event name won't help since anybody could subscribe to the public event stream and catch your chosen name in order to generate bogus events.

An explicit Particle.syncTime() should not be required since a fresh connection implicitly triggers a resync anyhow.
Also there is Time.isValid() which can/should be used instead of an arbitrary date check.

2 Likes

Thanks for the feedback!

We’ll adjust our code to take these suggestions into consideration.