Dynamically subscribe to certain device ID's (dynamic responseTopic?)

Hi there!

I’m looking to subscribe to events that’s being triggered by a specific set of devices (where sets of devices can >100, thus not creating unique event for each set of devices). What’s a bit tricky is that I don’t know what devices that is part of each set, since it’s defined on the server side that the cloud is communicating with. What I’ve done up to this point is only subscribe to the own devices requests/responses using

"responseTopic": "hook-response/eventName_{{SPARK_CORE_ID}}"

What I now want to do is somehow ask the server what devices that is included in the same set of devices as the device triggering an event, so I’m able to subscribe to these specific devices and their events.

My spontaneous guess would be that every device that comes online sends their unique SPARK_CORE_ID to the server, and when a new device that belongs to the same set comes online send a request to the server, that as a response says “Hello there, I got these X number of devices online too, belonging to your set, with Y and Z SPARK_CORE_ID’s”. And from there add more devices to my responseTopic. This feels a little bit cumbersome though so I’m wondering if there’s any better way of achieving the same result?

Thanks once again to this supportive and awesome community :smile:

You want to have one device subscribe to an arbitrary number of events for other devices?
If so, you need to know that you only have four subscriptions free on a devices.

My alternative suggestion would be to only subscribe to hook-response/eventName_ then check if the suffix of a received event is found in your (somehow maintained) list of “interesting” devices and just discard the trigger if the current one is not found in the list.
This might cause more events to be sent to your subscribing device, but allows for more than 4 devices in one group.

Alternatively you just forget about the device ID and hand out uniniquely created event names which can either be acquired via an “open new group” or “join some group” process.

1 Like

[quote=“ScruffR, post:2, topic:28718”]You want to have one device subscribe to an arbitrary number of events for other devices?
[/quote]

Well there’s only two or possibly three type of events that’s interesting for a single device, although the device only wants to listen to events that is triggered by devices within the same group. Also, the amount of devices comprising one group will in this stage not exceed four. Saying that “sets of devices >100” I meant that there will eventually be more than 100 groups.

Your suggestion subscribing to hook-response/eventName_ is as you say not optimal since within a couple of months the plan is to have a few hundred devices active simultaneously, triggering events once every five seconds or so, and thus wanting to do the filtering of events in the cloud and not in the device.

[quote=“ScruffR, post:2, topic:28718”]Alternatively you just forget about the device ID and hand out uniniquely created event names which can either be acquired via an “open new group” or “join some group” process.
[/quote]

Could you provide an example of this? Thanks!

@ftideman, if I understand your need correctly, I would suggest you set up a simple relational database (MySQL?) and use a script (ex PHP) as the target of a webhook. In the webhook you will include the device ID and then in the PHP script use this in a SELECT statement to a table where each row includes a device ID as well as the set ID. The PHP script would then respond with JSON messages (one per found row) that includes the device ID as well as whatever else you want to pass for devices in that set. On the Particle device, the subscribe callback function would first check to see if the received message was intended for that device by comparing its device ID with the device ID passed in the JSON message and ignore the message if it was not intended for it. Otherwise, it would process the other information that was passed.

Obviously, the expectation would be that the device and associated webhook would also send additional parameters via the webhook that would be sent to other members in the set.

This strategy would allow one code base for the device, the PHP script and the database and devices in sets would be able to easily broadcast information to other devices in the set.

I use a scheme such as this to pass configuration information to dozens of devices with a single webhook and PHP script.

FWIW

1 Like

Ok I’ve recently tried to implement this without any success.

My publish code:

if (Particle.connected()){
        char buf[150];
        snprintf(buf, sizeof(buf), "{\"group\":\"groupX\", \"clickerID\":\"%u\",\"clicks\":\"%d\"}", localID, clicks); // hardcoded group (groupX) for testing purposes
        Particle.publish ("test", buf, 60, PRIVATE);
 }

So basically no funky business going on here, the webhook “test” gets triggered and the relevant data sent to the server.

When I receive the hook is where the problems start, looking like this:

What I’m trying to achieve is to get the hook reponse to be “hook-response/test_groupX”. Where group is a string that is fetched from the server (that group the devices) and stored on the local device. My webhook looks like following

{
    "event": "test",
    "url": "xxx",
    "requestType": "POST",
    "json": {
  	"updates": 
	[
    		{
		      "localID": "{{localID}}",
		      "clicks": "{{clicks}}"
    		}
	]
     },

    "responseTopic": "hook-response/test_{{group}}",
    "responseTemplate": "{{message}}~{{CNOG}}~{{CNOGI}}~{{CNOGO}}~{{#clickers}}{{_id}}~{{CNOG}}~{{CNOGI}}~{{CNOGO}}~{{/clickers}}",
    "mydevices": true,
    "noDefaults": false //default use true, tried false for testing purposes

}

How can I achieve this? Using e.g. {{SPARK_CORE_ID}} works like a charm in my reponseTopic, but again, since I want devices part of the same group to receive the response I cannot use that. The suggested solution that you provided @ctmorrison makes all the connected devices receive all responses, and the device itself figures out whether the data is relevant to use through comparing the deviceID. But what I’m hoping to achieve is that the cloud does the filtering of what data that is sent to what devices, just like when using {{SPARK_CORE_ID}} in the responsetopic. At least that’s how I interpreted how the responseTopic works, that’s right isn’t it?

Did you have a solution to this @ScruffR ?

The problem here is that you have two seperate lines of execution where the input data does not directly carry over to the output.

The first one sends some data from your device to the Particle cloud with a set of key/value pairs which in turn sends some of these - the ones you told the webhook to pass on - to the destination server.
But since you didn’t pass your group on to the destination server, that info will get dropped there.
AFAIK there is no mechanism that keeps the extra data hanging around till the target server replies to re-insert that data.

In the second (somewhat independent) part the server responds to the Particle cloud but that response does not contain the group field, since the server never knew about its existance in the first place, and hence the cloud will also not be able to put that part into the response - it does know your device ID tho’ and hence will be able to add that bit of info on the way back to your device.

I’m pretty sure you can’t even use localID nor clicks in the hook-response unless the server explicitly passes these key/value pairs back.
Imagine, what if you sent in a "myValue":"1" to a server that should only increment the value and sends it back as "myValue":"2"? Which value would you want to see in myValue in the response?

The first one sends some data from your device to the Particle cloud with a set of key/value pairs which in turn sends some of these - the ones you told the webhook to pass on - to the destination server.
But since you didn't pass your group on to the destination server, that info will get dropped there.
AFAIK there is no mechanism that keeps the extra data hanging around till the target server replies to re-insert that data.

Yeah passing the group thing was a somewhat desperate attempt to solve this. I figured since there's something (in the firmware I guess?) that send the SPARK_DEVICE_ID without the user having to do so, which in turn can be used in the responseTopic, I though it may be a way to solve this.

So what you're saying, if I would make the server deal with "group" as well, the webhook could retain this field as well, and allowing the responseTopic to populate test_{{group}} from the server?

Not actually the firmware, but the Particle cloud adds that into the event. It knows where the event came from and where the response needs to get routet to.

Generally speaking yes. If the server would take that value and just pass it back as is you could do what you intended there.

1 Like

@ScruffR Works like a charm! Thank you so much :slight_smile:

1 Like