Has anyone experienced difficulty subscribing to multiple webhooks?
Searched the forum to no avail...
Spark.subscribe("hook-response/gmail_count", gotGmailAtomFeed, MY_DEVICES);
//delay(2000); // tried delays here...
Spark.subscribe("hook-response/princeton_weather", gotWeather, MY_DEVICES);
EDIT:
From the documentation:
NOTE: A Core can register up to 4 event handlers. This means you can call Spark.subscribe() a maximum of 4 times; after that it will return false.
I cannot seem to get two to work...
@BulldogLowell , I can’t find any reference to it, but with 31 char is your second filter quite long.
Could you just try to make it a bit shorter?
As said, it’s only a “starting with”-filter, so you will still catch the event you’re looking for.
Just a blind guess - and I might burn my hands with it again
On the other hand, have you checked if you can subsribe to either event when it’s your only subscription?
Can you also check the return value of your Spark.subscribe()
calls whether you do get a true
result.
1 Like
I shortened it:
Spark.subscribe("hook-response/nj_weather", gotWeather, MY_DEVICES);
but that didn't work either.
Either works, but not both. I am going to try to write a small sketch with just the two Spark.subscribe() hooks
1 Like
@ScruffR
I confirmed with this small sketch that only the first instance will work… the first one in setup( )
bool pubToggle = true;
int emailCount = -99;
int outdoorDewpoint = -99;
int windSpeed = -99;
String windDirection;
String weatherCondition;
int outsideHumid = -99;
int outsideTemp = -99;
unsigned long pubTime = 0;
//
void setup()
{
Serial.begin(9600);
//Spark.subscribe("hook-response/nj_weather", gotWeather, MY_DEVICES);
Spark.subscribe("hook-response/gmail_count", gotGmailFeed, MY_DEVICES);
Spark.subscribe("hook-response/nj_weather", gotWeather, MY_DEVICES);
}
//
void loop()
{
if (millis() - pubTime > 10000UL)
{
Serial.print("publishing...");
if (pubToggle)
{
Spark.publish("gmail_count");
Serial.println("gmail count");
}
else
{
Spark.publish("nj_weather");
Serial.println("weather");
}
pubToggle = !pubToggle;
pubTime = millis();
}
}
void gotGmailFeed(const char *event, const char *data)
{
String gMailBuffer = String(data);
String emailReturn = extractString(gMailBuffer, "<fullcount>", "</fullcount>");
if (emailReturn != NULL)
{
emailCount = emailReturn.toInt(); //
Serial.println("Email Count Retrieved");
Serial.println(emailCount);
}
}
void gotWeather(const char *event, const char *data)
{
Serial.println("getting Weather");
String weatherBuffer = String(data);//<temp_f>35.6</temp_f>
String temperatureReturn = extractString(weatherBuffer, "<temp_f>", "</temp_f>");
String humidityReturn = extractString(weatherBuffer, "<relative_humidity>", "</relative_humidity>");//<relative_humidity>56%</relative_humidity>
String dewpointReturn = extractString(weatherBuffer, "<dewpoint_f>", "</dewpoint_f>");
String windDirectionReturn = extractString(weatherBuffer, "<wind_dir>", "</wind_dir>");
String windSpeedReturn = extractString(weatherBuffer, "<wind_mph>", "</wind_mph>");
String todayHighReturn = extractString(weatherBuffer, "<high> <fahrenheit>", "</fahrenheit>");
//String todayLowReturn = extractString(weatherBuffer, "<wind_mph>", "</wind_mph>");
String weatherReturn = extractString(weatherBuffer, "<weather>", "</weather>");
if (temperatureReturn != NULL)
{
outsideTemp = temperatureReturn.toInt();
Serial.println(outsideTemp);
}
if (humidityReturn != NULL)
outsideHumid = humidityReturn.toInt();
if (weatherReturn != NULL)
weatherCondition = weatherReturn;
if (windDirectionReturn != NULL)
windDirection = windDirectionReturn;
if (windSpeedReturn != NULL)
windSpeed = windSpeedReturn.toInt();
if (dewpointReturn != NULL)
outdoorDewpoint = dewpointReturn.toInt();
//
}
String extractString(String myString, const char* start, const char* end)
{
if (myString == NULL)
{
return NULL;
}
int idx = myString.indexOf(start);
if (idx < 0) {
return NULL;
}
int endIdx = myString.indexOf(end);
if (endIdx < 0) {
return NULL;
}
return myString.substring(idx + strlen(start), endIdx);
}
That’s rather odd.
Maybe it’s time to call on @Dave and @BDub for some assistance, but meanwhile could you try two more things?
Check if the second Spark.subscribe()
returns true
or false
Try one handler for both, which just looks for "hook-response/"
and Serial.println(event)
. You could also use this handler to parse event
to then call your respective functions (as workaround for the time being).
I’d also edit your topic title to attract more attention of Webhook pros
e.g. “Issues with more than one instance of Spark.subscribe( ) for Webhooks”
thanks for the help @ScruffR
yup, returns true.
not sure what you mean there
Since one Spark.subscribe("hook-response/", webhookHandler, MY_DEVICES);
would catch both webhooks, you will be able to do this
void webhookHandler(const char *event, const char *data)
{
Serial.println(event); // just for debugging
// to see how the webhook was actually called
if (strpos(event, "gmail_count") >= 0)
gotGmailFeed(event, data);
if (strpos(event, "nj_weather") >= 0)
gotWeather(event, data);
}
2 Likes
that did it...
MUCH appreciated. We will have to see what's up here.
(using strstr()
, FYI):
bool pubToggle = true;
int emailCount = -99;
int outdoorDewpoint = -99;
int windSpeed = -99;
String windDirection;
String weatherCondition;
int outsideHumid = -99;
int outsideTemp = -99;
unsigned long pubTime = 0;
//
void setup()
{
Serial.begin(9600);
delay(6000);
Spark.subscribe("hook-response/", webhookHandler, MY_DEVICES);
//Spark.subscribe("hook-response/", gotGmailFeed, MY_DEVICES);
//Spark.subscribe("hook-response/", gotWeather, MY_DEVICES);
}
//
void loop()
{
if (millis() - pubTime > 10000UL)
{
Serial.print("publishing...");
if (pubToggle)
{
Spark.publish("gmail_count");
Serial.println("gmail count");
}
else
{
Spark.publish("nj_weather");
Serial.println("weather");
}
pubToggle = !pubToggle;
pubTime = millis();
}
}
void gotGmailFeed(const char *event, const char *data)
{
String gMailBuffer = String(data);
String emailReturn = extractString(gMailBuffer, "<fullcount>", "</fullcount>");
if (emailReturn != NULL)
{
emailCount = emailReturn.toInt(); //
Serial.println("Email Count Retrieved");
Serial.println(emailCount);
}
}
void gotWeather(const char *event, const char *data)
{
Serial.println("getting Weather");
String weatherBuffer = String(data);
String temperatureReturn = extractString(weatherBuffer, "<temp_f>", "</temp_f>");
if (temperatureReturn != NULL)
{
outsideTemp = temperatureReturn.toInt();
Serial.print("outsideTemp = ");
Serial.println(outsideTemp);
}
//
}
String extractString(String myString, const char* start, const char* end)
{
if (myString == NULL)
{
return NULL;
}
int idx = myString.indexOf(start);
if (idx < 0) {
return NULL;
}
int endIdx = myString.indexOf(end);
if (endIdx < 0) {
return NULL;
}
return myString.substring(idx + strlen(start), endIdx);
}
void webhookHandler(const char *event, const char *data)
{
Serial.println(event); // just for debugging
// to see how the webhook was actually called
if (strstr(event, "gmail_count"))
gotGmailFeed(event, data);
else if(strstr(event, "nj_weather"))
gotWeather(event, data);
}
outputs:
publishing...gmail count
hook-response/gmail_count/0
Email Count Retrieved
7
hook-response/gmail_count/1
hook-response/gmail_count/2
hook-response/gmail_count/3
hook-response/gmail_count/4
hook-response/gmail_count/5
hook-response/gmail_count/6
hook-response/gmail_count/7
publishing...weather
hook-response/nj_weather/0
getting Weather
hook-response/nj_weather/1
getting Weather
hook-response/nj_weather/2
getting Weather
hook-response/nj_weather/3
getting Weather
outsideTemp = 37
hook-response/nj_weather/4
getting Weather
hook-response/nj_weather/5
getting Weather
hook-response/nj_weather/6
getting Weather
hook-response/nj_weather/7
getting Weather
2 Likes
Do I interpret this wrong or does only one of the eight retriggers of the webhook actually carry some data
payload?
Could you try this
void webhookHandler(const char *event, const char *data)
{
Serial.print(event); // debug full event name
Serial.print(" (");
Serial.print(strlen(data)); // debug payload length
Serial.println(")");
...
}
1 Like
you can see when there is no email that much fewer chunks of data are sent... I am using the Weather Underground API to retrieve the weather. In the test code, I am only extracting a single value from the XML.
publishing...gmail count
hook-response/gmail_count/0
(361)
Email Count Retrieved
0
publishing...weather
hook-response/nj_weather/0
(560)
getting Weather
hook-response/nj_weather/1
(562)
getting Weather
hook-response/nj_weather/2
(547)
getting Weather
hook-response/nj_weather/3
(556)
getting Weather
outsideTemp = 25
hook-response/nj_weather/4
(569)
getting Weather
hook-response/nj_weather/5
(546)
getting Weather
hook-response/nj_weather/6
(573)
getting Weather
hook-response/nj_weather/7
(73)
getting Weather
publishing...gmail count
hook-response/gmail_count/0
(361)
Email Count Retrieved
0
1 Like
Dave
March 31, 2015, 6:28pm
11
Hmm, am I reading this right? you’re getting bad echo’s / responses of the hook firing?
Thanks,
David
No... I cannot get more than one webhook to return (without a custom handler like @ScruffR advised).
check out the first post...
Dave
March 31, 2015, 9:15pm
13
Hmm, that’s weird, I’ll check things on this end.
Thanks!
David
Dave
March 31, 2015, 9:27pm
14
Just wrote up this demo,
void setup() {
Serial.begin(115200);
Spark.subscribe("one", oneHandler);
Spark.subscribe("two", twoHandler);
Spark.subscribe("three", threeHandler);
Spark.subscribe("four", fourHandler);
Serial.println("subscribed! waiting...");
}
void oneHandler(const char *topic, const char *data) {
Serial.println("1.)" + String(topic) + ": " + String(data));
}
void twoHandler(const char *topic, const char *data) {
Serial.println("2.)" + String(topic) + ": " + String(data));
}
void threeHandler(const char *topic, const char *data) {
Serial.println("3.)" + String(topic) + ": " + String(data));
}
void fourHandler(const char *topic, const char *data) {
Serial.println("4.)" + String(topic) + ": " + String(data));
}
void loop() {
}
With the CLI:
spark publish one 123
spark publish two 234
spark publish three 345
spark publish four 456
Serial output:
1.)one: 123
2.)two: 234
3.)three: 345
4.)four: 456
It’s possible you’re using webhooks too fast? You’re limited to 10 hook triggers per minute per core on your account, so if you have two you’re triggering every 10 seconds, you might be running over the limits?
I hope that helps!
Thanks,
David
1 Like
@Dave
my issue was tied to webhooks created like this:
5.) Hook #55171cbc2df05a607a544e1b is watching for "nj_weather"
and posting to: http://api.wunderground.com/api/MyApiKey/conditions/q/NJ/Princeton.xml
created at 2015-03-28T21:27:24.305Z
trying to work with another webhook like this:
3.) Hook #55006fa9a32e23062da048db is watching for "gmail_count"
and posting to: https://myEmail:MyPassword@mail.google.com/mail/feed/atom/
created at 2015-03-11T16:39:05.758Z
Calling (alternating) once per minute...
1 Like
Dave
April 1, 2015, 10:23pm
16
Hi @BulldogLowell ,
I think you’re right that there might be an issue here, digging in to see if I can track it down.
Thanks!
David
1 Like
thanks @Dave I appreciate your looking into it.
1 Like
Hi All,
Not wanted to create a new article so i use this one.
I have two webhooks configured. Plus in my code two times “spark.subscribe” defined in setup() which both call their own function. After some fiddling i detected that only the first defined spark.subscribe works.
How can i subscribe to two webhooks at the same time?!
Regards,
Bart
Have you read through the whole thread. There is your answer already
@ScruffR Humz, i think i have written over it, time for weekend i think … i’ll read it again, if I do not succeed i’ll let you know!
Update; Works! webhookHandler FTW!
2 Likes