La vie d’une petite famille tourne autour des jours d’école. Du coup, certains automatismes d’une maison connectée vont dépendre du mode de vie des marmots.
Impensable, par exemple, d’ouvrir automatiquement tous les volets de la maison quand on se lève un dimanche matin si les enfants, eux, ne sont pas levés.
Un jour d’école, c’est quoi ?
Un jour d’école, c’est :
- Pas un jour ferié
- Pas un mecredi/samedi/dimanche (rayez la mention inutile)
- Pas un jour de vacances
Les approches possibles sous Home Assistant
J’ai dégagé pour ma part deux façons différentes d’aborder le problème : via les « Local Calendar », et via les « Restful templates ».
Local Calendar
Local Calendar est une intégration native de Home Assistant. Elle permet d’utiliser des fichiers de format ICS stockés en local pour gérer des évènements ou des états.
Il suffirait, en théorie, de télécharger régulièrement un calendrier des jours fériés et un calendrier des vacances.
Restful templates
Cette méthode permettrait d’appeler des services REST pour vérifier si un jour est pendant les vacances ou non, ferié ou non
Open data : les services du gouvernement Français
Pour obtenir ces données, nous allons nous tourner vers les données ouvertes du gouvernement Français.
Le service des jours fériés
Le gouvernement met à disposition un service permettant d’obtenir les jours feriés de l’année
https://api.gouv.fr/les-api/jours-feries
Les données sont disponibles en différents formats :
- CSV
- ICS
- Json via un service REST
Il est largement possible d’importer l’ICS et de le mettre au sein de son installation Home Assistant. Mais vu que je n’ai pas envie de faire des imports réguliers, je préfère passer par le JSON.
Pour nos besoins l’URL du service sera
https://calendrier.api.gouv.fr/jours-feries/metropole/{{année en cours}}.json
Ce service nous envoie des données de la sorte
resultObj = {
"2025-01-01": "Jour de l'an",
"2025-04-21": "Lundi de Pâques",
"2025-05-01": "Fête du Travail",
"2025-05-08": "Victoire des alliés",
"2025-05-29": "Ascension",
"2025-06-09": "Lundi de Pentecôte",
"2025-07-14": "Fête Nationale",
"2025-08-15": "Assomption",
"2025-11-01": "Toussaint",
"2025-11-11": "Armistice",
"2025-12-25": "Noël"
}
Il suffira juste de vérifier que la date du jour est dans les clefs de l’objet JSON utilisé en tant que tableau associatif.
Le service des vacances scolaires
Ce service est fourni par le ministère de l’éducation nationale.
On peut le trouver à cette adresse
https://data.education.gouv.fr/explore/dataset/fr-en-calendrier-scolaire/api/
C’est un service remarquablement complet. Il permet d’utiliser les données sous plusieurs formats dont, notamment ICS et JSon. Mais il a également un constructeur d’appel REST extrêment élaboré : on peut préciser des clauses assez proches de ce qu’on a en SQL, avec du WHERE et du ORDER BY par exemple, et la page génèrera automatiquement l’URL du service à appeler. Perso, j’aime beaucoup.
Par exemple, l’URL suivante donne les prochaines vacances par ordre chronologique pour l’académie de Grenoble
Le résultat est sous la forme
resultObj ={
"total_count": 4,
"results": [
{
"description": "Vacances de Noël",
"population": "-",
"start_date": "2023-12-22T23:00:00+00:00",
"end_date": "2024-01-07T23:00:00+00:00",
"location": "Grenoble",
"zones": "Zone A",
"annee_scolaire": "2023-2024"
},
{
"description": "Vacances d'Hiver",
"population": "-",
"start_date": "2024-02-16T23:00:00+00:00",
"end_date": "2024-03-03T23:00:00+00:00",
"location": "Grenoble",
"zones": "Zone A",
"annee_scolaire": "2023-2024"
},
{
"description": "Vacances de Printemps",
"population": "-",
"start_date": "2024-04-12T22:00:00+00:00",
"end_date": "2024-04-28T22:00:00+00:00",
"location": "Grenoble",
"zones": "Zone A",
"annee_scolaire": "2023-2024"
},
{
"description": "Pont de l'Ascension",
"population": "-",
"start_date": "2024-05-09T22:00:00+00:00",
"end_date": "2024-05-10T22:00:00+00:00",
"location": "Grenoble",
"zones": "Zone A",
"annee_scolaire": "2023-2024"
}
]
}
C’est riche et en vrai nous n’avons pas besoin de tout ça. Il suffit en réalité de vérifier si la date du jour est comprise entre le début et la fin de vacances scolaires pour l’académie, et la valeur qui nous intéresse c’est le total_count qui doit être supérieur à 0.
Donc, nous allons utiliser une URL comme celle ci:
https://data.education.gouv.fr/api/explore/v2.1/catalog/datasets/fr-en-calendrier-scolaire/records?where=location%20%3D%20%22Grenoble%22%20and%20start_date%20%3E%3D%20now()%20and%20end_date%20%3C%3D%20now()&limit=20
Il suffira juste de changer l’académie si vous voulez intégrer ce service à votre HA. Chose importante : les ponts de jours fériés admis par l’éducation nationale sont inclus !
Intégration dans Home Assistant
Il faut maintenant intégrer tout cela dans Home Assistant.
Alors, désolé, il va falloir mettre les mains dans le camboui et aller modifier le YAML de configuration.
Pour cela, on utilisera l’outil que l’on préfère, je conseille pour ma part l’Add On « File Editor » qui a tout ce qu’il faut sous la main.
Nous allons rajouter les lignes suivantes sous la partie « Sensor »
sensor:
# Is today a bank holliday ?
- platform: rest
resource_template: https://calendrier.api.gouv.fr/jours-feries/metropole/{{now().year}}.json
name: is_bank_holliday
value_template: >
{% set today = '%d-%d-%d' | format(now().year,now().month,now().day) %}
{{ today in value_json.keys() }}
# Is today a school hollyday ?
- platform: rest
resource: https://data.education.gouv.fr/api/explore/v2.1/catalog/datasets/fr-en-calendrier-scolaire/records?where=location%20%3D%20%22Grenoble%22%20and%20start_date%20%3E%3D%20now()%20and%20end_date%20%3C%3D%20now()&limit=20
name: is_school_holliday
value_template: >
{{ value_json.total_count > 0 }}
Je vais commencer par le capteur « is_school_hollyday » qui est le second.
Vu que nous avons bien pensé l’URL, fixe, de notre appel Rest, nous pouvons utiliser le paramètre « resource » directement, et le pointer sur l’URL. Comme nous disions, nous verifions juste si le paramètre « total_count » est supérieur à 0. Le template renverra un booléen, True ou False. Facile.
Pour les jours feriés, c’est un peu différent. Nous voulons uniquement les jours fériés pour l’année en cours (pas la peine de tout se ramener), et pour cela nous devons passer un paramètre dans l’URL.
Nous utiliserons donc à la place de « resource » un « resource_template » dans lequel nous pouvons insérer une valeur calculée via les templates Jinja, ici « {{ now().year }} » qui donnera l’année du jour.
Nous allons ensuite traduire la date du jour au format des données JSON renvoyées
{% set today = ‘%d-%d-%d’ | format(now().year,now().month,now().day) %}
« %d-%d-%d » est une chaine de caractère préformatée qui attend 3 entiers (%d). Nous les fournissons via le filtre format. Le résultat sera une chaine sous la forme « 2023-11-23 »
La propriété « keys » de la json_value renvoyée par le service contiendra les dates des différents jours fériés, il s’agit d’un set, nous pouvons donc vérifier si la date du jour est dedans, ce qui nous dira si le jour courant est ferié.
Après cela, il ne faut pas oublier de redémarrer Home Assistant Core, via les developper tools ou les settings par exemple.
Nous obtenons le résultat suivant
Finalement, nous allons utiliser la partie « template » de la config pour rajouter un capteur binaire
template:
- binary_sensor:
- name: is_school_day
state: >
{% set is_weekday = ( now().isoweekday() < 6 ) %}
{{ is_weekday and is_state("sensor.is_bank_holliday","False") and is_state("sensor.is_school_holliday","False" ) }}
La fonction « now().isoweekday() » issue de la partie DateTime de Python nous renvoit une valeur numérique allant de 1 pour Lundi à 7 pour Dimanche.
Donc nous obtenons un capteur binaire (on off) dont la valeur est positive si :
- Nous sommes un jour de semaine (du Lundi au Vendredi)
- Qui n’est pas en période de vacances scolaires ou un pont
- Qui n’est pas non plus un jour férié 🙂