Rule to create shading / tilt my blind

Hello,

I am using a shelly 2.5 that is configured as Roller and it is connected to a blind with a tilt/shading option. The motor has 2 buttons - UP and DOWN. When I press the DOWN button the blind goes down. Then, if I press the UP button, it first tilts until it changes its position and continues up. It goes the same the other way around.

I want to create a rule that will:

  • bring the blind to 35% - the staring position in this example
  • once arrives to 35%, bring it to 33% - make sure last movement is DOWN
  • once arrives to 33%, bring it to 34% (or up for 1 sec) – tilt it and create shading

Any idea how to implement it?

Thank you

Does the Shelly report the current open/closed percentage or do you have to guess it based on running time?

This is going to be exceptionally complicated with lots of time stamps and Timers to make it work. Break the Rule down into parts. First figure out how to bring the blind to a certain percentage. You will have to have Rules that keep track of where the blinds are based on how long it’s been going up or down. That alone is a very challenging task but there are several examples on the forum.

Once you figure that out, the other two steps will be much the same: turn on a relay for a certain amount of time and turning it off using a Timer.

Hi

As far as I get it the shelly originally supports only OPEN, CLOSE and STOP. Hence you don’t have any idea about the current position.

Did you checkout tasmota as an alternative FW. As per the documentation you can “calibrate” the shelly 2.5 in rollershutter mode so the device knows the times and can deal with percentages.

Thanks for the answers. I am working with the Shelly binding and I know the current position. It also supports setting the position (not only UP/DOWN/STOP).

Hey Yaron, do you have any updates on this? I have the same problem!
Thx for reply!

Hi,

After I got help from this community, I wrote the following code - keep in mind that I am not a programmer, so you can probably make it much better.
There are 5 steps:

  • Step 1 - open the blind all the way
  • Step 2 - take it to 25%. When I used it as 1st step it wasn’t accurate all the time
  • Step 3 - go back a little bit - you need to play with the new position - for me it was 22%
  • Step 4 - tilt - here also you need to play with the new position - for me it was 23%
  • Step 5 - turn off virtual switch
rule "Garden Blind Preset - 25% open"
when
    Item VS_Blind_Garden_Morning received command ON
then
    val logName = "My.Log - Garden.B - 25% open"
    var printLog = 1
    var VS_Blind=null as SwitchItem 
    VS_Blind=Shelly_Blind_Garden_Roller_Control
    var totalTime=75 //in sec - total open time
    var extraTime=3 //in sec - must be INT
    var newPos=0
    var currentPos=0
    var step=0
    var time=0

    if (printLog==1) logInfo(logName, "-------------- Start ---------------------")

    //Step 1 - open the blind all the way
    createTimer(now, [ |
        step = step + 1
        newPos = 0
        if (VS_Blind===null)
        {
            currentPos==null
        }
        else
        {
            currentPos = VS_Blind.state as Number
        }

        if (currentPos==null)
        {
            if (newPos>50)
            {
                currentPos=0
            }
            else
            {
                currentPos=100
            }
        }
		//calculate how much time it takes to move the blind to the new position + extra timne
        time = Math::round(((Math::abs((currentPos as Number).floatValue - (newPos as Number).floatValue)) * totalTime / 100 + extraTime).intValue)
		if (printLog==1) logInfo(logName, "Step " + step + " - Moving " + VS_Blind.name + " for " + time + " secs from " + currentPos + " to " + newPos)
        switch(newPos) 
        {
            case 0: 
            {
                VS_Blind.sendCommand(UP)
            }
            case 100: 
            {
                VS_Blind.sendCommand(DOWN)
            }
            default:
            {
                VS_Blind.sendCommand(newPos)
            }
        }
        currentPos = newPos

		//Step 2 - take it down to 25%
        createTimer(now.plusSeconds(time), [ |
            newPos = 25
            step = step + 1

            time = Math::round(((Math::abs((currentPos as Number).floatValue - (newPos as Number).floatValue)) * totalTime / 100 + extraTime).intValue)
            if (printLog==1) logInfo(logName, "Step " + step + " - Moving " + VS_Blind.name + " for " + time + " secs from " + currentPos + " to " + newPos)
            switch(newPos) 
            {
                case 0: 
                {
                    VS_Blind.sendCommand(UP)
                }
                case 100: 
                {
                    VS_Blind.sendCommand(DOWN)
                }
                default:
                {
                    VS_Blind.sendCommand(newPos)
                }
            }
            currentPos = newPos

            //Step 3 - go back a little bit
            createTimer(now.plusSeconds(time), [ |
                newPos = currentPos-3
                step = step + 1

                time = Math::round(((Math::abs((currentPos as Number).floatValue - (newPos as Number).floatValue)) * totalTime / 100 + extraTime).intValue)
                if (printLog==1) logInfo(logName, "Step " + step + " - Moving " + VS_Blind.name + " for " + time + " secs from " + currentPos + " to " + newPos)
                switch(newPos) 
                {
                    case 0: 
                    {
                        VS_Blind.sendCommand(UP)
                    }
                    case 100: 
                    {
                        VS_Blind.sendCommand(DOWN)
                    }
                    default:
                    {
                        VS_Blind.sendCommand(newPos)
                    }
                }
                currentPos = newPos

                //Step 4 - tilt
                createTimer(now.plusSeconds(time), [ |
                    newPos = currentPos+2
                    step = step + 1

                    time = Math::round(((Math::abs((currentPos as Number).floatValue - (newPos as Number).floatValue)) * totalTime / 100 + extraTime).intValue)
                    if (printLog==1) logInfo(logName, "Step " + step + " - Moving " + VS_Blind.name + " for " + time + " secs from " + currentPos + " to " + newPos)
                    switch(newPos) 
                    {
                        case 0: 
                        {
                            VS_Blind.sendCommand(UP)
                        }
                        case 100: 
                        {
                            VS_Blind.sendCommand(DOWN)
                        }
                        default:
                        {
                            VS_Blind.sendCommand(newPos)
                        }
                    }
                    currentPos = newPos

                    //Finish
                    createTimer(now.plusSeconds(time), [ |
                        step = step + 1
                        if (printLog==1) logInfo(logName, "Step " + step + " - Turn off virtual switch")
                        VS_Blind_Garden_Morning.sendCommand(OFF)
                    ])
                ])
            ])
        ])
    ])
end
1 Like