Multiple unexpected publishes using Time object

Hi all,

We have been seeing multiple messages being sent unexpectedly and have been trying to determine the cause of this. We are using the Time object in order to grab the current time and send a message every minute (top of the minute). It does this very frequently (only couple times a day), but can be replicated with the following code.

int tmp = 0;

void setup() {
}

void loop() {

  unsigned long start = millis();
  int cs = Time.second();
  tmp++;

  [sensor reading code...]

  if (cs == 0 || (cs < 3 && tmp > 15)) {

    char message[256];
    snprintf(message, sizeof(message), "{\"Time\":\"%s\"}",(const char*)Time.format("%FT%TZ"));
    Particle.publish("event", message, PRIVATE);

    tmp = 0;

  }

  while ((millis() - start) < 1000) {
    Particle.process();
  }

}

Here is an example of the output that shows what is going on:
{“Time”:“2020-04-02T15:22:00Z”}
{“Time”:“2020-04-02T15:23:00Z”}
{“Time”:“2020-04-02T15:23:01Z”}
{“Time”:“2020-04-02T15:24:00Z”}

As you can see, we got two messages for the minute of 23 that we believe should never occur. Any ideas on why this might be happening. It is disrupting our back end as we only expect one message every minute.

Thanks,
Jeff

Do a print trace on tmp and see if it’s doing things you don’t expect.

You could try it like this:

int cs;
void loop() {

  [sensor reading code...]
  cs = Time.second();
  if (cs == 0) {

    if (Particle.connected()) {
    char message[256];
    snprintf(message, sizeof(message), "{\"Time\":\"%s\"}",(const char*)Time.format("%FT%TZ"));
    Particle.publish("event", message, PRIVATE);
    delay(1000);
    }
  }

}

So long as your sensor reading code always takes < 1 then this will work. However, if there is a block on the application thread then you could get the example of the 2 events that you are seeing.

You should have SYSTEM_THREAD(ENABLED);

Ideally, you would spool off the publish to a send queue and let that be handled async to the application thread - try looking at the PublishAsyncQueueRK library.

The sensor reading code should always take < 1, but we have seen that every once in a while, it takes more (this can be fixed and are working it now). This is why we had that secondary check. We changed this check to the following in order to send data each minute though we seen it occur with this code as well:

if (previous_minute != Time.minute()) {
  previous_minute = Time.minute();
  ...
{

How does having a block on the application thread give 2 possible eventw. Can you explain this a little more?

Thank you referencing the PublishAsyncQueueRK, I will look into this library.