Récupération des couleurs Tempo EDF avec un ESP32

Ce tuto concerne uniquement ceux qui ont un contrat Tempo chez EDF.

Il explique comment accéder à la couleur du jour Tempo en cours et du lendemain, en utilisant un ESP32, qui facilite beaucoup les connexions sécurisées en https grâce à ses fonctionnalités.

Il existe une méthode relativement simple consistant à envoyer une requête HTTP GET à l'adresse suivante chez EDF :
https://particulier.edf.fr/services/rest/referentiel/searchTempoStore?dateRelevant=AAAA-MM-JJ
(remplacer AAAA-MM-JJ par la date du jour)
Cette requête retourne un résultat au format JSON d'où on peut extraire les infos des jour J et J+1.

Un exemple simple de code (necessitant les bibliothèques HTTPClient et ArduinoJson) pour vous donner l'idée :

  HTTPClient http;
  String requeteTempo = ("https://particulier.edf.fr/services/rest/referentiel/searchTempoStore?dateRelevant=");
  requeteTempo += String(annee)+'-'+String(mois)+'-'+String(jour);   // Année, mois et jour d'aujourd'hui
  http.begin(requeteTempo);
  http.setConnectTimeout(2000);
  httpCode = http.GET();
      if (httpCode == HTTP_CODE_OK)
      {
        StaticJsonDocument<100> doc;
        deserializeJson(doc, (http.getString()));
        JourJ = doc["couleurJourJ"].as<String>();   // Peut être "TEMPO_BLEU", "TEMPO_BLANC", "TEMPO_ROUGE"
        JourJ1 = doc["couleurJourJ1"].as<String>(); // Peut être "TEMPO_BLEU", "TEMPO_BLANC", "TEMPO_ROUGE", "NON_DEFINI"
        // le ".as<String>()" à la fin des requêtes Json sort la chaîne de caractère du résultat en String
        // plus facile à manipuler
      }
  http.end();

Ce code a l'avantage d'être simple, l'inconvénient éventuel c'est qu'EDF ne donne la couleur du lendemain qu'à 11h.

