[SOLVED] Rollershutter group & rule

Hi,
I am trying to set up a rollershutter rule. I am a true beginner at openhab, so it is really difficult for me and there are a few questions.

For example, this is the rule i am using to close the shutters:

rule "Rollläden schließen 1h nach Sonnenuntergang"

when
	Channel "astro:sun:home:set#event" triggered START
then 	if 	((zeit_rolladen.state == ON) && (Level_Kueche.state > 1)) {
			var Timer rolladen_nacht = null
				rolladen_nacht = createTimer(now.plusMinutes(60), [| 
						if (Level_Kueche.state > 1) {
						Besch_ZU.sendCommand(ON)
						sendTelegram("marco" , "Rollläden werden automatisch geschlossen")	}	])
			}
end

The rule to close all shutters:

rule "komplettes Haus schliessen"
when Item Besch_ZU received command ON 
then	{		Rolladen_Wohnzimmer.sendCommand("100")
				Thread::sleep(500)
				Rolladen_Buero.sendCommand("100")
				Thread::sleep(500)
				Rolladen_Schlafzimmer.sendCommand("100")
				Thread::sleep(500)
				Rolladen_Spielzimmer.sendCommand("100")
				Thread::sleep(500)
				Rolladen_Max.sendCommand("100")
				Thread::sleep(500)
				Rolladen_Bad.sendCommand("100")
				Thread::sleep(7000)
				Lamelle_Kueche.sendCommand("0")
				Thread::sleep(100)
				Jalousie_Kueche.sendCommand("0")
				Thread::sleep(1000)
				Lamelle_Esszimmer.sendCommand("0")
				Thread::sleep(100)
				Jalousie_Esszimmer.sendCommand("0")
				Thread::sleep(4000)
				Lamelle_Treppe.sendCommand("0")
				Thread::sleep(100)
				Jalousie_Treppe.sendCommand("0")
				Thread::sleep(1000)
				Lamelle_Wohnzimmer.sendCommand("0")
				Thread::sleep(100)
				Jalousie_Wohnzimmer.sendCommand("0")
				Thread::sleep(5000)
				Besch_ZU.sendCommand("OFF")
				Thread::sleep(70000)
				check_lamelle.sendCommand(ON)
		}
end

These Thread::sleeps i need because i am using homematic. Without them, the CCUs duty cycle is overloaded.

Only for explanation:

 zeit_rolladen is a proxy switch to change manually or automatically if i am not home
 Level_Kueche should be clear (kitchens shutter)
 Besch_ZU is also a proxy item with a rule in itself to close all shutters
 There are normal rollershutters and blinds with slats

I know, that there is a possibility to offset sunrise and sunset, but with the createTimer it is easier (in my opinion) to change the time if i need it. OK, with my solution I have to check a second time if the shutter is still open after expiring the timer.

And now my problem:
I only check one shutter if it is open or closed. Is there a possibility to check each member of the rollershutter group and close/open the shutter with the wrong state?

I read a lot in the design pattern tutorials, the problem still existing for me is how to create a rollershutter group?
Group:Rollershutter:OR(DOWN,UP) works fine to close or open, but i am not able to check the state
Tried a lot with state open/close, average,… in the group definition, but nothing gave me the solution.

I am still a beginner, so please be patient :wink:

I had that problem too. I didn’t get a fix but noticed that the dynamic icon for the group changes in a useful way.

There are safer alternatives to thread sleep including Timers or Design Pattern: Gate Keeper.

For example,

    Rolladen_Wohnzimmer.sendCommand("100")
    
    var sleep = 500
    createTimer(now.plusMillis(sleep), [| Rolladen_Buero.sendCommand("100")] )
    sleep = sleep + 500
    ...
