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
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).
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().
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.
Thank you @rickkas7 and @ScruffR ! That is very helpful. I think the flag will work fine for students.
I did have two followup questions.
With threading enabled, it is still fine to Particle.subscribe() in setup()?
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?
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.