Advanced Automations with the Rules API

Advanced Rules API Tutorial

We will use the rules API to create a trigger that will evaluate a condition then schedule to evaluate that condition again after a defined period of time. This rule could replace SmartApps like “Notify Me When” that were previously complex groovy apps.

Requirements:

Postman
PAT Token

Getting Started

Open Postman and add your PAT token to the header

Refresher

If you are new to the Rules API, you will need to supply the locationId you want to work with for most requests

GET https://api.smartthings.com/v1/rules?locationId=yourID

Will return a list of your existing rules

Let’s Go

Use Postman in a new tab to GET some device IDs. You will need to get a contact sensor and a light bulb.

Once you have these, we are going to be sending a POST command with the Rule.

We are going to post the following to the Rules endpoint

POST https://api.smartthings.com/v1/rules?locationId=your-location-id

{
  "name": "Notify Me When Door Left Open 2",
  "actions": [
    {
      "if": {
        "equals": {
          "left": {
            "device": {
              "devices": [
                "your-contact-id"
              ],
              "component": "main",
              "capability": "contactSensor",
              "attribute": "contact"
            }
          },
          "right": {
            "string": "open"
          }
        },
        "then": [
            {
                "sleep": {
                    "duration": {
                        "value": {
                            "integer": 30
                        },
                        "unit": "Second"
                    }
                }
            },
              {
                "if": {
                    "equals": {
                    "left": {
                        "device": {
                        "devices": [
                            "your-contact-id"
                        ],
                        "component": "main",
                        "capability": "contactSensor",
                        "attribute": "contact"
                        }
                    },
                    "right": {
                        "string": "open"
                    }
                },
                "then": [
                            {
                                "command": {
                                    "devices": [
                                        "your-light-id"
                                    ],
                                    "commands": [
                                        {
                                            "component": "main",
                                            "capability": "switch",
                                            "command": "on",
                                            "arguments": []
                                        }
                                    ]
                            }
                        }
                    ]
                }
            }
        ]
      }
    }
  ]
}

Let’s break down what is happening here.

We are first using a door open event as a trigger, that is the first IF block. If the door opens we will schedule to sleep for 30 seconds.

 {
          "if": {
            "equals": {
              "left": {
                "device": {
                  "devices": [
                    "your-contact-id"
                  ],
                  "component": "main",
                  "capability": "contactSensor",
                  "attribute": "contact"
                }
              },
              "right": {
                "string": "open"
              }
            },
            "then": [
                {
                    "sleep": {
                        "duration": {
                            "value": {
                                "integer": 30
                            },
                            "unit": "Second"
                        }
                    }
                },

After 30 Seconds, we will check the door again. If it is open we will turn on a light as a notification that the door has been left open.

  {
                "if": {
                    "equals": {
                    "left": {
                        "device": {
                        "devices": [
                            "your-contact-id"
                        ],
                        "component": "main",
                        "capability": "contactSensor",
                        "attribute": "contact"
                        }
                    },
                    "right": {
                        "string": "open"
                    }
                },
                "then": [
                            {
                                "command": {
                                    "devices": [
                                        "your-light-id"
                                    ],
                                    "commands": [
                                        {
                                            "component": "main",
                                            "capability": "switch",
                                            "command": "on",
                                            "arguments": []
                                        }
                                    ]
                            }
                        }
                    ]
                }
            }
        ]
      }
    }
  ]
}

This simple example shows off the power of the rules engine. Soon you will be able to schedule notifications and trigger scenes just like this.

5 Likes

Jody, just so i’m clear, this is checking again after a simple wait period. It isn’t truly checking a duration over time, right? So the door could have opened and closed X number of times between that 30 seconds and it would still run at 30 seconds if the door was open.

Now i’m confused. Is soon today?
https://mailchi.mp/smartthings/developer-newsletter-august2020?e=a45052f395

That is correct. The trigger is the door opening and then it is waiting for the specified amount of time to check if the condition is still true. If the door closes within the time frame the second check will fail. If you open the close and open the door again during the time frame there will be another check triggered N minutes from that event.

This is basically an example of the popular “Notify me when”, we are still waiting on notifications to be added to the rule API and I don’t have a hard date for those features.

2 Likes

sorry but it’s ugly… the basic

if (contact_id.is_open) {
sleep(30*1000)
if (contact_id.is_open) {
your-light-id.on()
}
}

