Horaires SNCF via api.sncf

Bonjour,
Voilà après quelque jours de prompting GPT j’ai réussis à récupérer et afficher les horaires des trains dans HA. Je sais qu’il y a une integration dédié mais j’ai préféré utiliser directement une api.
Voilà ce qu’il vous faut pour le faire:

  1. S’enregistrer pour obtenir un token API sur Demandez votre clé d'accès gratuite - SNCF NUMÉRIQUE

  2. Recupérer le code de la gare ( Nice pour moi ) depuis Fréquentation en gares — SNCF Open Data

  3. Créer un sensor dans rest.yaml :

# SNCF Departures from Nice
  - resource: https://<votre token ici>@api.sncf.com/v1/coverage/sncf/stop_areas/stop_area:SNCF:87756056/departures?data_freshness=realtime
    scan_interval: 60
    sensor:
      - name: SNCF Next Departure Nice
        value_template: >
          {% set departures = value_json['departures'] %}
          {% if departures | length >= 1 %}
            {% set dep1 = departures[0]['stop_date_time']['departure_date_time'] %}
            {{ strptime(dep1, '%Y%m%dT%H%M%S').strftime('%Y-%m-%d %H:%M:%S') }}
          {% else %}
            No upcoming departures
          {% endif %}
        json_attributes:
          - departures
  1. Créer une carte:
    4.1:
type: markdown
title: Trains départs Nice
content: >-

  {% set departures = state_attr('sensor.sncf_next_departure_nice',
  'departures') %}

  {% if departures and departures | length >= 1 %}

  {% for next_train in departures[:10] %}

  {% set dep_time = next_train['stop_date_time']['departure_date_time'] %}

  {% set base_dep_time =
  next_train['stop_date_time']['base_departure_date_time'] %}

  {% set delay_minutes = ((strptime(dep_time, '%Y%m%dT%H%M%S') -
  strptime(base_dep_time, '%Y%m%dT%H%M%S')).seconds / 60) | int %}

  {% set dep_time_formatted = strptime(dep_time,
  '%Y%m%dT%H%M%S').strftime('%H:%M') %}

  {% set base_dep_time_formatted = strptime(base_dep_time,
  '%Y%m%dT%H%M%S').strftime('%H:%M') %}

  {% if delay_minutes > 0 %}

  {% set display_time = "<s>" ~ base_dep_time_formatted ~ "</s> " ~
  dep_time_formatted %}

  {% else %}

  {% set display_time = dep_time_formatted %}

  {% endif %}

  {% if 'canceled' in next_train.get('additional_informations', []) %}

  {% set status = "🚫 Annulé" %}

  {% elif delay_minutes > 0 %}

  {% set status = "🚨 Retard: " ~ delay_minutes ~ " min" %}

  {% else %}

  {% set status = "✅ À l'heure" %}

  {% endif %}

  {% set destination =
  next_train['display_informations']['direction'].split('(')[0].strip() %}

  {% if destination in ['Monaco', 'Menton', 'Ventimiglia'] %}

  **{{ display_time }} {{ destination.upper() }}, {{
  next_train['display_informations']['trip_short_name'] }} - {{ status }}**

  {% else %}

  {{ display_time }} {{ destination }}, {{
  next_train['display_informations']['trip_short_name'] }} - {{ status }}

  {% endif %}

  {% endfor %}

  {% else %}

  🚫 Aucun départ imminent

  {% endif %}

4.2:

