Sonoff Dual Window Cover with set position

With your alternative I still get the error in the logs: “Invalid value: 26.0 (range 0.0 - 25.0)” (and the complementary when the value reaches below 0.0)

Anyway, thank you for the suggestion!

You are correct. My bad.

Perhaps:

value: {{ [states.input_number.window_position.state | int) + 1 , 18] | min }}

for ‘411’ and

value: {{ [states.input_number.window_position.state | int - 1 , 0] | max }}

for ‘412’

is more concise.

Forgive me. I’m always trying to make code as short as possible.

Thank you very much for sharing. It helped me a lot. I have already set up two window covers with it.

But that got me to my next problem.

What do I have to do to let my window covers run for only 10 seconds for example… only to get to the half-position?

My Covers take 24 seconds to be completly closed. But I would want to have a setting that only closes them by half.

I tried a script closing the covers… wait for 10 seconds and than execute a stop command. But it did not work. Obviously covers_close means all the way down.

So I am wondering if it would work when I automatically set the “input_number.window_set_position” value to 50.

But I haven’t figured out how to set it to a predefined value.

Thx a lot. Greetings.

Thank you very much: this code is awesome!!! :grinning:

I have different times : 46 seconds up to down, 48 down to up.
I used 46 all over the place and 2 seconds are really missing.
Can someone help me telling where to use 48 ?

Thanks

FYI. you have some typos there.

I used your mods but could only get it to work / pass config check like below

value: “{{ (states.input_number.window_position.state | int + 1 , 18) | min }}”
for 411
and
value: “{{ (states.input_number.window_position.state | int + 1 , 18) | min }}”
for 412

Hi

‘411’ section is for UP/open
‘412’ section is for Down/close

Correct.

There was an extra ‘)’ in the ‘411’ bit.

“…wait for 10 seconds and than execute a stop command. But it did not work. Obviously covers_close means all the way down…”

Did you use the ‘cover.stop_cover’ to stop after 10 seconds? It’s not clear from the statement above.

Guys,

I’ve copied the original code and made the suggestions from @PierreScerri.
Changed the 18 seconds to my own duration (45 seconds).

In the beginning the Window Position was updating, but now it’s not updating anymore. Had this issue on 0.75 - 0.75.1 and 0.75.2. Don’t know if it appeared when moving from 0.74. Does anyone has the same issue?

Excellent solution!

I added support In HomeKit for custom position by adding set_cover_position support
Add this in configuration.yaml

set_cover_position:
          - service: input_number.set_value
            entity_id: input_number.window_set_position
            data_template:
              value: '{{ position }}'
icon_template: >-
          {% if (states.input_number.window_position.state | int) > 0 %}
            mdi:window-open
          {% else %}
            mdi:window-closed
          {% endif %}

Just a question…what hardware do u guys here for the blinds motor . Would like to add those to my house and system …I also want to add physical buttons for my wife …wife acceptance is very important

First of all, thank the creator of the code for the work.

Second, I wonder if you can share the structure to follow to sort the blinds like this, I’m a bit new to this and I want to do it like you.
I tried to stop seeing the clocks and I did not get it either.
Thank you
*sorry for my engish, i help me with traductor.

I found this diagram online that should help with the wiring.
It is exactly how I wired my window cover.
The switch changes the states of the relays in the Line Out 1 & 2.

1 Like

To get the structure to sort the blinds, I used ‘groups’.

Define a group for each set of entities that you would like grouped together like so:

sitting_room_shutters:
  name: Sitting Room
  view: no
  entities:
    - cover.sitting_room_front_shutter
    - input_number.sitting_room_front_shutter_position
    - cover.sitting_room_door_shutter
    - input_number.sitting_room_door_shutter_position
    - cover.sitting_room_back_shutter
    - input_number.sitting_room_back_shutter_position

Then add the groups to a view like so:

shutters_view:
  name: Shutters
  view: yes
  entities:
    - group.bedroom_shutters
    - group.sitting_room_shutters
    - group.dining_room_shutters
    - group.other_shutters

All this goes in a file called groups.yaml in the same folder as the configuration.yaml. (create it if it is not there)

Put this line:

group: !include groups.yaml

in your configuration.yaml

Check Config and restart.

Hi. I’ve tried a bit and I think I have a lot of things to do besides these.

I have currently operating 1 shutter with the code of the first post.

In config.yaml, I have the windows and time position. I think I should get it out of there but as soon as I play some time the blind never stops sending a signal.

