Roller shutter different up/down times

My rollershutter has different times for down and up (going down is a bit faster)

Now I wanted to fix this issue with a rule, but it is not working. Somebody with an idea whats wrong?

rule "Arbeitszimmer_Rollo"
when
Item Arbeitszimmer_Rolladen changed
then	
    var Number counter = 0
    
 if (Arbeitszimmer_Rolladen.state==100){
    
    while ((counter-0.9)>0) {
	Thread::sleep(1000)
    }
	if (counter<=0){
		Arbeitszimmer_Rolladen.SendCommand(STOP)
	}

 }

 if (Arbeitszimmer_Rolladen.state==0){
    while ((counter+1)<12) {
	Thread::sleep(1000)
    }
	if (counter>=12){
		sendCommand(Arbeitszimmer_Rolladen.state,STOP)
	}

 }
    	
end

The first while loop will never execute because counter = 0
So counter - 0.9 will never be >0
Also, you never increment the counter in the loop so once in the loop it will never come out

You need to give a value to counter just before the while loop in each if case
I don’t know what value you want to give so I put some random values below
Also I tidied up a bit :smile:

rule "Arbeitszimmer_Rollo"
when
    Item Arbeitszimmer_Rolladen changed
then	
    var Number counter = 0
    
 if (Arbeitszimmer_Rolladen.state==100) {
    counter = 12
    while (counter > 0) {
        Thread::sleep(1000)
        counter = counter - 0.9
    }
    if (counter <= 0){
        Arbeitszimmer_Rolladen.SendCommand(STOP)
    }
}

if (Arbeitszimmer_Rolladen.state==0) {
    counter = 0
    while (counter < 12) {
        Thread::sleep(1000)
        counter = counter + 1
    }
    if (counter >= 12) {
        sendCommand(Arbeitszimmer_Rolladen.state,STOP)
    }

 }
    	
end

I see the problem now with “So counter - 0.9 will never be >0”

I think I need to create an Item counter which is never reset.

The main goal is that the counter should not be always restarted. Means, if somebody lowers the shutter to ~50% (counter+1), and later on it is opened again, it should take the old value of the counter (~50%) and calculate counter-0.9 (as going up is slower)

but which one is right?
Arbeitszimmer_Rolladen.SendCommand(STOP)
or
sendCommand(Arbeitszimmer_Rolladen.state,STOP)

That’s the right one

Then you need more rules to reset the counter whenever the shutter is fully opened or closed.
You should also declare the counter variable at the top of the rule file so that it is “visible” to all the rules in that file.

why more rules? the counter should never be reset.

If the shutter is going down it counts to 12 and stops
If the shutter goes up it counts from 12 to 0 with -0.9 (this gives 2 sec. more which is enough to fully open the shutter).

all I have to do is if counter<0 --> counter=0

if the shutter is going down to 50% it counts to 6 and stops (turning 6sec)
Opening again to 0 with -0.9 --> turning (7sec)
if counter<0 --> counter=0

I think this will do the job

Edit: even better: counter will be an item later!



rule "Arbeitszimmer_Rollo"
when
    Item Arbeitszimmer_Rolladen changed
then	
    
 if (Arbeitszimmer_Rolladen.state==100) {
    while (counter > 0) {
        Thread::sleep(1300)
        counter = counter - 1
    }
    if (counter <= 0){
       Arbeitszimmer_Rolladen.SendCommand(STOP)
    }
}

if (Arbeitszimmer_Rolladen.state==0) {
    counter = 0
    while (counter < 10) {
        Thread::sleep(1200)
        counter = counter + 1
    }
    if (counter >= 10) {
        Arbeitszimmer_Rolladen.SendCommand(STOP)
    }

 }
    	
end

not working as the qubino is not sending updates as foreseen.

The counter has to start somewhere. Presumably it is a global variable? And it somehow maps to the current position of the shutter I’m assuming (e.g. if the shutter is 50% open the counter is 6).

With those assumptions:

This is a really dangerous implementation. It is a really bad idea to have long sleeps inside a Rule. You can only run 5 Rules at the same time. If something goes wrong or for some reason Arbeitszimmer_Rolladen changes a too much it will cause ALL your Rules to stop running until one exits. And if you have an error like Vincent pointed out, the Rule will never exit.

It is much better to use Timers to push the delay outside of the Rule. And you really don’t need a counter. You know how long to wait so just wait for that amount of time.

Also, a counter is a really poor choice for this. You can just calculate how long to wait based on the desired % and sleep for that amount of time.

val totalUp = 2000 // total time to go from fully closed to fully open in millis
cal totalDown = 3000 // total time to from fully open to fully closed in millis

rule "Arbeitszimmer_Rollo"
when
    Item Arbeitszimmer_Rolladen_Proxy received command // send a command to tell it what percent you want the shutter opened to
then
    val percent = Math::abs((Arbeitszimmer_Rolladen.state - Arbeitszimmer_Rolladen_Proxy.state).intValue) // calculate the difference
    val direction = if(Arbeitszimmer_Rolladen.state < Arbeitszimmer_Rolladen_Proxy.state) DOWN else UP
    val time = if(direction == UP) (totalUp * percent) / 100 else (totalDown * percent) / 100

    Arbeitszimmer_Rollo.sendCommand(direction)
    createTimer(now.plusMillis(time), [ |
        Arbeitszimmer_Rollo.sendCommand(STOP)
        Arbeitszimmer_Rollo_Proxy.postUpdate(Arbeitszimmer_Rollo.state)
    ]
end

I may have the directions mixed up above and there could be other typos but the overall concept is:

  • you have a proxy Item that you use to send the command to the rollershutter telling it what percent you want the shutter to open to.
  • you calculate the difference between the current percentage and the desired percentage
  • you calculate the direction the shutter needs to go to reach the desired percentage
  • you calculate how long it will take to get there based on how far it needs to go and how long it takes to get there based on the direction going. Put in words, if it takes 2 seconds to go up and you need to go up by 25%, you need to go up for 500 milliseconds (i.e. 2000 * .25).
  • Now send the command to start going in the right direction and create a timer to sleep for the needed amount of time and when the timer goes off stop the rollershutter.
  • Make sure to synchronize the proxy with the actual rollershutter once it stops.
1 Like