Mise en place de la fonction packages dans configuration.yaml

bonjour @noiwid

Je viens de tester ta methode sur mon haos de test.

J’ai donc ceci :

config |--configuration.yaml
       |           
       |----packages--|---input_numbers--/--volets.yaml
                      |                 /--switch_auto.yaml 
                      |
                      |---sensors--/-- system_monitor.yaml
                      |           /-- datetime.yaml                             
                      |
                      |---etc..etc..

dans configuration.yaml jai :

## packages
homeassistant:
# Load packages
#  packages: !include_dir_named packages
#  packages: !include_dir_named integrations
  packages: !include_dir_merge_named packages/
  whitelist_external_dirs:
    - /config/

quand je verifie dans outils de devellopement j’ai cette erreur :

Configuration non valide !
 attendu un dictionnaire pour la valeur du dictionnaire @ data['packages']['name']  

pourquoi sa ne va pas ?

Merci pour les retours.

Par contre je n’avais aucune erreur qui remonter quand je testé la config. C’est bien que HA ne détecte pas mon dossier.
Voici le message que j’ai
image

car ton fichier yaml dans le dossier de chaque package doit avoir le même nom que le package :slight_smile:

/packages/input_numbers/input_numbers.yaml

disons que ce yaml est le fichier de conf « principal » de ton package. rien n’empêche qu’il include lui même d’autres fichiers yaml inclus dans le même dossier, je pense à tes switchs…

J’ai modifié mais c’est pas bon…

Configuration non valide !
 Package input_number setup failed. Component input_auto_offset_matin Integration 'input_auto_offset_matin' not found.
Package input_number setup failed. Component input_auto_offset_soir Integration 'input_auto_offset_soir' not found.
Package input_number setup failed. Component volets_auto_offset_ouvre Integration 'volets_auto_offset_ouvre' not found.
Package input_number setup failed. Component volets_auto_offset_ferme Integration 'volets_auto_offset_ferme' not found.
Package input_number setup failed. Component volets_auto_offset_ouvre_rdc Integration 'volets_auto_offset_ouvre_rdc' not found.
Package input_number setup failed. Component volets_auto_offset_ferme_rdc Integration 'volets_auto_offset_ferme_rdc' not found.
Package input_number setup failed. Component volets_auto_offset_ouvre_1er Integration 'volets_auto_offset_ouvre_1er' not found.
Package input_number setup failed. Component volets_auto_offset_ferme_1er Integration 'volets_auto_offset_ferme_1er' not found. 

mon yaml

#############
#   ENTREE  #
#############
input_number:

  input_auto_offset_matin:
    icon: mdi:weather-sunset-up
    name: Offset matin 2
    min: -90
    max: 90
    step: 1
    mode: slider
  
  input_auto_offset_soir:
    icon: mdi:weather-sunset-down
    name: Offset soir 2
    min: -90
    max: 90
    step: 1
    mode: slider  

  volets_auto_offset_ouvre:
    icon: mdi:weather-sunset-up
    name: Offset matin
    min: -90
    max: 90
    step: 1
    mode: slider
  
  volets_auto_offset_ferme:
    icon: mdi:weather-sunset-down
    name: Offset soir
    min: -90
    max: 90
    step: 1
    mode: slider

  volets_auto_offset_ouvre_rdc:
    icon: mdi:weather-sunset-up
    name: Offset matin
    min: -90
    max: 90
    step: 1
    mode: slider
  
  volets_auto_offset_ferme_rdc:
    icon: mdi:weather-sunset-down
    name: Offset soir
    min: -90
    max: 90
    step: 1
    mode: slider
  
  volets_auto_offset_ouvre_1er:
#    icon: mdi:weather-sunset-up
    name: Offset matin
    min: -90
    max: 90
    step: 1
    mode: slider
  
  volets_auto_offset_ferme_1er:
#    icon: mdi:weather-sunset-down
    name: Offset soir
    min: -90
    max: 90
    step: 1
    mode: slider  

Bonjour,