type: markdown
title: Trains départs Nice2
content: >-
  {%- set departures = state_attr('sensor.sncf_next_departure_nice',
  'departures') -%}   {%- if departures and departures | length >= 1 %}
    {%- for next_train in departures[:10] %}
      {%- set stop_date_time = next_train.get('stop_date_time', {}) -%}
      {%- set dep_time_str = stop_date_time.get('departure_date_time') -%}
      {%- set base_dep_time_str = stop_date_time.get('base_departure_date_time') -%}
      {%- if dep_time_str and base_dep_time_str %}
        {%- set dep_time = strptime(dep_time_str, '%Y%m%dT%H%M%S') -%}
        {%- set base_dep_time = strptime(base_dep_time_str, '%Y%m%dT%H%M%S') -%}
        {%- if dep_time and base_dep_time %}
          {%- set delay_minutes = ((dep_time - base_dep_time).total_seconds() / 60) | int -%}
          {%- set dep_time_formatted = dep_time.strftime('%H:%M') -%}
          {%- set base_dep_time_formatted = base_dep_time.strftime('%H:%M') -%}
          {%- if delay_minutes > 0 %}
            {%- set display_time = "<s>" ~ base_dep_time_formatted ~ "</s> " ~ dep_time_formatted -%}
            {%- set status = "🚨 Retard: " ~ delay_minutes ~ " min" -%}
          {%- else %}
            {%- set display_time = dep_time_formatted -%}
            {%- set status = "" -%}
          {%- endif %}
          {%- set display_informations = next_train.get('display_informations', {}) -%}
          {%- set direction = display_informations.get('direction', '') -%}
          {%- set destination = direction.split('(')[0].strip() -%}
          {%- set trip_short_name = display_informations.get('trip_short_name', '') -%}
          {%- set commercial_mode = display_informations.get('commercial_mode', '') -%}
          {%- set train_type_and_number = commercial_mode ~ '-' ~ trip_short_name -%}
          {%- if destination in ['Monaco', 'Menton', 'Ventimiglia'] %}
            {%- set output_line = "**" ~ display_time ~ "** **" ~ destination | upper ~ "**, " ~ train_type_and_number -%}
          {%- else %}
            {%- set output_line = "**" ~ display_time ~ "** " ~ destination ~ ", " ~ train_type_and_number -%}
          {%- endif %}
          {%- if status %}
            {%- set output_line = output_line ~ " - " ~ status -%}
          {%- endif %}
          {{ output_line }}
        {%- endif %}
      {%- endif %}
    {%- endfor %}
  {%- else %}
    '🚫 Aucun départ imminent'
  {%- endif %}

  1. Admirer votre carte et suivre les départs :grin: (j’ai mis en gras/majuscule les destinations qui m’itéresse le plus )
    5.1:

    5.2:
7 « J'aime »

Hello , dans le fichier Rest.yaml , si je colle le code tel que j ai une erreur ,
Je l ai bien déclaré dans config.yaml , ,
Tu peux m orienté stp ?

quelle est l’erreur?
Si tu declares le sensor dans configuration.yaml, pas besoin de le mettre dans rest.yaml.
Si tu veux rest.yaml, il faut dans configuration.yaml indiquer que pour les sensors rest il y a un autre fichier. Tu mets donc:
rest: !include rest.yaml

[quote=« akunia, post:3, topic:48506 »]

Magique :slight_smile: simplement un problème entre le clavier et la chaise ^^
Tuto parfaitement fonctionnel !
Merci a toi

T’es sur que c’est bon? Ca m’étonnerai que tu ai des départs de Lille à Sospel par ex :laughing:
Blague à part, je suis content que ça servira à quelqu’un.

Merci ^^ en effet tu as tout a fait raison ^^


c est une peu plus de mon coin ^^

Salut,
J’ia modifié un peu la carte ( point 4.2 et 5.2 dans le premier post) en enlevant l’information sur les trains annulés ( je ne voie pas la data dans le sensor qui permettrai de le determiner), en enlevant l’information sur les trains qui sont à l’heure, en ajoutant le type de train ( p.ex. TER) et rendant la carte plus compacte. Voici ce que ça donne:

Ça marche aussi chez moi. Merci @akunia pour ce partage.

Avoir les horaires des trains dans HA, ça ouvre plein de possibilités. Par exemple :

  • Avoir des notifications si un train est en retard.
  • Décaler l’heure du réveil si le train est en retard ou annulé (bon encore faudrait-il avoir un réveil pilotable :laughing:)

Je t’en prie @XavB :grin:

Décaler l’heure du réveil si le train est en retard ou annulé (bon encore faudrait-il avoir un réveil pilotable :laughing:)

Comme j’ai mentionné je n’ai pas trouvé comment tracker les trains annulés, donc pas possible ( a moins que quelq’un a une idée, car rien dans le réponse à la requête ne permet de le trouver).
Pour le réveil en fonction de retards de train, tu peux sans doute pouvoir le configurer avec l’app sur le téléphone si tu n’as pas de source audio pilotable.

Perso, je prends toujours le même train le matin, donc une bonne stratégie serait de détecter son absence du tableau d’affichage.

Je vais essayer de jouer avec https://api.sncf.com/v1/coverage/sncf/disruptions endpoint pour voir si l’info remonte, mais cela impliquera un autre sensor donc un rafraichissement moins fréquent car sncf limite le compte gratuit à 5000 requêtes/jour. Si on a plusieurs stations faudra faire attention