I’m curious why the following causes good data for the first publish and corrupted data for the second publish? Seems that using String(data) corrupts the value for any code that reads it afterwards.
The pointers that your subscription function gets for the event and and data are pointers into the internal data structure used by the cloud connection. That means when you call the cloud connection to publish, you can’t expect the underlying memory to contain that same bytes–it has been overwritten by your first publish call’s interaction with the cloud data structures. It wouldn’t really be efficient for the cloud connection to make copies of all the data it hands out pointers to, so that job falls to you if you need to receive from cloud and transmit to the cloud in a subscription function handler.
If you want to do what you are trying here, you need to copy the data into your own memory so it won’t get overwritten like this:
void setup() {
Spark.subscribe("testSub", processRemoteData, MY_DEVICES);
Spark.publish("testSub","test data", 60, PRIVATE);
}
void processRemoteData(const char *event, const char *data)
{
char buf[64];
memcpy(buf,data,strlen(data)+1); //plus one to get the terminating zero
Spark.publish("test","Received data: " + String(buf), 60, PRIVATE);
Spark.publish("test2","Received data: " + String(buf), 60, PRIVATE);
}
void loop() {
}
Well, it makes some sense, but I’m not sure it’s documented anywhere.
If calls to any Spark.foo() function can modify data that was already supplied by other Spark.* infrastructure, this needs to be stated.
Extra credit for at least not fubar’ing any data until the callback specified in Spark.subscribe() has returned, regardless of what other Spark.foo() is called therein.
The docs need to be checked to ensure they clearly state that *data is not persistent outside the scope of the callback (this test proves that at present it’s not even persistent inside that scope), and the user is responsible for copying the content, not just the reference; if they want to continue to use it out of scope.