Gestion des horaires de chauffage avec Schedy
Supervisor > Addons store > appdaemon > install
Puis dans la configuration de l'addon APPDAEMON rentrez cela :
system_packages: [] python_packages: - hass-apps init_commands: []
Save et Start l’add-on AppDaemon
Dans les logs, on peut le voir récupérer la package hass-apps.
Dans un terminal :
cd /config/appdaemon/apps wget https://raw.githubusercontent.com/efficiosoft/hass-apps/master/hass_apps_loader.py
Avec le File editor, créer un fichier /config/appdaemon/apps/schedy_heating.yaml
Voici ma configuration : Dans APPDAEMON (/config/appdaemon/apps/schedy_heating.yaml)
schedy_heating: module: hass_apps_loader class: SchedyApp actor_type: thermostat expression_environment: | def workday(): return state("binary_sensor.workday_sensor") def weekday(): return state("sensor.weekday") def semaine(): return state("sensor.semaine_paire_impaire") def heating_mode_ch_parents(): return state("input_select.heating_mode_ch_parents") def heating_mode_ch_simon(): return state("input_select.heating_mode_ch_simon") def heating_mode_bureau(): return state("input_select.heating_mode_bureau") def time_between(start, end): current = time.hour * 60 + time.minute + 1 if start >= end: return current >= start or current < end return current >= start and current < end watched_entities: - sensor.time - sensor.weekday - sensor.semaine_paire_impaire - binary_sensor.workday_sensor - binary_sensor.capteur_fenetre_ch_parents - binary_sensor.capteur_fenetre_ch_simon - binary_sensor.capteur_fenetre_pignon_bureau - binary_sensor.capteur_fenetre_facade_bureau - input_boolean.thermostats_on_off - input_number.consigne_confort_chambres - input_number.consigne_eco - input_number.consigne_boost - input_number.consigne_absent - input_select.heating_mode_ch_parents - input_select.heating_mode_ch_simon - input_select.heating_mode_bureau schedule_prepend: - x: "OFF if is_off('input_boolean.thermostats_on_off') else Next()" - x: "Mark(OFF, Mark.OVERLAY) if not is_empty(filter_entities('binary_sensor', window_room=room_name, state='on')) else Next()" rooms: ch_parents: rescheduling_delay: 120 actors: climate.ch_parents: watched_entities: - input_boolean.absent_ch_parents - input_boolean.boost_ch_parents - sensor.ch_parents_start_sem - sensor.ch_parents_start_we - sensor.ch_parents_stop_sem - sensor.ch_parents_stop_we schedule: - weekdays: 1-7 rules: # Mode de chauffage [[NORMAL]] # Jours de semaine travaillée - x: state("input_number.consigne_confort_chambres") if (heating_mode_ch_parents() == 'Normal') and (workday() == 'on') and (state("input_boolean.absent_ch_parents") == "off") and (state("input_boolean.boost_ch_parents") == "off") and time_between(int(state("sensor.ch_parents_start_sem")), int(state("sensor.ch_parents_stop_sem"))) else Next() # Weekend, jours fériés ou MODE VACANCES - x: state("input_number.consigne_confort_chambres") if (workday() == 'off') and (state("input_boolean.absent_ch_parents") == "off") and (state("input_boolean.boost_ch_parents") == "off") and time_between(int(state("sensor.ch_parents_start_we")), int(state("sensor.ch_parents_stop_we"))) else Next() # MODE VACANCES - x: state("input_number.consigne_confort_chambres") if (heating_mode_ch_parents() == 'Vacances') and (state("input_boolean.absent_ch_parents") == "off") and (state("input_boolean.boost_ch_parents") == "off") and time_between(int(state("sensor.ch_parents_start_we")), int(state("sensor.ch_parents_stop_we"))) else Next() # Plage BOOST, ABSENT, ECO - x: state("input_number.consigne_boost") if (state("input_boolean.absent_ch_parents") == "off") and (state("input_boolean.boost_ch_parents") == "on") else Next() - x: state("input_number.consigne_absent") if (state("input_boolean.absent_ch_parents") == "on") else Next() - x: state("input_number.consigne_eco") ch_simon: rescheduling_delay: 120 actors: climate.ch_simon: watched_entities: - input_boolean.absent_ch_simon - input_boolean.boost_ch_simon - sensor.ch_simon_start_sem - sensor.ch_simon_start_we - sensor.ch_simon_stop_sem - sensor.ch_simon_stop_we schedule: - weekdays: 1-7 rules: # Mode de chauffage [[NORMAL]] # Jours de semaine travaillée - x: state("input_number.consigne_confort_chambres") if (heating_mode_ch_simon() == 'Normal') and (workday() == 'on') and (state("input_boolean.absent_ch_simon") == "off") and (state("input_boolean.boost_ch_simon") == "off") and time_between(int(state("sensor.ch_simon_start_sem")), int(state("sensor.ch_simon_stop_sem"))) else Next() # Weekend, jours fériés - x: state("input_number.consigne_confort_chambres") if (workday() == 'off') and (state("input_boolean.absent_ch_simon") == "off") and (state("input_boolean.boost_ch_simon") == "off") and time_between(int(state("sensor.ch_simon_start_we")), int(state("sensor.ch_simon_stop_we"))) else Next() # MODE VACANCES - x: state("input_number.consigne_confort_chambres") if (heating_mode_ch_simon() == 'Vacances') and (state("input_boolean.absent_ch_simon") == "off") and (state("input_boolean.boost_ch_simon") == "off") and time_between(int(state("sensor.ch_simon_start_we")), int(state("sensor.ch_simon_stop_we"))) else Next() # Plage BOOST, ABSENT, ECO - x: state("input_number.consigne_boost") if (state("input_boolean.absent_ch_simon") == "off") and (state("input_boolean.boost_ch_simon") == "on") else Next() - x: state("input_number.consigne_absent") if (state("input_boolean.absent_ch_simon") == "on") else Next() - x: state("input_number.consigne_eco") bureau: actors: climate.ch_amis_bureau: watched_entities: - input_number.consigne_confort_bureau - input_boolean.absent_bureau - input_boolean.boost_bureau - sensor.bureau_start_vendredi_paire - sensor.bureau_start_sam_dim_paire - sensor.bureau_stop_vendredi_paire - sensor.bureau_stop_sam_dim_paire - sensor.bureau_start_vendredi_impaire - sensor.bureau_start_sam_dim_impaire - sensor.bureau_stop_vendredi_impaire - sensor.bureau_stop_sam_dim_impaire - sensor.bureau_start_sem - sensor.bureau_stop_sem - sensor.bureau_start_we - sensor.bureau_stop_we schedule: - weekdays: 1-7 rules: # MODE BUREAU SEMAINE PAIRE # Vendredi - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Paire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Vendredi') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_vendredi_paire")), int(state("sensor.bureau_stop_vendredi_paire"))) else Next() # Samedi - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Paire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Samedi') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_sam_dim_paire")), int(state("sensor.bureau_stop_sam_dim_paire"))) else Next() # Dimanche - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Paire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Dimanche') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_sam_dim_paire")), int(state("sensor.bureau_stop_sam_dim_paire"))) else Next() # Lundi - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Paire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Lundi') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int("01"), int(state("sensor.bureau_stop_sam_dim_impaire"))) else Next() # MODE BUREAU SEMAINE IMPAIRE # Vendredi - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Impaire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Vendredi') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_vendredi_impaire")), int(state("sensor.bureau_stop_vendredi_impaire"))) else Next() # Samedi - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Impaire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Samedi') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_sam_dim_impaire")), int(state("sensor.bureau_stop_sam_dim_impaire"))) else Next() # Dimanche - x: state("input_number.consigne_confort_bureau") if (semaine() == 'Impaire') and (heating_mode_bureau() == 'Bureau') and (weekday() == 'Dimanche') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_sam_dim_impaire")), int(state("sensor.bureau_stop_sam_dim_impaire"))) else Next() # MODE BUREAU Hors plage Bureau # semaine - x: state("input_number.consigne_confort_chambres") if (heating_mode_bureau() == 'Bureau') and (workday() == 'on') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_sem")), int(state("sensor.bureau_stop_sem"))) else Next() # Weekend - x: state("input_number.consigne_confort_chambres") if (heating_mode_bureau() == 'Bureau') and (workday() == 'off') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_we")), int(state("sensor.bureau_stop_we"))) else Next() # MODE CHAMBRE # Semaine - x: state("input_number.consigne_confort_chambres") if (heating_mode_bureau() == 'Chambre') and (workday() == 'on') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_sem")), int(state("sensor.bureau_stop_sem"))) else Next() # Weekend - x: state("input_number.consigne_confort_chambres") if (heating_mode_bureau() == 'Chambre') and (workday() == 'off') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_we")), int(state("sensor.bureau_stop_we"))) else Next() # MODE VACANCES - x: state("input_number.consigne_confort_chambres") if (heating_mode_bureau() == 'Vacances') and (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "off") and time_between(int(state("sensor.bureau_start_we")), int(state("sensor.bureau_stop_we"))) else Next() # Plage BOOST, ABSENT, ECO - x: state("input_number.consigne_boost") if (state("input_boolean.absent_bureau") == "off") and (state("input_boolean.boost_bureau") == "on") else Next() - x: state("input_number.consigne_absent") if (state("input_boolean.absent_bureau") == "on") else Next() - x: state("input_number.consigne_eco")
Dans HOME ASSITANT j'ai réalisé un package incluant toutes les entitées créées : (/config/packages/schedy.yaml)
### AUTOMATISATION
automation:
- id: '1603671785286'
alias: Update Sensor Semaine Paire / Impaire
description: ''
trigger:
- platform: time_pattern
minutes: /30
condition: []
action:
- service: homeassistant.update_entity
data: {}
entity_id: sensor.semaine_paire_impaire
mode: single
### BINARY_SENSOR
binary_sensor:
# Workday
- platform: workday
country: FRA
workdays: [mon, tue, wed, thu, fri]
excludes: [sat, sun]
### CLIMATE
climate:
# Chambre Amis / Bureau
- platform: generic_thermostat
name: Ch Amis / Bureau
heater: switch.sonoff_4ch_relay_1
target_sensor: sensor.capteur_bureau_temp
min_temp: 05
max_temp: 35
ac_mode: false
target_temp: 16
cold_tolerance: 0.1
hot_tolerance: 0
initial_hvac_mode: "heat"
# Chambre Parents
- platform: generic_thermostat
name: Ch Parents
heater: switch.sonoff_4ch_relay_2
target_sensor: sensor.capteur_chambre_parents_temp
min_temp: 05
max_temp: 35
ac_mode: false
target_temp: 16
cold_tolerance: 0.1
hot_tolerance: 0
initial_hvac_mode: "heat"
# Chambre Simon
- platform: generic_thermostat
name: Ch Simon
heater: switch.sonoff_4ch_relay_3
target_sensor: sensor.capteur_chambre_simon_temp
min_temp: 05
max_temp: 35
ac_mode: false
target_temp: 16
cold_tolerance: 0.1
hot_tolerance: 0
initial_hvac_mode: "heat"
### GROUP
group:
fenetres_bureau:
name: Fenêtre Bureau
entities:
- binary_sensor.capteur_fenetre_facade_bureau
- binary_sensor.capteur_fenetre_pignon_bureau
### INPUT_SELECT
input_select:
heating_mode_ch_parents:
name: Mode du Chauffage
icon: mdi:radiator
options:
- Normal
- Vacances
heating_mode_ch_simon:
name: Mode du Chauffage
icon: mdi:radiator
options:
- Normal
- Vacances
heating_mode_bureau:
name: Mode du Chauffage
icon: mdi:radiator
options:
- Bureau
- Chambre
- Vacances
### INPUT_BOOLEAN
input_boolean:
thermostats_on_off:
boost_bureau:
boost_ch_simon:
boost_ch_parents:
absent_bureau:
absent_ch_simon:
absent_ch_parents:
### INPUT_NUMBER
input_number:
consigne_confort_chambres:
name: Confort Chambres
min: 18
max: 22
step: 0.5
unit_of_measurement: °C
consigne_confort_bureau:
name: Confort Bureau
initial: 20.5
min: 18
max: 24
step: 0.5
unit_of_measurement: °C
consigne_absent:
name: Absent
min: 10
max: 15
step: 0.5
unit_of_measurement: °C
consigne_eco:
name: Eco
min: 15
max: 18
step: 0.5
unit_of_measurement: °C
consigne_boost:
name: Boost
min: 18
max: 24
step: 0.5
unit_of_measurement: °C
### INPUT_DATETIME
input_datetime:
# chambre parents
ch_parents_start_sem:
has_date: false
has_time: true
ch_parents_stop_sem:
has_date: false
has_time: true
ch_parents_start_we:
has_date: false
has_time: true
ch_parents_stop_we:
has_date: false
has_time: true
# chambre simon
ch_simon_start_sem:
has_date: false
has_time: true
ch_simon_stop_sem:
has_date: false
has_time: true
ch_simon_start_we:
has_date: false
has_time: true
ch_simon_stop_we:
has_date: false
has_time: true
# bureau
bureau_start_sem:
has_date: false
has_time: true
bureau_stop_sem:
has_date: false
has_time: true
bureau_start_we:
has_date: false
has_time: true
bureau_stop_we:
has_date: false
has_time: true
bureau_start_vendredi_paire:
has_date: false
has_time: true
bureau_start_sam_dim_paire:
has_date: false
has_time: true
bureau_start_vendredi_impaire:
has_date: false
has_time: true
bureau_start_sam_dim_impaire:
has_date: false
has_time: true
bureau_stop_vendredi_paire:
has_date: false
has_time: true
bureau_stop_sam_dim_paire:
has_date: false
has_time: true
bureau_stop_vendredi_impaire:
has_date: false
has_time: true
bureau_stop_sam_dim_impaire:
has_date: false
has_time: true
### SENSORS
sensor:
- platform: template
sensors:
weekday:
friendly_name: "Jour de la Semaine"
icon_template: mdi:calendar-today
value_template: >
{% set days = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"] %}
{{ days[now().weekday()] }}
- platform: template
sensors:
semaine_paire_impaire:
friendly_name: "Semaine Paire Impaire"
icon_template: mdi:calendar-today
value_template: >
{% set week_number = now().isocalendar()[1] %}
{{ "Paire" if week_number % 2 == 0 else "Impaire" }}
- platform: min_max
entity_ids:
- sensor.capteur_chambre_simon_temp
- sensor.capteur_chambre_parents_temp
- sensor.capteur_bureau_temp
type: mean
name: Température Chambres
#chambre parents
- platform: template
sensors:
ch_parents_start_sem:
friendly_name: "ch_parents_start_sem"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_parents_start_sem', 'timestamp') / 60)|int }}"
ch_parents_stop_sem:
friendly_name: "ch_parents_stop_sem"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_parents_stop_sem', 'timestamp') / 60)|int }}"
- platform: template
sensors:
ch_parents_start_we:
friendly_name: "ch_parents_start_we"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_parents_start_we', 'timestamp') / 60)|int }}"
ch_parents_stop_we:
friendly_name: "ch_parents_stop_we"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_parents_stop_we', 'timestamp') / 60)|int }}"
#
# chambre simon
- platform: template
sensors:
ch_simon_start_sem:
friendly_name: "ch_simon_start_sem"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_simon_start_sem', 'timestamp') / 60)|int }}"
ch_simon_stop_sem:
friendly_name: "ch_simon_stop_sem"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_simon_stop_sem', 'timestamp') / 60)|int }}"
- platform: template
sensors:
ch_simon_start_we:
friendly_name: "ch_simon_start_we"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_simon_start_we', 'timestamp') / 60)|int }}"
ch_simon_stop_we:
friendly_name: "ch_simon_stop_we"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.ch_simon_stop_we', 'timestamp') / 60)|int }}"
#
# bureau
- platform: template
sensors:
bureau_start_sem:
friendly_name: "bureau_start_sem"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_start_sem', 'timestamp') / 60)|int }}"
bureau_stop_sem:
friendly_name: "bureau_stop_sem"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_stop_sem', 'timestamp') / 60)|int }}"
- platform: template
sensors:
bureau_start_we:
friendly_name: "bureau_start_we"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_start_we', 'timestamp') / 60)|int }}"
bureau_stop_we:
friendly_name: "bureau_stop_we"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_stop_we', 'timestamp') / 60)|int }}"
- platform: template
sensors:
bureau_start_vendredi_paire:
friendly_name: "bureau_start_vendredi_paire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_start_vendredi_paire', 'timestamp') / 60)|int }}"
bureau_stop_vendredi_paire:
friendly_name: "bureau_stop_vendredi_paire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_stop_vendredi_paire', 'timestamp') / 60)|int }}"
- platform: template
sensors:
bureau_start_sam_dim_paire:
friendly_name: "bureau_start_sam_dim_paire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_start_sam_dim_paire', 'timestamp') / 60)|int }}"
bureau_stop_sam_dim_paire:
friendly_name: "bureau_stop_sam_dim_paire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_stop_sam_dim_paire', 'timestamp') / 60)|int }}"
- platform: template
sensors:
bureau_start_vendredi_impaire:
friendly_name: "bureau_start_vendredi_impaire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_start_vendredi_impaire', 'timestamp') / 60)|int }}"
bureau_stop_vendredi_impaire:
friendly_name: "bureau_stop_vendredi_impaire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_stop_vendredi_impaire', 'timestamp') / 60)|int }}"
- platform: template
sensors:
bureau_start_sam_dim_impaire:
friendly_name: "bureau_start_sam_dim_impaire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_start_sam_dim_impaire', 'timestamp') / 60)|int }}"
bureau_stop_sam_dim_impaire:
friendly_name: "bureau_stop_sam_dim_impaire"
icon_template: mdi:timer-sand
value_template: "{{ (state_attr('input_datetime.bureau_stop_sam_dim_impaire', 'timestamp') / 60)|int }}"
Ce qui vous donnera un lovelace pour gérer les variable Schedy :