Can't Particle.publish() in setup() with CPP file

I'm updating some classroom projects that use the older .INO templates. In the code, there is a call to Particle.publish() in setup(). For simplicity, it looks like this

void setup() {
    Serial.begin(9600);
    Particle.publish("SETUP", "SETUP DATA");
    Serial.println("Setup publish");
}

However, when I switch to the .CPP template using the same code, the publish never shows up on the Particle Console (but the Serial.println does.

Is it not possible to call Particle.publish() in setup() when using a .CPP file? If that's the case, is there a simple way to execute publish statement at startup (I could set a flag that is checked for one-time actions, but putting the code in setup() seems more appropriate).

Thanks
Rob

Are you using SYSTEM_THREAD(ENABLED) or any of the non-AUTOMATIC SYSTEM_MODE()s?

You can only publish once Particle.connected() returns true.
And even then, if you wish to subscribe to a such an event (or remote response to it) chances are high, that the subcription will not become active till after the end of setup().

3 Likes

What ScruffR said. The old template did not enable threading, but the new .cpp one does. It's not a .ino/.cpp difference per se, but rather:

SYSTEM_THREAD(ENABLED);

When threading is enabled setup runs before cloud connectivity is established and publish may fail.

With threading disabled (or the line is missing), setup and loop only run when cloud connected and publish will generally succeed.

Setting a flag and publishing from loop when cloud connected is the best long-term solution, but you could insert this right before the publish call to make setup wait until cloud connected so the publish works.

waitUntil(Particle.connected);
Particle.publish("SETUP", "SETUP DATA");
2 Likes

Thank you @rickkas7 and @ScruffR ! That is very helpful. I think the flag will work fine for students.

I did have two followup questions.

  1. With threading enabled, it is still fine to Particle.subscribe() in setup()?

  2. I tried using a flag approach to publish in loop() but it doesn't seem to be working with threading enabled (but the print statement works). Is there a different event I should be waiting for?

bool runOnce = true;

void loop() {
    if (runOnce == true) {
        runOnce = false;
        Particle.publish("WeatherStackJSON", "", PRIVATE);
        Serial.println("run once");
    }

Yes, you should subscribe in setup. However, you cannot rely on subscriptions taking effect until after you return from setup.

You need to check for runOnce && Particle.connected() in loop.

2 Likes

Thank you!

@rickkas7 As a followup, it seems that Serial.println() also doesn't work with threading enabled. For example,

SYSTEM_THREAD(ENABLED);
void setup() { 
  Serial.println("setup!");
   }

This doesn't ever show the print. I wouldn't think this would be connected to Particle.publish() situation you described above. Is this the intended behavior?

It works, it's just that the statement is executed before USB serial can reconnect. If you need early log message, you can add this to the beginning of setup():

waitFor(Serial.isConnected, 15000);
delay(1000);

This will wait 15 seconds for USB serial to connect, then wait 1 more second before continuing. Comment this out before deploying the device in production so it won't wait 16 seconds on every boot if there's no USB serial monitoring.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.