Enphase renew token

Bonjour j'utilise la library ayushsharma82/AsyncElegantOTA @ ^2.2.5. Je cherche une méthode pour renouveler le token pour mon compte enphase .
Il existe diffèrent tuto en python ou en shell script .
Avez vous une idée d un petit code en C pour faire la même fonction ?
Doc get token

j ai realiser ce test

Get a token programmatically through GET on a URL

Follow the procedure to retrieve a token programmatically. Enphase provides a URL to retrieve a
token and mentions the duration for which the token is valid.
To construct the correct URL for the IQ Gateway:

  1. Paste the token retrieval URL into the web browser’s address bar:
https://enlighten.enphaseenergy.com/entrez-auth-token?serial_num=%3CIQ

j'obtiens bien ceci (faux token indiqué ici)

{
    "generation_time": 1707135095,
    "token": "eyJraWQiOiI3ZDEwMDA1ZC03ODk5LTRkMGQtYmNiNC0yNDRmOThlZTE1NmIiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiIxMjIxNDUwNzY5OTYiLCJpc3MiOiJFbnRyZXoiLCJlbnBoYXNlVXNlciI6Im93bmVyIiwiZXhwIjoxNzM4Njcxkjg1LCJpYXQiOjE3MDcxMzUwOTUsImp0aSI6ImQ5M2MyYTBkLWYyMDgtNDE3Mi04MDJmLTBjMTJlZjYwNmQ3MSIsInVzZXJuYW1lIjoiamVyZW15Y29saW4zMUBnbWFpbC5jb20ifQ.lRbEF6t7X5t7WU4sBbKRXRRNlghtqsrjrofWxqqfUPc5BdynaXH3shjtR4GM4H5nzvPOQsi_Xh0rqekeDlgbdg",
    "expires_at": 1738671095
}

Merci pour votre aide

si vous avez un ESP32 essayez un truc comme cela

je n'ai pas de compte donc je n'ai pas pu tester, mais le principe correspond à peu près au script python

il faut bien sûr mettre vos données dans les éléments suivants

const char* ssid = "xxx";
const char* password = "xxx";

#define user "<UserName>"
#define passwordEnphase "<Password>"
const char* envoySerial = "<Envoy_Serial_No>";

➜ à tester et affiner

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "xxx";
const char* password = "xxx";

#define user "<UserName>"
#define passwordEnphase "<Password>"
const char* envoySerial = "<Envoy_Serial_No>";

const char* url = "http://enlighten.enphaseenergy.com/login/login.json?";
const char* data = "user[email]="  user  "&user[password]=" passwordEnphase;

void authenticateEnphase() {
  HTTPClient http;
  http.begin(url);
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  int httpResponseCode = http.POST(data);

  if (httpResponseCode > 0) {
    String response = http.getString();
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, response);
    const char* sessionId = doc["session_id"];      // Récupération de la session_id

    // Construction des données pour la deuxième requête POST
    String urlTokens = "http://entrez.enphaseenergy.com/tokens";
    String dataTokens = "{\"session_id\":\"" + String(sessionId) + "\",\"serial_num\":\"" + String(envoySerial) + "\",\"username\":\"" + String(user) + "\"}";

    // Envoi de la deuxième requête POST
    http.begin(urlTokens);
    http.addHeader("Content-Type", "application/json");
    httpResponseCode = http.POST(dataTokens);

    if (httpResponseCode > 0) {
      String tokenRaw = http.getString();
      Serial.print("Token : ")
      Serial.println(tokenRaw);
    } else {
      Serial.println("Échec de la requête pour obtenir le token");
    }

    http.end();
  } else {
    Serial.println("Échec de la requête d'authentification Enphase");
  }
}

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

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("...");
  }
  Serial.println("\nConnecté au WiFi");

  authenticateEnphase();
}

void loop() {}



Bonjour J-M-L

ton code semble vraiment top .
Je reviens vers toi une fois le test/debug effectué =) un grand merci

Je viens de faire le test
J ai pas grand chose dans le terminal , voici le resultat

Connecté au WiFi
Token : <html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>

Bon ça veut dire que le serveur n’a pas répondu….
Il faut que je passe le code en https sans doute
Je suis sur mon iPhone pour 48h donc ce ne sera pas pour tout de suite :slight_smile:

Pas de problème =) , tu es déjà bien gentil de me filer la patte sur ce sujet que je ne maitrise pas

bon j'ai eu un peu de temps mais juste sur mon iPhone donc totalement non testé

j'ai modifié le code précédent pour passer en WiFiClientSecure pour du HTTPS

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "xxx";
const char* password = "xxx";

#define user "<UserName>"
#define passwordEnphase "<Password>"
const char* envoySerial = "<Envoy_Serial_No>";

const char* url = "https://enlighten.enphaseenergy.com/login/login.json?";
const char* data = "user[email]="  user  "&user[password]=" passwordEnphase;

