Como criar um cover para estores com indicação e controlo da percentagem de abertura aproximada [DESACTUALIZADO]

Versão actualizada e mais completa: 📑 MadBlinds v2 - Como Controlares os estores eléctricos e "estimares" a sua posição (Desactualizado) - #3
(editado para incluir possibilidade de tempos diferentes para subida e descida)

(nova edição - alterada forma como é feito o delay pelo slider para que possa "incluir" décimos de segundo e seja "imune" a lag de comunicação entre HA e sonoff)

(mais uma pequena correcção de bugs para ligar com possíveis delays de comunicação...)

Como o título indica, esta é uma configuração que fiz para ter cover de estores com indicação de percentagem de abertura estimada e possibilidade de escolher a percentagem de abertura (alterando o valor directamente no slider)…

Acabou por ficar bastante complexa, mas, após muitos testes, parece-me estar a funcionar bem…

Os pressupostos são os seguintes:

  • Sonoff dual ou equivalente com firmware tasmota
  • no exemplo o estore demora ligeiramente menos de 10 segundos a fechar completamente
    (é aconselhavel configurar no tasmota o powerretain off)

De uma forma simplista:
Raciocínio 1 - o estore demora 10 segundos a fechar portanto, se os relés estiverem activos apenas durante uma fracção desse tempo, o estore abriu apenas X%. Se, em seguida se activar o relé mais algum tempo, o estore está agora aberto X+Y%. Para abrir aplica-se o mesmo.
raciocínio 2 - ao escolher a percentagem no slider, a diferença de percentagens corresponde à activação do relé por X segundos.

