Sonoff Dual Window Cover with set position

I used the slider-entity row: https://github.com/thomasloven/lovelace-slider-entity-row

type: entities
entities:
  - entity: cover.back_bedroom_shutter
  - entity: cover.back_bedroom_shutter
    full_row: true
    type: 'custom:slider-entity-row'

which gives:

34

I use slider-entry-row and it works perfectly. Only one problem: when I restart home assistant, the slider is setted to 0 even if the shutter is in other position. And on my sonoff dual (whit tasmota and shutter configuration) the position is right. Thers’s an automation to announce the current position that I have to call on home assistant start?
This is my cover configuration:

  - platform: mqtt
    name: "Cameretta_f"
    availability_topic: "tele/sonoffdual002/LWT"
    state_topic: "stat/sonoffdual002/RESULT"
    command_topic: "cmnd/sonoffdual002/Backlog"
    value_template: '{{ value | int }}'
    qos: 1
    retain: false
    payload_open: "ShutterOpen1"
    payload_close: "ShutterClose1"
    payload_stop: "ShutterStop1"
    state_open: "ON"
    state_closed: "OFF"
    payload_available: "Online"
    payload_not_available: "Offline"
    optimistic: false
    set_position_topic: "cmnd/sonoffdual002/ShutterPosition1"
    position_topic: "stat/sonoffdual002/SHUTTER1"

Hi all, today I will receive my Sonoff Dual and I will setup this project, so thanks for sharing!

This is al very new for me and I am still a bit concerned about a possible short circuit and breaking the motor. I know that power1 OFF is being published before power2 ON, but what if something is wrong with publishing power1 OFF? Then power2 ON should not be published. Is this possible or should I trust HA for 100% publishing them in the right order?

There is an interlock option for both solutions which only enables one relay at a time, though in my motor if both are pressed it just stops.

Thanks, I founfd it! Very useful

Hi, I’m trying to enter the availability_template command but I’m getting an error. Can you help me?

  - platform: template
    covers:
      window_cover_cucina:
        friendly_name: "Cucina"
        availability_template: 'tapparella/status'
        position_template: "{{ (((states.input_number.window_position_cucina.state | int) * 100)/39 | int) }}"
        open_cover:
          - service: mqtt.publish
            data:
              topic: 'tapparella/switch/tenda_cucina_giu/command'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'tapparella/switch/tenda_cucina_su/command'
              payload: 'ON'
        close_cover:
          - service: mqtt.publish
            data:
              topic: 'tapparella/switch/tenda_cucina_su/command'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'tapparella/switch/tenda_cucina_giu/command'
              payload: 'ON'
        stop_cover:
          - service: mqtt.publish
            data:
              topic: 'tapparella/switch/tenda_cucina_su/command'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'tapparella/switch/tenda_cucina_giu/command'
              payload: 'OFF'

this setup could be also valid to XIAOMI AQARA ZIGBEE to control covers?

autoanswer, yes it’s working… !!!
but i have some issues with the "set_position! but im working in progress to fix it.

@bkbilly thank you so much for this very intested post! very usefull

in my case, seems that everything is working fine but I have some problem with command timer. when I turn down the blind and stop halfway then when I start to go down again it does not start from the time that remained. it’s starting from the total timer configured… i have the comand recorder configured…

any idea why is not recording the timers?

thanks!

Hello takezo,

I’m interesting by your work can you share it ? please
Did you find the issue concerning timer ?
in my case several bug appear.

Thank you for your help.

sorry for replying so late … Here it’s the setup i have implemented :

configuration.yaml:

timer:
    window_1_up:
    duration: '00:00:30'
  window_1_down:
    duration: '00:00:30'


input_number:
  window_1_position:
    name: "Window Position"
#    initial: 100
    min: 0
    max: 100
    step: 1
  window_1_set_position:
    name: "Window Set Position"
#    initial: 100
    min: 0
    max: 100
    step: 1

#MQTT Xiaomi Zigbee
switch:

  - platform: "mqtt"
    state_topic: "zigbee2mqtt/0x00158d0003e82ee9"
    availability_topic: "zigbee2mqtt/bridge/state"
    payload_off: "OFF"
    payload_on: "ON"
    value_template: "{{ value_json.state_l1 }}"
    command_topic: "zigbee2mqtt/0x00158d0003e82ee9/l1/set"

  - platform: "mqtt"
    state_topic: "zigbee2mqtt/0x00158d0003e82ee9"
    availability_topic: "zigbee2mqtt/bridge/state"
    payload_off: "OFF"
    payload_on: "ON"
    value_template: "{{ value_json.state_l2 }}"
    command_topic: "zigbee2mqtt/0x00158d0003e82ee9/l2/set"    


