"if then else" Logic in Routines

Any plans for adding if-then-else statements to routines?

2 Likes

I would think that’s a longshot. We can’t even get “waits” like in amazon routines.

Especially as they are already available in the Rules API and it would involve an overhauling of the app routine UI. :man_shrugging:
I started using rules for these reasons (including ‘wait’) a while back and have managed to set up nearly all the automations I need.
Not for using every time - the routine interface continues to be easier and quicker to use.

9 Likes

It just needs to happen, or create a rules engine…

Why is it that there seems to be (semi-)active development of the app in general, but seemingly no interest in making routines more powerful by finally implementing the features that are already present in the Rules API? One would think that automations are a pretty important feature of a smart home platform.

2 Likes

The issue I see with if then else is that routines are typically triggered by a condition or are dependent on time constraints.

Putting an else cause in can lead to the trigger looping for ever

Eg
If sensor a (movement detected)
Then turn on light
Else
Turn off light

Either the if clause or the then clause would always be true, execution would repeat ad infinitum without an exit condition. This would waste value processor time for the hub

As a hypothetical Routine, what that would actually do is subscribe to the motion events from the sensor. It would then do nothing until one arrives.

When one is received, which usually means the motion attribute has changed, the Routine will re-evaluate the condition to see if it is true (motion is being detected) or false (motion is not being detected).

The Routine will then be triggered, which means it evaluates all its conditions as a boolean combination (it already knows the boolean values of all its individual preconditions and conditions) to decide whether it needs to run the then actions or the else actions.

In this case there is only one condition to consider. If it is true the light is turned on. If it is false the light is turned off.

It will then do nothing until the next motion event occurs.

The light being turned on or off is not going to make the Routine do anything. It is all about handling events.

2 Likes

Ok, but that’s a little different to else clauses which fire always fire when the if condition is FALSE.
In this case it’s effectively firing only when there is no motion detected.

A better example might be

If (it’s 8pm) then
Flash a light
Else
Play a sound

For most of the day it’s not 8pm so it should be playing sound continuously.

In the event scenario it would have to fire the first time it didn’t evaluate to true for the if clause condition and then suppress further executions till the if condition became true again.

It is exactly the same. The prerequisite is that something is evaluating the ‘if … then … else …’ and then taking the required actions.

That’s an understandable expectation but it would require that the ‘if … then … else …’ was constantly being evaluated in a loop, or something along similar lines. In the case of Routines that isn’t happening.

Yes, that’s how Routines, and indeed all the broadly similar home automation tools I’ve used work. Something that affects the conditions happens. The automation does something in response. The automation waits for something else that affects the conditions to happen.

Having said all that, this is likely to be one of the reasons that ‘if … then … else’ isn’t implemented. Users will have different expectations.

2 Likes

I guess it depends on how it’s designed, and if you allow predicates in the else clause then you are stuffed as the else action won’t necessarily fire when the if predicate is false.

But they’d probably rule that out due to complexity

I think the else condition should also be executed if the “main” conditions (i.e., what the Rules API calls the triggers) are met, but not the preconditions.

For example:
If: A button is pressed
And (precondition): The lights are off
Then: Switch on the lights
Else: Switch off the lights

The routine is executed every time the trigger condition is met. If all conditions (including preconditions) are fulfilled, the “then” action should be executed, otherwise the “else” action.

I think a lot would depend on creating an intuitive UI. The problem is that even with the current UI, it is not always clear what the function of preconditions is. With two conditions, it often makes no difference if one condition is a main condition and the other is a precondition, or if both are main conditions and the routine is set to execute only if both conditions are met. It would be clearer if preconditions would go underneath the main “if conditions” as “and conditions”. I believe that’s essentially how they work anyway, isn’t it?

In a second step, it should then also be possible to decide if the preconditions (or “and conditions”) have to be met cumulatively or alternatively, like it is for the main conditions.

No… A precondition needs to be met before the corresponding if condition is evaluated:

