Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rules concepts] Add triggers & conditions #4

Merged
merged 5 commits into from
Aug 25, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions rules/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,151 @@ In some cases, it is useful to have a rule that is only manually triggered.
Sometimes there is advantage in a rule that calls another rule.
In both cases, the rule has no triggers and no conditions.

## Triggers

Now that we know what rules are, we need to have something to make them run when something happens.
This is when we need triggers.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

There are different categories of rule triggers:

| Trigger type | Description |
|-------------------|------------------------------------------------------------------------|
| **Item**-based | Those react on commands or state updates for the Item |
| **Group**-based | Those react on commands or state updates for member Items of the Group |
| **Time**-based | Those react at special times, e.g. at midnight, every hour, etc. |
| **Channel**-based | Those react on trigger channels provided by some add-ons |
| **Thing**-based | Those react on thing status, e.g. change from `ONLINE` to `OFFLINE` |
| **System**-based | Those react on certain system statuses, e.g. startup completed |

florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
::: tip Triggers and Events - What's the difference?
You might have heard or will hear about events and triggers, and wonder about the difference.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

An event is something that happens and is detectable by openHAB.
The most important events for rules are time events (e.g. midnight), system events (e.g. startup completed), Item state events and Item command events.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
There are some more events, but it's not necessary to mention them here.

In contrast to this, a trigger identifies one of those events and makes the rule run.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
:::

Here are the details for each trigger type:

### **Item**-based Triggers
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

You can listen to commands for a specific item, on status updates or on status changes (an update might leave the status unchanged).
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
You can decide whether you want to catch only a specific command/status or any.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

