I’m having an issue that may be a bug? I need help to confirm.
In short:
void handler(const char *Name, const char *Value)
{
Particle.publish("Name", Value) //# Does works
Serial.writeln("Name", Value) //# Does works
Particle.variable("Name", Value); //# Does not work
Particle.variable("Name", String(Value)); //# Does not work
Particle.variable("Name", String(Value).c_str()); //# Does not work
Particle.variable("Name", "123"; //# Does work
};
Verification is by API: https://api.particle.io/v1/devices/180028001447343338333633/Value?access_token=########
You should also ensure that the variable pointer is in global scope - if it’s allocated on the stack then the contents will be erased when the function returns.
The simplest way to ensure this is to declare a global variable:
if (Serial.available()) // is only available when a connection & data has been recived.
{
Serial.printlnf("System version: %s", System.version().c_str());
Serial.println("name: " + String::format("%s", String(name).c_str()));
Serial.println("value: " + String::format("%s", String(value).c_str()));
}
Particle.variable("Name", String(name).c_str());
Particle.variable("Value", String(value).c_str());
delay (1000);
}
Serial.available() returns the number of characters that the Photon has recieved (i.e. you typed something) so that seems wrong.
You should declare your Particle.variables in setup() with global scope variables. You can assign to these in handler but the way your code is written now cannot work since the variable go out of scope and do not exist after you exit you handler routine.
Serial.available() is working correctly ( it only sends back information if the serial interface is connected to usb ( it works and has no change on the output of Particle.variable if i remove it).
You may be correct on the Particle.variables? i’ll check for references but not sure how to correctly do this (i’m new to the photon ).
@Moors7 now i’m wondering if that is why i’m having such issues pulling values at any time is that the values are only set very quickly and as you are saying not in the global scope The var would then be destroyed before the cloud polls the values?
Particle.variables() are only set up once to expose a global variable and are not published (as you seem to be trying).
Once you've exposed a variable any change to the underlying variable will immediately be accessible via the Particle.variable().
Taking your code slightly refurbished
const int LED = D7;
String strName;
String strValue;
void setup()
{
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
Particle.variable("Name", strName); // make strName available to the cloud
Particle.variable("Value", strValue); // ditto for strValue
Particle.subscribe("spark/", handler);
Particle.publish("spark/device/ip");
Particle.publish("spark/device/name");
}
void handler(const char *Name, const char *Value)
{
strName = String(Name); // new content will now be available as Particle.variable
strValue = String(Value); // ditto
// delay (1000); // NEVER delay a handler
}
To clarify for drivers-by: Since the Serial RX buffer is never read or flushed one byte entered will stay there and keep the expression TRUE forever.
Thank you very much i have a huge understanding now of how it is working …
Particle.variable is only a reference to the cloud to pull this variable when requested… and is not a push to the server of the current value as expected.
I’ve cleaned up my code for future working reference below.
Thank you again!
int LED = D7; // Onboard LED
String IP = "";
String NAME = "";
void setup()
{
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
Particle.variable("IP", IP); // Tells the cloud to reference this global variable.
Particle.variable("NAME", NAME); // Tells the cloud to reference this global variable.
Particle.subscribe("spark/", handler); // Tells the cloud what information to listen for and what function to use.
Particle.publish("spark/device/ip"); // Trigger to get this information (need to verify why it is needed)
Particle.publish("spark/device/name"); // Trigger to get this information (need to verify why it is needed)
}
void handler(const char *Name, const char *Value)
{
if (String(Name).equalsIgnoreCase("spark/device/name"))
{
NAME = String(Value);
}
if (String(Name).equalsIgnoreCase("spark/device/ip"))
{
IP = String(Value);
}
}
void loop()
{
if (Serial.available()) // is only available when a connection & data has been recived.
{
Serial.printlnf("System version: %s", System.version().c_str());
Serial.println("Device Name: " + NAME);
Serial.println("Device IP: " + IP);
}
digitalWrite(LED, LOW);
delay(5000);
digitalWrite(LED, HIGH);
delay(5000);
}
The point here is that these infos are not available to the device itself but to the cloud (name is only stored there and the external IP is only visible from the "outside").
Any events starting with spark are reserved for Particle system use and so these two events actually are not directly meant for your device but instruct the cloud to send these events to your device with and add the referenced payload, so that you can subscribe to it.
My thoughts: Publishing to pull a value, seems a funny way of doing this? I would have expected to subscribe to 'spark/device/ip' to get the IP. Where if I subscribed to 'spark/device' i would get all underlying values.
Yes, but how would you instruct the cloud to publish an event that you have subscribed to?
Or would you expect them to be published on a regular basis? How often? For all Particle devices all over the world?
A subscription does not trigger anything, it just places a note in the cloud: “Whenever this event happens call my number”.
This does not cause the event to happen.
When you subscribe for a magazine, your subscription does not cause the magazine to be printed, but once it got printed you’ll get an issue delivered to the address you provided with your subscription.
And the publish to trigger a republish is like you want a historic issue of a mag you have subscribed to, so shoot them a letter and once the editor gets your letter (event) they will immediately send the already printed and archived issue.
Yes but to get the information it requires a subscription and a trigger to instruct the cloud. Why not one line?
Example:
Particle.subscribe("spark/device/ip", handler);
Server Response:
Receives the registration and adds the IP to the feed queue to send back? They are special feeds, they could have special response triggers.
Were just taking about peace of programming mind not functionality....