Simple Coding Question

I’m having a senior moment, see my rule below.
I intended to have it so that after switching some dimming lights bulbs to 20% as a prelude to OFF I would check in case they had been changed during the timer - e.g. if someone turned them back up as they didn’t want them off

I realised the logic was wrong but the lights are still turned off - I had both an OR and AND but either way the lights go off and I’m confused why the IF returns TRUE and executes the next line

rule "Lounge Lamps Off"

when
    Time cron "0 30 22 1/1 * ? *" // Expression for everyday at 10.30pm
then
    if (gLoungeLights.state == ON)
    {
        logInfo ("LightRule", "Turn off the Lounge Lamps at 10:30pm")
        LoungeRL_Dimmer.sendCommand(20)
        LoungeTV_Dimmer.sendCommand(20)
        logInfo("LightRule", "Having set Dimmer to 20% now setting timer for 5 mins")
        DimmerTimer = createTimer(now.plusMinutes(5), [|
            logInfo("LightRule", "Timer Expired set dimmer to 0 or off")
            if ((LoungeRL_Dimmer.state as Number !== 20) || (LoungeTV_Dimmer.state as Number !== 20))
                gLoungeLights.sendCommand(OFF) //One command to set both bulbs off.
            DimmerTimer = null
            ])
    }
    else
        logInfo("LightRule", "Lounge Lamps already off, no action")
end

I know (I hope) I could just test if they both = 20 but I need to understand why the logical test is wrong.I.e for “gLoungeLights.sendCommand(OFF)” to execute the IF must be TRUE
I’ve seen other examples of casting dimmer states as Number to check their level but is that correct?

Similar ish rules work here, but I’e never use “as number”, just something like:

KitchenSmall.state < 7 && KitchenSmall.state > 0

Ira

Dimmers use PercentType so to do a numeric comparison I believe(d) they had to be cast to Numbers.

I just found this:


where an intermediate step is putting the dimmer value in a variable and then doing the comparison, maybe someone will tell me whether that is what I need to do?

I would do it using the expire feature now that I understand it, kind of like this:
The first line goes in your items file, the rest in rules.

Ira

Switch gLoungeLightsAutoOff   "Lounge Lights Auto-Off"  {expire="5m, command=OFF"}


rule "Lounge Lamps Off"

when
    Time cron "0 30 22 1/1 * ? *" // Expression for everyday at 10.30pm
then
    if (gLoungeLights.state == ON)
    {
        logInfo ("LightRule", "Turn off the Lounge Lamps at 10:30pm")
        LoungeRL_Dimmer.sendCommand(20)
        LoungeTV_Dimmer.sendCommand(20)
        logInfo("LightRule", "Having set Dimmer to 20% now setting timer for 5 mins")
		gLoungeLightsAutoOff.postUpdate(ON) 
	}
end

rule "Lounge Lights Off Step 2"
when
	Item gLoungeLightsAutoOff changed to OFF
then
           logInfo("LightRule", "Timer Expired set dimmer to 0 or off")
            if ((LoungeRL_Dimmer.state as Number !== 20) || (LoungeTV_Dimmer.state as Number !== 20))
                gLoungeLights.sendCommand(OFF) //One command to set both bulbs off.
end


I assume you are referring to this line:

if ((LoungeRL_Dimmer.state as Number !== 20) || (LoungeTV_Dimmer.state as Number !== 20))

tl;dr, use != instead of !==.

==: is equivalent to
`===: is identical to, said another way, points to the exact same location in memory.

When you drop a number into an expression, a new variable is created and populated with the value 20. So LoungeRL_Dimmer.state as Number === 20 would always return false because LoungeRL_Dimmer.state points to a different place in memory than the unnamed variable populated with the value 20. LoungeRL_Dimmer.state as Number == 20 could return true if the Item’s state is equivalent to the value 20.

Thank you Rich for that clear and detailed explanation.
Now I know I was told to use !== in other situations so is that only for use when testing to null?

As in

if (presenceTimer !== null)

Something specific to NULL testing?

OR if testing two states

dimmer1.state === dimmer2.state

Only with null. It probably works with NULL but recommend only using it with null.