I think I should integrate this into covers?

And on the other hand I think that the file automatitions.yaml, should I redo it for each one of the blinds? ** I do not understand the ration between covers or groups and automations. That is to say in autamations we have id301 but nowhere do I see where that id is called to make it work.
I’m very new with this,

Could you hit me all the files that are related to the blinds? or by message if it is very large. I think I do not do it.

Thank you

Hi

You can put everything in the configuration.yaml if you like, but this gets very big, very messy, very quickly.

You would be better off splitting it into multiple files. There is ample documentation on this in the Home-Assistant help files. It may prove tricky at first but it can be done.

A cover is a component of HA like switch, sensor

An automation reacts to events to make things happen. The automation ID is used by HA.

A group is a way to put entities in one place eg on the frontend of HA.

My configuration.yaml contains these references:

group: !include groups.yaml
automation: !include automations.yaml
automation old: !include_dir_merge_list automation/
cover: !include covers.yaml
input_number: !include input_numbers.yml
timer: !include timers.yml

In the CONFIG folder create files that you need (if not already there):

covers.yaml (contains all cover definitions)
input_numbers.yaml (contains all input_number definitions)
groups.yaml
timers.yaml (contains all timer definitions)
etc

Also, it you have multiple covers you need automations for each cover.
I made a folder ‘automation’ that contains the automations for each cover (see screen grab).
Each of these files contains the automation for each cover.
Each cover will have a different entity_id and the automations have to be unique for that cover.

This is my master_bedroom_shutter.yaml for example:

- id: '301'
  alias: Master Bedroom - MQTT Button1 OFF (up)
  trigger:
  - payload: 'OFF'
    platform: mqtt
    topic: stat/sonoff03/POWER1
  action:
  - service: timer.cancel
    entity_id: timer.master_bedroom_shutter_up

- id: '302'
  alias: Master Bedroom - MQTT Button2 OFF (down)
  trigger:
  - payload: 'OFF'
    platform: mqtt
    topic: stat/sonoff03/POWER2
  action:
  - service: timer.cancel
    entity_id: timer.master_bedroom_shutter_down

- id: '303'
  alias: Master Bedroom - Timer stopped
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.master_bedroom_shutter_up
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.master_bedroom_shutter_down
  action:
  - service: cover.stop_cover
    entity_id: cover.master_bedroom_shutter

- id: '311'
  alias: Master Bedroom - MQTT Button1 ON (up)
  trigger:
  - payload: 'ON'
    platform: mqtt
    topic: stat/sonoff03/POWER1
  action:
  - service: timer.start
    data:
      duration: 00:00:16
    entity_id: timer.master_bedroom_shutter_up

- id: '312'
  alias: Master Bedroom - MQTT Button2 ON (down)
  trigger:
  - payload: 'ON'
    platform: mqtt
    topic: stat/sonoff03/POWER2
  action:
  - service: timer.start
    data:
      duration: 00:00:16
    entity_id: timer.master_bedroom_shutter_down

- id: '411'
  alias: Master Bedroom - Position UP
  trigger:
    platform: time
    seconds: '/1'
  condition:
    condition: state
    entity_id: 'timer.master_bedroom_shutter_up'
    state: 'active'
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.master_bedroom_shutter_position
      value: "{{ states.input_number.master_bedroom_shutter_position.state | int + 1 }}"

- id: '412'
  alias: Master Bedroom - Position Down
  trigger:
    platform: time
    seconds: '/1'
  condition:
    condition: state
    entity_id: 'timer.master_bedroom_shutter_down'
    state: 'active'
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.master_bedroom_shutter_position
      value: "{{ states.input_number.master_bedroom_shutter_position.state | int - 1 }}"

