OH3 rule conditions AND | OR

Hey Guys,
i playing around with some rules on the new OH3 gui.
I would like to achieve the following if all 3 conditions are fulfilled the rule should be executed… currently only one condition is needed to execute the rule.
Is it possible to link the conditions with an AND?

conditions:

  • inputs: {}
    id: “6”
    configuration:
    itemName: C_EG_simum
    state: ON
    operator: “!=”
    type: core.ItemStateCondition
  • inputs: {}
    id: “5”
    configuration:
    itemName: SimonHandy_Online
    state: OFF
    operator: =
    type: core.ItemStateCondition
  • inputs: {}
    id: “4”
    configuration:
    itemName: AnniHandy_Online
    state: OFF
    operator: =
    type: core.ItemStateCondition

Thanks
Simon

To my understanding, and I am happy to be corrected, the conditions are always OR, hence to achieve 3 conditions with AND you would need to write a script and include them in there with &&.

No. Conditions refer to events, not states, and there’s never two events at the same time.
Test for states inside the rule, return if they do not match.

If “executed” as in “triggered”, Markus is correct, triggering conditions can only be check with OR. However you did show the conditions part of your rule (known as the “But only if” part), these condtions are checked with AND!
So the question arises why are your conditions not linked with an AND?

thx, so they should be linked with an AND, so i think a Test rule may hit. i would Test it without.

I have made a test-rule with 3 conditions and the rule runs only if all of them are met!
Creating a log-entry for each checked state in the action part of the rule will give some hints!

1 Like

yes, right it was a Script causing the issue.
i was testing variables to check the Status of an item.

Hello, i’ve a question about rules. From UI i would like to make a rule to:

When
BathRollershutter changed
BedroomRollershutter changed
KitchenRollershutter changed

Then
Update morningshutters_switch to OFF

But only if
BathRollershutter state != 100
BedroomRollershutter state != 100
KitchenRollershutter state != 100

The point is that i want OR in “But only if” when if just one state change (or all of them).
Let’s suppose that kitchen is at 90% and others are at 100%, and i move one of them to something different from 90% (for kitchen) or 100% (for bedroom or bathroom).

Is it possible? How can be created a rule for what i need?

Hi, I have the same issue, or in rule condition and and in but only condition. That was possibel in OH2.5 rules.

any clue ?

IMHO rules in OH2 had no explizit “but only if” section, you had to write such as an if statement in the Code (“then”) section. Doing it in the code section is possible in OH3 as well.

The IF conditions in UI rules are intentionally limited to AND to keep things simple. As @opus noted, you can make more complex rules by choosing “Run Script” as the action, which enables you to use Blockly, JavaScript, or Rules DSL.

Or you can just keep your rules in text files, same as OH2.

1 Like

It existed, but as is the case in OH 3, it only existed in UI created rules.

@KenkiCK if what you mean by “the same issue” is that you have multiple conditions where if any one of which is true the rule can run you will need to code it in a Script Condition.

To be clear how this all works.

Triggers always use OR. If this event or that event occurs run the rule.

Conditions are always AND. All of the conditions listed in the But Only If section must evaluate to true for the rule to be allowed to run.

However, one of the conditions you can apply is a Script Condition. This lets you write arbitrary code that needs to either evaluate to true or false. For more complicated cases such as defining OR conditions you need to use a Script Condition.

Note that a Script Condition is different from the Script Action (i.e. stuff that goes in the “Then” section of the rule). The last line executed in a Script Condition must evaluate to true.

For example, if you only want the rule to run when the new state is not NULL or UNDEF create a Script Condition with the following line:

event.newState.class != UnDefType.class;

That will evaluate to true or false. Another common one is only run the rule if the previous state was not NULL or UNDEF.

event.previousState.class != UnDefType.class;

This second example isn’t even possible except as a Script Condition.

1 Like

Thanks for clarifying, Rich. I meant to write “as the condition”, not “the action”. Though I suppose you can also just script IF conditions and case statements into the rule action.

True but there are some differences. For example, when one calls a rule from another rule, there is an option to ignore the conditions and run the rule anyway or to take the conditions into account. You can’t easily do that with if statements.

Rules in the UI very much lend themselves to being broken up into rules that call other rules. For example, my Alarm Clock Rule template. All it does is handle scheduling another rule to be called based on the state of a DateTime Item. But then you, as the user only need to worry about coding that rule that does something at the scheduled time. In this case, I set the flag to follow the called rule’s conditions so you can add conditions to the called rule to prevent it from running even though the Alarm Clock Rule template called it based on the DateTime Item.

So, for example you could create a DateTime Item and populate it with a DateTime to start. Tag it with the “totd” tag. Then install the To Today rule template and create a rule from that which will move that DateTime Item’s to today’s date. Then create a rule that does something you want at that DateTime. But you only want it to happen on weekdays so add a Condition that only evaluates to true on weekdays based on ephemeris. Now install and create a rule from the Alarm Clock Rule instance to use the DateTime Item as the trigger.

The only code you’ve had to write is the what happens when the “alarm” goes off. The condition lets you control when the alarm goes off regardless of the state of the DateTime Item. Everything else was done for you. All you had to do was install the template and instantiate and configure the rule with the Item to use.

I’ve several rule templates that work on this general model. For example there is a template that looks at a Group of Items and calls another rule with the list of those Items that match a given condition (e.g. >= threshold). So all you as the user needs to do is focus on what to do when one or more of the Items matches the conditions. Actually detecting that case is handled for you. Here too, you can set a condition to further refine when the rule can run (e.g. only run if someone is home).