cover:

  - platform: template
    covers:
      window_1_cover:
        friendly_name: "Cover door"
        position_template: "{{ (states.input_number.window_1_position.state | int) }}"
        open_cover:
          - service: mqtt.publish
            data:
              topic: 'zigbee2mqtt/0x00158d0003e82ee9/l1/set'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'zigbee2mqtt/0x00158d0003e82ee9/l2/set'
              payload: 'ON'
        close_cover:
          - service: mqtt.publish
            data:
              topic: 'zigbee2mqtt/0x00158d0003e82ee9/l2/set'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'zigbee2mqtt/0x00158d0003e82ee9/l1/set'
              payload: 'ON'
        stop_cover:
          - service: mqtt.publish
            data:
              topic: 'zigbee2mqtt/0x00158d0003e82ee9/l2/set'
              payload: 'OFF'
          - service: mqtt.publish
            data:
              topic: 'zigbee2mqtt/0x00158d0003e82ee9/l1/set'
              payload: 'OFF'

automations.yaml

- id: '301'
  alias: window_1 - MQTT Button1 OFF (up)
  trigger:
  - payload: 'OFF'
    platform: mqtt
    topic: zigbee2mqtt/0x00158d0003e82ee9/l2/set
  action:
  - service: timer.cancel
    entity_id: timer.window_1_up
  - service: input_number.set_value
    data_template:
      entity_id: input_number.window_1_set_position
      value: >-
          {{ states.input_number.window_1_position.state }}
- id: '302'
  alias: window_1 - MQTT Button2 OFF (down)
  trigger:
  - payload: 'OFF'
    platform: mqtt
    topic: zigbee2mqtt/0x00158d0003e82ee9/l1/set
  action:
  - service: timer.cancel
    entity_id: timer.window_1_down
  - service: input_number.set_value
    data_template:
      entity_id: input_number.window_1_set_position
      value: >-
          {{ states.input_number.window_1_position.state }}
- id: '303'
  alias: window_1 - Timer stopped
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.window_1_up
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.window_1_down
  action:
  - service: cover.stop_cover
    data:
      entity_id: cover.window_1_cover
- id: '311'
  alias: window_1 - MQTT Button1 ON (up)
  trigger:
  - payload: 'ON'
    platform: mqtt
    topic: zigbee2mqtt/0x00158d0003e82ee9/l2/set
  condition:
    condition: template
    value_template: '{{ as_timestamp(now()) - as_timestamp(states.input_number.window_1_set_position.last_updated) > 3 }}'
  action:
  - service: timer.start
    data:
      duration: 00:00:30
    entity_id: timer.window_1_up
- id: '312'
  alias: window_1 - MQTT Button2 ON (down)
  trigger:
  - payload: 'ON'
    platform: mqtt
    topic: zigbee2mqtt/0x00158d0003e82ee9/l1/set
  condition:
    condition: template
    value_template: '{{ as_timestamp(now()) - as_timestamp(states.input_number.window_1_set_position.last_updated) > 3 }}'
  action:
  - service: timer.start
    data:
      duration: 00:00:30
    entity_id: timer.window_1_down
- id: '411'
  alias: window_1 - Position UP
  trigger:
    platform: time_pattern
    seconds: '/1'
  condition:
    condition: state
    entity_id: timer.window_1_up
    state: active
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.window_1_position
      value: >-
          {% set step=100/30 %}
          {% if (states.input_number.window_1_position.state | float + step) < 100 %}
            {{ states.input_number.window_1_position.state | float + step | int }}
          {% else %}
            100
          {% endif %}
- id: '412'
  alias: window_1 - Position Down
  trigger:
    platform: time_pattern
    seconds: '/1'
  condition:
    condition: state
    entity_id: timer.window_1_down
    state: active
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.window_1_position
      value: >-
          {% set step=100/30 %}
          {% if (states.input_number.window_1_position.state | float - step) > 0 %}
            {{ states.input_number.window_1_position.state | float - step | int}}
          {% else %}
            0
          {% endif %}
- id: '511'
  alias: window_1 - Set Position Down
  trigger:
    platform: state
    entity_id: input_number.window_1_set_position
  condition:
    condition: template
    value_template: >-
        {{ (states.input_number.window_1_position.state | int) >
           (states.input_number.window_1_set_position.state | int) }}
  action:
  - service: timer.start
    data_template:
      entity_id: timer.window_1_down
      duration: >-
          {{ '00:00:%02d' | format(((
              (states.input_number.window_1_position.state | int) - 
              (states.input_number.window_1_set_position.state | int)
             ) * 33 /100) | int | abs )
          }}
  - service: cover.close_cover
    data:
      entity_id: cover.window_1_cover