now takes 50 lines of json =(
Do you believe many developers will use this “language”?
what gonna happen if I do a mistake like “unit”: “Scond” ?

2 Likes

It’s true, your example takes a few lines. The complexity is just hidden.

  • How many lines is the function is_open
  • How many lines is the function .on()
  • Would this accept any conditional function?
  • Units have validation

The rule is just JSON it’s not a new language. The grammar is specific to the usage of running rules on the SmartThings platform.

If you have suggestions on how to improve, happy to hear them. Give it a shot.

@ady624 and @vlad might be able to elaborate on the design choices.

The rule is just JSON it’s not a new language. The grammar is specific to the usage of running rules on the SmartThings platform.

you are promoting “sleep” function like something “Advanced” in 2020, just think about it.
and now sleep takes 250 characters and 13 words.

 "sleep": {
                        "duration": {
                            "value": {
                                "integer": 30
                            },
                            "unit": "Second"
                        }
                    }

I’d rather use something with hidden complexity. So I can build more complex (advanced) apps by myself.

for example

n = 1
on_door_open {
  your-light-id.on()
  n*=2
  sleep (n*1000)
  your-light-id.off()
}
2 Likes

Could there be a way to actually wait for any updates for a period of time, rather than poll twice and miss temporary events? E.g. by adding a "for": {"duration": ...} to the "if" clause?
Example use-case:
I want to get a notification that my dehumidifier’s tank is full. It has an internal humidity sensor, and stops working when either the humidity is low enough, or the tank is full. With the current API, after initially finding that the power usage is low, the automation needs to sleep for long enough that the dehumidifier will kick in again, but not too long that it will may stop working once more.

Also, is there a plan to make automations created using the app available in the API?

Yes. There is an upcoming feature that is “remains”, so if a thing remains in a certain state then do something.

This is just an example of something that you can do today.

You may be looking for something more like our JS SDK. This is not “Advanced for 2020” it’s a more advanced example of how to use our new rules engine.

Excellent, thank you for adding this.

I have to say that trying to build an executable language out of JSON is just about the worst idea I have seen in a very long time.
The programmatic flow gets lost within the required json syntax.

Please please please reconsider this, because I will not write code this way. Consider something cleaner like putting the program text into a single json object.

But this is stupid and breaks all the rules of new computer language definition. It is overly verbose, has multiple syntaxes (json and whatever the other syntax is), and provides little added functionality (the new functionality is added by the platform- not the language or syntax).

Please, i am completely serious here. I will leave the SmartThings platform if you guys continue down this road.

Ray

3 Likes

Maybe programming with jsons is common practice in korea but I’m already sick of this new platform after two days with the CLI.

If it ain’t broke don’t fix it

I think most of the developers will jump ship to that other platform that shall not be named

2 Likes

Why not name the other platforms? I think anything we can do to start a full on developer revolt would help to get some attention from Samsung. Without real developers, the platform is doomed to be over taken by many of the other platforms be them open source Raspberry PI based or very large company based with voice control built in.

It doesn’t matter, we can revolt but no one will listen. This forum is only . 1% of the userbase. Samsung doesn’t care.

1 Like

I have to say I’m with @RayCaruso and @mvevitsis on this. I think I understand from an architecture standpoint that this approach makes rules simpler to interpret on the server side (and therefore faster and cheaper, which is good) but it does so at a significant cost to developer accessibility.

Of course, rules are only a small part of the platform and thankfully actual SmartApps are not this hideous. But getting rules to work still matters, and the poor readability of using JSON for this will result in bugs that would otherwise be easy to avoid. Hell, it looks like it already has - even after preconditions were fixed, for months now the built-in official automation tool in the app still doesn’t work consistently if you use location modes in conjunction with presence conditions in a “when any condition below is met” rule.

If SmartThings own developers can’t implement rules this way without bugs creeping in, what hope do the rest of have?

3 Likes

Whats the difference between Rules via the API and Automations via the Smartthings Phone App, because you use the word Automations in the title but when I query the ST API, I dont see my automations i created in the phone app I only see rules created via the API. The terminology is confusing, or am i doing something wrong?

How can i programmatically enable and disable Automations created in the phone app via the ST API?

Thanks

That is probably the best interpretation. The word ‘automation’ was being used generically in the title and arguably would have been better without the upper case ‘A’, but when styling of a single letter causes confusion the problem is really in the name. People might find many of the engine metaphors in webCoRE rather contrived but using the term ‘pistons’ for the automations was a superb choice. Automations need something equally recognisable.

You can’t at the moment as they aren’t exposed in the API. I’ve no idea if they ever will be. I’d imagine it depends how ST want to pitch Automations in future. They might choose to keep them as an entry level tool in the app, for example, with limited functionality overlapping with ‘pro’ functionality like the Rules API.

2 Likes

Thanks @orangebucket things are clearer now. Its disappointing that you can’t query the Automations in the ST App via ST rules API or vice versa , seems like a total disconnect.
What if I duplicated the ST APP Automations via the Rules API, can it then be enabled and disabled programmatically(based on Rules) and from the ST APP via a virtual button or something? Thanks

That’s because automations created in the app aren’t using the Rules API as their backend (yet?). They are two totally different backends.