Or, if you’re going to use mustache, you can just eliminate the entire JSON library, saving lots of code space and reducing the data down to 92 bytes.
Mustache template:
{{Data.batV.S}},{{Data.batSoC.S}},{{Data.lat.S}},{{Data.lon.S}},{{Data.uvI.S}},{{Data.wDir.S}},{{Data.wSpd.S}},{{Data.wGst.S}},{{Data.hum.S}},{{Data.temp.S}},{{Data.pres.S}},{{Data.tm.N}},{{Data.deviceId.S}}
Code with manual parsing:
#include "Particle.h"
const char *rawData = "4.00,88,41.2083,-73.3440,0.0,0,0.0,0.0,29.0,21.3,970.7,1459294350,540056000a51343334363138";
void parseWeather(const char *data); // forward declaration
void setup() {
Serial.begin(9600);
delay(5000);
parseWeather(rawData);
}
void loop() {
}
typedef struct {
float batV;
int batSoC;
float lat;
float lon;
float uvI;
int wDir;
float wSpd;
float wGst;
float hum;
float temp;
float pres;
long tm;
String deviceId;
bool read(const char *data);
} WeatherData;
const char *dataSeparator = ",";
bool WeatherData::read(const char *data) {
char buf[32];
// Mustache template:
// {{Data.batV.S}},{{Data.batSoC.S}},{{Data.lat.S}},{{Data.lon.S}},{{Data.uvI.S}},{{Data.wDir.S}},{{Data.wSpd.S}},{{Data.wGst.S}},{{Data.hum.S}},{{Data.temp.S}},{{Data.pres.S}},{{Data.tm.N}},{{Data.deviceId.S}}
char *dataCopy = strdup(data);
char *cp = strtok(dataCopy, dataSeparator);
if (cp != NULL) {
batV = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
batSoC = atoi(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
lat = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
lon = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
uvI = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
wDir = atoi(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
wSpd = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
wGst = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
hum = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
temp = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
pres = atof(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
tm = atol(cp);
cp = strtok(NULL, dataSeparator);
}
if (cp != NULL) {
deviceId = cp;
}
free(dataCopy);
// This would be easier with sscanf, but I can't get it to properly read the floating point values
//if (sscanf(data, "%f,%f,%d,%f,%d,%f,%f,%f,%f,%f,%f,%ld,%31s", &batV, &lat, &batSoC, &uvI, &wDir, &wSpd, &wGst, &hum, &temp, &lon, &pres, &tm, buf) == 13) {
return (cp != NULL);
}
void parseWeather(const char *stringData) {
WeatherData weather;
if (!weather.read(stringData)) {
Serial.println("failed to parse");
return;
}
Serial.printlnf("batV=%f", weather.batV);
Serial.printlnf("batSoC=%d", weather.batSoC);
Serial.printlnf("lat=%f", weather.lat);
Serial.printlnf("lon=%f", weather.lon);
Serial.printlnf("uvI=%f", weather.uvI);
Serial.printlnf("wDir=%f", weather.wDir);
Serial.printlnf("wSpd=%f", weather.wSpd);
Serial.printlnf("wGst=%f", weather.wGst);
Serial.printlnf("hum=%f", weather.hum);
Serial.printlnf("temp=%f", weather.temp);
Serial.printlnf("pres=%f", weather.pres);
Serial.printlnf("tm=%ld", weather.tm);
Serial.printlnf("deviceId=%s", weather.deviceId.c_str());
}