Simple GET call to URL w/ webhooks

Hi everyone.

I am missing something super simple.

I am trying to pull a variable from my heroku app to my Photon. I set up a webhook to the heroku URL using GET (I do not need to send any data) called SERVICEBUTTON1. My issue is that I do not understand how to get/use the response in my .ino code.

I have tried:

Particle.subscribe(“servicebutton1”, handler, MY_DEVICES);

Particle.subscribe doesnt seem to fire for me at all. I do not see any event triggering in my console.

and…

Particle.publish(“servicebutton1”, “25”, PRIVATE);

This works and I see the correct response from Heroku in the console. However, I have no idea how to use the data. Also, this sends data “25” in this case… which I do not need to do.

Any advice is appreciated…

My full code:

const int checkinterval = 20000;
unsigned long currenttime = 0;
unsigned long previoustime = 0;

int redPin = D0;   
int greenPin = D1; 
int bluePin = D2;

int redPin2 = D3;
int greenPin2 = D4;
int bluePin2 = D5;
 
 
void setup(){
    
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);  
    
    pinMode(redPin2, OUTPUT);
    pinMode(greenPin2, OUTPUT);
    pinMode(bluePin2, OUTPUT); 
    

  
}

void loop() {
    
    currenttime = millis();
    
    if (currenttime - previoustime >= checkinterval) {
        
        // setColor(255, 0, 0, 1);  
        // delay(1000);
        // setColor(255, 0, 0, 2);  
        // delay(1000);
        // setColor(0, 255, 0, 1);  
        // delay(1000);
        // setColor(0, 255, 0, 2);  
        // delay(1000);
        
        Particle.publish("servicebutton1", "25", PRIVATE);
        Particle.subscribe("servicebutton1", handler, MY_DEVICES);
        
        
        
        previoustime = currenttime;
    }

}

void handler(const char *event, const char *data) {
    
    Particle.publish("triggerlight1 function called");
  
    //if(data == "Water 1 Status: 0"){
        setColor(255, 0, 0, 1); 
    //}else{
        //setColor(0, 255, 0, 1); 
    //}
  
}
          

void setColor(int red, int green, int blue, int lightnumber){
    
    if(lightnumber == 1){
        
        digitalWrite(redPin, 255 - red);
        digitalWrite(greenPin, 255 - green);
        digitalWrite(bluePin, 255 - blue); 

    }else{
        
        digitalWrite(redPin2, 255 - red);
        digitalWrite(greenPin2, 255 - green);
        digitalWrite(bluePin2, 255 - blue); 
        
    }
 
}

It would help if you show what data you're getting from Heroku, and what you want to do with it. Also, you should not have a Particle.subscribe in loop(). It should be executed only once, so put it in setup().

That should work; what Particle.publish did you use when you tried that?

Thanks for the response @Ric.

Ok good to know about the subscribe in loop. I did try putting it in SETUP and still no response.

I am returning a simple string from heroku. I just need to the string value as a toggle for different RGB LED values.

Again Particle.publish is returning my string correctly but I am not sure how to use the response as a variable in my code.

New code below with your suggestion…

const int checkinterval = 20000;
unsigned long currenttime = 0;
unsigned long previoustime = 0;

int redPin = D0;   
int greenPin = D1; 
int bluePin = D2;

int redPin2 = D3;
int greenPin2 = D4;
int bluePin2 = D5;
 
 
void setup(){
    
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);  
    
    pinMode(redPin2, OUTPUT);
    pinMode(greenPin2, OUTPUT);
    pinMode(bluePin2, OUTPUT); 
    
    Particle.subscribe("servicebutton1", togglelight1, MY_DEVICES);
  
}

void loop() {
    
    currenttime = millis();
    
    if (currenttime - previoustime >= checkinterval) {
        
        // setColor(255, 0, 0, 1);  
        // delay(1000);
        // setColor(255, 0, 0, 2);  
        // delay(1000);
        // setColor(0, 255, 0, 1);  
        // delay(1000);
        // setColor(0, 255, 0, 2);  
        // delay(1000);
        
        //Particle.publish("servicebutton1", "25", PRIVATE);
        
        previoustime = currenttime;
    }

}

void togglelight1(const char *event, const char *data) {
    
    Particle.publish("triggerlight1 function called");
  
    //if(data == "Water 1 Status: 0"){
        setColor(255, 0, 0, 1); 
    //}else{
        //setColor(0, 255, 0, 1); 
    //}
  
}
          

