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 :