Lorsque j’ai repondu un peu plus tôt, j’avais testé le package.

fichier test.yaml avec

input_number:
  test_position:
    name: "Test - Position désirée"
    min: -1
    max: 100
    step: 1
    unit_of_measurement: "%"

et configuration.yaml avec

  packages: !include_dir_named .packages

mon dossier s’appelle .packages pour qu’il soit en premier…

J’ai ou j’essaie d’avoir un fichier yaml par integration ou par fonction.
Chaque yaml peut donc avoir une section input_number:, sensor:, template:, script:, automation: si elle est utilisée.

C’est le un peu prnicipe des packages. SI je ne veux plus d’une intégration or d’une fonction, je supprime le yaml correspondant de mon dossier .package et au prochain redémarrage tout est parti

Le document suivant (si l’anglais ne te fais par peur) https://hometechhacker.com/organizing-my-home-assistant-configuration-files/ a des examples avec les differents !include…

Cordialement

Abel

Un sujet expliquant le principe :

1 « J'aime »

voici un exemple concret d’un package que j’utilise, et qui fonctionne:

tiko:
  climate:
    - platform: generic_thermostat
      name: Bureau 1
      heater: switch.radiateurs_on_off
      target_sensor: sensor.bureau_1_temperature
    - platform: generic_thermostat
      name: Entrée
      heater: switch.radiateurs_on_off
      target_sensor: sensor.entree_temperature
    - platform: generic_thermostat
      name: Bureau 2
      heater: switch.radiateurs_on_off
      target_sensor: sensor.bureau_2_temperature
  shell_command:
    bureau_1_set_temp: '/usr/bin/curl -X POST https://mondomaine.com/tiko.php?hash=montoken&room_id=room1&temperature={{ state_attr("climate.bureau_1", "temperature") }}'
    entree_set_temp: '/usr/bin/curl -X POST https://mondomaine.com/tiko.php?hash=montoken&room_id=room2&temperature={{ state_attr("climate.entree", "temperature") }}'
    bureau_2_set_temp: '/usr/bin/curl -X POST https://mondomaine.com/tiko.php?hash=montoken&room_id=room3&temperature={{ state_attr("climate.bureau_2", "temperature") }}'
  automation:
    - id: sync_status_on_bureau_1
      alias: sync_status_on_bureau_1
      description: >
        on H.A startup or heater status change,
        check if heater is currently on to
        update the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: binary_sensor.bureau_1_chauffage
      condition:
        -     condition: state
          entity_id: binary_sensor.bureau_1_chauffage
          state: 'on'
      action:
        -     service: climate.turn_on
          target:
            entity_id: climate.bureau_1
      mode: single
    - id: sync_status_off_bureau_1
      alias: sync_status_off_bureau_1
      description: >
        on H.A startup or heater status change,
        check if heater is currently off to
        update the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: binary_sensor.bureau_1_chauffage
      condition:
        -     condition: state
          entity_id: binary_sensor.bureau_1_chauffage
          state: 'off'
      action:
        -     service: climate.turn_off
          target:
            entity_id: climate.bureau_1
      mode: single
    - id: sync_temp_bureau_1
      alias: sync_temp_bureau_1
      description: >
        on H.A startup or temp change, update
        the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: sensor.bureau_1_temperature_target
      condition: [ ]
      action:
        -     service: climate.set_temperature
          target:
            entity_id: climate.bureau_1
          data:
            temperature: "{{ states('sensor.bureau_1_temperature_target') }}"
      mode: single
    - id: set_temp_bureau_1
      alias: set_temp_bureau_1
      description: >
        on climate update, send update command
        to endpoint
      trigger:
        -     platform: state
          entity_id:
            - climate.bureau_1
          attribute: temperature
      condition:
        -     condition: and
          conditions:
            -         condition: state
              entity_id: switch.radiateurs_off
              state: 'off'
            -         condition: state
              entity_id: switch.radiateurs_hors_gel
              state: 'off'
            -         condition: state
              entity_id: switch.radiateurs_absence
              state: 'off'
      action:
        -     service: shell_command.bureau_1_set_temp
      mode: single
    - id: sync_status_on_entree
      alias: sync_status_on_entree
      description: >
        on H.A startup or heater status change,
        check if heater is currently on to
        update the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: binary_sensor.entree_chauffage
      condition:
        -     condition: state
          entity_id: binary_sensor.entree_chauffage
          state: 'on'
      action:
        -     service: climate.turn_on
          target:
            entity_id: climate.entree
      mode: single
    - id: sync_status_off_entree
      alias: sync_status_off_entree
      description: >
        on H.A startup or heater status change,
        check if heater is currently off to
        update the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: binary_sensor.entree_chauffage
      condition:
        -     condition: state
          entity_id: binary_sensor.entree_chauffage
          state: 'off'
      action:
        -     service: climate.turn_off
          target:
            entity_id: climate.entree
      mode: single
    - id: sync_temp_entree
      alias: sync_temp_entree
      description: >
        on H.A startup or temp change, update
        the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: sensor.entree_temperature_target
      condition: [ ]
      action:
        -     service: climate.set_temperature
          target:
            entity_id: climate.entree
          data:
            temperature: "{{ states('sensor.entree_temperature_target') }}"
      mode: single
    - id: set_temp_entree
      alias: set_temp_entree
      description: >
        on climate update, send update command
        to endpoint
      trigger:
        -     platform: state
          entity_id:
            - climate.entree
          attribute: temperature
      condition:
        -     condition: and
          conditions:
            -         condition: state
              entity_id: switch.radiateurs_off
              state: 'off'
            -         condition: state
              entity_id: switch.radiateurs_hors_gel
              state: 'off'
            -         condition: state
              entity_id: switch.radiateurs_absence
              state: 'off'
      action:
        -     service: shell_command.entree_set_temp
      mode: single
    - id: sync_status_on_bureau_2
      alias: sync_status_on_bureau_2
      description: >
        on H.A startup or heater status change,
        check if heater is currently on to
        update the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: binary_sensor.bureau_2_chauffage
      condition:
        -     condition: state
          entity_id: binary_sensor.bureau_2_chauffage
          state: 'on'
      action:
        -     service: climate.turn_on
          target:
            entity_id: climate.bureau_2
      mode: single
    - id: sync_status_off_bureau_2
      alias: sync_status_off_bureau_2
      description: >
        on H.A startup or heater status change,
        check if heater is currently off to
        update the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: binary_sensor.bureau_2_chauffage
      condition:
        -     condition: state
          entity_id: binary_sensor.bureau_2_chauffage
          state: 'off'
      action:
        -     service: climate.turn_off
          target:
            entity_id: climate.bureau_2
      mode: single
    - id: sync_temp_bureau_2
      alias: sync_temp_bureau_2
      description: >
        on H.A startup or temp change, update
        the climate object in HA
      trigger:
        -     platform: homeassistant
          event: start
        -     platform: state
          entity_id: sensor.bureau_2_temperature_target
      condition: [ ]
      action:
        -     service: climate.set_temperature
          target:
            entity_id: climate.bureau_2
          data:
            temperature: "{{ states('sensor.bureau_2_temperature_target') }}"
      mode: single
    - id: set_temp_bureau_2
      alias: set_temp_bureau_2
      description: >
        on climate update, send update command
        to endpoint
      trigger:
        -     platform: state
          entity_id:
            - climate.bureau_2
          attribute: temperature
      condition:
        -     condition: and
          conditions:
            -         condition: state
              entity_id: switch.radiateurs_off
              state: 'off'
            -         condition: state
              entity_id: switch.radiateurs_hors_gel
              state: 'off'
            -         condition: state
              entity_id: switch.radiateurs_absence
              state: 'off'
      action:
        -     service: shell_command.bureau_2_set_temp
      mode: single
  sensor:
    - platform: template
      sensors:
        bureau_1_temperature:
          friendly_name: Bureau 1 temperature
          value_template: "{{ state_attr('sensor.tiko_settings','bureau_1_cur')}}"
          unit_of_measurement: °C
          device_class: temperature
    - platform: template
      sensors:
        bureau_1_humidity:
          friendly_name: Bureau 1 humidité
          value_template: "{{ state_attr('sensor.tiko_settings','bureau_1_dry')}}"
          unit_of_measurement: '%'
          device_class: humidity
    - platform: template
      sensors:
        bureau_1_temperature_target:
          friendly_name: Bureau 1 temperature target
          value_template: "{{ state_attr('sensor.tiko_settings','bureau_1_tar')}}"
          unit_of_measurement: °C
          device_class: temperature
    - platform: template
      sensors:
        entree_temperature:
          friendly_name: Entrée temperature
          value_template: "{{ state_attr('sensor.tiko_settings','entree_cur')}}"
          unit_of_measurement: °C
          device_class: temperature
    - platform: template
      sensors:
        entree_humidity:
          friendly_name: Entrée humidité
          value_template: "{{ state_attr('sensor.tiko_settings','entree_dry')}}"
          unit_of_measurement: '%'
          device_class: humidity
    - platform: template
      sensors:
        entree_temperature_target:
          friendly_name: Entrée temperature target
          value_template: "{{ state_attr('sensor.tiko_settings','entree_tar')}}"
          unit_of_measurement: °C
          device_class: temperature
    - platform: template
      sensors:
        bureau_2_temperature:
          friendly_name: Bureau 2 temperature
          value_template: "{{ state_attr('sensor.tiko_settings','bureau_2_cur')}}"
          unit_of_measurement: °C
          device_class: temperature
    - platform: template
      sensors:
        bureau_2_humidity:
          friendly_name: Bureau 2 humidité
          value_template: "{{ state_attr('sensor.tiko_settings','bureau_2_dry')}}"
          unit_of_measurement: '%'
          device_class: humidity
    - platform: template
      sensors:
        bureau_2_temperature_target:
          friendly_name: Bureau 2 temperature target
          value_template: "{{ state_attr('sensor.tiko_settings','bureau_2_tar')}}"
          unit_of_measurement: °C
          device_class: temperature
    - platform: template
      sensors:
        tiko_consumption_vs_lastmonth:
          friendly_name: Écart conso. vs mois dernier
          value_template: "{{ (((state_attr('sensor.tiko_consumption', 'this_month_total_wh') - state_attr('sensor.tiko_consumption', 'last_month_total_same_day_wh')) / state_attr('sensor.tiko_consumption', 'last_month_total_same_day_wh')) * 100)|round(0) }}"
          unit_of_measurement: '%'
    - platform: template
      sensors:
        tiko_consumption_vs_yesterday:
          friendly_name: Écart conso. vs hier
          value_template: "{{ (((state_attr('sensor.tiko_consumption', 'today_total_wh') - state_attr('sensor.tiko_consumption', 'yesterday_total_same_time_wh')) / state_attr('sensor.tiko_consumption', 'yesterday_total_same_time_wh')) * 100)|round(0) }}"
          unit_of_measurement: '%'
  binary_sensor:
    - platform: template
      sensors:
        bureau_1_chauffage:
          friendly_name: Bureau 1 chauffage
          value_template: "{{ is_state_attr('sensor.tiko_settings','bureau_1_on', true)}}"
          device_class: heat
    - platform: template
      sensors:
        entree_chauffage:
          friendly_name: Entrée chauffage
          value_template: "{{ is_state_attr('sensor.tiko_settings','entree_on', true)}}"
          device_class: heat
    - platform: template
      sensors:
        bureau_2_chauffage:
          friendly_name: Bureau 2 chauffage
          value_template: "{{ is_state_attr('sensor.tiko_settings','bureau_2_on', true)}}"
          device_class: heat
  command_line:
    - sensor:
        name: Tiko_consumption
        json_attributes:
          - today_total_wh
          - yesterday_total_same_time_wh
          - yesterday_total_same_time_wh
          - last_month_total_wh
          - this_month_total_wh
          - last_month_total_same_day_wh
        command: "curl -s 'https://mondomaine.com/tiko.php?hash=montoken&consumption=true'"
        unit_of_measurement: W
        scan_interval: 3600
        value_template: 1
    - sensor:
        name: Tiko_settings
        json_attributes:
          - boost
          - frost
          - absence
          - disableHeating
          - bureau_1_cur
          - bureau_1_tar
          - bureau_1_dry
          - bureau_1_on
          - entree_cur
          - entree_tar
          - entree_dry
          - entree_on
          - bureau_2_cur
          - bureau_2_tar
          - bureau_2_dry
          - bureau_2_on
        command: "curl -s 'https://mondomaine.com/tiko.php?hash=montoken'"
        scan_interval: 60
        value_template: 1
    - switch:
        name: Radiateurs on/off
        command_on: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=0'"
        command_off: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=disableHeating'"
        command_state: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken'"
        value_template: '{{value_json["disableHeating"]}}'
        icon: '{% if (value_json.disableHeating) %} mdi:radiator-off {% else %} mdi:radiator-off {% endif %}'
    - switch:
        name: Radiateurs off
        command_on: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=disableHeating'"
        command_off: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=0'"
        command_state: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken'"
        value_template: '{{value_json["disableHeating"]}}'
        icon: '{% if (value_json.disableHeating) %} mdi:radiator-off {% else %} mdi:radiator-off {% endif %}'
    - switch:
        name: Radiateurs boost
        command_on: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=boost'"
        command_off: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=0'"
        command_state: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken'"
        value_template: '{{value_json["boost"]}}'
        icon: '{% if (value_json.boost) %} mdi:sun-thermometer {% else %} mdi:lightning-bolt-outline {% endif %}'
    - switch:
        name: Radiateurs absence
        command_on: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=absence'"
        command_off: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=0'"
        command_state: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken'"
        value_template: '{{value_json["absence"]}}'
        icon: '{% if (value_json.absence) %} mdi:door-closed-lock {% else %} mdi:door {% endif %}'
    - switch:
        name: Radiateurs hors gel
        command_on: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=frost'"
        command_off: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken&mode=0'"
        command_state: "curl -g 'https://mondomaine.com/tiko.php?hash=montoken'"
        value_template: '{{value_json["frost"]}}'
        icon: '{% if (value_json.frost) %} mdi:snowflake-thermometer {% else %} mdi:snowflake-thermometer {% endif %}'