void setColor(int red, int green, int blue, int lightnumber){
    
    if(lightnumber == 1){
        
        digitalWrite(redPin, 255 - red);
        digitalWrite(greenPin, 255 - green);
        digitalWrite(bluePin, 255 - blue); 

    }else{
        
        digitalWrite(redPin2, 255 - red);
        digitalWrite(greenPin2, 255 - green);
        digitalWrite(bluePin2, 255 - blue); 
        
    }
 
}

To advise you, I need to see what this "simple string" looks like. Please provide an example. Does it look like this, "Water 1 Status: 0"? If so, what changes from event to event, the "1", the "0", both, or something else?

1 Like

Hey @Ric . Yes that is the string for now.

My question though isn’t necessarily about the string. In the above code, I am using the line

Particle.publish(“triggerlight1 function called”);

as a console.log(); It doesn’t seem to be executing? regardless of the strings content shouldn’t this be firing?

Thank you for your time.

BUT if you do need the content of the string finalized - lets assume that “Water 1 Status: 0” would be it :wink:

It should be if you're doing a publish with the event name, servicebutton1 . The code you posted has that publish commented out. Is the code you posted what you're using now?

Thanks @Ric yes this is the code I am using. Here is my console output showing no webhooks being called.

And my code with your suggestions…:

const int checkinterval = 5000;
unsigned long currenttime = 0;
unsigned long previoustime = 0;

int redPin = D0;   
int greenPin = D1; 
int bluePin = D2;

int redPin2 = D3;
int greenPin2 = D4;
int bluePin2 = D5;
 
 
void setup(){
    
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);  
    
    pinMode(redPin2, OUTPUT);
    pinMode(greenPin2, OUTPUT);
    pinMode(bluePin2, OUTPUT); 
    
    Particle.subscribe("servicebutton1", handler);
  
}

void loop() {
    
    currenttime = millis();
    
    if (currenttime - previoustime >= checkinterval) {
     

        previoustime = currenttime;
        
    }

}

void handler(const char *event, const char *data) {
    
    if(data == "Water 1 Status: 0"){
        setColor(255, 0, 0, 1); 
    }else{
        setColor(0, 255, 0, 1); 
    }
  
}

void setColor(int red, int green, int blue, int lightnumber){
    
    if(lightnumber == 1){
        
        digitalWrite(redPin, 255 - red);
        digitalWrite(greenPin, 255 - green);
        digitalWrite(bluePin, 255 - blue); 

    }else{
        
        digitalWrite(redPin2, 255 - red);
        digitalWrite(greenPin2, 255 - green);
        digitalWrite(bluePin2, 255 - blue); 
        
    }
 
}

You have to do a publish for a webhook to be called. Are you publishing from somewhere else (CLI, another devise, etc.)?

Yup… I have tried publish as I mentioned in my initial post. And it worked. What I need to do is get the returned string. I am not sure how to make the returned string into a usable variable from the webhook.

Does that make sense?

No, not really. In every other post you're asking about not getting a response, and now you say you are getting a response, but you don't know what to do with it, so I'm confused as to what your problem is.

If what you're trying to do is compare the data with a string, you can't do this,

data == "Water 1 Status: 0"

data is a const char*, and you can't compare them that way; you shold use strcmp

if (strcmp(data, "Water 1 Status: 0") == 0) {
    //do whatever
}

Ok getting closer thank you. If I go back to Particle.publish… I have this code. I still cannot seem to get access to ‘data’.

void loop() {
    
    currenttime = millis();
    
    if (currenttime - previoustime >= checkinterval) {
       

        Particle.publish("servicebutton1", data);
       
        if (strcmp(data, "Water 1 Status: 0") == 0) {
            //do whatever
            setColor(255, 0, 0, 1); 
        }

        previoustime = currenttime;
        
    }

}

"data"is one of the arguments you have in your subscribe handler, and that's where the code I posted needs to go.

void handler(const char *event, const char *data) {
    
    if (strcmp(data, "Water 1 Status: 0") == 0) {
        setColor(255, 0, 0, 1); 
    }else{
        setColor(0, 255, 0, 1); 
    }
  
}

I don't know what you're trying to do here, since I don't see anywhere in your code that you define "data", so what are you sending with that statement? The "data" that's passed in to your handler is a local variable, so you don't have access to it outside that function. If you need it outside the function, then you need to copy it to a global variable (but it's not clear to me that you do need it outside the handler).

1 Like

Hey @Ric Ok thank you for keeping on this with me. I have been trying to be as clear as possible. To reiterate this is what I am trying to do:

  • Use a GET webhook to pull a variable from my heroku service
  • return that variable as a string to use in my .ino as a switch
  • turn an led either red or green

I have tried as you mentioned Particle.subscribe (I do NOT see an event trigger in my console):

