Race condition with two different recipes on same variable?

First off, the functions and variables work when called from C# over REST API. I have a published variable “humidity” (logging a DHT22) and a function “switch1” that takes the following parameters “on”, “On”, “ON”, “off”, “Off”, “OFF” that triggers a relay. I’m connected over the serial port and are manually monoitoring the humidity while IFTTT switches the relay.

I have two recipes as seen below. The problem is that they seem to race. If I only have one of them activated they run once and trigger as they should but when I have both activated they switch on and off almost randomly. It’s as if they get confused when two different “THIS” check the same variable (but with distinctively different conditions as you can see).

I have nothing else running on my IFTTT and no logic on my Spark that does anything by itself, it’s just a slave device (and no other external logic triggering the switch1 function that could interfere).

1 Like

Hi Jon,

Ooh, interesting! Thanks for posting, I’ll look into it :slight_smile:

Thanks,
David

Is the value fluctuating above/below 50 somewhat frequently? IFTTT rules only run periodically, and I’m sure there’s no guarantee what order they will run in, or how much time will pass between your rules being checked. And for that matter, it may well be that the running of the “output” rules could be decoupled from the “input” checks.

It could be that IFTTT checks your value according to the first rule, finds it true, then queues up the output (without actually executing it yet). Then a few minutes later, the second rule runs, but the humidity has dropped, so this check is true, and they queue up the “off” rule. A few minutes after that, they might start flushing out all the output queues, and you end up with an “on” quickly followed by an “off”.

Just a theory, but I wouldn’t be surprised if this is what is happening.

1 Like

@jon, besides what @dougal said, your test values create a condition called hysteresis. A value fluctuating around your test value (50) will change between on and off very quickly. You can try this by controlling the relay with the same rules on the Spark. One way to avoid hysteresis is to create a “dead band” around the value. In your case, you would trigger the relay ON at value >50 but OFF at value < 45 for example. :smile:

1 Like

In this case, I find it more useful to use server sent events. Regardless of the fact that you can apply the above mentioned logic on a Spark internally, a SSE ensures that the notification is as ‘live’ as possible. It’s pushing the data instead of polling it, which is always more accurate. In this case you could make the Spark sent a server sent event when the humidity rises above 50, and let IFTTT react to that by calling a function.

Also, apply the logic @peekay provided :wink:

1 Like

Thanks for your input, I will try it out. Though I was watching the humidity on serial-out and it was steadily at 40% when IFTTT kept switching my relay.


So I just updated my recipe to turn the relay on when humidity > 65 and my other recipe to turn it off at humidity < 45. I am again looking at the serial output logging the humidity as IFTTT recipes are running. I am looking at the same variables that IFTTT is reading.

I breathe on the sensor so humidity goes up to 80-90% and I keep it there. After a while IFTTT triggers my relay “on” but almost immediately IFTTT triggers it “off” though humidity is steadily well above 70% during the whole time. Humidity is now (a couple of minutes later) down to 40% for some time and IFTTT still triggers the relay on an off though it shouldn’t.

The triggering is not as frequent now as before so the hysteresis added had some effect (hysteresis is when there is a span, not lack of as before. Right?). But still it seems like the IFTTT implementation gets confused and mixes the rules up somehow. Or there is some other error I fail to see. My Spark code is dead simple and just exposes the variables and functions.

@dougal @peekay123 @Moors7 humidity was steadily around 40% while the recipes kept arguing about whether it was over or under 50%, also see above. Have you tried a similar setup using IFTTT with two recipes triggering on the same Spark variable with different “That” and got it working?

@Moors7 I agree and for solving this case I would not need IFTTT at all, but now I am taking IFTTT for a test drive. I will try publishing events when humidity is high or low too.

I would not like to hard code what high or low is though and setting that value through a function from IFTTT based on some other input seems a bit over the top. Any suggestion?

