Where do you call Cloud::Startup()? You can really only call it from setup() or loop() (once, controlled by a flag). You can’t call it from a constructor for a globally declared object or STARTUP block.
You can see the same effect by having your Particle variable declarations in setup() after a long delay. When you think about what declaring a variable does, it just enters stuff into an internal data structure. The actual cloud connection mechanism is not synced to the setup() call, and too much delay means the declaration message to the cloud has already happened.
Thanks for this clarification - its exactly what I assumed was happening - AFTER finding the issue with delay :-O.
What it DOES however highlight (IMO) is that it is not clear in the docs that a variable cal ONLY be defined at app startup - NOR do we know how long we might have to complete that process. By returning TRUE - the ‘Particle.variable’ suggests to us that all is OK :-O. Had it returned FALSE - I would have known immediately
This means that a variable cannot be defined at some time later than this - say when a photon (etc.) has decided what it wants ‘to be’ based on some other external influence.
For example - it might want to ‘discover’ what is has connected to it before registering the vars to define results etc.
I may for example want to ‘poll’ on a serial but to see whats connected to that bus - and then declare a variable dependent on what I found ;-)).
NB I don’t see this as a problem - just something a developer needs to be aware of ;-)) - I obviously wasn’t…
If we were to allow ‘late declaration’ - we might also want a function to ‘unregister’ a previously defined var (to free up space maybe) ;-)). This capability would thus allow an external device to be connected, register itself with a variable, and then removed again, cleaning up when done, thus allowing some other device to be connected.
I DO provide serial buses on my photon devices - including RS485 devices, which can simply be plugged in and addressed…
I was under the impression that you could use Particle.variable() in loop(), as long as you only call it once per variable, but that does not appear to be the case, at least with 0.4.9 on the Photon as tested below. I thought that “loop” would be registered as a variable when D0 is brought low. It returns true, but the registration does not occur. What’s interesting is that if you tie D0 low so the code gets executed immediately, on the first loop after reset, it does get registered! I’ll have to dig into this some more when I have more time, because that doesn’t sound like the correct behavior to me.
The result from Particle.variable() and Particle.function() isn’t really intended to be a flag that indicates that the cloud function actually succeeded, because that’s unknowable since it will happen some time in the future. It really only returns true if a few basic conditions are met, namely that the name is short enough (12 characters) and that the variable isn’t passed by reference (Particle.variable(“loop”, &loopValue)). That is working correctly, though it probably should be documented better.
One additional criterion to be met is that there has to be room to register an extra function/variable in the device (fixed len arrays).
The registration of fn/var has two sides.
The local part in the device itself can happen at any time (with or without cloud connection)
the remote part which is not actually done by the respective Particle.xxx() (since this doesn’t require cloud - as said above) calls but happens during “enumeration” some time after the connection got established.
So if you pull down the connection after registering a new fn/var, wait till the cloud side realizes the disconnect and then reestablish the connection, you should see the new fn/var.
I’m not sure if there might even be a spark/device/... event that could trigger a “re-enumerate”.
Correct, the variable / function registration is an all or nothing event that needs to either happen early in startup, or later. Make sure you don’t have any delays between registering functions or variables in a block, because if you have at least 1 func / var when the cloud asks, it’ll assume that’s all your firmware had. The cloud does support getting updates on that information at runtime, but the firmware doesn’t yet volunteer / push that information on change.
@Dave, how about my suggested “workaround” to disconnect/reconnect and even more what about a proposal for a re-register event that could be published by application code and a subscribe handler to make the firmware volunteer?