Passos:

  • definir um pulsetime de 10s para os relés (o valor pode ser igual para os 2 ou não - mudar de acordo com o tempo que o vosso demora - convém 2 ou 3 segundos mais) no tasmota digitando na consola dele (sem as aspas): “pulsetime1 100” (para o relé de subida) e “pulsetime2 100” (para o relé de descida); definir “setoption14 on”, para activar interlocking; “poweronstate 0”, “powerretain1 off” e “powerretain2 off”!

  • criar um “package” no home assistant com o código seguinte ou “encaixar” na configuração os seguintes componentes, alterando “apenas” o valor inicial dos input_text tempodeabertura e tempodefecho com o tempo de abertura e de fecho do vosso e os tópicos para os vossos (aconselhável usar a função “subtituir tudo” do vosso editor para trocar “wemosd1mini” pelo tópico do vosso sonoff). Por fim, colocar num grupo o cover.persiana e o input_number.aberturapersiana…

    input_text:
    #Alterar "inicial" para o valor em segundos que o estore demora a abrir desde a posição fechada e vice-versa nos input_text tempodeabertura e tempodefecho.
      tempodeabertura:
        name: tempo de maximo de abertura
        initial: 10
      tempodefecho:
        name: tempo de maximo de fecho
        initial: 10
      iniciofecho:
        name: iniciofecho
      inicioabertura:
        name: inicioabertura
    
    cover:
      - platform: template
        covers:
          persiana:
            friendly_name: "Persiana"
            position_template: '{{ states.input_number.aberturapersiana.state }}'
            open_cover:
              - service: mqtt.publish
                data:
                  topic: 'cmnd/wemosd1mini/POWER1'
                  payload: 'ON'
            close_cover:
              - service: mqtt.publish
                data:
                  topic: 'cmnd/wemosd1mini/POWER2'
                  payload: 'ON'
            stop_cover:
              - service: mqtt.publish
                data:
                  topic: 'cmnd/wemosd1mini/Backlog'
                  payload: 'POWER1 OFF; POWER2 OFF'
    
    binary_sensor:
      - platform: mqtt
        name: rele 1
        state_topic: "stat/wemosd1mini/POWER1"
        payload_on: "ON"
        payload_off: "OFF"
      - platform: mqtt
        name: rele 2
        state_topic: "stat/wemosd1mini/POWER2"
        payload_on: "ON"
        payload_off: "OFF"
    
    input_boolean:
      alterarslider:
        name: Alterar o slider
        initial: on
    
    input_number:
      aberturapersiana:
        name: Abertura
        min: 0
        max: 100
        step: 1
        unit_of_measurement: '%'
        icon: mdi:blinds
      aberturapersianaold:
        name: valor antigo de abertura
        min: 0
        max: 100
        step: 1
        unit_of_measurement: '%'
    
    automation:
      - id: iniciofecho
        alias: começou a fechar
        trigger:
        - platform: state
          entity_id: binary_sensor.rele_2
          to: 'on'
        action:
          service: input_text.set_value
          data_template:
            entity_id: input_text.iniciofecho
            value: '{{ now() }}'
      - id: fimfecho
        alias: parou de fechar
        trigger:
        - platform: state
          entity_id: binary_sensor.rele_2
          to: 'off'
        condition:
        - condition: state
          entity_id: 'input_boolean.alterarslider'
          state: 'on'
        action:
        - service: input_number.set_value
          data_template:
            entity_id: input_number.aberturapersianaold
            value: >-
              {% if (states.input_number.aberturapersiana.state)|int - ((as_timestamp(now()) - (as_timestamp(states.input_text.iniciofecho.state))|float|round(2))*100/(states.input_text.tempodefecho.state|int))|int < 4 %}
                0
              {% else %}
                {{ (states.input_number.aberturapersiana.state)|int - ((as_timestamp(now()) - (as_timestamp(states.input_text.iniciofecho.state))|float|round(2))*100/(states.input_text.tempodefecho.state|int))|int }}
              {% endif %}
        - service: input_number.set_value
          data_template:
            entity_id: input_number.aberturapersiana
            value: '{{ states.input_number.aberturapersianaold.state }}'
      - id: inicioabertura
        alias: começou a abrir
        trigger:
        - platform: state
          entity_id: binary_sensor.rele_1
          to: 'on'
        action:
          service: input_text.set_value
          data_template:
            entity_id: input_text.inicioabertura
            value: '{{ now() }}'
      - id: fimabertura
        alias: parou de abrir
        trigger:
        - platform: state
          entity_id: binary_sensor.rele_1
          to: 'off'
        condition:
        - condition: state
          entity_id: 'input_boolean.alterarslider'
          state: 'on'
        action:
        - service: input_number.set_value
          data_template:
            entity_id: input_number.aberturapersianaold
            value: >-
              {% if (states.input_number.aberturapersiana.state)|int + ((as_timestamp(now()) - (as_timestamp(states.input_text.inicioabertura.state))|float|round(2))*100/(states.input_text.tempodeabertura.state|int))|int > 96 %}
                100
              {% else %}
                {{ (states.input_number.aberturapersiana.state)|int + ((as_timestamp(now()) - (as_timestamp(states.input_text.inicioabertura.state))|float|round(2))*100/(states.input_text.tempodeabertura.state|int))|int }}
              {% endif %}
        - service: input_number.set_value
          data_template:
            entity_id: input_number.aberturapersiana
            value: '{{ states.input_number.aberturapersianaold.state }}'
    
      - id: aberturapeloslider
        alias: Abertura pelo slider
        trigger:
          platform: state
          entity_id: input_number.aberturapersiana
        condition:
        - condition: template
          value_template: '{{ states.input_number.aberturapersiana.state|int > states.input_number.aberturapersianaold.state|int }}'
        action:
        - service: input_boolean.turn_off
          data:
            entity_id: input_boolean.alterarslider
        - service: mqtt.publish
          data:
            topic: 'cmnd/wemosd1mini/Backlog'
            payload_template: "POWER1 ON; delay {% if is_state('input_number.aberturapersiana', '100.0') %} {{ (((states.input_number.aberturapersiana.state|int - states.input_number.aberturapersianaold.state|int)*(states.input_text.tempodeabertura.state|float)/100)|round(1)*10)|round(0) + 20 }} {% else %}
    {{ (((states.input_number.aberturapersiana.state|int - states.input_number.aberturapersianaold.state|int)*(states.input_text.tempodeabertura.state|float)/100)|round(1)*10)|round(0) }} {% endif %}; POWER1 OFF"
        - delay:
            milliseconds: 800
        - wait_template: "{{ is_state('binary_sensor.rele_1', 'off') }}"
        - service: input_boolean.turn_on
          data:
            entity_id: input_boolean.alterarslider
        - service: input_number.set_value
          data_template:
            entity_id: input_number.aberturapersianaold
            value: '{{ states.input_number.aberturapersiana.state }}'
      - id: fechopeloslider
        alias: Fecho pelo slider
        trigger:
          platform: state
          entity_id: input_number.aberturapersiana
        condition:
        - condition: template
          value_template: '{{ states.input_number.aberturapersiana.state|int < states.input_number.aberturapersianaold.state|int }}'
        action:
        - service: input_boolean.turn_off
          data:
            entity_id: input_boolean.alterarslider
        - service: mqtt.publish
          data:
            topic: 'cmnd/wemosd1mini/Backlog'
            payload_template: "POWER2 ON; delay {% if is_state('input_number.aberturapersiana', '0.0') %} {{ (((states.input_number.aberturapersianaold.state|int - states.input_number.aberturapersiana.state|int)*(states.input_text.tempodefecho.state|float)/100)|round(1)*10)|round(0) + 20 }} {% else %}
    {{ (((states.input_number.aberturapersianaold.state|int - states.input_number.aberturapersiana.state|int)*(states.input_text.tempodefecho.state|float)/100)|round(1)*10)|round(0) }} {% endif %}; POWER2 OFF"
        - delay:
            milliseconds: 800
        - wait_template: "{{ is_state('binary_sensor.rele_2', 'off') }}"
        - service: input_boolean.turn_on
          data:
            entity_id: input_boolean.alterarslider
        - service: input_number.set_value
          data_template:
            entity_id: input_number.aberturapersianaold
            value: '{{ states.input_number.aberturapersiana.state }}'
    

