OH3 rule conditions AND | OR

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?

That’s the rub though, null isn’t and Object. It’s its own special thing in JS and most other programming languages.

There is special handling for null or else the logger would be throwing exceptions all over the place.

I don’t quite understand that but in Java it’s the same as in JaveScript. null is a special type of primitive and not an Object and therefore does not have a toString().

By the time it gets to the Widget, it’s just text anyway, null, number, or otherwise.

I took it straight from the code in openhab-js. And this method has not changed as long as I’ve been using openhab-js.

In JS Scripting, .state has always been the String representation of the Item’s state. Towards the end of OH 3, numericState and quantityState were added which returns the state as a primitive JavaScript float or as a JavaScript Quantity.

Example Type Result
items.Temperature.state String "65 °F"
items.Temperature.quantityState Quantity 65 °F
items.Temperature.numericState float 65
items.Temperature.rawState org.openhab.library.types.State 65 °F

Note, I’m guessing at the full name of the Java State. And it will come over as a State but can be used as a QuantityType or a DecimalType. But you’ll have to convert it to a JS type to do much of anything with it in your rule.

Unless you go out of your way, in JS Scripting you are always working with JavaScript Objects. So the Item you get from Items.getItem() is a JavaScript Object. Unless it has raw in the name, it’s JavaScript.

ohh i forgot to include that in the screen the strange behaviour of javaScript with regards to typeof(null)
But stackoverflow also has it nicely:

undefined behaves like you described for null, but

typeof(null)

reutrns object… but

null instanceof Object

returns false, which makes somewhat sense an empty list ist somehow not an Object or is it.

There is reason I fkn hate all kind of scripting languages :-).

So for me I come to conclusion, Blockly does it right with setting null in that system. my querry somehow does what it should, even null != “Null”, so most probably the .state method returns nulland not “Null” if the state is questioned and the item is Null. A widget will Dispaly “Null” most prbably as it is cathed if an item is null…

By the way thank you with the list of state and what it returns… I have to closer figure out what exactly changed between OH3 and OH4 breaking my scripts regarding item.state with GrallJS that worked before in NashornJS.

The thing is I looked at all that code. It doesn’t return null, ever. Neither the Java Item class nor the openhab-js code has anything to convert NULL to null and that’s leaving UNDEF completely out of the discussion. All openhab-js does is convert the Java UnDefType.NULL object to the string "NULL". (same as it does for all Item state types).

If that way, then it get’s tricky with the blockly null… will investigate that when I finally found the unknown ID js from the other discussion… It drives me crazy :slight_smile: