How to create a complex light status check rule?

Hi,

I created (based on forum inspiration here and there) the following rule that works fine:
rule "Check lights"
when Item Lights received update
then
Lights.members.forEach[light |
// Only create a Timer if there isn’t one already
var isOn = false
if (light.type == “Dimmer”)
isOn = (light.state > 0)
else
isOn = (light.state == ON)
if ( isOn == true && lightTimers.get(light.name) == null )
{
logInfo(“xxx”, "START timer for "+ light.name)
lightTimers.put(light.name, createTimer(now.plusMinutes(60), [|
var isStillOn = false
if (light.type == “Dimmer”)
isStillOn = (light.state > 0)
else
isStillOn = (light.state == ON)
if (isStillOn) {
var msgTxt = light.name + " is ON for too long "
logInfo(“xxx”, msgTxt)
notifyMyAndroid(“ALARME LUMIERE”, msgTxt)
lightTimers.put(light.name, null) // remove the timer from the Hashmap
}
]))
} else {
if ( isOn == false && lightTimers.get(light.name) != null ) {
logInfo(“xxx”, "STOP timer for "+ light.name)
lightTimers.get(light.name).cancel
lightTimers.put(light.name, null) // remove the timer from the Hashmap
}
}
]
end

My problem is that I have a fix timer of 60 minutes for each light.
I would like to make it more accurate.

As I have quite a high number of light I wouldn’t like to hard code a logic for each light.
So my idea was to create a kind of control table with the light name as key and different allowed ON time depending on different criteria.
For example a table like
Column 1 : light name
Column 2 : Allowed ON time during the night
Column 3 : Allowed ON time during the day

My question is what would be the most elegant way to implement such a table (or any equivalent) in a rule?

Thanks in advance,
OvO

Please use code fences:

```
code goes here
```

It is really difficult to read code when it is not properly formatted.

I recommend:

To apply this Design Pattern you would create a Number Item for each Light named in such a way as to easily construct the Number Item’s name given its associated Light Item. Put these number Items into a Group and use the code example to get a reference to the Number Item associated with a given Light.

The only part that is not addressed by the design pattern above is how to bootstrap the Number Items. To do this create a System started rule that populates the Number Items with an initial value. If you are using persistence with restoreOnStartup you can eliminate this rule after it runs the first time.

An advantage with this approach is, should you choose to, you can put the Number Items on your sitemap with a Setpoint or Slider and adjust the times without editing your rules.

This addresses part of your problem. The second part of your problem is determining whether the light is allowed on at night and/or during the day.

You can solve this part of the problem the same way, with associated Items. But I would solve it a different way, with Groups.

Create a Group for each of the time periods you care about. in your example you would have a gNightLights group and a gDayLights group.

Add each light to the appropriate Group or Groups.

I recommend tracking your time of day using the Time of Day Design Pattern and make sure the value of TimeOfDay matches what you use in your Group names.

Now, before turning on a light you just need to:

if(light.groupNames.contains("g"+TimeOfDay.state.toString+"Lights")) {
    // its OK to turn on the light
}

Finally, I’ll mention that you should look into the Expire binding for your timers. Those coupled with Associated Items and Working with Groups in Rules can drastically reduce the amount of code required to do things like this.

Thanks.
Sorry for the code Here it is again in case anyone interested

rule "Check lights"
when Item Lights received update
then
	Lights.members.forEach[light |
        // Only create a Timer if there isn't one already
    var isOn = false
    if (light.type == "Dimmer")
    	isOn = (light.state > 0)
    else
    	isOn = (light.state == ON)
	if ( isOn == true && lightTimers.get(light.name) == null ) 
	{
			logInfo("xxx", "START timer for "+ light.name)
            lightTimers.put(light.name, createTimer(now.plusMinutes(60), [|
            	var isStillOn = false
			    if (light.type == "Dimmer")
			    	isStillOn = (light.state > 0)
			    else
			    	isStillOn = (light.state == ON)
		        if (isStillOn) {		
				var msgTxt = light.name + " is ON for too long"
	                	logInfo("xxx", msgTxt)
				notifyMyAndroid("ALARM", msgTxt)
				lightTimers.put(light.name, null) // remove the timer from the Hashmap
			}
            ]))
    } else {
       	if ( isOn == false && lightTimers.get(light.name) != null ) {
       		logInfo("xxx", "STOP timer for "+ light.name)
			lightTimers.get(light.name).cancel
			lightTimers.put(light.name, null) // remove the timer from the Hashmap
		}
	}
] 
end

The control of the duration looks like an elegant way, this will create quite a number of items. Maybe I will have to revise my naming convention :slight_smile:
But my understanding of the solution is that I will then have only one duration allowed per light.
It might be sufficient but I was thinking more about different duration allowed depending on context.

I already have an astro binding that give me the period of the day and also some lightness sensors to control during the day if it is allowed or not to switch on lights. I may also combine it with the weather (but this is kind of the same info of the sensors one).

Thanks for the tips this is already giving quite some things to think and work on.

Based on your table that was the impression you left.

You can add additional Number Items based on each context. You just need to be able to construct the proper Item name from the Light and the Context.

The main point is that you need to name the Groups based on what ever you are using to track the time of day.