How to attach events to exposed variables

Hi Everyone,
I made a hack to get an event before a variable is being read by the cloud server. To achieve this I dove into the class files of the spark and wrote a little hack to create this ‘event’. This is how it works:
I abuse a Spark.function as a callback function with the name of the variable about to be exposed as parameter. This function is called before the variable’s content is send to the cloud server. After sending the variable to the cloud server it calls the callback function again, with a different parameter.
This means you can alter the variable, malloc memory for it temporarily or so. And after it is send you can reset the variable, or free memory, what ever you like.

I choose for this approach because it avoids the difficult to implement, almost impossible to implement, calls to member functions from unknown classes, our classes in our apps. A known weakness of C++. (Yeah, Yeah I know that the C++ guru’s will comment on this, but trust me after some research I came to the conclusion that it’s not worth the trouble to use pointer to member operators when the calling classes are unknown!)

This implementation is a hack. it works perfect, 2*5 lines of code in the spark_protocol.cpp file and your done!

Maybe an idea to implement this in the current codebase :smiley: Spark team? Then we can all use it with the IDE!

The following code shows the code needed in your app:

int callback(String data) {
    if (data.endsWith("secs")) { //in my test I used a variable called... secs.
        if (data.charAt(0) == 'p') { //on get variable event
            Serial1.println("secs are asked by cloud");
            if (secs > 10) //manipulate before it's to late.
                secs = 10;
        } else if (data.charAt(0) == 'P') { // on post get variable
            Serial1.println("secs send to cloud!");
        }
    }
    return 0;
}   

Recipe:
It works currently only when you compile locally!
Open the file spark_protocol.cpp
Find the following function:

 bool SparkProtocol::handle_received_message(void)

Scroll down to the following lines:

char variable_key[13];
memcpy(variable_key, queue + 8, variable_key_length);
memset(variable_key + variable_key_length, 0, 13 - variable_key_length);

Add this code snippet:

 // Callback mechanism hacked into the code by Marcus Hund
 // an exposed function with the name 'callback' is called with the parameter string set to
// the letter 'p' followed by the name of the variable. 
// The letter p tells the callback function that this a pre situation. This gives the programmer
// the option to manipulate the variable before it is send to the cloud.
// see further down the code for the post hack!
//start of hack:
            char cb_variable_key[14];
            *cb_variable_key = 'p';
            memcpy(cb_variable_key + 1, variable_key, variable_key_length);
            int rc = descriptor.call_function("callback", cb_variable_key);
            //end of hack

Next find this code snipped:

  // buffer length may have changed if variable is a long string
    if (0 > blocking_send(queue, (queue[0] << 8) + queue[1] + 2)) {
                 // error
                 return false;
             }

Add this code snipped below the lines:

//post send variable hack. First character of the callback variable key is altered into 'P'
//to indicate this is a post call to callback.
//start of hack
            *cb_variable_key = 'P';
            descriptor.call_function("callback", cb_variable_key);
//end of hack

So now you’re ready! Try to compile, it should work…

For who needs this, have fun!

Marcus

1 Like