Sending variables to an electron

Hi All,

I have a product using electrons that has some site specific variables that I need to get into the electron and to save them in non-volatile memory or EEPROM.

I want to send these variables to the unit when it is first installed, probably using a photon as the server to do so.

I’m thinking having a newly deployed unit send a publish with it’s ID to request the site variables, and have a photon hear this publish, and respond with a publish of it’s own with the data.

The data would have to then be parsed and put into the non-volatile memory.

Data Example:

 String myID = "34002c000a4737xxxxxxxxxx"
 String deviceName = "NumberOne";
 int myChannelNumber = 341851; 
 String myWriteAPIKey = "KQVBCMxxxxxxxxxx"; 
 int sensorDistanceMM = 330;
 int depth = 1830;

What’s the best way to do this that is easy to parse upon receipt? simply separating the data by commas? JSON? Is there a tutorial somewhere on parsing multiple data points out of a Particle.publish event?

Thanks,
J

Both options are quite reasonable. Using comma (or tab) separated values and sscanf works well (except for floating point numbers, sscanf on the Photon/Electron don’t support sscanf of a %f).

I’ll also throw in a plug for my library, which includes both a parser and a generator, which is handy for composing the JSON, taking care of quoting the strings, escaping special characters, and such.

4 Likes

Thanks @rickkas7,

I'm working on this now, will try your library.

I'm going to send the following from a photon to my electron to test the parsing, but it won't compile. It gives me the following error for the publish code:

variableserver.ino:5:86: invalid conversion from 'int' to 'const char*' [-fpermissive]

Particle.publish("jsonParserTest", '{"a":1234,"b":"test":"c":[1,2,3]}', 60, PRIVATE);

What you are trying to send there is not a string, but Particle.publish() requires a string as payload parameter.
If you want to write this as string literal, you need to use double quotes to correctly wrap a string (single quotes are only for single characters).
Internal/embedded double quotes need to be escaped like "this \" is a double quote".
So written correctly, the code highlighting shows a valid string like this

Particle.publish("jsonParserTest", "{\"a\":1234,\"b\":\"test\":\"c\":[1,2,3]}", 60, PRIVATE);

Just some additional notes when using EEPROM with your set of variables.

  • String does not play well with Particle.put() as the object doesn't actually store the string internally
  • when storing multiple values in EEPROM, bundling them in a struct makes storing and requesting the data a lot easier
  • with bigger sets of data it's good practice to also store some checksum (and possibly some magic number) to have some means to check the validity of the data.
2 Likes

OK,
I'm making progress but having an issue sending my deviceID.

This code:

void loop() {
String myID = System.deviceID();
delay(10000);
Particle.publish("myID", myID, 60, PRIVATE);

sprintf(message, "{%s, %s, %i}", deviceName, myID, myChannelNumber);
Particle.publish("siteData", message, 60, PRIVATE);   

}

Gives me this output:

myID 2800200007473432xxxxxxxx
siteData {DeviceNAME, ��, 36xxxxx}

Why can I get the ID in the first Publish, but not in the one where I use:

sprintf(message, "{%s, %s, %i}", deviceName, myID, myChannelNumber);

?????

Because you can't use %s with a String object, only a char* (a c-string). You can fix that with a cast:

sprintf(message, "{%s, %s, %i}", deviceName, (const char*)myID, myChannelNumber);
2 Likes

Thanks @Ric

OK, so now I'm working on the receiving side.
this is my first attempt at parsing, and it's not going very smoothly!

I receive the data and confirm that with a Serial.println,
but when I try to print the sscanf data, it's blank or zero.

Whats wrong with my sscanf statement?

The received String:

{Some_Photon, 2800200007xxxxxxxxxxxxxxx, 3699999}

The handler code:

void saveSiteData(const char *topic, const char *data) {
    strncpy(my_c_String, data, sizeof(my_c_String)-1);
    Serial.println(my_c_String);

    sscanf(my_c_String, "%s, %s, %i", deviceName, myID, myChannelNumber);

    Serial.println(deviceName);
    Serial.println(myID);
    Serial.println(myChannelNumber);
    Serial.println("Handler Complete");
}

How and where are deviceName, myID, and myChannelNumber declared? Also, Since myChannelNumber is an integer rather than a string, then you need to pass the address of that variable, &myChannelNumber.

1 Like

I declared these outside of setup and loop, so they should be global.

char my_c_String[256];

char * myID;
char * deviceName;
int myChannelNumber;

As @Rick said, in order to write your parsed integers back into the variable, you need to pass the variable by reference (not by value as you do there).
You’d rather write it this way

sscanf(my_c_String, "%s, %s, %i", deviceName, myID, &myChannelNumber);

You don’t need the address-of operator for the strings, since arrays withouth the [] are treated as address-of the array already.
Your string also doesn’t parse, because your format doesn’t match the incoming string. You send the string wrapped in curly braces ({...}) but try to parse without - that won’t work.

But once you have corrected that, you may be running into a SOS panic crash, since char *deviceName and char *myID don’t provide any space for the strings to be copied to, potentially resulting in corrupting data of some arbitrary memory location.
Your strings need to be defined as char myID[32]; and char deviceName[25]; and for safe measure, I’d also limit the count of characters parsed for the strings to not exceed these arrays (e.g. "{%31s, %24s, %d}").

2 Likes

OK, got it. working, thanks for the help @Ric and @ScruffR!

I’m not sure I’ll ever get to a level of basic competency programming these things!

But I really appreciate you guys helping me through.

:grinning:

1 Like