Automation of venetian blinds

Hi,

since a month I’m using OH, a really great software to automate our new home - thank you!

Currently I’m struggling with the automation of our venetian blinds. The blinds are grouped as items and I’ve configured a HABPanel to control groups of them by widgets, e.g. to send them all Up, Down or Stop. Usually I send all of them Up and then stop after 2 seconds. By this way, they are “opened”, i.e. the “opening angle” is configured in a way that we can look out.

Currently, I’m trying to automate this procedure. Therefore, I want to code a script the can be triggered from a button widget out of my HABPanel. In principle, the script should just perform the following tasks:

  1. Send “UP” command to a defined group of blinds
  2. Initialize a Timer object, which sends after a defined timespan the “STOP” command

Unfortunately, I don’t know how to start. Does anybody have some hints for me?

Regards,
BananaBender

You could probably do this without rules: try the Expire binding

Currently I’m using MQTT binding for the rollershutter shellies. I’m not sure, but an additional binding for the same things may results into problems?

A replacement of the MQTT binding for the shellies is not possible, because the former desribed “opening feature” is only one kind of control (other, existing control features should remain).

As extension to my first post: The procedure should accept two arguments:

  • Name of item group
  • Time span

The expire binding is not a binding that is going to replace your MQTT binding. You can use it on top th define a command that is to be sent after a specified amount of time expired.
E.g. I can ask Alexa to turn on light for 5 minutes. This means a specific switch will be turned on. By using expire the switch will be turned off after 5 minutes without further manual interaction.
The item in my case looks like:

Switch Rule_Fuenf_Minuten_Aussenlicht_einschalten "Fuenf_Minuten_Aussenlicht" ["Switchable"] { expire="300s,command=OFF" }

the related rule that I have uses a script to turn on/off the physical switch of the light via a UDP command. That script could be adapted to send MQTT commands:

rule "rule triggered by Rule_Fuenf_Minuten_Aussenlicht_einschalten"
when
        Item Rule_Fuenf_Minuten_Aussenlicht_einschalten received command
then
        if (receivedCommand === ON ) {
                executeCommandLine( "/etc/openhab2/scripts/aussenlicht.sh OUT4  1" )
        }
        else if ( receivedCommand == OFF ) {
                executeCommandLine( "/etc/openhab2/scripts/aussenlicht.sh OUT4  0" )
        }
end

I do not use Expire binding that was mentioned in a previous post because it is a V1 binding that will not be supported in the upcomming OH3.
Instead I use a jython replacement which is described here:

I was also of the same opinion, but Expire will be supported in V3 - it will become it’s own Profile, so minimal, if any, changes required when switching to V3.

In fact, that seems to be a possibility. As far as I understood, it looks like this:

  • define a switch for this purpose
  • create a rule which interacts with the events resp. commands of that switch
  • the switch can be activated by a widget, i.e. the widget is the indirect trigger for the rule

In this case, probably I’ve to create the switch for every rollershutter (and cannot re-use the existing groups)?

1 Like

Thanks for that link. Looks like somehow I missed that poll.

Thank you!

As far as I understood, using the Expire Binding looks like this:

  • define a “special” rollershutter item for each blind (a copy of the existing rollershutter item, which contains the additional expire config)
  • define a new group to apply on the former mentioned “special” rollershutter items
  • use a widget on the group

Hold up I’m not sure if the below will actually work, due to this: https://github.com/openhab/openhab1-addons/issues/5751 from @rossko57. I had assumed the Expire binding could be attached to a Group Item, but it doesn’t look like it…


I would miss out step 1, and just create a new Switch group Item, to which all your original Items are also attached (a single Item can belong to multiple groups).

Group:Switch:OR(ON,OFF) gVenetianBlinds

The Expire binding config goes on your new Switch group Item.

Group:Switch:OR(ON,OFF) gVenetianBlinds { expire="2s,command=OFF" }

Then yes, add the new Switch group Item to HABPanel.

I don’t promise that this is the best way of doing this, but I think it’s the simplest method of satisfying your original requirements!

Maybe as an explanation (for better understanding), my current config looks like this:

// raffstores hierarchical grouped by direction (of type rollershutter)
Group RaffstoreControls "Raffstore-Steuerung via Gebäudeseite" <Blinds>
Group RaffstoreControlsNorth "Raffstore-Steuerung der Nordseite" <Blinds> (RaffstoreControls)
Group RaffstoreControlsEast "Raffstore-Steuerung der Ostseite" <Blinds> (RaffstoreControls)
Group RaffstoreControlsSouth "Raffstore-Steuerung der Südseite" <Blinds> (RaffstoreControls)
Group RaffstoreControlsWest "Raffstore-Steuerung der Westseite" <Blinds> (RaffstoreControls)

Rollershutter guest_raffstore_west "Raffstore Arbeitszimmer/Fenster/West" <Blinds> (Raffstores, RaffstoreControlsWest, RaffstoreLevelControlsGroundFloor, GroundFloor, GuestRoom) { channel="mqtt:topic:shelly_guest_raffstore_west:control" }
Rollershutter guest_raffstore_north "Raffstore Arbeitszimmer/Fenster/Nord" <Blinds> (Raffstores, RaffstoreControlsNorth, RaffstoreLevelControlsGroundFloor, GroundFloor, GuestRoom) { channel="mqtt:topic:shelly_guest_raffstore_north:control" }
... all the other 20 venetian blinds ("raffstore")

Currently I’m using the groups to control

  • all venetian blinds
  • venetian blinds of a specific building site (e.g. north, south, …)
  • venetian blinds of a specific level (e.g. upper floor, …)

