Programador Semanal de Persianas

 

 

 

 

Este tutorial parte de la idea de Macs, sin el cual, habría abandonado ya que me faltan conocimientos de como funciona yaml y sin su ayuda, el ordenador hubiera acabado por la ventana mientras configuraba los parámetros.

Antes que nada, quiero explicaros un poco como funcionan los diferentes apartados que tiene.

Como veis, dispone de un apartado con la vista semanal, el cual permite variar el estado de cada día individualmente o todos de una vez mediante la pestaña «Todos»

Pasamos a los apartados:

  • Apagado: No hace nada como es lógico.
  • H.Manual: Sube la persiana hasta el limite puesto en el apartado correspondiente y la baja completamente a las horas que le indiques en las casillas correspondientes.
  • Automático: Sube la persiana hasta el limite puesto en el apartado correspondiente y la baja completamente coincidiendo con las horas de Amanecer/Atardecer.
  • R.Temperatura: Sube o baja la temperatura en función de la diferencia de temperatura exterior e interior y siempre por encima de la temperatura mínima que le pongamos de confort para que no se active en invierno.

Explicare un poco mas a fondo la función de Regulación de Temperatura, por ejemplo si la casa esta a 20º y la calle a 21º bajara un 20% (se puede cambiar, ahora esta 20% por cada grado de diferencia) hasta un limite mínimo que permita la entrada de luz por los agujeritos de la persiana (en mi caso este limite coincide con el 20% de posición que ademas desactiva un input boolean al llegar a esa posición, luego explicare para que sirve.)          

Y que pasa cuando es de noche y la tº exterior da la casualidad de que es inferior a la interior y por encima de la mínima de confort, pues que la persiana se va abriendo hasta el limite puesto en el apartado correspondiente y ademas activa un input boolean.

Bien este input boolean esta diseñado para asociarlo a 2 posibles opciones que se me ocurren ahora mismo para ventilar la casa y bajar su temperatura, pudiendo así mantenerla «hermética» y fresca el resto del día.

  • Motor de Ventana: los cuales han bajado bastante de precio y funcionan en ventanas con cualquier tipo de apertura.
  • Ventilación forzada: con lo que con un gasto mínimo (unos 15w según he leído, habrá que ver si es verdad) renueva el aire y lo refresca o calienta por medio de un intercambiador de temperatura, en este caso refrescaría con el aire de la calle.

Os dejo las partes del código que necesitáis:

input_datetime:

hora_persianas_programador_up:
  name: Hora de Apertura
  has_date: false
  has_time: true
hora_persianas_programador_down:
  name: Hora de Cierre
  has_date: false
  has_time: true

input_number:

posicion_apertura_persianas_programador:
  name: Posicion Apertura
  min: 0
  max: 100
  step: 1
  mode: box
  unit_of_measurement: "%"
####################################
temperatura_maxima_confort:
  name: Max. Confort
  min: 0
  max: 40
  step: 1
  mode: box
  unit_of_measurement: "ºC"
  temperatura_minima_confort:
  name: Min. Confort
  min: 0
  max: 40
  step: 1
  mode: box
  unit_of_measurement: "ºC"
 
input_select:
 
todo:
  name: Todo
  options:
    - -------
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

lunes:
  name: Lunes
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

martes:
  name: Martes
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

miercoles:
  name: Miercoles
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

jueves:
  name: Jueves
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

viernes:
  name: Viernes
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

sabado:
  name: Sabado
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura

domingo:
  name: Domingo
  options:
    - Apagado
    - Automático
    - H.Manual
    - R.Temperatura
 
sensor:
 
- platform: template
  sensors:
  dia_de_la_semana:
  friendly_name: Dia de la Semana
  value_template: " {{ ['Lunes','Martes','Miercoles','Jueves','Viernes','Sabado','Domingo'][now().weekday()] }}"
  entity_id: sensor.time
 
- platform: template
  sensors:
  next_sunrise:
    friendly_name: Amanecer
    value_template: '{{ as_timestamp(states.sun.sun.attributes.next_rising) | timestamp_custom("%H:%M") }}'
  next_sunset:
    friendly_name: Atardecer
    value_template: '{{ as_timestamp(states.sun.sun.attributes.next_setting) | timestamp_custom("%H:%M") }}'
 
automation:
 