- id: '512'
  alias: Window_1 - Set Position UP
  trigger:
    platform: state
    entity_id: input_number.window_1_set_position
  condition:
    condition: template
    value_template: >-
        {{ (states.input_number.window_1_position.state | int) <
           (states.input_number.window_1_set_position.state | int) }}
  action:
  - service: timer.start
    data_template:
      entity_id: timer.window_1_up
      duration: >-
          {{ '00:00:%02d' | format(((
              (states.input_number.window_1_position.state | int) - 
              (states.input_number.window_1_set_position.state | int)
             ) * 30 /100) | int | abs )
          }}
  - service: cover.open_cover
    data:
      entity_id: cover.window_1_cover

As I said, everything works well: it goes up, it goes down correctly according to the automation but the manual option does not work and it does not save position if I stop at 30%

any support for this will be welcome!!

Hey all!

First, big thanks to all on the forum for sharing your experiences and knowledge. I am quite fresh in HA…I managed to configure my sonoffs and other devices and I have few Dual R2 for blinds with physical switches…and now the question: on this diagram is live wire from mains? I had to ask because I will wire it and don’t want to burn the module…

Thanks!!

Thanks

The buttons are not connected to the mains.
The only live wires are on the right side of the diagram. The Red is the mains (220v), Blue Neutral, and the Black/Brown controls the motor for the blinds. The Green one I don’t know why is on the diagram, but my blinds don’t have this extra wire.
As long as you put the Neutral and Line on the correct place, you won’t fry anything.

Thanks Basilis!
But how exactly works button on board?

I connected with physical switch (1-0-2) (it’s a switch not a push button) and if I press on 1 - nothing happens, then if I put switch back to 0 the motor goes up. To stop the motor I have to put switch back to 1 and then back to 0…
Does anyone have a hint how to have sonoff r2 dual with physical switch (1-0-2) - my wife will go crazy if I change switches to touch :upside_down_face:

You can’t have any blinds with switches because you risk on destroying the motor and if it is how you found them, someone didn’t know their job.
I would recommend changing them into buttons. No need to have touch buttons, just the regular ones for blinds. They look like switches but they recoil once you let go.

Thank you!! I finally managed it, I found buttons with the same design…and it works! You were right,it could burn motors…
Now I can proceed to phase 2…cover and position :grin:.

One stupid question…since I’m a noob…
I’m using sonoffs (not flashed to Tasmota) with AlexxIT/SonoffLAN in HA…and before even trying your great project for cover with set position, … would it even work since there is no MQTT?

I didn’t know about this project. Seems interesting.
As for your question, I think that with a few modifications it can be achieved.
I would recommend though to leave everything as it is and create some automations that send status of each button change to an MQTT server and listen to the specific events.
This is just a draft to get an idea of what I am talking about:

- alias: Button1_Changed_on
  trigger:
    - platform: state
      entity_id: switch.button1
      to: 'on'
  action:
    - service: mqtt.publish
      data:
        topic: stat/window_1/POWER1
        payload: 'on'
- alias: Button1_Set_on
  trigger:
    - platform: mqtt
      topic: cmnd/window_1/power1
      payload: 'OFF'
  action:
    - service: switch.turn_on
      entity_id: switch.button1

You should create 2 more for button2.

1 Like

Thanks! Tried with mqtt, success! Now have to configure buttons with power in right way, something changed when I adjusted code to my sonoff’s…

Pretty new in Home Assistant, I’ve been struggling for days to implement this in my setup (not for it being complicated but for my lack of knowledge).

Finally, I got it working and with configuration splitted into several files, but I am having a little problem:

I don’t know how to exactly calibrate the seconds that the blind is going up or down. Let me please explain:

I have a sonoff dual r3 device, flashed with tasmota, changed to be seen as a blind controller. I set pulsetime1 & pulsetime 2 to 120 (just testing, attached to nothing).

Then I go to automations.yaml (as a matter of fact, I go to my “ventana1.yaml” file inside the automation folder) and change every “16” by a “20”. Reboot the machine (just in case), and try the “down” button.

Now in “window 1 down” it starts a count down from 24, which suddenly stops at 5. Window Position stops at “5,0”, and both arrows remain enabled as it didn’t go to 0.

Could you please help me figure out which numbers should I use, and if I have to do it in tasmota console, in automations.yaml, both, etc.?

Thanks.