Outils pour utilisateurs

Outils du site


installation_de_schedy_via_appdaemon

Installation de Schedy via Appdaemon

Gestion des horaires de chauffage avec Schedy

  1. Installer AppDaemon et la package hass-apps
  2. Déployer le fichier hass_apps_loader.py
  3. Faire sa configuration avec le module thermostat

1°/ Installer AppDaemon et la package hass-apps

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.


2°/ Déployer le fichier hass_apps_loader.py

Dans un terminal :

cd /config/appdaemon/apps
wget https://raw.githubusercontent.com/efficiosoft/hass-apps/master/hass_apps_loader.py

3°/ Faire sa configuration avec le module thermostat

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 :

Doc Schedy Tuto Tuto2

installation_de_schedy_via_appdaemon.txt · Dernière modification : de 127.0.0.1