alias: 'Programador Persiana Estudio Select'
trigger:
- platform: state
  entity_id: input_select.todo
- platform: sun
  event: sunset
- platform: sun
  event: sunrise
- platform: template
  value_template: "{{ states('sensor.time') == (states.input_datetime.hora_persianas_programador_up.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
- platform: template
  value_template: "{{ states('sensor.time') == (states.input_datetime.hora_persianas_programador_down.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
- platform: time_pattern
  minutes: '/30'
action:

- service: input_select.select_option
  data_template:
    entity_id: input_select.lunes, input_select.martes, input_select.miercoles, input_select.jueves, input_select.viernes, input_select.sabado, input_select.domingo
    option: >
{% if (trigger.entity_id == 'input_select.todo') %}
{% if ((states.input_select.todo.state) == 'H.Manual') %}
H.Manual
{% elif ((states.input_select.todo.state) == 'Automático') %}
Automático
{% elif ((states.input_select.todo.state) == 'R.Temperatura') %}
R.Temperatura
{% elif ((states.input_select.todo.state) == 'Apagado') %}
Apagado
{% endif %}
{% endif %}
- delay:
  seconds: 2
- service: input_select.select_option
  data_template:
  entity_id: input_select.todo
  option: >
{% if (trigger.entity_id == 'input_select.todo') %}
{% if ((states.input_select.todo.state) != '-------') %}
-------
{% endif %}
{% endif %}

- service: cover.set_cover_position
  data_template:
  position: >
{% if ((states.sensor.time.state) == (states.input_datetime.hora_persianas_programador_up.attributes.timestamp | int |timestamp_custom('%H:%M', False))) and
(((states.sensor.dia_de_la_semana.state == 'Lunes') and (states.input_select.lunes.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Martes') and (states.input_select.martes.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Miercoles') and (states.input_select.miercoles.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Jueves') and (states.input_select.jueves.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Viernes') and (states.input_select.viernes.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Sabado') and (states.input_select.sabado.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Domingo') and (states.input_select.domingo.state == 'H.Manual'))) %}
{{ states('input_number.posicion_apertura_persianas_programador') | int }}

