I have been working on a solar powered Particle Electron project and a Vapor 3.0 (Swift) based back-end. While the Electron itself is a great platform, getting the data in the back-end feels quite cumbersome.
When you want to publish a single value, all is fine (well, ‘fine’ because this still has to a cast to String
for Particle.publish
to work properly ). But when you want to do anything a little more complicated, things start breaking and leading to non-compliant requests.
One of the things I added was keeping track of battery / charge status, trying to send a batch of data to the backend. Because it’s not possible to send multiple values in one Publish event (other than concatenating them into a string) I went the nested JSON route:
/// Battery and Solar Charging Status
float batteryChargePercentage = 0.0; // initial value
void readPowerStatus() {
FuelGauge fuel;
PMIC power_management;
// get the battery percentage
float chargePercentage = fuel.getSoC();
// only submit every 2% change
if (abs(chargePercentage - batteryChargePercentage) >= 2) {
Serial.printlnf("Battery: %.4f v (%.4f %% charged, has power: %d)", fuel.getVCell(), fuel.getSoC(), power_management.isPowerGood());
// battery voltage, state of charging and whether or not we have usb power
// {"v": "4.05", "soc": "77.81", "c": true, "h": false}
char publishString[64];
sprintf(publishString,
"{\"v\": %.4f, \"soc\": %.4f, \"c\": %s, \"h\": %s}", // the JSON to publish
fuel.getVCell(), // battery voltage, e.g. 3.86
chargePercentage, // battery State of Charge, e.g. 44.87
(power_management.isPowerGood() ? "true" : "false"), // whether or not we have USB power from solar panel (0/1)
(power_management.isHot() ? "true": "false")); // whether or not In Thermal Regulation (bad!)
Particle.publish("b", publishString, PRIVATE);
// remember batter percentage
batteryChargePercentage = chargePercentage;
}
}
I created a web hook that would trigger on this event and call my RESTful Vapor based back-end:
url: http://myubuntuserver/cores/{{PARTICLE_DEVICE_ID}}/charges
payload:
{
"battery": "{{PARTICLE_EVENT_VALUE}}",
"published_at": "{{PARTICLE_PUBLISHED_AT}}"
}
The issue here is that the moustache templates enforce that you need to send everything as a string, which basically means that the nested JSON I am trying to send becomes a String.
So instead of the expected (or wanted) payload:
{
"battery": {
"v": 4.05,
"soc": 77.81,
"c": true,
"h": false
},
"published_at": "2018-02-22T11:39:15.159Z"
}
This becomes:
{
"battery": "{\"v\": 3.9950, \"soc\": 76.8320, \"c\": false, \"h\": false}",
"published_at": "2018-02-22T11:39:15.159Z"
}
Which basically results in having to double parse incoming requests
This is already a workaround, because I would rather have the following payload without having to go nested JSON altogether:
{
"v": 4.05,
"soc": 77.81,
"c": true,
"h": false,
"published_at": "2018-02-22T11:39:15.159Z"
}
And this is not possible either because Publish
only takes Strings. So this would become
{
"v": "4.05",
"soc": "77.81",
"c": "true",
"h": "false",
"published_at": "2018-02-22T11:39:15.159Z"
}
Where you would have -again- to add in additional transformations for changing Double-As-A-String into Doubles and Boolean strings into booleans…
Sorry, but I am getting pretty frustrated with having to jump through so many hoops to get something -in my eyes- pretty simple working… Are moustache templates really the right solution here?