I have multiple Particle devices running in my installation. I want one device to call a function on another device. I have been looking for sample code on how to call the REST API’s using the built in TCPClient and also httpclient libraries, but have not been successful.
Has anyone done this? And if so, can you post a code snippet to show how to pull it off?
That would be commonly done via Particle.publish() to send the request event and the serving device catches that event via Particle.subscribe().
If you need some response of the serving device, it would send back a response event.
Yes, I use that method for some items. But, that is a push method rather than a pull method. It is better in a number of ways for my system if I can call directly.
There is no direct way to do that within the Particle object and via TCPClient you’d have to establish an HTTPS connection which is not supported without heavy impact on your application space.
That extra demand for the HTTPS connection outweighs the benefit of “direct” request over the pub/sub route.
@IUnknown, I am not aware of any way to call a Particle.function() without going through the Particle Cloud. You could implement a TCPServer on the device that you can call from another device with TCPClient. You could implement a simple command protocol which would cause the server device to call the function normally called by Particle.function(). You could do the same using UDP with reduced reliability.
There is also an open-source local cloud server available:
Another approach is to use MQTT with a local broker running on an rPi (for example) to basically do the same thing as the TCPServer/Client.
My sentence prior to that "subjective" statement sets the context for the latter.
If you are losing 50-60% of available RAM and a considerable portion of flash memory for the sole purpose of gaining the ability to directly call a Particle.function() of a different device (for which you'd also need to get the respective access token and device ID) while pub/sub would rid you of all these extra demands, then the "subjective" statement has at least some factual merit IMO.
However, as @peekay123 pointed out there are TCP and UDP based solutions which won't incure these extra costs but that comes at the expense of security as that would be then unencrypted communication.
Theoretically, from a high-level perspective, being able to directly call a Particle.function() from another device isn’t a whole lot different from a bi-directional pub/sub. Device A says “Hey Device B, whatcha got?”, then Device B responds, and Device A receives the result.
The biggest differences at a lower level are that a direct function call would use less network overhead (because you eliminate at least one connection open + teardown), and it would be (or could be) a synchronous operation, rather than async.
It would also feel like maybe some good symmetry in the API.
I’m curious what the Particle devs think about the possibility of adding this to deviceOS? It would require modifications to the Cloud platform as well, to handle this type of connection.
Hi @IUnknown,
I have never done this, but if I really had to, and none of the previous solutions seemed tempting, this is what I would do:
use a webhook to call the function!
Like this:
Since https is pretty complex for the Photon, I wouldn't even try it. I would use the Cloud, which was created to do the heavy lifting and more. And from the Cloud, you communicate with 3rd party sites with webhooks. Just that in this case, the 3rd party is the Particle Cloud itself.
Although I see no reason why this wouldn't work, I cannot promise it would. But it is easy enough to try, I hope.
I’ve done something very similar (for another Cloud API) and works just fine with an appropriately constructed Webhook. You can include varying parameters in the publish data to control what function is called, with what data, on what device, etc.
I am using Argons and Xenons. I am starting to look at httpsclient-particle. It seems like it should have the functionality I need. I will also mention that Pub/Sub has had some issues where the Xenons or the Argon go offline. Resetting the Argon corrects this, as long as it knows that it needs to. Sometimes when in this state some communication continues, but I have seen from the Web side that the function of the affected device is missing, so an attempt by the Argon to call this function would fail, letting it know that there’s a problem.
I have implemented a ping protocol between them, and this helps some, though as I’ve said when it gets in this state things are somewhat confusing. My use case for this system are puzzles in an Escape Room, so they are not IoT devices per se but independent processors communicating with each other. Pub/Sub works in general, but I’m looking for a way to communicate that is more direct and can detect the error state.
It would seem that the OS must already have most of what’s required to perform this communication, so it would be perfect if it were supported natively. I sort of expected that it was when I started out.
I certainly appreciate the commentary, and when (if) I get this working I will most definitely post the code for basic communications – unless someone has pulled this off – either for a Particle device or in talking to some other device.
I pretty much just copy pasted the example code. Note that JSON newlines are \r\n.
I’m also working on a project that uses code for a research project that has funding and I don’t have the decision making power to put it online here without sterilizing it heavily.
On the other hand, there’s nothing preventing me from making an attempt at what you’re asking for, and that would take less effort than sterilizing my code; I’ll start that in about an hour. I’ll edit this post with the code after.
edit: I can’t do it today; I’ll try tomorrow. The example code pretty much works; if you understand REST API’s it’s pretty easy. Just remember that you have to \r\n.
It makes total sense why it isn’t in the core OS. It has many drawbacks and requires tons of resources. I haven’t ever gotten close to filling up the memory without using this library.
It makes sense as an optional library that you can include when you need to do this stuff, but I would like to see people recommending it more.