Automatic light dimming

That is ambiguous.
Is it (A <= B) && C , or is it A <= (B && C) ?
I’m sure it evaluates in a predictable way (if you know the rules - I don’t), but that may not be what you intended.
This is probably another place to go step by step - multiple if() until you can confirm things are happening just the way you want.

Well when it was coded as per below the behaviour was the same, when @rlkoshak suggested a cleaned up version of my code he removed all the extra brackets, thus I assumed they did not make a difference:

if (((ZwaveEye1Lux.state as DecimalType) <= ( LuxSetpoint.state as DecimalType - 30)) && (Standard_ALD.state == ON) && (Presence_Mobile_Mike.state == ON || Presence_Iris_Saxion.state == ON || Presence_Pepijn_Saxion.state == ON || Presence_Diamant_Saxion.state == ON || Presence_Euan_Saxion.state == ON ))

It evaluates the <= first and then the && so it is (A <= B) && C

Here is a handy cheet sheet.

I completely agree though, when debugging separate if statements for each can be very revealing, expecially when you drop a log statement in each one so you know how far you get down the evaluations.

It depends on the context as to whether they make a difference. To elaborate on rossko’s example:

`(A <= B) && C` is the same as A <= B && C`

So in this case the parens are supurfluous. However, if you want the B && C to evaluate first you must use the parens:

`A <= (B && C)`

The parens are a way for you to somewhat control the order things are evaluated in the if statements. It also isn’t always a bad thing to put in supurflous parens because it helps document the order that everything is evaluated (for example, by putting (ZwaveEye1Lux.state as DecimalType) in parens you are forcing it to evaluate first before the <=. However, in this case it is superflous because the as evaluates before the <= anyway.

So, in the above, the only parens that are actually functionally doing anything (besides the outer parens for the if statement itself) are the ones around all the || checks on Presence. So the following is functionally equavalent to your example:

if(ZwaveEye1Lux.state as DecimalType <= LuxSetpoint.state as DecimalType - 30 &&
   Standard_ALD.state == ON && (Presence_Mobile_Mike.state == ON ||
   Presence_Iris_Saxion.state == ON || Presence_Pepijn_Saxion.state == ON ||
   Presence_Diamant_Saxion.state == ON || Presence_Euan_Saxion.state == ON))

I might add a parens around the LuxSetpoint as DecimalType - 30 just to emphasize that there is some math going on in that part before the boolean evaluations. But it is not necessary.

The parens around the Presence checks ARE required though because you want to evaluate all the presence switches at once and the parens force them to be evaluated first and then the result compared with the rest.

All that being said, I would recommend using a Group:

    Group:SwitchOR(ON,OFF) gPresence
    Switch Presence_Mobile_Mike ... (gPresence) ...
    ...
    if (ZwaveEye1Lux.state as DecimalType <= LuxSetpoint.state as DecimalType - 30 &&
       Standard_ALD.state == ON && gPresence.state == ON)

Thanks alot for the clarification, at this point I am going to have to provide log files and/or use separate IF statemements to pinpoint the isse. That being said I have also coded it using the group exactly how you outlined (see code below), and still the lights were still being dimmed when the virtual switch Standard_ALD was switched OFF once the rule was running:

 if (ZwaveEye1Lux.state as DecimalType <= LuxSetpoint.state as DecimalType - 30 &&
           Standard_ALD.state == ON && gPresence.state == ON)

It’s invariably quicker to do the diagnostics than flail around hoping.

1 Like