I’ve put together a bit of a script to be able to set the position of an RF blind, I’m using a Dooya RF blind with up, down, and stop commands set up as switches using a Broadlink RM Pro.
I tried the ‘timedcover’ mentioned elsewhere in the forum, it works, but the problem I came across is it doesn’t ‘reset’, so the calibration slowly falls out of wack as setting 0 or 100 doesn’t fully open or close the blind. There’s a few mentions of using similar scripts, but I couldn’t find anything quite complete enough to use.
This can probably be fixed more elegantly in a component, but this works for me. It’s a script with a few smarts to track and set the blind position anywhere within 1-99%, setting either 0 or 100% tells it to simply open all the way, or close all the way, regardless of where it thinks the blind is.
The biggest limitation is that it doesn’t handle multiple commands. If you start trying to change the blind position while it’s operating, you’re going to have a bad time.
There’s a few parts to it, first, the template cover (which passes some info to let the script be generic).
cover:
- platform: template
covers:
blind_bedroom:
friendly_name: 'Bedroom Blind'
position_template: "{{ states('input_number.blind_bedroom_position') }}"
open_cover:
service: switch.turn_on
entity_id: switch.blind_bedroom
close_cover:
service: switch.turn_off
entity_id: switch.blind_bedroom
stop_cover:
service: switch.turn_on
entity_id: switch.blind_bedroom_stop
set_cover_position:
service: script.set_cover_position
data_template:
position_set: '{{ position }}'
position_previous: 'input_number.blind_bedroom_position'
entity_id: 'cover.blind_bedroom'
opening_time: 35.6
closing_time: 35.6
We also need an input_number to track the position of the blind:
input_number:
blind_bedroom_position:
name: Bedroom Blind Position
unit_of_measurement: '%'
min: 0
max: 100
step: 1
And the script, this has been set up to be generic (and takes some variables from the cover’s data_template).
script:
set_cover_position:
sequence:
- service_template: >
{% if position_set | float == 0 %}
cover.close_cover
{% elif position_set | float == 100 %}
cover.open_cover
{% elif position_set | float == states(position_previous) | float %}
script.dummy
{% elif position_set | float > states(position_previous) | float %}
cover.open_cover
{% elif position_set | float < states(position_previous) | float %}
cover.close_cover
{% endif %}
data_template:
entity_id: "{{ entity_id }}"
- delay:
seconds: >
{% if position_set | float == 0 %}
{{ ( states(position_previous) | float / 100 * closing_time | round ) | int }}
{% elif position_set | float == 100 %}
{{ ( ( 100 - states(position_previous) | float ) / 100 * opening_time | round ) | int }}
{% elif position_set | float > states(position_previous) | float %}
{{ (( position_set | float - states(position_previous) | float ) / 100 * opening_time | round ) | int }}
{% elif position_set | float < states(position_previous) | float %}
{{ (( states(position_previous) | float - position_set | float ) / 100 * closing_time | round ) | int }}
{% endif %}
- service_template: >
{% if position_set | float == 0 %}
cover.close_cover
{% elif position_set | float == 100 %}
cover.open_cover
{% elif position_set | float > states(position_previous) | float %}
cover.stop_cover
{% elif position_set | float < states(position_previous) | float %}
cover.stop_cover
{% endif %}
data_template:
entity_id: "{{ entity_id }}"
- service: input_number.set_value
data_template:
entity_id: "{{ position_previous }}"
value: "{{ position_set }}"