En fait les couleurs Tempo se décident chez RTE (Réseau de Transport de l'Electricité).
Leur site met à disposition une API qui donne la couleur Tempo du lendemain bien plus tôt, parfois déjà vers 6h du matin.

Sauf que la procédure est un peu plus complexe.
Il faut tout d'abord ouvrir un compte chez RTE et s'abonner à l'API correspondante.

Et ensuite la requête (sécurisée) se fera en deux temps, avec une première requête pour recevoir un token (jeton), puis une deuxième, où l'on s'identifiera avec le token obtenu pour pouvoir obtenir les couleurs des jours Tempo.

Voici comment s'abonner à l'API correspondante :
Se rendre à cette adresse : https://data.rte-france.com/catalog/all_categories
Là vous trouverez la liste des nombreuses API que propose RTE.

La première opération à faire est de créer un compte chez RTE, pour cela cliquer en haut à droite sur "Se connecter", puis, sur la nouvelle page qui s'ouvre, sur "Créer mon compte"

Ceci fait, et une fois connecté à son compte, on peut maintenant aller choisir l'API qui nous intéresse, du doux noms de "Tempo Like Supply Contract" et à s'y abonner en cliquant sur le bon bouton.

En allant dans "Mes applications" vous devriez vous retrouver avec une fenêtre ressemblant à ça :

Ce qui nous intéresse ici c'est le bouton "Copier en base 64", qui va nous permettre de récupérer une chaîne de caractère qui comprend l'ID client et l'ID secret, chaîne dont nous allons avoir besoin dans notre programme.
Il y a aussi sur la page de l'API un "Guide utilisateur de l'API", qui explique "comment ça marche" !

Voilà du côté RTE tout devrait être bon, reste maintenant à programmer la récupération des couleurs Tempo.

Cela implique d'envoyer une requête POST en https, et aussi de connaître le certificat racine du site de RTE nécessaire pour les connexions sécurisées que nous allons effectuer.
N'ayant jamais fait de requête POST pour accéder à un site en https, ni utilisé de certificat racine, j'avoue que j'ai passé quelques heures à m'arracher les cheveux pour trouver les bonnes syntaxes (je suis très loin d'être un dieu du C++) et que je n'étais pas loin d'abandonner...

Heureusement, dans mes recherches je suis tombé sur cette page du forum Arduino :

@J-M-L donne une solution quasi clés-en-mains pour accéder à une autre API de RTE
Je n'avais donc plus qu'à modifier les liens pour accéder à l'adresse correspondant à l'API "Tempo Like Supply Contract" et à faire la requête me permettant de récupérer mes couleurs TEMPO.

Donc avant d'aller plus loin, à tout seigneur tout honneur :
/----------------------------------------------------------------------------------------------
UN GRAND MERCI à @J-M-L QUI A DÉJÀ FAIT 80% DU TRAVAIL
ET SANS LEQUEL JE NE SERAIS PAS ARRIVÉ A ÉCRIRE CE TUTO
SANS M'ARRACHER LES QUELQUES CHEVEUX QUI ME RESTENT !
/----------------------------------------------------------------------------------------------

Pour récupérer les couleurs Tempo du jour et du lendemain, il faudra faire une requête avec comme date de début la date d'aujourd'hui et comme date de fin la date d'aujourd'hui + 2 jours.

Voici comme exemple un programme qui se connecte au Wifi, se synchronise sur un serveur NTP et qui ensuite interroge le site de RTE tous les quarts d'heures.
Les couleurs des jour J et J+1 renseignerons les variables String "JourJ" et "JourJ1".
Sans plus attendre voici le code :

/* **** Routine d'extraction des couleurs Tempo du site de RTE ****
 * ****************** **2023 Roland MATHIS ************************


   Les 2 requêtes HTTP utilisées dans ce programme ont été créées
   par J-M-L du forum francophone Arduino (un très GROS merci !)
   ici : https://forum.arduino.cc/t/api-rte-ecowatt/1017281
   D'où la notice de copyright ci-dessous :

 ============================================
  KEEP THIS INFORMATION IF YOU USE THIS CODE

  This "API RTE" demo code for ESP 32 is placed under the MIT license
  Copyright (c) 2022 J-M-L For the Arduino Forum

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
  ===============================================
*/

#include <WiFi.h>
#include <esp_sntp.h>      // Permet le contrôle de la synchro avec un serveur NTP
#include <HTTPClient.h>
#include <ArduinoJson.h>

// ******* Valeurs nécessaires à l'accès à l'API "Tempo Like Supply Contract" de RTE *******
    // ID Client et ID Secret en base 64, créées sur le site de RTE avec le bouton "Copier en base 64"
    #define identificationRTE   "YTI1Y----------------------------------------------------------------ExMmUzMDZmNDZjMg=="

    const char * idRTE = "Basic " identificationRTE;

    // Certificat racine (format PEM) de https://digital.iservices.rte-france.com
    const char* root_ca = \
    "-----BEGIN CERTIFICATE-----\n" \
    "MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\n" \
    "A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\n" \
    "Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\n" \
    "MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\n" \
    "A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\n" \
    "hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\n" \
    "RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\n" \
    "gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\n" \
    "KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\n" \
    "QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\n" \
    "XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\n" \
    "DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\n" \
    "LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\n" \
    "RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\n" \
    "jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n" \
    "6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\n" \
    "mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\n" \
    "Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\n" \
    "WD9f\n" \
    "-----END CERTIFICATE-----\n";

bool FirstCycleDone = false;                 // Mis à "true" après la première boucle de loop()
String JourJ, JourJ1 ;                       // Strings contenant les couleur du jour actuel et du lendemain

// ******** Variables pour gérer l'intervalle de lecture de l'API de RTE
long intervalle = 900000;                    //  = 15 minutes
unsigned long top_lect_API_RTE;

// ******** Valeurs en relation avec l'horloge internet et la gestion de la date et de l'heure
const char* ntpServer = "fr.pool.ntp.org";   // Adresse du serveur NTP
time_t moment;                               // utilisé pour stocker la date et l'heure au format unix
struct tm loc;                               // Structure qui contient les informations de l'heure et de la date
struct tm loc2;                              // Structure qui contient les informations de l'heure et de la date de dans 2 jours

void setup()
{
  Serial.begin(115200);
  delay(2000);

  connect_WiFi();
}

String errorDescription(int code, HTTPClient& http)
// Liste des codes d'erreurs spécifique à l'API RTE ou message général en clair
{
  switch (code) 
  {
    case 400: return "Erreur dans la requête";
    case 401: return "L'authentification a échouée";
    case 403: return "L’appelant n’est pas habilité à appeler la ressource";
    case 413: return "La taille de la réponse de la requête dépasse 7Mo";
    case 414: return "L’URI transmise par l’appelant dépasse 2048 caractères";
    case 429: return "Le nombre d’appel maximum dans un certain laps de temps est dépassé";
    case 509: return "L‘ensemble des requêtes des clients atteint la limite maximale";
    default: break;
  }
  return http.errorToString(code);
}

bool getRTEData()
// ****** Deux requêtes vers l'API de RTE, nécessite que le WiFi soit actif ******
{
  int HTTPcode;
  const char* access_token;
  bool requeteOK = true;
  const char* oauthURI =   "https://digital.iservices.rte-france.com/token/oauth/";

  if (WiFi.status() != WL_CONNECTED)
  {
    Serial.println("WiFI non disponible. Requête impossible");
    return false;
  }
  WiFiClientSecure client;     // on passe en connexion sécurisée (par https...)
  HTTPClient http;
  client.setCACert(root_ca);   // permet la connexion sécurisée en vérifiant le certificat racine

// ************** Première des deux requêtes pour obtenit un token **************
  http.begin(client, oauthURI);

  // Headers nécessaires à la requête
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  http.addHeader("Authorization", idRTE);

  // Send HTTP POST request     
  HTTPcode = http.POST(nullptr,0);     

  if (HTTPcode == HTTP_CODE_OK)
  {
    String oauthPayload = http.getString();
    Serial.println("------------ Contenu renvoyé par la requête 1 : ------------");
    Serial.println(oauthPayload);
    Serial.println("------------------------------------------------------------\n");
    StaticJsonDocument<192> doc;
    DeserializationError error = deserializeJson(doc, oauthPayload);
    if (error)     // cas où il y a un problème dans le contenu renvoyé par la requête
    {
      Serial.print("deserializeJson() failed: ");
      Serial.println(error.c_str());
      access_token = "";
      requeteOK = false;
    }
    else           // cas où le contenu renvoyé par la requête est valide et exploitable
    {
      access_token = doc["access_token"];
    }
  } 
  else 
  {
    Serial.print("erreur HTTP POST: ");
    Serial.println(errorDescription(HTTPcode, http));
    requeteOK = false;
  }
  http.end();
  if (!requeteOK) return false;

// ***** Deuxième des deux requêtes pour obtenir la couleur des jours, nécessitant le token *****

  // REMARQUES : l'adresse pour la requête est sous la forme :
  // https://digital.iservices.rte-france.com/open_api/tempo_like_supply_contract/v1/tempo_like_calendars?start_date=2015-06-08T00:00:00%2B02:00&end_date=2015-06-11T00:00:00%2B02:00
  // avec (dans notre cas) "start_date" la date du jour et "end_date" la date du jour + 2
  // Après les "%2B" (signe +) on a le décalage horaire par rapport au temps UTC. On doit obligatoirement avoir "02:00" en heures d'été et "01:00" en heure d'hiver
  // Les heures de début et de fin peuvent rester à "T00:00:00" pour la requête mais doivent être présentes !
  // Pour les mois et les jours, les "0" au début peuvent être omis dans le cas de nombres inférieurs à 10

  String requete = "https://digital.iservices.rte-france.com/open_api/tempo_like_supply_contract/v1/tempo_like_calendars?start_date=";
  requete += String(loc.tm_year+1900)+"-"+String(loc.tm_mon+1)+"-"+String(loc.tm_mday)+"T00:00:00%2B0"+String(loc.tm_isdst+1)+":00&end_date="+String(loc2.tm_year+1900)+"-"+String(loc2.tm_mon+1)+"-"+String(loc2.tm_mday)+"T00:00:00%2B0"+String(loc2.tm_isdst+1)+":00";
  // Remarque : "loc.tm_isdst" est à 0 en heure d'hiver et à 1 en heure d'été   
  
  Serial.println("---------------- Adresse pour la requête 2 : ---------------");
  Serial.println(requete);
  Serial.println("------------------------------------------------------------\n");
  http.begin(client, requete);

    String signalsAutorization = "Bearer "+ String(access_token);
    
    // Headers nécessaires à la requête
    http.addHeader("Authorization", signalsAutorization.c_str());
    http.addHeader("Accept", "application/xml");
    // Mettre la ligne précédente en remarque pour avoir le résultat en json plutôt qu'en xml

    // On envoie la requête HTTP GET
    HTTPcode = http.GET();

    if (HTTPcode == HTTP_CODE_OK)
    {
      String recup = http.getString();              // "recup" est une chaîne de caractères au format xml
      Serial.println("------------ Contenu renvoyé par la requête 2 : ------------");
      Serial.println(recup);
      Serial.println("------------------------------------------------------------\n");

      // Récupération des couleurs
      int posi = recup.indexOf("<Couleur>",100);    // Recherche de la première occurence de la chaîne "<Couleur>"
                                                    // à partir du 100ème caractère de "recup"
      if (recup.length() > 200)                     // Si la couleur J+1 est connue le String "recup" fait plus de 200 caractères 
      {
        JourJ1 = (recup.substring(posi+9,posi+13)); // Récupération du substring des 4 caractères contenant couleur du lendemain
                                                    // peut être "BLEU", "BLAN" ou "ROUG"
        posi = recup.indexOf("<Couleur>",230);      // Recherche de la deuxième  occurence de la chaîne "<Couleur>"
                                                    // à partir du 230ème caractère de "recup"
        JourJ = (recup.substring(posi+9,posi+13));  // Récupération du substring des 4 caractères contenant la couleur du jour
                                                    // peut être "BLEU", "BLAN" ou "ROUG"
      }
      else                                          // cas où la couleur de J+1 n'est pas encore connue
      {
        JourJ = (recup.substring(posi+9,posi+13));  // Récupération du substring des 4 caractères contenant la couleur du jour
                                                    // peut être "BLEU", "BLAN" ou "ROUG"
        JourJ1 = "NON_DEFINI";
      }
      Serial.print("Couleur Tempo du jour : "); Serial.println(JourJ);
      Serial.print("Couleur Tempo de demain : "); Serial.println(JourJ1 + "\n");
    } 
    else
    {
      Serial.print("erreur HTTP GET: ");
      Serial.print(HTTPcode);
      Serial.print(" => ");
      Serial.println(errorDescription(HTTPcode, http));
      requeteOK = false;
    }
  http.end();
  return requeteOK;
}

void connect_WiFi()
{
  const char* ssid = "mon_SSID";
  const char* mdp = "mon_mot_de_passe";
  const int TimeOut_connexion = 40;                 // Time-out connexion après 40 essais
  int timeOut_counter = 0;                          // Compteur de nombre d'essais de connexion au Wifi
  sntp_sync_status_t syncStatus;                    // Renvoie le statut de synchro au serveur SNTP, nécessite la librairie "esp_sntp.h"

  Serial.println("Connection au WiFi");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, mdp);

  while (WiFi.status() != WL_CONNECTED) 
    {
     delay(250);
     Serial.write('.');
     ++timeOut_counter;                             // redémarrage de l'ESP si pas de connexion pendant 10 sec
    if (timeOut_counter > TimeOut_connexion) ESP.restart();

    }
  Serial.print("\nConnecté au WiFi avec l'adresse IP ");
  Serial.println(WiFi.localIP());
  delay(1000);

  // Prise en compte automatique du décalage horaire et des dates de début et de fin d'heure d'été par rapport au temps UTC
  // Fonction intégrée à la librairie "time.h"
  configTzTime("CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", ntpServer);

  // Vérification de la synchronisation effective de l'heure au démarrage  
  timeOut_counter = 0;
  Serial.println("\nSynchronisation de l'heure en cours ");
   while (syncStatus != SNTP_SYNC_STATUS_COMPLETED)
   {
    syncStatus = sntp_get_sync_status();    
    delay(250); 
     Serial.write('.');
    ++timeOut_counter;                              // redémarrage de l'ESP si pas de connexion pendant 10 sec
    if (timeOut_counter > TimeOut_connexion) ESP.restart();
   }
  Serial.println("\nSynchronisation de l'heure OK !\n");
  delay(1000);
}

void loop()
{
  // ****** Accès périodique à l'API de RTE ******
  if (millis() - top_lect_API_RTE >=  intervalle || FirstCycleDone == false)  // condition vraie tous les "intervalle" ou au premier loop()
    {
      top_lect_API_RTE=millis();
      // Définition de la date et de l'heure actuelles
      moment = time(NULL);            // Mise de la date et de l'heure au format unix dans la variable "moment" de type time_m
      loc = *(localtime(&moment));    // Mise dans la structure loc des éléments de date et de l'heure
      Serial.printf("Date et heure actuelles : %02d/%02d/%04d %02d:%02d:%02d\n", loc.tm_mday, loc.tm_mon+1, loc.tm_year+1900, loc.tm_hour, loc.tm_min, loc.tm_sec);
      Serial.printf("Décalage par rapport à l'heure UTC actuelle : +%01d heure(s)\n", loc.tm_isdst + 1);

      // Définition de la date et de l'heure de dans 2 jours (172800 = 2 jours en secondes)
      moment = moment+172800;         // Mise de la date et de heure de dans 2 jours au format unix dans la variable "moment" de type time_m
      loc2 = *(localtime(&moment));   // Mise dans la structure loc2 des éléments de date et de l'heure de dans 2 jours
      Serial.printf("Date et heure de dans 2 jours : %02d/%02d/%04d %02d:%02d:%02d\n", loc2.tm_mday, loc2.tm_mon+1, loc2.tm_year+1900, loc2.tm_hour, loc2.tm_min, loc2.tm_sec);       
      Serial.printf("Décalage par rapport à l'heure UTC de dans 2 jours : +%01d heure(s)\n", loc2.tm_isdst + 1);
      Serial.println();

      // REMARQUE : le décalage horaire et l'heure d'été sont automatiquemment pris en compte
      //            grâce à la commande "configTzTime" après la connexion au WiFi

      getRTEData();
    }
  FirstCycleDone = true; 
}

Remarques :

  • Pour la connexion au WiFi il faudra mettre les bons SSID et mot de passe au lieu de "mon_SSID" et "mon_mot_de_passe"
  • Pour la connexion sur le site de RTE il faudra fournir votre identifiant personnel (ligne commençant par "#define identificationRTE" (voir plus haut pour comment le récupérer)
  • J'ai mis pas mal de commentaires pour aider à la compréhension
  • Le programme est à utiliser conjointement avec le moniteur série qui informe de son déroulement
  • La gestion du décalage par rapport à l'heure UTC et par rapport à l'heure d'été/hiver est tout à fait transparente
  • Pour les essais il existe une "sandbox" pour la deuxième requête, à l'adresse
    '''https://digital.iservices.rte-france.com/open_api/tempo_like_supply_contract/v1/sandbox/tempo_like_calendars'''
    Cela permet de ne pas dépasser le quota de requêtes à l'API dans un certain laps de temps.
    Sauf que pendant mes essais je n'ai jamais été gêné par une quelconque limite...
    Le guide en parle mais ne donne aucune info sur ce quota...

En espérant que ça pourra être utile...
Toute critique constructive est bien sûr bienvenue !

Roland

2 Likes

Bravo

Je bouge le post dans la zone des tutos

Genial, ca marche du premier coup sur un Lolin D32. je vais me faire des petits boitiers avec un mini ESP32 sur batterie et 3 LED que je vais mettre à coté du lave linge et du four :face_with_monocle:
Rapide, car j'avais déjà un compte chez RTE pour une intégration de tempo dans Home Assistant !
Joyeuses fêtes. :partying_face:
Eric

1 Like

Content que ça marche !
Bonnes fêtes à vous aussi...

Roland

Bonjour,
Tout nouveau sur ce forum, j'ai une question sur ces infos envoyée par EDF/RTE...
J'ai de la domotique (basée sur eWelink avec modules SonOff) que j'utilise pour piloter divers equipements tels que PAC, Lave-linge,...
J'itilisais une Applet IFTTT pour gérer des modules de relais et prises commandées en fonction des états Tempo.
Ca fonctionnait jusqu'à novembre dernier.
L'Applet IFTTT ne fonctionnant plus j'ai contacté le Helpdesk IFTTT qui a été très reactif et m'a expliqué qu'EDF avait arrêté l'emission des signaux qui permettaient à IFTTT de faire fonctionner leur Applet...

Est-ce que à ce jour (04/01/24) l'application à base d'ESP décrite ici fonctionne toujours.

D'avance merci.

Bonjour et bonne année !

Oui, à ce jour cela marche toujours, j'ai implémenté le code dans ma petite station à base d'ESP 32...

Roland

1 Like

Super.
Merci pour la réponse rapide.

Il a l'air super ton projet.

Bonne année 2024

Bonjour,
@eric4esp32 , c'est exactement ce genre de boitier que je souhaite faire.
J'ai sous la main un "super starter kit UNO R3 project" et je prévois dans les prochaines semaines la mise en place d'un serveur domotique (jeedom ou autre, le choix n'est pas encore arrêté).
Je débute totalement dans le domaine, mes recherches commencent tout juste et j'aurai souhaité avoir des pistes/articles/tuto pour bien commencer. J'ai des notions en électronique et en programmation (php et python notamment).
Merci d'avance.
bonne

Re,
je me répond tout seul car en fouillant un peu, j'ai trouvé plusieurs vidéos qui ont bien dégrossit l'affaire.
Je me faisais un peu tout un monde de tout ça, et finalement ça ne semble pas si compliqué.
Je dis pas que c'est super simple, mais ça semble l'être bien plus que ce que je pensais :slight_smile: .
je repasserai surement pour poser quelques questions au besoin.
A+

Bonjour
Pour la réalisation du boîtier, si j'ai bien compris le code, c'est la sortie suivante qu'il faut modifier pour le traduire en affichage led:

J'ai trouvé sur Amz des esp32 mini S2 a une dizaine d'euros. Y a-t-il des vérifications particulières à faire en fonction des modèles dispo pour ce genre de projet ou bien un esp32 mini est un esp32 mini sans des dizaines de variantes?
Merci pour vos lumières.
Bonne journée.
Cedric

Bonjour !
J'avoue que je ne comprends pas très bien la question (c'est quoi la sortie suivante ?)
Si tu pouvais être un peu plus précis !

Roland

D'après ce que je comprends du code le "serial.print" renvoie un message dans la console au format texte (je suppose) indiquant la couleur du jour.
Ne souhaitant pas mettre d'écran mais plutôt des led, j'en déduis que c'est cette partie du code qu'il faut modifier pour "gérer l'affichage" sur 3 LEDs (bleu blanc et rouge).
A moins que les LEDs sachent interpréter un message sous forme de texte :slightly_smiling_face:.
Mais je me trompe peut-être.
Cordialement

Je comprends mieux !
Oui j'ai écrit ce code pour qu'il indique ce qui se passe dans le moniteur série, pour la compréhension.
Libre à chacun de l'adapter et de faire autre chose avec !
Tu as les variables JourJ et JourJ1 qui contiennent l'info, il suffira de faire par exemple des vérifications du genre :
if (Jour1 == "BLEU") ......
et selon le résultat piloter une sortie.

Roland

Ok, impec.
Y'a moyen des tester le code sans avoir d'esp32? Sur tinkercad j'ai vu qu'on pouvait faire des circuits Arduino mais j'ai pas vu d'esp32 dans les composants. Y'aurait un équivalent ?
J'ai essayé de bidouiller un circuit avec des boutons pour simuler les jours mais j'ai pas réussi.

sur wokwi ça doit fonctionner (mais ça veut dire que vous mettez votre identificationRTE en ligne sur leur site )

Super merci. Je vais regarder pour simuler le retour de la requête directement dans le code comme ça j'envoie rien de perso. :crossed_fingers:

Bonjour à tous.
sur Wokwi, j'ai implémenté ce code à partir de la requête simple car dans l'immédiat je n'ai besoin que de la couleur du jour à l'instant T.

#include <Wire.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
//#define SCREEN_WIDTH 128 // OLED display width, in pixels
//#define SCREEN_HEIGHT 64 // OLED display height, in pixels
//#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
//#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

const char* ssid = "Wokwi-GUEST";
const char* password = "";

const String url = "https://particulier.edf.fr/services/rest/referentiel/searchTempoStore?dateRelevant=2024-01-26";

const int ledBleu = 0;     // Broche de la première LED BLEU
const int ledBlanc = 4;     // Broche de la deuxième LED BLANC
const int ledRouge = 5;     // Broche de la deuxième LED ROUGE

HTTPClient http;

void setup() {
  pinMode(ledBleu, OUTPUT);
  pinMode(ledBlanc, OUTPUT);
  pinMode(ledRouge, OUTPUT);

  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }

  Serial.print("CONNECTED to SSID: ");
  Serial.println(ssid);
  delay(2000);
}

void loop() {
  int counter = 0;
  char* JourJ;
  char* JourJ1;
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Getting current data...");

    http.begin(url);
    int httpCode = http.GET();
    Serial.print("HTTP Code: ");
    Serial.println(httpCode);
    //if (httpCode == HTTP_CODE_OK)
    if (httpCode == 200)
      {
        StaticJsonDocument<100> doc;
        deserializeJson(doc, (http.getString()));
        Serial.println("JourJ:" + doc["couleurJourJ"].as<String>());
        Serial.println("JourJ1:" + doc["couleurJourJ1"].as<String>());
        JourJ = doc["couleurJourJ"].as<String>();
        if (JourJ == "TEMPO_BLEU")
        {
          digitalWrite(ledBleu, HIGH);
          digitalWrite(ledBlanc, LOW);
          digitalWrite(ledRouge, LOW);
        } else if (JourJ == "TEMPO_BLANC")
        {
          digitalWrite(ledBleu, HIGH);
          digitalWrite(ledBlanc, LOW);
          digitalWrite(ledRouge, LOW);
        } else if (JourJ == "TEMPO_ROUGE")
        {
          digitalWrite(ledBleu, HIGH);
          digitalWrite(ledBlanc, LOW);
          digitalWrite(ledRouge, LOW);
        } else
        {
          while (counter < 10)
          {
          digitalWrite(ledBlanc, HIGH);
          delay(1000);
          digitalWrite(ledBlanc, LOW);
          Serial.println("Couleur Tempo Inconnu.");
            ++counter;                              // redémarrage de l'ESP si pas de connexion pendant 10 sec
          }
        }
      }
    http.end();
  }
  delay(5000);
}

et j'ai fait un cablage simple avec 3 leds sur les pin 0 4 et 5.
Je récupère bien l'info JourJ et Jour J1 dans la console, mais impossible d'affecter la valeur du jour dans une variable
JourJ = doc["couleurJourJ"].as<String>(); me retourne une erreur de compilation.
De plus, si JourJ est inconnu, je voulais faire clignoter la led blanche pendant 10s (pour les tests, je verrai après comment gérer le cas), mais ça ne fonctionne pas, elle reste allumée.
Pouvez-vous m'aiguiller sur ce qui cloche, notamment sur l'affectation de la valeur à la variable?
Cordialement,

postez le lien du wokwi

Essaie pour voir de déclarer JourJ et JourJ1 en String.
String JourJ;
String JourJ1;

Tu les a déclaré en char et .as<String>() s'attend à un string !

Roland

Oui c'etait ça. Je n'avais pas encore vu ta réponse.
J'ai vu des exemples de code avec char ou char* pour des chaines... c'est pour ça que j'avais mis ça.
Le code et moi, ça fait pas tout à fait deux mais presque :smile:
Il ne me reste plus qu'à corriger mon clignotement de led et ce sera bon. J'aurai plus qu'à commander le matériel...