#- id: '511'
#  alias: Master Bedroom - Set Position Down
#  trigger:
#    platform: state
#    entity_id: input_number.master_bedroom_shutter_set_position
#  condition:
#    condition: template
#    value_template: "{{ (states.input_number.master_bedroom_shutter_position.state | int) > ((((states.input_number.master_bedroom_shutter_set_position.state | int ) * 16 )/100) | int) }}"
#  action:
#  - service: timer.start
#    data_template:
#      entity_id: timer.master_bedroom_shutter_down
#      duration: "{{ '00:00:%02d' | format( ((states.input_number.master_bedroom_shutter_position.state | int) - ((((states.input_number.master_bedroom_shutter_set_position.state | int ) * 16 )/100) | int) ) | abs ) }}"
#  - service: cover.close_cover
#    entity_id: cover.master_bedroom_shutter
#
#- id: '512'
#  alias: Master Bedroom - Set Position UP
#  trigger:
#    platform: state
#    entity_id: input_number.master_bedroom_shutter_set_position
#  condition:
#    condition: template
#    value_template: "{{ (states.input_number.master_bedroom_shutter_position.state | int) < ((((states.input_number.master_bedroom_shutter_set_position.state | int ) * 16 )/100) | int) }}"
#  action:
#  - service: timer.start
#    data_template:
#      entity_id: timer.master_bedroom_shutter_up
#      duration: "{{ '00:00:%02d' | format( ((states.input_number.master_bedroom_shutter_position.state | int) - ((((states.input_number.master_bedroom_shutter_set_position.state | int ) * 16 )/100) | int) ) | abs ) }}"
#  - service: cover.open_cover
#    entity_id: cover.master_bedroom_shutter

I am not using the Set_position feature and that is why the code is commented out. I have also removed some of the code from the original as it is not useful to me.

This is the input_number.yaml for that cover:

master_bedroom_shutter_position:
  name: "Position"
  min: 0
  max: 16

and the timers.yaml:

master_bedroom_shutter_up:
master_bedroom_shutter_down:

You need to change all MQTT topics, aliases, entity_id’s, timer durations, etc., for each cover. Don’t forget the duration in ‘value_template’ in id511 & id 512. If you compare my files with the original you will see the differences.

Do 1 cover first. Get it working as you wish, then duplicate all the automations for each cover in a new yaml and do all the config changes one cover at a time. Use a sensible and clear naming strategy to help avoid confusion. It’s a long, tedious job.

Make sure that the first cover you do is working properly before duplicating.

Happened to me and had to edit all the automations for 11 covers. That’s 99 automations. Boring.

Hope this helps.

1 Like

Thank you very much for your answer.

I undestardand with this “tutorial” a lot of things.

I go to start work with this, thank you thank you thank you :slight_smile:

Hi Pierre,

I have it working but i have problems, i think is a code error easy but i dont look it.
The blind up / down but never stop. When timer finish the relay no stop. And when i adjust the set position bar nothing happens in the blind (in menu yes, timers start count and the bar move)

I paste all the codes that have to do with the blind.

configuration.yaml

group: !include groups.yaml
automation: !include automations.yaml
automation old: !include_dir_merge_list automation/
script: !include scripts.yaml
cover: !include cover.yaml
switch: !include switch.yaml
timer: !include timers.yaml
input_number: !include input_numbers.yaml

timers.yaml

persiana_salon_pequena_up:
  duration: '00:00:16'
persiana_salon_pequena_down:
  duration: '00:00:16'

input_numbers.yaml

persiana_salon_pequena_position:
  name: "Posición persiana"
  initial: 5
  min: 0
  max: 16
persiana_salon_pequena_set_position:
  name: "Ajustar posición persiana"
  initial: 5
  min: 0
  max: 100 

groups.yaml

persianas_salon:
  name: Salón
  view: no
  entities:
  - cover.persiana_salon_pequena
  - input_number.persiana_salon_pequena_position
  - input_number.persiana_salon_pequena_set_position

shutters_view:
  name: Persianas
  view: yes
  entities:
    - group.persianas_salon

cover.yaml

- platform: template
  covers:
     persiana_salon_pequena:
        friendly_name: "Salón pequeña"
        position_template: "{{ (((states.input_number.persiana_salon_pequena_position.state | int) * 100)/16 | int) }}"
        open_cover:
          - service: mqtt.publish
            data:
              topic: 'cmnd/sonoff_d1/power2'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'cmnd/sonoff_d1/power1'
              payload: 'ON'
        close_cover:
          - service: mqtt.publish
            data:
              topic: 'cmnd/sonoff_d1/power1'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'cmnd/sonoff_d1/power2'
              payload: 'ON'
        stop_cover:
          - service: mqtt.publish
            data:
              topic: 'cmnd/sonoff_d1/power1'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'cmnd/sonoff_d1/power2'
              payload: 'OFF' 

and persiana_salon_pequena.yaml (inside dir automation)

- id: '301'
  alias: Window - MQTT Button1 OFF (up)
  hide_entity: True
  trigger:
  - payload: 'OFF'
    platform: mqtt
    topic: stat/sonoff_d1/POWER1
  action:
  - service: timer.cancel
    entity_id: timer.persiana_salon_pequena_up

