Calling a Photon Function... from another Photon


#1

Please forgive the juvenile question. I’ve been successfully using my photons for a while now. I interface with them via a website on my cell phone. Essentially when I want to do something I use the URL to call a function and drive specific behavior (basically using: https://docs.particle.io/reference/api/#call-a-function). Now I would like to cut the cell phone out, and use another photon to do the same job. Is there any way I can use another photon and “post” (I think that’s the term)? I’m trying to keep compatibility with the cellphone… so I see the idea of subscribing, etc… but I’m trying to see if I can not change the current implementation and simply have the photon “click” the same link that I push on the website. Man I hope this makes sense… lol.

An example of my site code:
function ON1() {
var requestURL = “https://api.particle.io/v1/devices/” +deviceID1 + “/” + setOffOn + “/”;
$.post( requestURL, { params: onValue, access_token: accessToken1 });
}

… I’m wondering if the photon could do the same thing… the video at the bottom of this post my help clarify my current implementation: WiFi LED Driver

Thank you for your help!


#2

Not really, because there are two basic problems with this scheme: 1. The Photon doesn’t support https (TLS/SSL encryption) without a fairly cumbersome library. 2. None of the Particle devices can call a function on another device because it’s not supported either.

However, there is an easy solution to this problem that won’t break your phone app. There is no reason why the receiving Photon can’t implement both a function AND a subscription handler.

Here’s the sender code. With a switch connected between D2 and ground, it toggles the light on the receiver when pressed.

#include "Particle.h"

const int SWITCH_PIN = D2;
unsigned long lastSent = 0;
bool ledState = false;

void setup() {
	pinMode(SWITCH_PIN, INPUT_PULLUP);
}

void loop() {
	if (digitalRead(SWITCH_PIN) == LOW) {
		if (millis() - lastSent > 1000) {
			lastSent = millis();

			ledState = !ledState;
			const char *stateString;
			if (ledState) {
				stateString = "on";
			}
			else {
				stateString = "off";
			}

			Particle.publish("light", stateString, 60, PRIVATE);
		}
	}

}

Here’s the receiver code. The light can be triggered using either a publish with on or off in the data, or by a function.

#include "Particle.h"


int functionHandler(String data); // forward declaration
int subscriptionHandler(const char *event, const char *data); // forward declaration
int sharedHandler(const char *data); // forward declaration

void setup() {
	Serial.begin(9600);
	pinMode(D7, OUTPUT);

	Particle.function("light", functionHandler);
	Particle.subscribe("light", subscriptionHandler, MY_DEVICES);
}

void loop() {

}


int functionHandler(String data) {
	Serial.printlnf("functionHandler data=%s", data.c_str());
	return sharedHandler(data);
}

int subscriptionHandler(const char *event, const char *data) {
	Serial.printlnf("subscriptionHandler event=%s data=%s", event, data);
	return sharedHandler(data);
}

int sharedHandler(const char *data) {
	if (data != NULL && strcmp(data, "on") == 0) {
		// On
		digitalWrite(D7, HIGH);
	}
	else {
		// Off
		digitalWrite(D7, LOW);
	}
	return 0;
}


#3

If you don’t want a mix of functions and publish/subscribe, why not switch over the web side of things to publishes as well? Then they use a common system that can be used for both.


#4

Thank you for your replies. I will try this fused approach.


#5

@rickkas7 Rick, you were saying about a year ago… [quote=“rickkas7, post:2, topic:23056”]
None of the Particle devices can call a function on another device because it’s not supported either.
[/quote] - do you know if in that respect anything has changed with the firmware updates in the meantime? I mean, whether or not it is possible to call a particle function from another particle device?

The reason why I ask is the following. I have a number of particle devices set up (a home automation system) and they communicate with each other through the particle cloud by posting events. Actually, I use two “channels”, i.e. one event for requests (i.e. make another particle do something) and a second one for status messages (will be parsed and saved by the particles locally, e.g. as boolean variables). The system works fine although I notice a little lag, which probably is normal (fractions of a second to a second). I was just curious whether a direct function call, if technically possible, would be even faster (lower lag time) and whether such a setup would have any advantages?
Thanks for you opinion.


#6

It’s (unfortunately, still) not possible to directly call Particle.function()s between devices.

I don’t think it would be much faster, if at all. The request would still need to make a round-trip to the very same servers, so there won’t be much of a noticeable difference there. You could play around with local communications over your own network if the latency is annoying you that much.


#7

@hbierau, the only “direct” call you could make is if you are running a TCP, UDP or Web Server on the target Photon and the calling Photon knows its local IP. Otherwise, pub/sub is your best way.


#8

a really duct-tapey way to fix this is through IFTTT…

I made a “if DEVICE1 publishes TOPIC with DATA than call a function on DEVICE2 with ARGUMENTS=DATA” applet on IFTTT te achieve exactly this.