@jon, thinking about it I realize there is a possibility that around the 45% and 65%, it is possible that the IFTTT rules could send several ON or OFF commands. I wonder if this is causing some issues. To get rid of that chatter, you only send the command if the setpoint is reached and the relay is in a state opposite of what you are switching to. In your serial debug output, print out when you get the ON and OFF messages along with the humidity to get a better idea of what’s going on.

Also, you could set your setpoints using a Spark.function()! :smile:

@peekay123 thanks, how would you go about checking if the relay state is in a state opposite of what I am swithing to? I assume you mean in the recipe?

Yes, but something has to call that function to set the setpoints and that being IFTTT makes it messy… I kind of feel I am doing something not meant to be done. I should stick to “post to Facebook when someone is showering” and not turn on the ventialtion :wink:

Jon, forget the relay state thing for now. Start with adding debug output to your function that gets called by IFTTT. That will give you an idea of what is coming from IFTTT in the first place.

Then, forget the IFTTT rules and add the if/then stuff in your loop() code and control the relay there. If the logic is correct and there is nothing weird going on, the relay should cleanly go ON and OFF based on the rules. If not, then you have a bug to figure out.

@peekay123 yes I agree totally, but I wrote this post as an input to testing IFTTT and I found something weird. My goal is not to turn on the ventialtion when someone is showering for that there is far better products then Spark :smile:

Debug output, other then that the relay switches? I thought that was quite distincitive output. I’ll add some output but please elaborate, I’d like to rule out that it is someting in my code and concentrate on giving input to IFTTT.

@jon, from what I understand, your code is simple. It reads a DHT22 into a Spark.variable() and has a function which IFTTT calls in response to some recipes which read the DHT22. So debug output from the Spark will help to establish:

  1. The DHT22 values are good - does IFTTT expect integer or can it work with float? How is your Spark.variable() setup?

  2. What the IFTTT is sending to the Spark via the function call and approximate timing (vis-a-vis the humidity debug output).

As you say, the point is not the humidity/fan control but establishing if the IFTTT is working as expected and if you have setup your code to work correctly with IFTTT. This is about establishing what is causing the weirdness. :smile:

Can you share your code with us?

@peekay123 I realized your suggestion wasn’t so bad :wink: so I added a printout of when the switch function got called and this is what I got.

@jon, what a mess! Can you share your test code? I wonder if IFTTT is having an issue with the way it reads Spark.variable() or how your variable is set up?

@dougal @peekay123 it’s the DHT lib sample with the addition that it publishes the Temp and Humidity data. Here’s the code for the switch function:

int relay1(String command) { Serial.print("--switch1 "); Serial.println(command);
if (command == "on" || command == "ON" || command == "On") {
    digitalWrite(RELAY1, HIGH);
    return -1;
}
if (command == "off" || command == "OFF" || command == "Off") {
    digitalWrite(RELAY1, LOW);
    return -1;
}
return 0;

}

and in my setup()

Spark.variable("temperature", &temperatureStr, STRING); Spark.variable("humidity", &humidityStr, STRING); Spark.function("switch1", relay1);

…from within the loop() (after DHT.acquireAndWait(); and other stuff is called)

humidity = DHT.getHumidity(); temperature = DHT.getCelsius();
sprintf(temperatureStr, "%.1lf", temperature);
sprintf(humidityStr, "%.1lf", humidity);


Serial.print("Humidity (%): ");
Serial.println(humidity, 2);

Serial.print("Temperature (oC): ");
Serial.println(temperature, 2);

//Serial.print("Temperature (oF): ");
//Serial.println(DHT.getFahrenheit(), 2);

//Serial.print("Temperature (K): ");
//Serial.println(DHT.getKelvin(), 2);

Serial.print("Dew Point (oC): ");
Serial.println(DHT.getDewPoint());

@jon, Is the Spark IFTTT recipe that reads variables expecting a string?

@peekay123 good question, I don’t see a way of setting that in my recipe? Isn’t it just JSON that gets published and that’s not typed?

@jon, good point so why did you chose to convert it to a string?

@peekay123 I am writing a unified sensor/actuator API wrapper in C# for Azure and when debugging that API I didn’t like seeing all the decimals…