I am a big fan of using MQTT as an agnostic data gathering platform. I also believe that the topic hierarchy architecture is crucial to large projects with thousands of deployed units. In the past, I accomplished this with Particle by directly using the MQTT lib on a firmware level. However, with the Gen 3 products, this is no longer possible in a simple way, as mesh connected devices do not have the ability to access TCP.
While we could do a workaround of first sending all data to the gateway, and then forwarding from there to the MQTT broker (c.f. Conceptual Difficulties), this has several disadvantages: code complexity, multiple codebases, dedicated gateway hardware, etc…
Particle.publish()
, on the other hand, works perfectly in Gen 3. The devices do not know or care if they are mesh’ed or gateway’ed units. So we can get all the data out of the mesh and up to Particle Cloud with trivial effort, perfect!
Once it’s there, we now have to move it on to the MQTT broker. I have done this in a simple way with webhooks via shitr.io (working code given below), but I now finding myself needing to have a bit of granularity.
Firmware:
// setup() runs once, when the device is first turned on.
void setup()
{
// Put initialization like pinMode and begin functions here.
}
// loop() runs over and over again, as quickly as it can execute.
void loop()
{
// Get some data
String owner = "foo/bar/";
String topic = owner + "kitchen/fridge";
float temperature = 20.0f + ((rand() % 100) - 50)/10.0f;
float co2_ppm = 400 + ((rand() % 10) - 50)/10.0f;
String data = String::format(
"{ \"_t\": \"%s\", \"temperature\": %f , \"co2\": %f }",
topic.c_str(), temperature, co2_ppm);
// Trigger the integration
Particle.publish("/", data, PRIVATE);
// Wait 5 seconds
delay(5000);
}
Example output published to Particle Cloud:
{
"_t":"foo/bar/kitchen/fridge"
"temperature":18.4
"co2":413.3
}
webhook:
{
"event": "/",
"url": "https://try:try@broker.shiftr.io/{{{_t}}}",
"requestType": "POST",
"noDefaults": false,
"rejectUnauthorized": true,
"body": "{{{co2}}}"
}
Note that we look for the very simple and low bandwidth character /
to trigger the hook. Then we use the _t
JSON field as the entire base topic hierarchy.
Now, I would like to publish to two final topic hierarchies:
foo/bar/kitchen/fridge/temperature
foo/bar/kitchen/fridge/co2
But I only have one webhook. In the above example it publishes only co2
. The temperature
field gets ignored.
It would be madness to make a separate webhook for each topic, as I will have dozens of distinct topics, so what I really need to do is have a teensy bit of intelligence in the webhook. What I would like is that for each JSON field in the output, the webhook triggers an HTTP POST call with the base topic + individual topic (as well as the data in that topic’s field).
I’m coming up blanks for how to do this in the Particle Ecosystem, and all I can think to do is add in a Heroku layer which receives the data from the Particle Cloud and then properly formats it for the MQTT bridge-- which is ugly, costly, and increases complexity by another node.
Anyone have insight into this?