Conditions are a very powerful way to control and manage when rules execute, especially in cases where one installed a rule template that calls another one of your rule but one wants to take into account other stuff too that isn’t a part of the rule template.

1 Like

Thanks @rlkoshak , I used now scripts and it works really fine.

I had to read this also, to determine how it works.

Triggers are OR (if any of the given triggers “fires”, then the actions get “executed”)
Conditions are AND (if all conditions are met, when the trigger fires, then the actions get executed)

regarding Conditions, if I want a different behavior I have two chances:
Option one, I can use a script (‘a given script evaluates to true’)
example:

items.getItem('a_item').state == null || items.getItem('another_Item').state == null;

would make the rule to execute the “action” only if one of the two items states is ‘null’ e.g. undefined / never read before / connected thing unaviable etc.

Option two, I define a script as action, that at the start or any point in between tests whatever I want to be tested and skips the unwanted actions.
On example above the script could begin with:

if (items.getItem('a_item').state == null || items.getItem('another_Item').state == null) {
<whatever to be done, if one of the two doesn't have a value, like giving it an value like "not aviable">
}

Suggestion: add this somewhere to the documentation, as I think many will have the question.
Or even better state that in the interface like:

When (one of following happens)
Then (execute all of following)
But only if (all conditions are met)

The state of an Item will never be null. Since this is JS Scripting it might be "NULL" but if the Item exists at all, it will always have a state. null is not the same as NULL and in JS Scripting, .state always returns the String representation of the Item’s state.

That’s one of the challenges when resurrecting a two year old thread. The code presented may no longer be best practice.

It is in Getting Started: Rules - Introduction | openHAB

Rule triggers are always evaluated with an OR . If there are two triggers listed, read that as “if x occurs or if y occurs”.

These are a list of comparisons that each must evaluate to true for the actions to be run.

We welcome PRs with better wording or descriptions. There is a link at the bottom of the page which will take you straight to where you can edit the page and submit a PR.

I could see this information being added to the Concepts->Rules page. It doesn’t seem to be there.

For that you’ll need to file an issue on the openhab-webui repo.

Hmm… Then the integrated blockly code generator cotains a big big big mistake… Because it generates definetly this for the GraalJS:

items.getItem('Piko_CI_Status').state == null || (things.getActions('astro', 'astro:sun:local').getEventTime('CIVIL_DUSK', null, 'START').isAfter(zdt.now())) || (things.getActions('astro', 'astro:sun:local').getEventTime('CIVIL_DAWN', null, 'END').isBefore(zdt.now()));

and it works, it does exactly do what it should, and yes in JavaScript “NULL” or “Null” should be the expression for it… One of the strange things in JS… as well as == and === and the wired behaviour of those operators :slight_smile:

And an Item can very easily be null, a String item in standard OH configuration is null after startup until actualized by the binding, as it doesn’t get a value from the rrd4j persistence service, as the default service cannot persist Strings… And as modbus binding e.g. doesn’t update a item if the connected device is not present, e.g. off, you have that issue…

And guess how this only if in a rule makes sense and works… If OH reboots for whatever reason in the night, e.g. because I am doing changes after sundown, the PV Inverter is off, as this model switches off, if it has no DC Power. So it will not answer a request… The state is a string, that doesn’t get persisted in rrd4j, so it stays null until the inverter wakes up in the morning…
At the same time some of the values from the inverter, like the AC real power value may get recovered from the persistence… Sometimes it happens, that the inverter switches off before the Modbus binding did send the request and getting the 0W of production… Or the persistence gets corrupted, as zram is used and the Pi lost it’s power… Then u have Status null while having a AC Production value… And thats what that only if tests for every some minutes… having a null value on the status at any timeof the day or when it is definitely night and the inverter is definitely off… In both that cases it will make sure, that all values willget the right value afterwards. (and yes I already have a even better request for it)…

And yes, the OR for the trigger si stated, but the AND for the only ifs is not :slight_smile: And yes the way to do it…

And yes I know about that link, how to contribute to the documentation… but think this is something someone that works on it anyways can add :slight_smile:

Yep, please file an issue on openhab-webuis.

Looking at the actual code, the .state is implemented as follows:

  /**
   * String representation of the Item state.
   * @type {string}
   */
  get state () {
    return this.rawState.toString();
  }

If the Item’s state is NULL the state is going to be "NULL".

Maybe there’s an automatic conversion to null?

A post here on the forum isn’t going to necessarily be seen by someone to make the changes. If you don’t at least file an issue nothing will happen…

Have to read more on null and strings…

But on numbers this is the official and strange behaviour of NULL in JS:

And yes stackoverflow describes it good:
Ah, yes, the abstract equality operator (== ), also known as the if-same-type-then-strict-equality-comparison-otherwise-treat-null-and-undefined-and-document-dot-all-as-equal-but-if-string-involved-with-number-or-bigint-then-coerce-string-to-respective-numeric-type-but-if-boolean-involved-then-coerce-it-to-number-but-if-object-involved-then-coerce-it-to-primitive-and-if-numeric-types-involved-then-compare-their-numeric-values-with-distinct-infinities-and-nans-being-unequal-and-then-repeat-as-needed operator. :joy: :joy: :joy:

null != “Null” in JS, but null.toString() fails there with error, even null is an object… But console.log(null) will result in ‘null’ appearing on the console… Java should return real null in case of null.toString(), and the widged displaying it may catch the null-state-item and display Null as a text… Then this would work exactly as it does and would be right…

And are we sure that

/**
   * String representation of the Item state.
   * @type {string}
   */
  get state () {
    return this.rawState.toString();
  }

Is the actual implementation… I thought state with oh 4 returns the dimensional state and not the raw number, isn’t that the breaking news in OH 4?