void authenticateEnphase() {
  WiFiClientSecure client;
  HTTPClient http;
  client.setInsecure(); // pour le moment on peut faire comme cela

  http.begin(client, url); 
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  int httpResponseCode = http.POST(data);

  if (httpResponseCode > 0) {
    String response = http.getString();
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, response);
    const char* sessionId = doc["session_id"];      // Récupération de la session_id

    // Construction des données pour la deuxième requête POST
    String urlTokens = "https://entrez.enphaseenergy.com/tokens";
    String dataTokens = "{\"session_id\":\"" + String(sessionId) + "\",\"serial_num\":\"" + String(envoySerial) + "\",\"username\":\"" + String(user) + "\"}";

    // Envoi de la deuxième requête POST
    http.begin(client, urlTokens); // Utilisation de WiFiClientSecure avec l'URL HTTPS
    http.addHeader("Content-Type", "application/json");
    httpResponseCode = http.POST(dataTokens);

    if (httpResponseCode > 0) {
      String tokenRaw = http.getString();
      Serial.print("Token : ");
      Serial.println(tokenRaw);
    } else {
      Serial.println("Échec de la requête pour obtenir le token");
    }

    http.end();
  } else {
    Serial.println("Échec de la requête d'authentification Enphase");
  }
}

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

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("...");
  }
  Serial.println("\nConnecté au WiFi");

  authenticateEnphase();
}

void loop() {}

Décidément =O Merci pour ton exemple il fonctionne parfaitement .
Du premier coup , ce ne doit pas être facile depuis un iPhone en plus .
=) a moi le boulot maintenant

Super (question d’habitude)

Bonsoir J-M-L , le code fonctionne parfaitement isolé par contre lorsque je le charge sur mon projet j obtient toujours Échec de la requête d'authentification Enphase .

Pense tu que cela puisse venir d une gestion trop lente de la requête par l esp ?

#ifndef ENPHASE_TOKEN_RENEW
#define ENPHASE_TOKEN_RENEW

#include <Arduino.h>
#include <FS.h>
#include "../config/config.h"
#include "../config/enums.h"
#include "../functions/Mqtt_http_Functions.h"
#include "SPIFFS.h"
#include "config/enums.h"

extern Config config; 






#define user "test@gmail.com"
#define passwordEnphase "test"
const char* envoySerial = "100145076996";

const char* url = "https://enlighten.enphaseenergy.com/login/login.json?";
const char* data = "user[email]="  user  "&user[password]=" passwordEnphase;

void authenticateEnphase() {


  //SessionId.clear();
  Serial.print("voici l'url=");
  Serial.println(url);

  Serial.print("voici les data=");
  Serial.println(data);


  WiFiClientSecure client;
  HTTPClient http;
  client.setInsecure(); // pour le moment on peut faire comme cela

  http.begin(client, url); 
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  int httpResponseCode = http.POST(data);

  if (httpResponseCode > 0) {
    String response = http.getString();
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, response);
    const char* sessionId = doc["session_id"];      // Récupération de la session_id

    // Construction des données pour la deuxième requête POST
    String urlTokens = "https://entrez.enphaseenergy.com/tokens";
    String dataTokens = "{\"session_id\":\"" + String(sessionId) + "\",\"serial_num\":\"" + String(envoySerial) + "\",\"username\":\"" + String(user) + "\"}";

    // Envoi de la deuxième requête POST
    http.begin(client, urlTokens); // Utilisation de WiFiClientSecure avec l'URL HTTPS
    http.addHeader("Content-Type", "application/json");
    httpResponseCode = http.POST(dataTokens);

    if (httpResponseCode > 0) {
      String tokenRaw = http.getString();
      Serial.print("Token : ");
      Serial.println(tokenRaw);
    } else {
      Serial.println("Échec de la requête pour obtenir le token");
      config.countbadtoken = 0;
      config.renewtoken = false;
      
    }

    http.end();
  } else {
    Serial.println("Échec de la requête d'authentification Enphase");
    config.countbadtoken = 0;
    config.renewtoken = false;
  }
}

#endif

Voici le log terminal

voici l'url=https://enlighten.enphaseenergy.com/login/login.json?
voici les data=user[email]=test@gmail.com&user[password]=test
Échec de la requête d'authentification Enphase

J'essaye de comprendre mon erreur . Merci pour ton aide précieuse

vous testez avant si le WiFi est bien établi ?

Oui car la partie serveur web fonctionne parfaitement , ainsi que l interrogation d un serveur pour la récupération d un json .

j ai rajouté ceci en debut de void , j obtiens bien le retour "Connecté au WiFi"

while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("...");
  }
  Serial.println("\nConnecté au WiFi");

et les codes secrets sont corrects ?

oops j ai modifié mon message du dessus entre temps :stuck_out_tongue:

les codes secret mentionné dans la discussion sont des exemples mais dans mon code il sont identique a ceux utilisés dans votre code qui fonctionne .
J ai ajouté ce petit debug pour vérifier l intégrité des données

Serial.print("voici l'url=");
Serial.println(url);

Serial.print("voici les data=");
Serial.println(data);

clairement la première requête ne passe pas... vous faites du https dans le reste du code?

oui dans la fonction de récupération du json

    Serial.print("voici le httpResponseCode =");
    Serial.println(httpResponseCode);

voici la valeur de httpResponseCode =-1 sur la premiere requête

