Callbacks for Variables


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

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:

#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() {