ANDing or ORing more than two items

Hey all,

I have had two leak sensors for a few years and I use a rule to combine these into an overall leak status for my house.

Part of the rule uses an AND (&&) in the IF statement:

if ((basementLeak.state == OPEN) && (hwtankLeak == OPEN)){
    houseLeak.postUpdate(OPEN)
    }

That works fine.

Now, I bought a new leak sensor so I want to add a 3rd unit to the mix

if ((basementLeak.state == OPEN) && (hwtankLeak == OPEN) && (dwLeak.state == OPEN)) {
    houseLeak.postUpdate(OPEN)
    }

This creates an error

2018-09-12 07:52:42.253 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘House Leak State’: An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.BooleanExtensions.operator_or(boolean,boolean) on instance: null

Anyone know the correct syntax to do this?

hwtankLeak.state == OPEN

And really you should use the OR statement ||

if ((basementLeak.state == OPEN) || (hwtankLeak.state == OPEN) || (dwLeak.state == OPEN)) {
    houseLeak.postUpdate(OPEN)
    }

Ah - yes, I see I missed that .state. Thanks.

Here is my full rule: (know that OPEN = Dry and Closed = wet)

Basically in words it check to see if all 3 sensors are dry, report the whole house dry. If any are wet, report as wet.

rule "House Leak State"
    when
            Item basementLeak changed or
            Item hwtankLeak changed or
            Item dwLeak changed
    then
            logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Leak State basement " + basementLeak.state)
            logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Leak State HWT " + hwtankLeak.state)
            logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Leak State DW " + dwLeak.state)
            if ((basementLeak.state == OPEN) && (hwtankLeak.state == OPEN) && (dwLeak.state == OPEN)) {
                    houseLeak.postUpdate(OPEN)
                    logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Im in OPEN/OPEN")
            } else if ((basementLeak.state == CLOSED) || (hwtankLeak.state == CLOSED) || (dwLeak.state = CLOSED)) {
                    houseLeak.postUpdate(CLOSED)
                    logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Im in CLOSED||CLOSED")
            }else {
                    houseLeak.postUpdate(OPEN)
                    logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Im in ELSE")
            }

    end

This is still throwing an error though even with at added .state

2018-09-12 07:58:40.901 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘House Leak State’: An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.BooleanExtensions.operator_or(boolean,boolean) on instance: null

logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Leak State basement " + basementLeak.state.toString)
logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Leak State HWT " + hwtankLeak.state.toString)
logInfo("house Leak State", "!!!!!!!!!!!!!!!!!!!!!! Leak State DW " + dwLeak.state.toString)

I think, one/some of it is null, check

if (basementLeak.state === null) {

Why don’t you use a Group item instead? Groups can automatically aggregate members’ state using AND, OR, NAND or NOR functions.

1 Like

@pacive -

Thanks - I’ll take a look at that.

OK - found my last error, I was missing one “=”

else if ((basementLeak.state == CLOSED) || (hwtankLeak.state == CLOSED) || (dwLeak.state = CLOSED)) {

should be

else if ((basementLeak.state == CLOSED) || (hwtankLeak.state == CLOSED) || (dwLeak.state == CLOSED)) {

This works now. I thought it was more of an issue with syntax that simply typos. Sorry to bug the group, but I will definitely look into using groups for this and possibly be able to eliminate a rule.

Have you looked at using VSCode with the OH addon? It does a good job catching the little things, like only one = when two is needed.

2 Likes

I haven’t, but will now. Back in the OH1 days I used the IDE (forget the name) which caught this stuff, but was super super slow and clunky. Now I have my OH on a RPI - ssh in and just use vim.

For the longest time that was all I used, ssh and nano on RPI but after trying VSCode I haven’t looked back.:wink: The only thing that kept me from using it sooner was the idea of having to set something else up but it wasn’t near as painful as I imagined. If you hit a snag let me know and maybe I can help.

2 Likes

Just for future reference, when it comes to
if ( XX && YY || ZZ )
it can be ambiguous, but you can use more brackets
if ( XX && (YY || ZZ) )

1 Like

And if your not a regular programmer, like me, here is a link, I keep in my bookmark toolbar and use often when working with rules and what operator does what.

https://www.w3schools.com/jsref/jsref_operators.asp

In a case like this it is important to understand the order of operations. As with math certain operators are performed before others. Assuming that the Rules DSL uses the same order as Java, && take place before the || when there are no parens to define the order.

So

if(XX && YY || ZZ) == if((XX && YY) || ZZ)

but

if(XX || YY && ZZ) == if(XX || (YY && ZZ))

Another thing that can be important is to realize that the boolean operators are fail fast. This means that as soon as the program knows that the expression will evaluate to true or false it immediately stops. For example:

if(XX || YY || ZZ)

If XX is true it will never evaluate YY or ZZ because if XX is true, the whole expression will evaluate to true. Similarly, if YY is true then it will evaluate XX and YY but never evaluate ZZ.

Similarly with

if(XX && YY && ZZ)

If XX is false then YY and ZZ are never evaluated because the expression can only be false.

Where this can cause problems for some users is when XX, YY, and ZZ are complex expressions in themselves, or when people try to make side effects happen inside their conditionals (e.g. if YY actually does something instead of just evaluating state) because depending on what XX is, YY may never execute.

That’s the trouble with programming. Even the lowly && operator has a ton of complexity behind it.