@Abel dans ton cas, tu veux charger des sensor input_number, depuis un package qui s’appelle input_number si j’ai bien compris. tu devrais donc avoir dans ton package test :

input_number: (le nom du package)
  input_number:
    test_position:
      name: "Test - Position désirée"
      min: -1
      max: 100
      step: 1
      unit_of_measurement: "%"```  

le but du package est plus de permettre de regrouper tout ce qui est lié à un périphérique ou une fonction dans un même package (exemple, des scripts, sensor, automation, etc… tous liés. Comme dans mon exemple lié aux fonctionnalités de gestion des mes radiateurs).

celà me semble avoir moins d’intérêt si un package est uniquement lié à un type d’objet H.A (comme ton exemple avec un package input_number qui ne charge que des input_number), pour cet usage, les includes semblent une meilleure solution.

1 « J'aime »

:+1: Merci pour vos explications, Il me reste quelques points a éclaircir mais je progresse.

Merci pour ton retour.

Juste une petite question: Pourquoi ce Tiko au début de ton fichier?

Si j’ai bien compris, tu as :
dossier Config |
puis un dossier packages|
puis un dossier tiko | avec le fichier tiko.yaml

ma questions :
est il possible d’avoir un 2eme fichier dans le dossier tiko.
exemple : avoir tiko1.yaml avec les sensors et des inputs…
et avoir tiko2.yaml avec les scripts et les automations ?

c’est le nom de mon package, destiné à gérer mes radiateurs via la solution proposée par TIKO…
le fichier de conf est /config/packages/tiko/tiko.yaml, ce qui veut dire qu’il cherche la config du package tiko dans ce fichier…

depuis ton package, tu peux refaire des include…
sensor: !include…

sinon une autre approche est de charger tous les yaml du dossier package, voir l’exemple ici :

+
le contenu des fichier YAML dans le dossier packages:

Une autre petite question.
J’ai modifier mon organisation avec packages, dans les 2 exemples ci dessous lequel type de fichier.yaml je dois conserver. je m’y perd un peu avec l’ancienne et la nouvelle méthode pour les templates. (les 2 sont apparemment fonctionnel, j’ai pas d’erreur)

test 1
# compteur eau test 1
template:
  - sensor:
      - name: "test ECS mètres cubes"
        unique_id: test_ecs_metres_cubes
        icon: mdi:counter
        device_class: volume    
        state: >
          {{ (states('counter.compteur_ecs') | float(default=0) / 1000) | round(3) }}
        unit_of_measurement: "m³"

      - name: "test ECS litres"
        unique_id: test_ecs_litres
        icon: mdi:counter
        device_class: volume
        state_class: measurement
        state: >
          {{ (states('counter.compteur_ecs') | float(default=0) / 1) | round(3) }}
        unit_of_measurement: "L"

utility_meter:
# Utility water Counter EF
  test_water_ef_l_hourly :
    source : sensor.compteur_ef_litre 
    cycle : hourly
  test_water_ef_l_daily :
    source : sensor.compteur_ef_litre 
    cycle : daily        

test 2
# compteur eau test 2
sensor:
- platform: template
  sensors:
# Comptage Eau  

    ecs_metres_cubes:
      friendly_name: "compteur eau chaude m³"
      icon_template: mdi:counter
      device_class: water 
      unit_of_measurement: "m³"      
      value_template: >
        {{ (states('counter.compteur_ecs') | float(default=0) / 1000) | round(3) }}


    ef_metres_cubes: 
      friendly_name: "Compteur eau froide m³"
      icon_template: mdi:counter
      device_class: water
      unit_of_measurement: "m³"      
      value_template: >
        {{ (states('counter.compteur_ef') | float(default=0) / 1000) | round(3) }}
        
   
utility_meter:
# Utility water Counter EF
  util_water_ef_l_hourly :
    source : sensor.compteur_ef_litre 
    cycle : hourly
  util_water_ef_l_daily :
    source : sensor.compteur_ef_litre 
    cycle : daily

Il me semble que c’est le modèle 1 qu’il convient d’appliquer maintenant…

c’est bien la méthode 2, la 1 est l’ancienne manière, qui génère des alertes depuis la 2023.6 dans h.a annonçant l’arrêt de la prise en charge à partir de 2023.8.

Je pense que tu as inversé… :grin: si tu peux me confirmer

Bonjour Benoit (@noiwid)

Je pense que c’est línverse, @pascal_ha a raison il fait référence aux sensors, binary_ sensors utilisant platform: template

sensor:
  - platform: template

ou

binary_sensor:
  - platform: template

Sont les anciens formats (Legacy Configuration Format)

C’est command_line qui genère des erreurs depuis 2023.06 et dont l’ancien format sera supprimé dans 2023.8.

Cordialement,

Abel

Bonjour à tous,

J’ai enfin réussi a faire remonter mon input_number contenu dans le package. Je vais faire un peu de nettoyage pour savoir ce qui l’a fait fonctionner et je vous ferai un retour.
Merci a tous pour votre aide.

1 « J'aime »

Alors, ce retour ? :smile:

J’ai pas trop eu le temps de finir. Mais aujourd’hui ça fonctionne. Et c’est plutôt bien pratique.

Salut

je migre progressivement aussi de mon coté

c’est vrai que c’est vraiment pratique et propre

il n’y a qu’un truc entre autre que j’ai pas encore migré c’est les automations