Send Json from Cloud to Photon

You can’t publish to a specific device, a publish event is like a broadcast, and any device that subscribes to a particular event name will receive the event. Of course, you can publish events under different names, and have your Photons only subscribe to the one you want them to receive. You could also have some info in the payload itself that could be used to determine if a particular device should do anything with the event that it receives, if you want to publish using the same event name for all devices.

1 Like

And with function? Can i specify which device am i talking to?
Thanks again @Ric

Yes, a function call is made to a specific device. Is your JSON small enough to fit in 63 characters? JSON isn’t the most compact way to send data, so if you need to squeeze more data into those 63 bytes, you could use a different encoding scheme if you have control over that.

You stated that you want Cloud->Photon, but of course, you need to get the JSON up to the cloud first using a web app or a native Android or iOs app.

Yes @Ric, im generating the Json using a web app.
And which encoding scheme would you suggest?

You can encode it any way you want depending on what kind of data you’re sending. I usually just send a comma separated string, and parse it with strtok on the device side. JSON contains escaped quotes, keys, and colons which use a lot of space in your payload.

Hi @alexgrauer,

I use a webhook for all my devices to make a request for configuration information from an API that I’ve developed. The webhook sends along the device ID of the requesting device. The response from the API is JSON that includes the requesting device’s device ID. When the devices receive the JSON string (due to their subscription to the event), they first check to see if the message was for that device and ignore it if it doesn’t specify that device’s ID. Just a thought for your consideration. I strongly prefer JSON, as it allows graceful addition of parameters without concern for ordering or impact to existing parameters. Using subscribes also allows for more data to be sent and greater flexibility. FWIW.

I would have taken the OP question to mean that he wants to publish data into the Particle cloud from outside the cloud and have a device subscribe to it. I am wondering this myself. It would make sense if this were possible. It would complete the pub/sub model.

Right now my current understanding of how to do pub/sub to outside the Particle cloud is like this:

Publish: use a webhook to link a published event to an external service or external. This pushes data to the external service as opposed to the service polling using the simple API request.

Function: use a function to listen for external service requests

Something like an inverse webhook that would generate an event in the Paticle cloud when an API call using a PUT method is made to events. A device could then subscribe to this external event in the same way it does an internal one. No device names needed like with function. That way more than one device could respond to a subscription from an external web service.

Maybe I’m not making any sense, but it seems to me that the pub/sub model in the Particle cloud is somewhat incomplete compared to say MQTT.

I'm not sure what you're getting at here; this is how it's always done. You have to start from outside the cloud, from a device, a web page, a native phone app, or the CLI.

Again, this is the normal way to use publish; a device subscribes to an event created by another device (so external) or a web page, phone app, etc. I'm not sure how you're using the terms "internal" and "external".

I'm not understanding what functionality you think is missing from pub/sub.

I said I might not be making sense :wink: I was just throwing that out there in case I missed something in the docs. I’ll have to work through more examples. It should be clearer then. And it just might be semantics. Thanks.

Hi, thanks to every one for this topic. I have a web app that sends JSON to the particle cloud with 4 integer data, but I am unable to receive correct data with my C++ code in the photon please check my C++ code. I have spent 3 weeks searching for an answer.

#include <JsonParserGeneratorRK.h>
#include <string.h>

JsonParserStatic<1024, 30> parser1;  

void setup() {
  Serial.begin(9600);
  Particle.function ("test1", Fsave1 );
}

void loop() {}

int Fsave1(String value) {
    parser1.clear(); // clear anything in the buffer
    parser1.addString(value); // add our string we got from the cloud
    if(parser1.parse()) {
        
        int onH;
        parser1.getOuterValueByKey("onH", onH);  //onHour: 1
        Serial.print("onHour = ");
        Serial.println(onH);
        Serial.print("");
        int onM;        
        parser1.getOuterValueByKey("onM", onM); // onMinute: 35
        Serial.print("onMinue = ");
        Serial.println(onM);
        Serial.print("");  
        int offH;
        parser1.getOuterValueByKey("offH", offH); // offHour: 2
        Serial.print("offHour = ");
        Serial.println(offH);
        Serial.print("");  
        int offM;
        parser1.getOuterValueByKey("offM", offM); // offMinute: 55
        Serial.print("offMinute = ");
        Serial.println(offM);
        Serial.print("");        
        
        return 1;
    }
    
    Serial.println("Unable to parse JSON");
    return 0;
}

I think the primary issue is that you are using parser1.addString() incorrectly. In the documentation it states that addString() expects a c-string (char array), not a String object. You may have seen a warning about this from the compiler. The easiest fix would be to change your Fsave1 function signature to:

int Fsave1(const char *value)

Thanks, for your reply @nrobinson2000, but it did not work

By not working I assume you mean the output was "Unable to parse JSON".

Could you try to have the function print out the char array so that you can verify if the JSON received is properly formatted?

Serial.println(value);

Thank you very much @nrobinson2000. I meant I do get wrong onHour and onMinut, so I think I am receiving some JSON string but it is wrong and I am getting no prints for the “value” you recommended.
According to the Chrome browser, my web app is sending JSON string correctly ??!!
Based on @Ric recommendations I may have to use strtok() because my string might be more than
63 bytes. I am going to eventually send 7 integer data variables. after thanking @Ric for his advice, I am learning how to use strtok() function that is after sorting out JSON data

void loop() {}
int Fsave1(const char *JSvalue) {
    parser1.clear(); // clear anything in the buffer
    parser1.addString(JSvalue); // add our string we got from the cloud
    if(parser1.parse()) {
        int onH;
        parser1.getOuterValueByKey("onH", onH);  //onHour: 1
        Serial.println(JSvalue); // print JSON string ??
        Serial.print("onHour = ");
        Serial.println(onH);
        Serial.print("");

Sorry I am changing the value to JSvalue to avoid confusion

You may want to add a Serial.println(JSvalue) to see what exactly arrives at your devices subscribe handler and then post that for us to see :wink:

1 Like

Hi @ScruffR, Sir with all due respect I am not sure what you mean. Sorry, I am not an expert C++ programmer. Would you elaborate, please?
Thanks

@ScruffR and I have suggested that you insert a line of code to print out the string received by the function. Doing so would greatly help with the debugging process. You could then copy the output and paste it here so we can analyze the JSON.

int Fsave1(const char *JSvalue) {
Serial.println(JSvalue);
...

Yes gentlemen, here is the output

JSvalue =                      //the print comand for this is right after, int Fsave1(const char *JSvalue) line
JSvalue =                       // the print comand for this is after, parser1.addString(JSvalue); line

onHour = 536882528     // incorrect datas
onMinue = 536910552   
offHour = 536910552
offMinute = 134878799

Nothing is printed for JSvalue as you see.
Thanks

Then how are you calling that function?
If you don’t see any contents in JSvalue you most likely have not sent any when calling the function.

For testing you can use console.particle.io/devices to call a function with parameters.

1 Like

@kazemzahedi I think you have discovered a potential bug with the JsonParserGeneratorRK library. I have submitted an issue.

@rickkas7 Have you seen this behavior before?


@kazemzahedi, back to your issue, you should ensure that you are actually sending the JSON when you are calling the function like @ScruffR has mentioned.

Also, as a workaround for this case, you could change the if(parser1.parse()) { line to the following to not try to get the values if the length of JSValue is zero:

if(strlen(JSvalue) != 0 && parser1.parse()) {
1 Like