[SOLVED] Reducing the impact of turning off MANY lights? How to optimise

I think you can filter on type here, to omit groups and select only “real” switches.

gAllLights?.allMembers.filter[Lights | Lights instanceof SwitchItem && Lights.state==ON]...

Seems not, i tried lower case o in instance, but it didnt accept it when the rule saved. Saved OK with capital O, but then errors under execution

09:20:30.227 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Turn off all Lights': The name 'instanceOf' cannot be resolved to an item or type; line 80, column 50, length 10


09:21:54.172 [WARN ] [del.core.internal.ModelRepositoryImpl] - Configuration model 'scenes.rules' has errors, therefore ignoring it: [80,50]: missing ']' at 'instanceof'
[80,91]: mismatched input ']' expecting 'end'

You’d better show us the line under complaint.

Certainly.


rule "Turn off all Lights"
when
        Item Proxy_gAllLights received command OFF
then
          gAllLights?.allMembers.filter[Lights | instanceof SwitchItem && Lights.state==ON].forEach[ LightsON |
               LightsON.sendCommand(OFF)
               logInfo("alloff","Item {} is set to OFF from {}",LightsON.name,LightsON.state)
          ]
end

Look closely, you forget to specify what you are interested in for instanceOf

Ill do some reading, im not following.

[Lights | Lights instanceOf SwitchItem && …

You want your filter to look at the object that you just got from allMembers of the Group, that you are temporarily calling Lights, and test to see if it is an Item of type Switch. (a Group won’t be, it will be type GroupItem)

It could be a Switch Item or a Dimmer Item that could be ON.

Then you’ll have to change the sense of the filter, Luckly “!” works for “not”, and you already know it’s the GroupItem type you want to reject.

Is there some documentation on this because I dont understand.

I assume I need an && for SwitchItem and DimmerItem. Not sure where you’re getting the not from, do you mean

SwitchItem && DimmerItem && !GroupItem?

No, I mean given you get three possible types and you want two of them; an alternative way to express the logic is that you want to test the target is NOT of the other type. Not-instanceOf.

...filter[Lights | Lights !instanceof GroupItem && Lights.state==ON]...

I think the next obstacle you will run into is that Dimmer types states are numeric, not ON. You could overcome that by casting to OnOffType, a kind of conversion.

Ah!

If I look at the Items for Switch/Dimmer, both of them are part of gAllLights, so if I ignore the Dimmer type also and just match the SwitchItem, that should turn it off (irrespective of if its a dimmer or switch)

But, that should mean my rule as it is should work!

Uh, I think you have lost sight of your objective - only sending commands to lights that are actually ON, not to all members of a Group.

Just to be clear, if you send a command to a Group it will regenerate that same command to every member, regardless of state or type. You cannot control that in any way, apart from not doing it to begin with.

Correct, so, why does instanceof SwitchItem not work?

Objective: Send an OFF command to every item of the group that is a Switch with the state ON. Without flooding off commands to stuff that’s not on

To me, the below does that? but clearly doesnt.

rule "Turn off all Lights"
when
        Item Proxy_gAllLights received command OFF
then
          gAllLights?.allMembers.filter[Lights | instanceof SwitchItem && Lights.state==ON].forEach[ LightsON |
               LightsON.sendCommand(OFF)
               logInfo("alloff","Item {} is set to OFF from {}",LightsON.name,LightsON.state)
          ]
end

Right. So you’re saying no matter what I do, the event log would be flooded with OFF commands irrespective of the filter?

Because it is incomplete. What is an instance of SwitchItem?
Once again, in this situation, the complete statement is
Lights instanceOf SwitchItem

But as discussed that won’t work because it will ignore Dimmer types as well as Group types it finds among the “top” group’s members.

No, this what the filtering is about. In the first version of the rule, we used the filter only to find things that are ON.
But as you have some things that are Groups that can also be ON, we have to miss those out as well.
And now there are Dimmers, which aren’t ON but 55% in their basic state.

It might be more comprehensible writing it out longhand, and doesn’t take much more processing.

gAllLights?.allMembers.forEach[ someItem |
      if (someItem instanceOf SwitchItem && someItem.state == ON) {
         someItem.sendCommand(OFF)
      } else if (someItem instanceOf DimmerItem && someItem.state > 0) {
         someItem.sendCommand(OFF)
      } //else if any other type we do nothing
]
1 Like

Now that makes far more sense to me!!!

So:


rule "Turn off all Lights"
when
        Item Proxy_gAllLights received command OFF
then
        gAllLights?.allMembers.forEach[ AllLights |
      if (AllLights instanceOf SwitchItem && AllLights.state == ON) {
         AllLights.sendCommand(OFF)
      } else if (AllDimmers instanceOf DimmerItem && AllDimmers.state > 0) {
         AllDimmers.sendCommand(OFF)
      } //else if any other type we do nothing
]
end

My point before was that a Light and a Dimmer is the same device, just a different type, ie if you turn off the Switch item, it turns off the Dimmer item. So technically, only the first if is needed right?

I don’t know what that means. Your devices are each represented by pairs of Items of different types?

Sure, see my example:

/*ZWave Dimmer 2 Movie Stair Lights*/
Switch Movie_Stairs_Sw1     "Movie Stair Lights"                             (gFamilyLights,gLivingLights)             { channel="zwave:device:6dad8bea:node171:switch_dimmer1" }
Dimmer Movie_Stairs_Dimmer1 "Movie Stair Lights"                             (gLivingDimmers)                          { channel="zwave:device:6dad8bea:node171:switch_dimmer1", alexa="PowerController.powerState,BrightnessController.brightness" }
Number Movie_Stairs_Num1    "Movie Stair - Current Consumption [%.1f W]"     (gAllLightsUsage,gEnergyRealTime)         { channel="zwave:device:6dad8bea:node171:meter_watts1" }
Number Movie_Stairs_Num2    "Movie Stair - Usage [%.1f kW]"                  (gPowerUsage)                             { channel="zwave:device:6dad8bea:node171:meter_kwh1" }

Well, you have full control over what the rule does, and the membership of the groups it acts on, it’s time to make what you want.

1 Like

Why defining two items for the same channel? This is crap! You can use the Dimmer Item as a switch, too.

I can’t see any command from the rule to any group in the logs, so the rule can’t do the wrong commands here.

If you want to use a Dimmer state as OnOffType, you could do it like this:

rule "Turn off all Lights"
when
    Item proxyAllLights received command OFF
then
    gAllLights?.allMembers.filter[Lights | !(Lights instanceof GroupItem) && Lights.getStateAs(OnOffType) == ON ].forEach[ LightsON |
        LightsON.sendCommand(OFF)
    ]
end

Please take note of the different boolean not - there is no “not instanceof” but only an “instanceof”, so you have to negate the term instead (this is why I use brackets)

1 Like