void setup(){
    
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);  
    
    pinMode(redPin2, OUTPUT);
    pinMode(greenPin2, OUTPUT);
    pinMode(bluePin2, OUTPUT); 
    
    Particle.subscribe("servicebutton1", handler, MY_DEVICES);
  
}

void loop() {
}

void handler(const char *event, const char *data) {
    if (strcmp(data, "Water 1 Status: 0") == 0) {
        setColor(255, 0, 0, 1); 
    }else{
        setColor(0, 255, 0, 1); 
    }
  
}

I have also tried Particle.publish (I see the event in the console as returning my heroku data properly but I am not sure how to get it into a variable using publish).:

void setup(){
    
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);  
    
    pinMode(redPin2, OUTPUT);
    pinMode(greenPin2, OUTPUT);
    pinMode(bluePin2, OUTPUT); 
  
}

void loop() {
     Particle.publish("servicebutton1", data, PRIVATE);
}

I feel like I am missing something super simple. @Ric I really appreciate your effort.

but...

you haven't posted your webhook, but I believe that it is case sensitive.

1 Like

Thanks @BulldogLowell I capitalized it for emphasis. It is lowercase in the name and subscribe call. Something else is wrong.

To get a response from a webhook, the subscribe name needs to start with hook-response/ followed by the name of the event you used to trigger the hook (the publish). So, in your case, you need to subscribe like so,

void setup(){
    
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);  
    
    pinMode(redPin2, OUTPUT);
    pinMode(greenPin2, OUTPUT);
    pinMode(bluePin2, OUTPUT); 
    
    Particle.subscribe("hook-response/servicebutton1", handler, MY_DEVICES);
}

If you just use “servicebutton1” to subscribe, that should call handler, but it bypasses the webhook, which is not what you want. You should be able to publish with Particle.publish(“servicebutton1”, PRIVATE) if you don’t need to send any data. Try this, and see if it works. If not, it would help to see how you setup your webhook.

1 Like

Morning @Ric :wink:

So thank you again. I tried both of your suggestions. Here is the output as well as my webhook.

Again, thank you staying with me on this one @Ric

=============

1. Particle.subscribe()

Something is up… this did work ONCE but didnt work again when I reflashed the board.

void setup(){
    Particle.subscribe("hook-response/servicebutton1", handler, MY_DEVICES);
}

void loop() {
}

void handler(const char *event, const char *data) {
    if (strcmp(data, "Water 1 Status: 0") == 0) {
        setColor(255, 0, 0, 1); 
    }else{
        setColor(0, 255, 0, 1); 
    }

}

Console Output:

=============

2. Particle.publish()

Again this is pulling the correct data from Heroku as you can see in the logs. I am just not sure how to use Particle.publish and utilize the returned response as a usable variable. Any ideas on how to do this?

void setup(){
}

void loop() {
     Particle.publish("servicebutton1", PRIVATE);
     //can I turn the response into a var here?
     //then create a led switch
}

=============

3. Webhook

For some reason the JSON tab does not show my webhook. Here is a screenshot of the webhook form. Hope this is enough.

this publishes too fast, try putting this inside a timer to fire every (30?) seconds while you debug your code as publish() is subject to rate limits.

Your webhook is getting called, however. You can see the response, so you are half way there... :smile:

The easiest way to verify that your subscribe() function is responding to the publish is to add a serial print to the function to see the event and data:

void handler(const char *event, const char *data) 
{
  Serial.printf("Event: %s\tData: %s\n", event, data);
    if (strcmp(data, "Water 1 Status: 0") == 0) {
        setColor(255, 0, 0, 1); 
    }else{
        setColor(0, 255, 0, 1); 
    }
}

I couldn't help but notice the lack of debugging prints...

1 Like

Thanks man. I do have a timer in the loop/publish code. I just shortened it for simplicity.

Tried putting a serial.print in the handler. No result.

Too many things could have made that appear not to work! You should post all of your real/actual code… it is way too hard to point to problems when you are not dealing in reality.

try this and show what displays on your Serial monitor:

void setup()
{
  Serial.begin(9600);
  Particle.subscribe("hook-response/servicebutton1", handler, MY_DEVICES);
}

void loop()
{
  static uint32_t lastPublishMillis = 0;
  if(millis() - lastPublishMillis > 15000)
  {
    Particle.publish("servicebutton1", PRIVATE);
    lastPublishMillis = millis();
  }
}

void handler(const char *event, const char *data)
{
  Serial.printf("Event: %s\tData: %s\n\n", event, data);
  if (strcmp(data, "Water 1 Status: 0") == 0) 
  {
    Serial.println("got what I expected");
  } 
  else 
  {
    Serial.println("Did not get what I expected");
  }
}

not tested or compiled…

1 Like