so for a routine:

Precondition A
If B (and/or C… ect.)
Then D

for D to execute precondition A must first be met and then trigger B must fire.

If trigger B is already met when the precondition is met then action D will not execute until a further trigger B event is received.

For a time based precondition A however there is the option to evaluate the trigger when the time precondition is met:

Which will execute D when the event for trigger B fired before the time was reached (or precondition A was met). This option is only currently available for time preconditions.

It would certainly be the natural way to add else to Routines given they have to map to Rules.

I think a problem with preconditions is that it is a little vague what they actually are, but with an if … then … structure it arguably doesn’t really matter that much. Once you introduce an else … it does.

Those who use, or previously used, webCore may be familiar with the ‘only when’ conditions that could be placed at the top of a piston. Those conditions effectively controlled whether the rest of the piston was executed or ignored (leaving out special cases like ‘every’).

The naming of preconditions and the vague way they are described does hint at an ‘only when’ equivalence. If that were strictly true the logic would be:

IF
  ALL the preconditions are true
THEN
  IF
    ALL/ANY of the conditions are true
  THEN
    Do stuff
  END IF
ENDIF

However if that were the case the UI should present preconditions before the if block. Instead it reflects the actual rules created which have the following basic structure.

IF
  ALL the preconditions are true
  AND
  ALL/ANY of the conditions are true
THEN
    Do stuff
END IF

That is logically equivalent to the previous example. The outcome is always either the then actions being performed, or nothing. So it doesn’t matter so much how you think about preconditions as long as you understand stuff is only done when the main conditions may have changed.

However stick an else … in and it does matter. In the ‘only when’ example the outcome can then be the then actions running, the else actions running, or nothing happening at all. With the real world example it becomes the then or the else. You have to appreciate what the preconditions are doing.

1 Like

I understand that that is how it’s worded in the app, but I think this essentially comes down to semantics.

If you look into the Developer Documentation on Rules, on the bottom of the page under “Operands” → “trigger” there is an example Rule with the name “Sample for precondition”. This Rule is exactly how I functionally understand preconditions (and else actions) to work:

In the example Rule below:

  • The if Action with equals Condition specifies that if button-device-id is pressed (the use of “trigger”:“Always” dictates that this Condition is used as a trigger for this Rule), then the Rule will check whether switch1-device-id is on.
  • If switch1 is on, then the Rule will turn switch2-device-id on. The use of “trigger”:“Never” in this then statement prevents this Condition from triggering the Rule whenever switch1 is on; this Condition is instead used as a check for the remaining Rule logic, determining the next actions of the Rule.
  • For all other cases (else), the Rule will turn switch2 off.

I will concede that if we look at how this example Rule is structured, it is actually different than how the JSON of a Routine looks when viewed in the Advanced Web App (my.smartthings.com/advanced).

The example Rule from the documentation is structured like this:

IF
    button is pressed (condition)
THEN
    IF
        switch1 is on (precondition)
    THEN
        Turn on switch2
    ELSE
        Turn off switch2

Whereas a Routine with a precondition would be structured like this (without an else action, as these are not currently possible in Routine):

IF
    button is pressed (condition with "trigger":"Always")
    AND
    switch1 is on (precondition with "trigger":"Never")
THEN
    turn on switch2

Functionally, however, both Rules are the same. In both Rules, switch2 will be turned on (action) if switch1 is on (precondition) at the time the button is pressed (trigger).

If you look at such a routine in the Advanced Web App, what it actually does is create a separate every Action in addition to the if Action to which the time-based precondition A applies:

IF
    time is between X and Y (precondition A)
    AND
    condition B is fulfilled
THEN
    do D

EVERY
    time is X
    IF
        condition B is fulfilled
    THEN
        do D

That’s the perfect summary.

2 Likes

That’s why I happen to like the structure of Sharptools Rules. It’s very straight forward for what is/are the trigger(s) and then what state to evaluate when the trigger(s) occur.

1 Like