I was looking for a way to have a callback dynamically set a variable only when it’s requested, and I didn’t come across anything, so included below is what I came up with as a test. It creates 3 variables and callbacks and tests overriding and modifying variables when queried from the cloud.
I don’t know how stable of an API this uses, or if there’s timing and/or threading issues, so YMMV. It was only tested on a Xenon.
These callbacks are already used for String
, so if you try to create a dynamic one of those the callback has to return a the c_str()
version (see https://github.com/particle-iot/device-os/blob/develop/wiring/inc/spark_wiring_cloud.h#L172-L179).
The idea is that you create a spark_variable_t
and set it’s update
field to a callback function that looks like 'const void* (*)(const char*, Spark_Data_TypeDef, const void*, void*)
, then create the variable manually with spark_variable()
.
When this callback is called you get a pointer to the original variable which you can modify and return, or simple return something different. I should also mention that you do need to pass a pointer as the second argument to spark_variable()
, otherwise it isn’t actually created.
I’ve created a gist of this code at: https://gist.github.com/KenMacD/611172a2f7e57da07335f46b5d430eaa
#include <Particle.h>
static char* var_str = (char *)"ORIG STR";
static int var_int = 1;
static double var_double = 1.23;
static double override_double;
static const void* static_str_test(const char* name, Spark_Data_TypeDef type,
const void* var, void *reserverd) {
return "STATIC UPDATE";
}
static const void* dynamic_int_test(const char* name, Spark_Data_TypeDef type,
const void* var, void *reserverd) {
*((int *)var) += 1;
return var;
}
static const void* static_double_test(const char* name, Spark_Data_TypeDef type,
const void* var, void *reservered) {
override_double = 2.34;
return &override_double;
}
void setup() {
spark_variable_t extra_str;
extra_str.size = sizeof(extra_str);
extra_str.update = static_str_test;
spark_variable("str", (void *)var_str, CloudVariableTypeString::value(), &extra_str);
spark_variable_t extra_int;
extra_int.size = sizeof(extra_int);
extra_int.update = dynamic_int_test;
spark_variable("int", (void *)&var_int, CloudVariableTypeInt::value(), &extra_int);
spark_variable_t extra_double;
extra_double.size = sizeof(extra_double);
extra_double.update = static_double_test;
spark_variable("double", (void *)&var_double, CloudVariableTypeDouble::value(), &extra_double);
}
void loop() {
}