It would be very great if I could re-use the existing item/group config. Therefore, my first idea was to add only a script which could be triggered by a widget. The script itself would be applied on

  • a single rollershutter; and/or
  • a group of rollershutters

At the moment I do the following tasks, to “open” the blinds

  • Click on a widget which triggers the UP command on a specific group
  • After nearly 2s I click on another widget which triggers the STOP command on a specific group

Unless and until:

  • one can apply a Profile to an Item without a Channel link
  • one can apply more than one Profile to an Item

The proposed approach of using a Profile to replace the binding will remain wholly inadequate. The last comment from rossko57 on that issue essentially states just this way back in June and there has been no activity on the issue and PR since then. I don’t think that it’s guaranteed that this will be implemented in OH 3 and even if it is, as I mention, it won’t be an adequate replacement for the binding for many if not most current users of the Expire binding.

The Jython drop-in replacement should work with Group Items. It’s not a binding so the issue rossko57 brings up doesn’t apply.

No, you can have more than one binding on an Item with no problems. But you need to understand that the Expire binding works on the Item’s state and I suspect you will want the Item to be in different states than just one all the time so Expire is likely not going to be a good choice here. Unless you follow Karsten’s suggestion. But if you already have to write a rule, you may as well do the Timers inside the rule anyway. See Design Pattern: Motion Sensor Timer for an example of how to create and manage timers like this.

2 Likes

Thank you!

Here is my first approach to do it via rules:

// global (constant) values
var String LOGGER = "raffstore.rules"
var String BLIND_UP = "UP"
var String BLIND_STOP = "STOP"
var String BLIND_DOWN = "DOWN"
var int TIME_TO_FULLY_OPEN = 1000 // runtime to turn blades into horizontal position (approx. 90 degree to ground)
var int TIME_TO_PARTLY_OPEN = 700 // runtime to turn blades into diagonal position (approx. 45 degree to ground)

rule "Full close of blinds in the evening"
when Time cron "0 0 21 * * ?"
    // seconds [0-59][,-*/]
    // minutes [0-59][,-*/]
    // hours [0-23][,-*/]
    // day of month [1-31][,-*?/LW]
    // month [1-12 or JAN-DEC][,-*/]
    // day of week [1-7 or SUN-SAT][,-*?/L#]
    // year [not mandatory][1970-2099][,-*/]
then
    logInfo(LOGGER, "Cron triggered to close all blinds")
    RaffstoreControls.members.forEach[ blind | blind.sendCommand(BLIND_DOWN) ]
end

rule "Open blinds in the morning"
when Time cron "0 30 6 ? * MON-FRI *"
    // seconds [0-59][,-*/]
    // minutes [0-59][,-*/]
    // hours [0-23][,-*/]
    // day of month [1-31][,-*?/LW]
    // month [1-12 or JAN-DEC][,-*/]
    // day of week [1-7 or SUN-SAT][,-*?/L#]
    // year [not mandatory][1970-2099][,-*/]
then
    logInfo(LOGGER, "Cron tiggered to open all blinds")
    RaffstoreControls.members.forEach[ blind | 
        blind.sendCommand(BLIND_UP)
        createTimer(now.plusMillis(TIME_TO_PARTLY_OPEN), [blind.sendCommand(BLIND_STOP)])
    ]
end

Now, all I need is a possibility to “manual” trigger a rule like “Open blinds in the morning”. Besides all the automation stuff, I want a Button in my HABPanel, to manual switch the blinds into that position (like the “manual override” switch outside on the starship enterprise :wink: … just a joke, it is more because of my children - they tap on the hardware switches of the blinds and do sometimes curious things with the blinds)

Note: I do not use the percentage values for positioning, because these values depend on the window height. The same blade position for a blind of a large window could be at 4 %, where a small window only need 2 %. From my point of view, this “runtime approach” is more precise and general (to reduce code lines and/or duplications)

What sort of control hardware are you using ?
Decent controllers know to drive to any percentage, including lamella tilt so you do not need timers.
Not a good idea to try emulating with rules, it’ll never be as precise as needed to remain in sync long term. Controllers can be recalibrated when needed.

No it’s the opposite. You can use a hash table or lambda to calculate the value for each window.
A couple of static code lines that is as opposed to modeling a finite state machine that easily looses state when commands don’t work or OH is restarted.

Shelly 2.5. All blinds are calibrated and I could use the calibrated positioning via percentage values. The motor itself is an Elero venetian blind motor.

Of course, that is another option. But from my point of view, it needs more lines of code and is in principle the same like position percentage (internally, these values are calculated by that way during calibration). The runtime value is equal for all blinds. But yeah … of course, there’s more than one way to skin a cat.

The best option would be something like a clinometer on the blades.

I don’t think you got my point. It isn’t about some LOC more or less, those don’t cost anything.
But it’ll be hard to make your way failsafe thus reliable in the long run, taking care of comms/device/OH outages, physical changes (blinds actually lengthen … and think repairs).

Create a Design Pattern: Unbound Item (aka Virtual Item) and use it to trigger the rule too.

THANK YOU

That solves my issue - example:

rule "Fully open blades"
when Item virtual_raffstore_controls_open_fully received command
then
    logDebug(LOGGER, "Fully open blades")
    RaffstoreControls.members.forEach[ blind | 
    blind.sendCommand(BLIND_UP)
    createTimer(now.plusMillis(TIME_TO_FULLY_OPEN), [blind.sendCommand(BLIND_STOP)])
    ]
end

where
virtual_raffstore_controls_open_fully
is the virtual item which is called by a widget.