{% elif ((states.sensor.time.state) == (states.input_datetime.hora_persianas_programador_down.attributes.timestamp | int |timestamp_custom('%H:%M', False))) and
(((states.sensor.dia_de_la_semana.state == 'Lunes') and (states.input_select.lunes.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Martes') and (states.input_select.martes.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Miercoles') and (states.input_select.miercoles.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Jueves') and (states.input_select.jueves.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Viernes') and (states.input_select.viernes.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Sabado') and (states.input_select.sabado.state == 'H.Manual')) or
((states.sensor.dia_de_la_semana.state == 'Domingo') and (states.input_select.domingo.state == 'H.Manual'))) %}
0

{% elif (trigger.event == 'sunrise') and
(((states.sensor.dia_de_la_semana.state == 'Lunes') and (states.input_select.lunes.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Martes') and (states.input_select.martes.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Miercoles') and (states.input_select.miercoles.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Jueves') and (states.input_select.jueves.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Viernes') and (states.input_select.viernes.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Sabado') and (states.input_select.sabado.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Domingo') and (states.input_select.domingo.state == 'Automático'))) %}
{{ states('input_number.posicion_apertura_persianas_programador') | int }}

{% elif (trigger.event == 'sunset') and
(((states.sensor.dia_de_la_semana.state == 'Lunes') and (states.input_select.lunes.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Martes') and (states.input_select.martes.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Miercoles') and (states.input_select.miercoles.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Jueves') and (states.input_select.jueves.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Viernes') and (states.input_select.viernes.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Sabado') and (states.input_select.sabado.state == 'Automático')) or
((states.sensor.dia_de_la_semana.state == 'Domingo') and (states.input_select.domingo.state == 'Automático'))) %}
0

{% elif (trigger.platform == 'time_pattern') and
(((states.sensor.dia_de_la_semana.state == 'Lunes') and (states.input_select.lunes.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Martes') and (states.input_select.martes.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Miercoles') and (states.input_select.miercoles.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Jueves') and (states.input_select.jueves.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Viernes') and (states.input_select.viernes.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Sabado') and (states.input_select.sabado.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Domingo') and (states.input_select.domingo.state == 'R.Temperatura'))) %}
{% if (((states.sensor.dark_sky_apparent_temperature.state |int ) > (states.input_number.temperatura_maxima_confort.state |int )) and (states.cover.persiana_estudio.attributes.current_position |int > 20)) %}
{% if ((states.cover.persiana_estudio.attributes.current_position |int) - ((states.sensor.dark_sky_apparent_temperature.state |int) - (states.input_number.temperatura_maxima_confort.state|int)) *20) <= 20 %}
20
{% elif ((states.cover.persiana_estudio.attributes.current_position |int) - ((states.sensor.dark_sky_apparent_temperature.state |int) - (states.input_number.temperatura_maxima_confort.state|int)) *20) > 20 %}
{{ ((states.cover.persiana_estudio.attributes.current_position |int) - ((states.sensor.dark_sky_apparent_temperature.state |int) - (states.input_number.temperatura_maxima_confort.state|int)) *20) }}
{% endif %}
{% elif ((states.sensor.dark_sky_apparent_temperature.state |int ) < (states.input_number.temperatura_maxima_confort.state |int )) and ((states.sensor.dark_sky_apparent_temperature.state |int ) > (states.input_number.temperatura_minima_confort.state |int )) %}
{% if ((states.cover.persiana_estudio.attributes.current_position |int + 20) < (states('input_number.posicion_apertura_persianas_programador') | int)) %}
{{ states.cover.persiana_estudio.attributes.current_position |int + 20 }}
{% elif ((states.cover.persiana_estudio.attributes.current_position |int + 20) >= (states('input_number.posicion_apertura_persianas_programador') | int)) %}
{{ states('input_number.posicion_apertura_persianas_programador') | int }}
{% endif %}
{% else %}
{{ (states.cover.persiana_estudio.attributes.current_position |int) }}
{% endif %}
{% endif %}
##### El else se pone para evitar que se quede atascado y condtinue al siguiente service ya que va en cascada y si no hace ningun cambio, no lo da por valido y no continua ###
- service_template: >
{% if (trigger.platform == 'time_pattern') and
(((states.sensor.dia_de_la_semana.state == 'Lunes') and (states.input_select.lunes.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Martes') and (states.input_select.martes.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Miercoles') and (states.input_select.miercoles.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Jueves') and (states.input_select.jueves.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Viernes') and (states.input_select.viernes.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Sabado') and (states.input_select.sabado.state == 'R.Temperatura')) or
((states.sensor.dia_de_la_semana.state == 'Domingo') and (states.input_select.domingo.state == 'R.Temperatura'))) %}
{% if (((states.sensor.dark_sky_apparent_temperature.state |int ) > (states.input_number.temperatura_maxima_confort.state |int )) and
(states.cover.persiana_estudio.attributes.current_position |int <= 20)) %}
input_boolean.turn_off
{% elif (((states.sensor.dark_sky_apparent_temperature.state |int ) < (states.input_number.temperatura_maxima_confort.state |int )) and
((states.sensor.dark_sky_apparent_temperature.state |int ) > (states.input_number.temperatura_minima_confort.state |int )) and
(states.cover.persiana_estudio.attributes.current_position |int >= 20)) %}
input_boolean.turn_on
{% endif %}
{% endif %}
  entity_id: input_boolean.ventanas_motorizadas
 
 
Bien ahora unos puntos importantes:
 
En mi caso he escogido como sensor externo el de dark sky, pero lo mejor seria tener uno propio, por tener algo mas de precisión justo en tu casa.
 
Como veréis, la configuración esta puesta para temperatura de confort, mínima y máxima, el sensor de temperatura máxima es el que tendréis que cambiar por el de vuestra casa (mejor si usáis el component para hacer la media de todos los sensores que tengáis distribuidos por casa )
 
La razón de poner el apartado de temperatura confort máxima y que lo podáis variar es para que simuléis las diferentes condiciones rápidamente y poder regular a vuestro gusto la posición de la persiana, el porcentaje de subida….., para esta regulación, también recomiendo bajar el «time_pattern a 1 para que no tengais que esperar 30 min que es lo que tarda entre barridos de comprobación.
 
Como siempre dar las gracias a toda la comunidad de telegram por aportar ideas sin las cuales esta no habría podido desarrollarse.

Deja un comentario

Síguenos

Siguenos en facebook