Fico a aguardar feedback! :wink:

3 Curtiram

Mal posso vou testar isso claro :slight_smile:

Vou testar isso de certeza. Só uma questão, consideraste que eles demoram mais tempo a subir do que a descer? ou assumes o mesmo tempo para os dois movimentos?

Assumi que demoram o mesmo tempo, no entanto, se acharem que a diferença é significativa posso modificar o código para isso facilmente (não o fiz para não o tornar ainda mais complexo)

Tiago, como solicitado, já está incluída a possibilidade de tempos diferentes! :wink:

1 Curtiu

Grande trabalho, no fim de semana já vou testar isso em obra.

ah boa. eu ia cronometrar o tempo para ver a diferença, mas como estou fora ainda não consegui. Assim sendo está resolvido :slight_smile: Obrigado.
Assim que tiver isto a funcionar (falta o hardware) vou tentar por o “hey google, close 50%” :wink:

Pulsetime , já testas-te desligar a corrente do sonoff e ligar ver o que acontece?

Tinha essa opçao de pulsetime para abrir a garagem e basicamente quando o modulo reiniciava o HA de X em X tempo andava abrir a porta sozinha e tinha o Power Retain off mas era o MQTT do HA…

Provavelmente estavas a usar um cover mqtt com “retain: true”, não?
Neste caso a cover não é mqtt, é template com comandos mqtt…

Mais uma edição - vejam no cabeçalho as mudanças e actualizem o código… :wink:

Mais uma pequena correcção de bugs… x2…

1 Curtiu

Sou novo nestas andanças, fiz esta config como descrito e esta a bombar no HA mas o problema é que não sei como colocar os botões físicos em funcionamento. Tentei como esta neste artigo: https://forum.cpha.pt/t/como-ligar-estores-electricos-a-um-sonoff-dual/94.
Tenho o sonoff dual r2 com tasmota.

Vê o post que acabei de fazer no tópico de comentários desse tutorial…

mais uma pequena correcção de bugs para ligar com possíveis delays de comunicação (a mudança foi apenas nas automações)…
Actualizem os códigos

Mais uma alteração. Agora deve ser a última… Actualizem!

Tenho umas perguntas de maçarico.

O FW que está instalado é o tasmota, certo ?
O Sonoff deve ser configurado como wemo
O nome que foi dado ao SONOFF DUAL foi “wemosd1mini” ?

@andrefilipecruz o tópico mais actualizado para este assunto está aqui:


Onde tens passo a passo como fazer. Alguma dúvida questiona .

Boa noite. Sou novo nestas andanças. Já tenho o sonoff r2 configurado noentanto tenho erros nesse código. Esse código coloca-se integralmente no configuration.yaml?

Obrigado

O código é para ser usado num ficheiro package. Podes ver como utilizar aqui:

Se não quiseres/puderes utilizar como package, podes dividir o código pelos vários ficheiros correspondentes (caso uses a configuração distribuída por vários ficheiros) ou colocar tudo no configuration.yaml.

Que erros dá? Transcreve essa parte do log…


Copyright © 2017-2021. Todos os direitos reservados
CPHA.pt - info@cpha.pt


FAQ | Termos de Serviço/Regras | Política de Privacidade