- id: '302'
  alias: Window - MQTT Button2 OFF (down)
  hide_entity: True
  trigger:
  - payload: 'OFF'
    platform: mqtt
    topic: stat/sonoff_d1/POWER2
  action:
  - service: timer.cancel
    entity_id: timer.persiana_salon_pequena_down

- id: '303'
  alias: Window - Timer stopped
  hide_entity: True
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.persiana_salon_pequena_up
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.persiana_salon_pequena_down
  action:
  - service: cover.stop_cover
    data:
      entity_id: cover.persiana_salon_pequena_cover

- id: '311'
  alias: Window - MQTT Button1 ON (up)
  hide_entity: True
  trigger:
  - payload: 'ON'
    platform: mqtt
    topic: stat/sonoff_d1/POWER1
  condition:
    condition: template
    value_template: '{{ as_timestamp(now()) - as_timestamp(states.input_number.persiana_salon_pequena_set_position.last_updated) > 3 }}'
  action:
  - service: timer.start
    data:
      duration: 00:00:16
    entity_id: timer.persiana_salon_pequena_up

- id: '312'
  alias: Window - MQTT Button2 ON (down)
  hide_entity: True
  trigger:
  - payload: 'ON'
    platform: mqtt
    topic: stat/sonoff_d1/POWER2
  condition:
    condition: template
    value_template: '{{ as_timestamp(now()) - as_timestamp(states.input_number.persiana_salon_pequena_set_position.last_updated) > 3 }}'
  action:
  - service: timer.start
    data:
      duration: 00:00:16
    entity_id: timer.persiana_salon_pequena_down

- id: '411'
  alias: Window - Position UP
  hide_entity: True
  trigger:
    platform: time
    seconds: '/1'
  condition:
    condition: state
    entity_id: 'timer.persiana_salon_pequena_up'
    state: 'active'
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.persiana_salon_pequena_position
      value: "{{ (states.input_number.persiana_salon_pequena_position.state | int) + 1 }}"

- id: '412'
  alias: Window - Position Down
  hide_entity: True
  trigger:
    platform: time
    seconds: '/1'
  condition:
    condition: state
    entity_id: 'timer.persiana_salon_pequena_down'
    state: 'active'
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.persiana_salon_pequena_position
      value: "{{ (states.input_number.persiana_salon_pequena_position.state | int) - 1 }}"

- id: '511'
  alias: Window - Set Position Down
  hide_entity: True
  trigger:
    platform: state
    entity_id: input_number.persiana_salon_pequena_set_position
  condition:
    condition: template
    value_template: "{{ (states.input_number.persiana_salon_pequena_position.state | int) > ((((states.input_number.persiana_salon_pequena_set_position.state | int ) * 16 )/100) | int) }}"
  action:
  - service: timer.start
    data_template:
      entity_id: timer.persiana_salon_pequena_down
      duration: "{{ '00:00:%02d' | format( ((states.input_number.persiana_salon_pequena_position.state | int) - ((((states.input_number.persiana_salon_pequena_set_position.state | int ) * 16 )/100) | int) ) | abs ) }}"
  - service: cover.close_cover
    data:
      entity_id: cover.persiana_salon_pequena_cover

- id: '512'
  alias: Window - Set Position UP
  hide_entity: True
  trigger:
    platform: state
    entity_id: input_number.persiana_salon_pequena_set_position
  condition:
    condition: template
    value_template: "{{ (states.input_number.persiana_salon_pequena_position.state | int) < ((((states.input_number.persiana_salon_pequena_set_position.state | int ) * 16 )/100) | int) }}"
  action:
  - service: timer.start
    data_template:
      entity_id: timer.persiana_salon_pequena_up
      duration: "{{ '00:00:%02d' | format( ((states.input_number.persiana_salon_pequena_position.state | int) - ((((states.input_number.persiana_salon_pequena_set_position.state | int ) * 16 )/100) | int) ) | abs ) }}"
  - service: cover.open_cover
    data:
      entity_id: cover.persiana_salon_pequena_cover

Its all, i dont find the problem.

** your timer.yaml and input numbers.yaml (not finish in .yaml, finish in .yml, its an error or why?

Thank you

Go to the web interface of the sonoff by typing its IP address in a browser. Click ‘console’. Type pulsetime1 116 and then pulsetime2 116. This will switch off the relays after 16 seconds.

Yaml or yml doesn’t matter as long as it is the same in the !include command and the actual file name.

I use text wrangler to edit yaml/yml files. It uses yml.

1 Like