A simplistic explanation of the differences between `command` and `update` can be found in the article about [openHAB core actions](/docs/configuration/actions.html#event-bus-actions).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like having a reference here. The Actions page seems to be an odd place to have the canonical explanation for the difference between a command and an update. But the only other two places where it's explained is on the Items page where I don't think it's explained very well, and the Rules page which I think has the best description: https://www.openhab.org/docs/configuration/rules-dsl.html#manipulating-item-states.

Given that we are rewriting both the Rules and the Actions pages anyway, this reference will become different before we are done. So at a minimum we should put a TODO here so we remember to come back and fix the reference later.

But I think we will be better off if we move and augment the description of the difference between updates and commands to Items and reference that here, or put it here and reference to here in the rewritten Actions and Rules pages (perhaps even the Items page too).

Does the ":::tip" show up in the table of contents and support direct linking? If so, maybe it could be another tip section.

Copy link
Author

@florian-h05 florian-h05 Aug 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I think we will be better off if we move and augment the description of the difference between updates and commands to Items and reference that here, or put it here and reference to here in the rewritten Actions and Rules pages (perhaps even the Items page too).

I would prefer to have this at Items, as it is the most logical page for me.

Does the ":::tip" show up in the table of contents and support direct linking? If so, maybe it could be another tip section.

I don‘t know, sorry. Shouldn‘t matter when we have the explanation at Items.

Copy link
Author

@florian-h05 florian-h05 Aug 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked the docs, https://www.openhab.org/docs/configuration/items.html#command-vs-status might help??

Anyway, I decided to explain the difference directly in the concepts page since it‘s a one liner.


**Item**-based triggers provide some information, e.g. the received command or the received state update, see [Available Values](#available-values).
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

When using a `received command` trigger, the rule might trigger **before** the Item's state is updated.
Therefore, if the rule needs to know what the command was, there is an [Available Value](#available-values).

### **Group**-based Triggers

As with Item based event-based triggers discussed above, you can listen for commands, status updates, or status changes on the direct (but not the indirect members of a nested subgroup) members of a given Group.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
You can also decide whether you want to catch only a specific command/status or any.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

The [Available Values](#available-values) are populated using the Item that caused the Group trigger to fire and that Item's name is stored in an additional value.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

Also, as with **Item**-based triggers, when using a `received command` trigger, the rule might trigger **before** the Item's state is updated.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
Therefore, if the rule needs to know what the command was, there is an [Available Value](#available-values).

### **Time**-based Triggers

Dependening on the rule language/engine, there are some predefined expressions you can use, but universally supported are only [cron expressions](https://www.quartz-scheduler.org/documentation/quartz-2.2.2/tutorials/tutorial-lesson-06.html).
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

Please be aware that openHAB is using the [Quartz Scheduler](https://www.quartz-scheduler.org/documentation/quartz-2.2.2/), which is using a slighly different form than the Unix cron scheduler.

**Time**-based triggers do not provide any information in the [Available Values](#available-values).

A Quartz cron expression takes the form of six or optionally seven fields:

1. Seconds
2. Minutes
3. Hours
4. Day of Month
5. Month
6. Day of Week
7. Year (optional field)

You may use the generator at [FreeFormatter.com](https://www.freeformatter.com/cron-expression-generator-quartz.html) or the openHAB WebUI rule setup to generate your cron expressions.

### **Channel**-based Triggers

Some add-ons provide trigger channels.
Compared with other types of channels, a trigger channel provides information about discrete events, but does not provide continuous state information.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

Your rules can take actions based upon trigger events generated by these trigger channels.
You can decide whether you want to catch only a specific or any trigger the channel provides.

When a binding provides such channels, you can find the needed information in the corresponding binding documentation.
There is no generic list of possible trigger events.
The `triggerEvent`(s) available depend upon the specific implementation details of the binding.

If the rule needs to know what the received event or the triggering channel was, use the [Available Values](#available-values).

### **Thing**-based Triggers

Your rules can take actions based upon status updates or status changes generated by Things.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
You can decide whether you want to catch only a specific or any status the Thing can get updated too.

You can find all the possible values for status from [Thing Status](/docs/concepts/things.html).

The `thingUID` is the identifier assigned to the Thing, manually in your configuration or automatically during auto discovery.
You can find it from UI or from `.things` files.
For example, one z-wave device can be "zwave:device:c5155aa4:node14".

If the rule needs to know what the triggering Thing was, or access the previous or new status, use the [Available Values](#available-values).

<!-- TODO: Update reference when actions are included in the reworked rule docs. -->
Refer to [Thing Status Action](/docs/configuration/actions.html#thing-status-action) to find how to get the new thing status details or description in the script.

### **System**-based Triggers

System-based triggers are provided as described in the table below:

| Trigger | Description |
|------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| System started | `System started` is triggered upon openHAB startup. In openHAB version 2, `System started` is also triggered after the rule file containing the System started trigger is modified, or after item(s) are modified in a .items file. |
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
| System reached start level <level> | `System reached start level <level>` is triggered when openHAB reaches a specific start level. A list of possible start levels is available below. Please note that only levels 40 and higher are useful as the rule engine needs to be ready first. |

You may wish to use the 'System started' trigger to initialize values at startup if they are not already set.
You can then execute a rule on the next startup level which depends on the value set by the initialization rule.

In openHAB version 3 the System-based Trigger for startlevel had been added, values depends on the startlevel:
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

```text
00 - OSGi framework has been started.
10 - OSGi application start level has been reached, i.e. bundles are activated.
20 - Model entities (items, things, links, persist config) have been loaded, both from db as well as files.
30 - Item states have been restored from persistence service, where applicable.
40 - Rules are loaded and parsed, both from db as well as dsl and script files.
50 - Rule engine has executed all "system started" rules and is active.
70 - User interface is up and running.
80 - All things have been initialized.
100 - Startup is fully complete.
```

Startlevels less than 40 are not available as triggers because the rule engine needs to start up first before it can execute any rules.
Please keep in mind that the rule engines of automation add-ons like JS Scripting can start up after startlevel 100 has been reached.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

## Conditions

With triggers, we have the *When __t__ happens* part completed, so next up is the *if __c__* part.
This part can limit when a rule can run by adding one or more condition(s).

Conditions as an extra part of the rule are only supported in UI-based rules.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
In file-based rules, you have to implement your conditions using an `if`-statement in the rule action, which is written in some language depending on the rule engine, e.g. JavaScript or Python.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

Available conditions in the UI include:
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
- An Item has a given state
- It’s a certain time of day
- It’s a certain day of week
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
- It’s a special day, e.g. holiday, weekday, weekend, etc.
- A script evaluates to `true`

The script condition is the most universal one, as you can choose one of the many available script/rule languages to build any condition you can think of.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved
This UI-based rule condition is comparable to using an `if`-statement in the (script) action of a rule.
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved

If you need help with setting up a condition for a UI-based rule, visit [Getting Started with Rules - Basic](/docs/tutorial/rules_basic.html#conditions).
florian-h05 marked this conversation as resolved.
Show resolved Hide resolved