voici la partie du code en https qui fonctionne

#ifndef ENPHASE_FUNCTIONS
#define ENPHASE_FUNCTIONS

#include <Arduino.h>
#include <FS.h>
#include "../config/config.h"
#include "../config/enums.h"
#include "../functions/Mqtt_http_Functions.h"
#include "SPIFFS.h"
#include "config/enums.h"

extern Config config; 

String SessionId;
HTTPClient https;
bool initEnphase = true; // Permet de lancer le contrôle du token une fois au démarrage

bool Enphase_get_7_Production(void)
{
  
  int httpCode;
  bool retour = false;
  String adr = String(config.enphaseip);
  String url = "/404.html" ;

  url = String(EnvoyS);
  Serial.print("type S ");
  Serial.println(url);
          
  Serial.println("Enphase Get production : https://" + adr + url);
  if (https.begin("http://" + adr + url)) 
  { 
    https.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
    https.setAuthorizationType("Bearer");
    https.setAuthorization(config.enphasetoken);
    https.addHeader("Accept-Encoding","gzip, deflate, br");
    https.addHeader("User-Agent","PvRouter/1.1.1");
    if (!SessionId.isEmpty()) 
    {
      https.addHeader("Cookie",SessionId);
    }
    httpCode = https.GET();
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
    {
      String payload = https.getString();
      //Serial.println(payload);
      DynamicJsonDocument doc(3072);
      deserializeJson(doc, payload);

      gDisplayValues.production = int(doc["production"][1]["wNow"]);
      gDisplayValues.watt = int(doc["consumption"][1]["wNow"]);
      gDisplayValues.whToday = int(doc["production"][1]["whToday"]);

      retour = true;
      // debug
      Serial.println("Enphase Get production > prod: " + String(gDisplayValues.production) + " conso: " + String(gDisplayValues.watt) + " total prod today: " + String(gDisplayValues.whToday));
    } 
    else 
    {
      Serial.println("[Enphase Get production] GET... failed, error: " + String(httpCode));
    }
    //https.end();
  }
  else 
  {
    Serial.println("[Enphase Get production] GET... failed, error: " + String(httpCode));
  }
  https.end();
  return retour;
}

bool Enphase_get_7_JWT(void) 
{
  bool retour = false;
  String url = "/404.html";
  url = String(EnvoyJ);
  String adr = String(config.enphaseip);


  Serial.println("Enphase contrôle token : https://" + adr + url);
  //Initializing an HTTPS communication using the secure client
  if (https.begin("https://" + adr + url)) 
  {
    https.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
    https.setAuthorizationType("Bearer");
    https.setAuthorization(config.enphasetoken);
    https.addHeader("Accept-Encoding","gzip, deflate, br");
    https.addHeader("User-Agent","PvRouter/1.1.1");
    const char * headerkeys[] = {"Set-Cookie"};
    https.collectHeaders(headerkeys, sizeof(headerkeys)/sizeof(char*));
    int httpCode = https.GET();
    
    // httpCode will be negative on error
    //Serial.println("Enphase_Get_7 : httpcode : " + httpCode);
    if (httpCode > 0) 
    {
      if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
      {
        retour = true;
        // Token valide
        Serial.println("Enphase contrôle token : TOKEN VALIDE ");
        config.badtoken = false;
        SessionId.clear();
        SessionId = https.header("Set-Cookie");
      } 
      else 
      {
          Serial.println("Enphase contrôle token : TOKEN INVALIDE !!!");
          config.badtoken = true;
          config.countbadtoken++;
          Serial.print("nombre echec token = ");
          Serial.println(config.countbadtoken);
          https.end();

          if(config.countbadtoken >= 5)
          {
            config.renewtoken = true;
            //config.countbadtoken = 0;

          }

          if(config.countbadtoken <= 0)
          {
            config.renewtoken = false;
          }


      }
    }
  }
  //https.end();
  return retour;
}

void Enphase_get(void) 
{
  if(WiFi.isConnected() ) 
  {
    //create an HTTPClient instance
    if (SessionId.isEmpty() || Enphase_get_7_Production() == false) 
    { // Permet de lancer le contrôle du token une fois au démarrage (Empty SessionId)
      SessionId.clear();
      Enphase_get_7_JWT();
    }
  } 
  else 
  {
    Serial.println("Enphase version 7 : ERROR");
  } 
}

#endif

vérifiez que vous avez bien des https.end(); dans tous les cas où vous avez réussi le begin()

je lis sur l'iPhone, donc pas simple, mais j'en vois un qui est commenté

les fonctions suivante sont désactivé si la fonction de récupération du token est lancé
par mesure de précaution j ai rajouter un https.end(); en debut de void authenticateEnphase()

cela vous semble t il logique ?

Sans résultat malheureusement

Sur votre exemple la récupération prend bien 8 secondes .
J ai l'impression que dans mon code cela prend trop de temps et la tache est terminé avant la réponse du serveur

Normalement ça attend la réponse

Quel est le code reçu ?

Toujours la reponse -1 :s

voici le httpResponseCode =-1
Échec de la requête d'authentification Enphase