val openSutters = rollershutter.members.filter[ rs | rs.state != 100 ].forEach[ rs, i | createTimer(now.plusMillis(500*i), [ | rs.sendCommand(100) ])

The important thing to realize is that Rollershutters actually store their state as a PercentType. So you need to check the percent. So if 100 == closed a Group definition like Group:Rollershutter:Min rollershutter and the state of rollershutter will be the Item with the smallest value.

2 Likes

@rlkoshak :heart_eyes:
Really? Is it so easy?

So the only things i have to do is creating a group like

Group:Rollershutter:Min rollershutter

And with this rule all my problems should be solved? Check every items state and close the open one?

rule "Rollläden schließen 1h nach Sonnenuntergang"

when
	Channel "astro:sun:home:set#event" triggered START
then 	if (zeit_rolladen.state == ON) {
		var Timer rolladen_nacht = null
		rolladen_nacht = createTimer(now.plusMinutes(60), [| 
			val openShutters = rollershutter.members.filter[ rs | rs.state != 100 ].forEach[ rs, i | createTimer(now.plusMillis(500*i), [ | rs.sendCommand(100) ])	
			sendTelegram("marco" , "Rollläden werden automatisch geschlossen")	])
			}
end

Let me understand this:

rollershutter.members.filter[ rs | rs.state != 100 ]

is the part which checks which one is not closed

forEach[ rs, i | createTimer(now.plusMillis(500*i)

like said, for each (which is not closed) there will be a 500ms timer

 [ | rs.sendCommand(100) ])

sends the “down” command to every (not closed) rollershutter

You are great!

I think you have it. The only trick is that it schedules the timers in 500 msec increments. That is what the i*500 does. So the first item in the list of open rollershutters will have a timer run immediately, the second one 500 msec after that, the next one 1000 msec after the first one and so on.

See Design Pattern: Working with Groups in Rules for more stuff you can do with Groups.

1 Like

@rlkoshak

There war a ] missing at the end, you are forgiven :wink:

Tried it today, and it is working like a charm… once again a big thx

But creating the minimum group isn’t working

Group:Rollershutter:Min         gRolladen_Gesamt

The log shows

2018-11-15 17:21:45.790 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'gruppen.items' has errors, therefore ignoring it: [46,21]: no viable alternative at input 'Min'

[46,33]: missing EOF at 'gRolladen_Gesamt'

Any idea?

EDIT:
Forget it, got it
MIN has to be written in capital letters

@rlkoshak
Your hint was great and helps me a lot, but it doesn’t solve my whole problem.

My existing problem:
At my house I am using normal rollershutters and blinds. And those blinds are still my problem. I have to send a command to open/close the slat and the associated blind itself. First I have to close/open the slat and after that open/close the blind itself with a delay about 100ms. After that I have to wait about one second to close/open the next one.

The rule I use at the moment is this one:

rule "komplettes Haus schliessen"
when Item Besch_ZU received command ON 
then	Lamelle_Kueche.sendCommand(0)
		Thread::sleep(100)
		Jalousie_Kueche.sendCommand(0)
		Thread::sleep(1000)
		Lamelle_Esszimmer.sendCommand(0)
		Thread::sleep(100)
		Jalousie_Esszimmer.sendCommand(0)
		Thread::sleep(1000)
		Lamelle_Treppe.sendCommand(0)
		Thread::sleep(100)
		Jalousie_Treppe.sendCommand(0)
		Thread::sleep(1000)
		Lamelle_Wohnzimmer.sendCommand(0)
		Thread::sleep(100)
		Jalousie_Wohnzimmer.sendCommand(0)
		Thread::sleep(100)
		gRolladen_Gesamt.members.filter[ sh | sh.state < 100 ].forEach[ sh, i | createTimer(now.plusMillis(100*i), [ | sh.sendCommand(DOWN) ])]
end

And now i read your post about thread::sleep :slight_smile:
I tried a lot, for example to create a group for slats and blinds and close them like the rollershutters. But it didnt work, there has to be a delay between the associated slat and blind. It is not possible to close all slat and after that all blinds itselves.
Any idea how to solve that?

Sleeps of 100 msec are not that much of a problem so just put the sleep 100 and close both in the forEach loop. See Design Pattern: Associated Items for deails on how the names are used.

rollershutter.members.filter[ rs | rs.state != 100 ].forEach[ rs, i | 
    createTimer(now.plusMillis(1000*i), [ | 
        rs.sendCommand(0)
        Thread::sleep(100)
        sendCommand(rs.name.replace("Lamelle", "Jalousie"), "0")
    ])
]

Only put the Lamelle Items into the Group.

1 Like

YOU ARE THE GREATEST
My (for the moment) final version

rule "komplettes Haus schliessen"
when Item Besch_ZU received command ON 
then	gLamellen_Gesamt.members.filter[ l | l.state != 0 ].forEach[ l, i | 
    	createTimer(now.plusMillis(1000*i), [ | 
        l.sendCommand(0)
        Thread::sleep(100)
        sendCommand(l.name.replace("Lamelle", "Jalousie"), "0")
    		])
		]
		Thread::sleep(100)
		gRolladen_Gesamt.members.filter[ r | r.state < 100 ].forEach[ r, i | createTimer(now.plusMillis(100*i), [ | r.sendCommand(DOWN) ])]
end

Since upgrading to OH 2.4 I have a “long” delay in executing rules, especially in this rule and I don’t know why. With OH 2.3 everything works fine.
Here are the log entries to show the timedelay.

2019-02-11 18:43:04.822 [ome.event.ItemCommandEvent] - Item 'Besch_ZU' received command ON
2019-02-11 18:43:04.831 [vent.ItemStateChangedEvent] - Besch_ZU changed from OFF to ON
2019-02-11 18:43:07.640 [ome.event.ItemCommandEvent] - Item 'Lamelle_Treppe' received command 0
2019-02-11 18:43:07.646 [nt.ItemStatePredictedEvent] - Lamelle_Treppe predicted to become 0
2019-02-11 18:43:07.667 [vent.ItemStateChangedEvent] - Lamelle_Treppe changed from 99 to 0
2019-02-11 18:43:07.746 [ome.event.ItemCommandEvent] - Item 'Jalousie_Treppe' received command 0
2019-02-11 18:43:07.752 [nt.ItemStatePredictedEvent] - Jalousie_Treppe predicted to become 0
2019-02-11 18:43:07.755 [vent.ItemStateChangedEvent] - Jalousie_Treppe changed from 99 to 0
**!!Here is the delay!!**
2019-02-11 18:43:45.526 [ome.event.ItemCommandEvent] - Item 'Lamelle_Kueche' received command 0
2019-02-11 18:43:45.532 [nt.ItemStatePredictedEvent] - Lamelle_Kueche predicted to become 0
2019-02-11 18:43:45.569 [vent.ItemStateChangedEvent] - Lamelle_Kueche changed from 99 to 0
2019-02-11 18:43:46.837 [ome.event.ItemCommandEvent] - Item 'Jalousie_Kueche' received command 0
2019-02-11 18:43:46.843 [nt.ItemStatePredictedEvent] - Jalousie_Kueche predicted to become 0
2019-02-11 18:43:46.856 [vent.ItemStateChangedEvent] - Jalousie_Kueche changed from 99 to 0
**Till now everything works fine**

I can live with it, but I don’t know why?!

There are other rules with a litte delay in it as well, but not so “big”

@rlkoshak any idea?

Do you have long running Rules? Rules with Thread::sleep, executeCommandLine with a timeout, sendHttp*Request calls, etc.

What do you exactly mean with long running rules?

Since your thread about thread::sleep I reorganized all my rules to createtimer.
There are only 5 or 6 rules with a thread::sleep in them, and these are only 100ms.

No rules with executeCommand Line, and no with sendHttp…

There are only 2 rules with a long createTimer, one with 60 minutes and one with 150 minutes.

OK, that should eliminate running out of threads as the cause of the delay.

Add logging to your Rule and compare the time when the Rule runs, particularly the time when the command is sent, to events.log to see with the Item received the command. It may not be that the Rule is taking long, it may be that the event is taking long.

Also, check the resource utilization on your machine. Run top and see if the CPU is being heavily used or you are running out of RAM.

Added logging at the beginning and end of the rule. Rule execution takes about a second, seems to be normal.

Also checked CPU and RAM usage. Both have only a minimal rise. Seems to be normal too.

I have the feeling, that all rules with xxx.members.filter have this delay.

This is a rule I am using when I leave home. And there is a delay in switching off some lights too.

rule "Verlasse Haus"
when Item leave received command ON
then	if	(gSicherheit.state == OPEN) {
			val leave = gSicherheit.members.filter[ l | l.state == OPEN ].map[ label ].reduce[ l, label | l + ", " + label ]
			sendTelegram("marco" , "Folgende Fenster sind noch offen: %s", leave.toString)
			}
		if (gLeave.state == ON) {
			val light = gLeave.members.filter[ lt | lt.state != OFF ].map[ label ].reduce[ lt, label | lt + ", " + label ]
			sendTelegram("marco" , "Folgende Lichter werden ausgeschaltet: %s", light.toString)
			gLeave.members.filter[ ll | ll.state != OFF ].forEach[ ll | ll.sendCommand(OFF)]
			}
		if (dark.state == OFF && gLeaveTimer.state == ON) {
			gLeaveTimer.members.filter[ lt | lt.state != OFF ].forEach[ lt | lt.sendCommand(OFF)]
		   }
		if (dark.state == ON) {
			gLeaveTimer.members.filter[ ltd | ltd.state != ON ].forEach[ ltd | ltd.sendCommand(ON)]
			createTimer(now.plusMinutes(5), [| gLeaveTimer.sendCommand(OFF) ])
			}
		Harmony_Activity.sendCommand("PowerOff")
		pl_sonos_kitchen_control.sendCommand("PAUSE")
		pl_sonos_bad_control.sendCommand("PAUSE")
end

Restarting openhab and clearing cache didn’t solve the problem.

Do not misunderstood me, this delay is not big, it is about 30 seconds. But I didn’t notice a behaviour like this in OH 2.3.

That’s way long for a Rule like this. How many members are in your Groups?

A rule like this should run well under a second unless you have tens of thousands of members in these groups.

Add some more logging to see if you can narrow the delay down to a specific line or lines.

Tried it again with a few more loggings


rule "komplettes Haus schliessen"
when Item Besch_ZU received command ON 
then	logInfo("shutter", "First step")
        gLamellen_Gesamt.members.filter[ l | l.state != 0 ].forEach[ l, i | 
    	createTimer(now.plusMillis(1000*i), [ | 
        l.sendCommand(0)
        Thread::sleep(100)
        sendCommand(l.name.replace("Lamelle", "Jalousie"), "0")
    		])
		]
		logInfo("shutter", "Second step")
        Thread::sleep(100)
        logInfo("shutter", "Third step")		
        gRolladen_Gesamt.members.filter[ r | r.state < 100 ].forEach[ r, i | createTimer(now.plusMillis(100*i), [ | r.sendCommand(DOWN) ])]
        logInfo("shutter", "End")
end

Time between Besch_ZU received command ON and First Step are 12ms
Time between First Step and Second Step are 68ms
Time between Second step and Third step are correctly 100ms
Time between Third step and end 51ms

So, the complete rule execution takes about 231ms. If I subtract the 100ms from thread::sleep, I think 131ms to execute a rule is OK?

In gLamellen are only 4 Blinds, and in gRolladen are 6 Shutters.

So rule execution seems to be OK, but why is there this delay about 35-40 seconds between first and second command in group gLamellen?
It is everytime between first and second “item”, the rest runs perfectly through?!

Installed systeminfo binding and did a every second influxdb persistance to cpu load and ram usage. CPU load is normally between 11-12%. While rule execution the maximum was 12,4%.
Available memory was between 45 and 40%, what is absolutely normal.

1 Like

That is what I would expect. Those are reasonable times.

With the information given it’s hard to say. Log out the 1000*i to make sure there isn’t something odd going on there causing the Timer to be scheduled longer into the future than expected or something.

Add logging inside the timers to see when the timers are triggering. There are only two threads for running timers. So if you have a bunch of timers or cron triggered Rules then these timers may have to wait on other timers to finish running first before it can run.

If you have more than one Rule that controls the Items in this Group, consider the Design Pattern: Gate Keeper Queue example. There might be an interaction between the rules that send these commands that isn’t apparent.