Configuration de Putty pour un monitoring à distance

Bonjour à tous,

Dans mon programme j’ai OTA qui me permet de charger un programme sur un ESP32 ainsi que Debug.print qui me permet de le monitorer. Tout ceci fonctionne parfaitement en local sur ma box.

Quand j’essaie de faire la même chose à distance chez un ami, je parviens à charger le programme mais pas à le monitorer.

Je dois probablement avoir un mauvais paramétrage de Putty

vous avez bien un telnet server dans votre code arduino sur votre ESP32 ? vous voudriez voir quoi par cette session ?

Visiblement non.

Mais comment expliquer que j’arrive à charger un programme à distance avec OTA ?

Mais à priori c’est inclus dans Remotedebug:

postez votre code ou un exemple minimal qui montre votre config.


/**********************************************************************************************
**                                    Affichage déporté                                      **
**                                 de consommation solaire                                   ** 
**                                       pour MSunPV                                         **
***********************************************************************************************
**                             Bibliothèques nécessaires:                                    **
**                        https://github.com/vshymanskyy/Preferences                         **
**                        https://github.com/mathertel/OneButton                             **
***********************************************************************************************
- Affichage production PV,conso cumulus,conso EDF,température exterieure et température cumulus
- Couleurs affichage températures changeantes 
  (de -10° à 35° du violet au rouge en passant par bleu, cyan, vert, jaune)
- Correction de la température extérieure mesurée par rapport à la température réelle
  (car sonde un peu abritée ): de -2° à +2°
- Affichage températures mini/maxi avec date et heure de chacune
- Mémorisation mini/maxi date et heure en cas de reboot ou coupure de courant
- Bouton reset avec temporisation de trois secondes
***********************************************************************************************
**     Ce code s'est inspiré du Companion de José Hontebeyrie ( un grand merci à lui! )      **      
**          Adresse du repositery : https://github.com/JJHontebeyrie/Companion               **
**********************************************************************************************/

/**********************************************************************************************
** Rentrer vos identifiants de point d'acces ainsi que l' adresse IP du routeur dans perso.h **
**        et les entrées du routeur à partir de la ligne 552 (sonde S1 = 0, etc...)          **
**  sans oublier de leur attribuer une string (PV, CU, CO, TEMPCU, TEMPExt) à la ligne 117   **
**********************************************************************************************/

#include <TFT_eSPI.h>
#include <WiFi.h>
#include <WiFiClient.h> //OTA
#include <WebServer.h> //OTA
#include <ESPmDNS.h> //OTA
#include <Update.h> //OTA
#include <ArduinoOTA.h> //OTA

// moniteur serie
#include <RemoteDebug.h>
#include "RemoteDebugger.h"
RemoteDebug Debug;

//#include <Preferences.h>
//#include <OneButton.h>
#include "perso.h"
#include "LogoTempo.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <esp_task_wdt.h>  //watchdog
//10 seconds WDT
#define WDT_TIMEOUT 100
#define EstAnneeBissextile(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0)) // L'année est elle bissextile ?

#include <string>

TFT_eSPI lcd = TFT_eSPI();
TFT_eSprite sprite = TFT_eSprite(&lcd);  // Tout l'écran
TFT_eSprite tempo = TFT_eSprite(&lcd);   // Sprite Tempo

// Couleurs pour température exterieure et cumulus
#define color10 0xF81F  //VIOLET pour temperature exterieure négative
#define color11 0xA81F
#define color12 0x501F
#define color13 0x001F  //BLEU
#define color14 0x021F
#define color15 0x041F
#define color16 0x05FF
#define color17 0x07FF
#define color18 0x07F7  //CYAN
#define color19 0x07F0
#define color20 0x07E8
#define color21 0x07E0
#define color22 0x47E0  //VERT
#define color23 0x87E0
#define color24 0xBFE0
#define color25 0xFF2B
#define color26 0xFDE0  //JAUNE
#define color27 0xFC00
#define color28 0xFA00
#define color29 0xF800
#define color30 0xF808   //ROUGE et blanc si Température exterieure > 42°

unsigned long couleurT;  // couleur texte pour Températures extérieures
unsigned long couleurC;  // couleur texte pour Température cumulus
unsigned long couleurP;  // couleur texte pour Température piscine

// Chemin acces au fichier de données MSunPV
char path[] = "/status.xml";

// Variables pour programme
long lastMSunPV = 0;
long lastTempo = 0;
unsigned long currentMillis = millis();
unsigned long previousMillis = 0;
unsigned long interval = 30000;
unsigned long basculeEclairage = millis();
int jourAnnee;
int heureJour;
int Annee;

String IP;     // Adresse IP de connexion du MsunPV
String jour;   // jour
String mois;   // mois
String an;     // date
String date;   // date
String heure;  // heure
String today;
String season;

String PuissanceWifi; // Puissance signal WiFi


//enregistrement date et heure sur températures mini/maxi
String heuremin;
String datemin;
String heuremax;
String datemax;
String jourAn;

// Pointeurs pour relance recherche valeurs
bool awaitingArrivals = true;
bool arrivalsRequested = false;

// Variables pour dimmer
const int PIN_LCD_BL = 38;
const int freq = 1000;
const int ledChannel = 0;
const int resolution = 8;
int dim = 150;  // Eclairage au lancement

float tmin = 99.00;
float tmax = -99.00;
float temperature = 20.00;
float temperaturep = 20.00;
float temperaturec = 20.00;

// Variables affichant les valeurs reçues depuis le MSunPV
String PV, CU, CO, TEMPCU, TEMPExt, TEMPPisc, PAC;           // Consos et températures. Il y a 16 valeurs, on en récupère 7
String tx, tp, tc, t1, t2, t3, tMini, tMaxi;  // Températures mini et maxi
String restantsBleus, restantsBlancs, restantsRouges, JourJJ, JourJJ1;  // jours restants Tempo

// Wifi
int status = WL_IDLE_STATUS;
WiFiClient client;

// Chaines pour decryptage
String matchString = "";
String MsgContent;
String MsgContent2;
String MsgSplit[16];  // 8 valeurs à récupérer pour les consos et températures;
String MsgSplit2[16];  // 4 valeurs à récupérer pour les sorties;

//Reglage heure GMT et heure d'été
const char* ntpServer = "time.google.com";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;

//Variables recuperation jcouleur jours Tempo
const char* JourJ ;
const char* JourJ1 ;
int couleurParamBLANC ;
int couleurParamROUGE ;
int couleurParamBLEU ;
bool bouton;
int totalBlueDays;
const int totalWhiteDays = 43;
const int totalRedDays = 22;

//Preferences preferences;  // pour la mise en mémoire des températures mini/maxi bouton

//OTA
const char* host = "esp32";
WebServer server(80);

/*
 * Login page
 */

const char* loginIndex =
 "<form name='loginForm'>"
    "<table width='20%' bgcolor='A09F9F' align='center'>"
        "<tr>"
            "<td colspan=2>"
                "<center><font size=4><b>ESP32 Login Page</b></font></center>"
                "<br>"
            "</td>"
            "<br>"
            "<br>"
        "</tr>"
        "<tr>"
             "<td>Username:</td>"
             "<td><input type='text' size=25 name='userid'><br></td>"
        "</tr>"
        "<br>"
        "<br>"
        "<tr>"
            "<td>Password:</td>"
            "<td><input type='Password' size=25 name='pwd'><br></td>"
            "<br>"
            "<br>"
        "</tr>"
        "<tr>"
            "<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
        "</tr>"
    "</table>"
"</form>"
"<script>"
    "function check(form)"
    "{"
    "if(form.userid.value=='francois' && form.pwd.value=='saruna')"
    "{"
    "window.open('/serverIndex')"
    "}"
    "else"
    "{"
    " alert('Error Password or Username')/*displays error message*/"
    "}"
    "}"
"</script>";

/*
 * Server Index Page
 */

const char* serverIndex =
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
   "<input type='file' name='update'>"
        "<input type='submit' value='Update'>"
    "</form>"
 "<div id='prg'>progress: 0%</div>"
 "<script>"
  "$('form').submit(function(e){"
  "e.preventDefault();"
  "var form = $('#upload_form')[0];"
  "var data = new FormData(form);"
  " $.ajax({"
  "url: '/update',"
  "type: 'POST',"
  "data: data,"
  "contentType: false,"
  "processData:false,"
  "xhr: function() {"
  "var xhr = new window.XMLHttpRequest();"
  "xhr.upload.addEventListener('progress', function(evt) {"
  "if (evt.lengthComputable) {"
  "var per = evt.loaded / evt.total;"
  "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
  "}"
  "}, false);"
  "return xhr;"
  "},"
  "success:function(d, s) {"
  "console.log('success!')"
 "},"
 "error: function (a, b, c) {"
 "}"
 "});"
 "});"
 "</script>";

///////////////////////////////////////////////////
//               Routine SETUP                   //
///////////////////////////////////////////////////

void setup() {

// Initialisation ecran
    lcd.init();
    lcd.setRotation(rotation);

  // Creation des sprites affichage
   
    sprite.createSprite(320, 170);              // Tout l'ecran
    sprite.setTextColor(TFT_WHITE, TFT_BLACK);  // Ecriture blanc sur fonf noir
    tempo.createSprite(220, 150);
    tempo.setSwapBytes(true);    
            
    //Initialisation port série et attente ouverture
    Serial.begin(115200);

    Debug.println("Configuraton du WDT...");
    esp_task_wdt_init(WDT_TIMEOUT, true);  //enable panic so ESP32 restarts
    esp_task_wdt_add(NULL);                //add current thread to WDT wat
    
    // delete old config et vérif de deconnexion
    WiFi.disconnect(true);
    delay(1000);

    // Etablissement connexion wifi
    WiFi.mode(WIFI_STA);
    WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN);  // Force to scan all channels to find best AP.

  //*****************************************************************************
  // Si difficultés à se connecter >  wpa minimal (décommenter la ligne suivante)
    WiFi.setMinSecurity(WIFI_AUTH_WPA_PSK);
    //*****************************************************************************

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
  Debug.print(".");
    sprite.setTextColor(TFT_BLACK, TFT_WHITE);
    sprite.setTextDatum(4);
    sprite.drawString(" essai connexion ", 160, 50, 4);
    sprite.pushSprite(0, 0);
    delay(1000);
  }
  Debug.println("WiFi connected.");
    IP = WiFi.localIP().toString();
    PuissanceWifi = String(WiFi.RSSI());

    esp_task_wdt_reset();

    // Affichage texte sur écran de départ
    sprite.setTextColor(TFT_BLACK, TFT_WHITE);
    sprite.setTextDatum(4);
    sprite.drawString(" CONNEXION OK ", 160, 50, 4);
    sprite.drawString("PuissanceWifi" + (PuissanceWifi) + " dB",150,80,4);
    sprite.drawString(IP, 150, 120, 4);
    sprite.pushSprite(0, 0);
   
    // Paramètres pour dimmer
    ledcSetup(ledChannel, freq, resolution);
    ledcAttachPin(PIN_LCD_BL, ledChannel);

    // Tamisage écran dim 250 (va de 0 à 255)
    ledcWrite(ledChannel, dim);
    
    // Init and get the time
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    printLocalTime();
    
    /*//lecture des mini/maxi en mémoire en cas de reboot ou de panne de courant
    preferences.begin("minimaxi", false);
    tmin = preferences.getFloat("MINI", tmin);
    tmax = preferences.getFloat("MAXI", tmax);
    datemin = preferences.getString("DATEMINI", datemin);
    heuremin = preferences.getString("HEUREMINI", heuremin);
    datemax = preferences.getString("DATEMAXI", datemax);
    heuremax = preferences.getString("HEUREMAXI", heuremax);*/

        basculeEclairage = millis();

    recupHttp();
    decrypte();
    delay(5000);
    Affiche();

    tmin = 99.00;
    tmax = -99.00;

    //OTA
  if (!MDNS.begin(host)) { //http://esp32.local
    Debug.println("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }
  Debug.println("mDNS responder started");
  /*return index page which is stored in serverIndex */
  server.on("/", HTTP_GET, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", loginIndex);
  });
  server.on("/serverIndex", HTTP_GET, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", serverIndex);
  });
  /*handling uploading firmware file */
  server.on("/update", HTTP_POST, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
    ESP.restart();
  }, []() {
    HTTPUpload& upload = server.upload();
    if (upload.status == UPLOAD_FILE_START) {
      Debug.printf("Update: %s\n", upload.filename.c_str());
      if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
        Update.printError(Serial);
      }
    } else if (upload.status == UPLOAD_FILE_WRITE) {
      /* flashing firmware to ESP*/
      if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
        Update.printError(Serial);
      }
    } else if (upload.status == UPLOAD_FILE_END) {
      if (Update.end(true)) { //true to set the size to the current progress
        Debug.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
      } else {
        Update.printError(Serial);
      }
    }
  });
  server.begin();

  // init Moniteur serie
  Debug.begin("ESP32");

        
    esp_task_wdt_reset();
    
  }

////////////////////////////////////////////////////
//                 Routine LOOP                   //
////////////////////////////////////////////////////
void loop() {

  if (awaitingArrivals) {
    if (!arrivalsRequested) {
      arrivalsRequested = true;
      getArrivals();
      decrypte();
      printLocalTime();
    }
  }

    // Relance de lecture des données (7,5 secondes)
  if (lastMSunPV + 7500 < millis()) {
  Debug.println("lecture MsunPV");
    resetCycle();
    Affiche();
    affichagePac();
    calculTempMaxiMini();
    lastMSunPV = millis();
    bouton = !bouton;
  }

  // Requete de la couleur des jours Tempo
     if (lastTempo + 900000 < millis()) {
  Debug.println("requete Tempo");
    recupHttp();
    lastTempo = millis();
  }
  
    // Temporisation Ecran forte luminosité (secondes*1000)
    if(basculeEclairage + 60000 < millis()) {
    dim = 50;
    ledcWrite(ledChannel, dim);
    basculeEclairage = millis(); }

     //  Reconnexion wifi en cas de perte
     if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >=interval)) {
  Debug.println("Reconnection au WiFi...");
     setup();
     previousMillis = currentMillis;  }

  server.handleClient();
  delay(1);
  
  // init Moniteur serie
  ArduinoOTA.handle();
  Debug.handle();
  esp_task_wdt_reset();

}

 void initOTA() {
  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname("ESP32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
  .onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    Debug.println("Start updating " + type);
  })
  .onEnd([]() {
    Debug.println("\nEnd");
  })
  .onProgress([](unsigned int progress, unsigned int total) {
    Debug.printf("Progress: %u%%\r", (progress / (total / 100)));
  })
  .onError([](ota_error_t error) {
    Debug.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Debug.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Debug.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Debug.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Debug.println("Receive Failed");
    else if (error == OTA_END_ERROR) Debug.println("End Failed");
  });

  ArduinoOTA.begin();



/*************************************************************
**     sauvegarde en mémoire des températures mini/maxi     **
*************************************************************/
/*void sauvegarde() {

    preferences.putFloat("MINI", tmin);
    preferences.putFloat("MAXI", tmax);
    preferences.putString("DATEMINI", datemin);
    preferences.putString("HEUREMINI", heuremin);
    preferences.putString("DATEMAXI", datemax);
    preferences.putString("HEUREMAXI", heuremax);
  Debug.println("sauvegarde OK ! ");
}*/

//surveillance boutons
if (digitalRead(14) == 0) bouton1();
if (digitalRead(0) == 0) bouton2();
 
}
/*********************************************************************
**   Appui bouton1: affichage des températures mini/maxi     **
*********************************************************************/
void bouton1() {

  AfficheMaxiMini();
  basculeEclairage = millis();
  lastMSunPV = millis();
  dim = 255;
  //rafraichissement();
  ledcWrite(ledChannel, dim);
}

/**********************************************************
** Appui bouton 2: Affichage jours restants Tempo **
**********************************************************/
void bouton2() {

recupHttp();
  basculeEclairage = millis();
  lastMSunPV = millis();
  dim = 255;
  //  Dessin fenêtre noire et titre
  sprite.fillSprite(TFT_BLACK);
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite.setTextDatum(4);  // centre droit

  // Affichage des légendes
  sprite.setFreeFont(&FreeSerifBold12pt7b);
  sprite.setTextColor(TFT_BLACK, TFT_BLUE);
  sprite.drawString(" Jours bleus restants : ", 118, 20);
  sprite.setTextColor(TFT_BLACK, TFT_WHITE);
  sprite.drawString(" Jours blancs restants : ", 120, 80);
  sprite.setTextColor(TFT_BLACK, TFT_RED);
  sprite.drawString(" Jours rouges restants : ", 120, 140);
  // Affichage jours restants
  sprite.setFreeFont(&FreeSerifBold24pt7b);
  sprite.setTextColor(TFT_BLUE, TFT_BLACK);
  sprite.drawString(restantsBleus, 273, 20);
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite.drawString(restantsBlancs, 270, 80);
  sprite.setTextColor(TFT_RED, TFT_BLACK);
  sprite.drawString(restantsRouges, 270, 140);
  rafraichissement();
  ledcWrite(ledChannel, dim);
 
}


/******************************************
**    Recuperation infos Tempo     **
*******************************************/
void recupHttp() {

 /* DynamicJsonDocument qq(ESP.getMaxAllocHeap());
Debug.println("capacityavant:");
Debug.println  (qq.capacity());*/

// Construire la saison en cours
  if ( jourAnnee < 245 ) {
  season = String(Annee - 1) + "-" + String(Annee);}
else {
  season = String(Annee) + "-" + String(Annee + 1);}
  HTTPClient http;
  String url = "https://www.services-rte.com/cms/open_data/v1/tempo?season=" + season;
  http.begin(url);        
    int httpJoursRestants = http.GET();
    String recup = http.getString();

    Debug.println("ok HHTP:");
    Debug.println(recup);
   
// Décode le JSON
        DynamicJsonDocument doc(40000);
        deserializeJson(doc, recup);
        JsonObject values = doc["values"];

// Initialiser les compteurs pour chaque couleur
      int blueCount = 0;
      int whiteCount = 0;
      int redCount = 0;

// Parcourir les données et compter les jours par couleur
      for (JsonPair kv : values) {
        String color = kv.value().as<String>();
        if (color == "BLUE") {
          blueCount++;
        } else if (color == "WHITE") {
          whiteCount++;
        } else if (color == "RED") {
          redCount++;
        }
      }
      Debug.println("bluecount:");
      Debug.println(blueCount);

// Calculer le nombre total de jours Bleus selon l'année (bissextile ou pas)
      uint year = an.substring(0,4).toInt();
      totalBlueDays = EstAnneeBissextile(year) ? 366 : 365;
      totalBlueDays -= totalWhiteDays + totalRedDays;
      

// Calculer les jours restants
      restantsBleus =  String(totalBlueDays - blueCount);
      restantsBlancs = String(totalWhiteDays - whiteCount);
      restantsRouges = String(totalRedDays - redCount);

 
//formatage aujourd'hui Tempo
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
Debug.println("Failed to obtain time");
    return;
  }
    char Today[15];
  strftime(Today, 15, "%F", &timeinfo);
  today = String(Today);
Debug.println("today:");
Debug.println(today);
  
//formatage demain Tempo
  time_t now = time(NULL);
  //time_t now = 1709131608;
  time_t tomorrownow;
  tm* tomorrowtimeinfo;
  tomorrownow = now + 86400;
  tomorrowtimeinfo = localtime(&tomorrownow);
  char Tomorrow[30];
  strftime(Tomorrow, 30, "%F", tomorrowtimeinfo);
  String tomorrow = String(Tomorrow);
Debug.println("tomorrow:");
Debug.println(tomorrow);


// Extraire les couleurs pour aujourd'hui et demain du 1er novembre au 31 mars
    if (( jourAnnee < 92 ) || ( jourAnnee > 303 )) {
        JourJJ = doc["values"][today] | "UNKNOWN";
        JourJJ1 = doc["values"][tomorrow] | "UNKNOWN";
Debug.println("JourJJ:");
Debug.println(JourJJ);
    } 
    Debug.println("JourJJ:");
Debug.println(JourJJ);
     
  //  Dessin fenêtre noire et titre
  sprite.fillSprite(TFT_BLACK);
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite.setTextDatum(4);  // centre droit

  // Affichage des légendes
  sprite.setFreeFont(&FreeSerifBold12pt7b);
  sprite.setTextColor(TFT_BLACK, TFT_BLUE);
  sprite.drawString(" Jours bleus restants : ", 118, 20);
  sprite.setTextColor(TFT_BLACK, TFT_WHITE);
  sprite.drawString(" Jours blancs restants : ", 120, 80);
  sprite.setTextColor(TFT_BLACK, TFT_RED);
  sprite.drawString(" Jours rouges restants : ", 120, 140);

  // Affichage jours restants
  sprite.setFreeFont(&FreeSerifBold24pt7b);
  sprite.setTextColor(TFT_BLUE, TFT_BLACK);
  sprite.drawString(restantsBleus, 273, 20);
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite.drawString(restantsBlancs, 270, 80);
  sprite.setTextColor(TFT_RED, TFT_BLACK);
  sprite.drawString(restantsRouges, 270, 140);

  
  
  rafraichissement();

http.end();  // Ferme la connexion

DynamicJsonDocument qqq(ESP.getMaxAllocHeap());
Debug.println("capacityapres:");
Debug.println  (qqq.capacity());

esp_task_wdt_reset();

}

/******************************************
**    affichage PAC   **
*******************************************/

void affichagePac() {

if (PAC.toInt() == 100) {
  if (( jourAnnee > 91 ) && ( jourAnnee < 303 )) {
  
      tempo.pushImage(0,0,80,55,BtnPAC);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  
  Debug.println("PAC");
      rafraichissement();
  }
}

}

/******************************************
**    Calcul températures mini/maxi    **
*******************************************/
void calculTempMaxiMini(){

  if (temperature + 0.5 < tmin) {
    tmin = temperature +0.5;
    datemin = date;
    heuremin = heure;
  }
  

  if (temperature + 0.5 > tmax) {
    tmax = temperature +0.5;
    datemax = date;
    heuremax = heure;
  }
  
 
  tMini = String(tmin, 1);  // On convertit la valeur numérique en chaîne avec un seul chiffre après la virgule
  tMini.replace('.', ',');  // on met une virgule à la place du point
  tMaxi = String(tmax, 1);
  tMaxi.replace('.', ',');
  

  Debug.println("tmin:");
  Debug.println(tmin);
  Debug.println("tmax:");
  Debug.println(tmax);
  Debug.println("datemin:");
  Debug.println(datemin);
  Debug.println("datemax:");
  Debug.println(datemax); 
  
  esp_task_wdt_reset();
}

/******************************************
**   Affichage températures Maxi/Mini    **
*******************************************/
void AfficheMaxiMini() { 
  
  //  Dessin fenêtre noire et titre
  sprite.fillSprite(TFT_BLACK);
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite.setTextDatum(4);  // centre droit

  // Affichage des légendes
  sprite.setFreeFont(&FreeSerifBold12pt7b);
  sprite.setTextColor(TFT_BLACK, color29);
  sprite.drawString(" Temp Maxi  ", 235, 26);
  sprite.setTextColor(TFT_BLACK, color12);
  sprite.drawString(" Temp Mini  ", 80, 26);

  // Affichage mini/maxi
  sprite.setFreeFont(&FreeSerifBold24pt7b);
  sprite.setTextColor(color29, TFT_BLACK);
  sprite.drawString(tMaxi, 230, 80);
  sprite.setTextColor(color12, TFT_BLACK);
  sprite.drawString(tMini, 75, 80);
  sprite.drawCircle(280, 75, 4, color29);  // pour °
  sprite.drawCircle(125, 75, 4, color12);  // pour °

  // mémoriser date et heure des températures mini et maxi
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite.drawString(String(datemin), 40, 130, 4);
  sprite.drawString(String(heuremin), 110, 130, 4);
  sprite.drawString(String(datemax), 205, 130, 4);
  sprite.drawString(String(heuremax), 274, 130, 4);

  esp_task_wdt_reset();

  rafraichissement();
  
}
/***************************************************
**           Affichage principal                  **
***************************************************/
void Affiche() {

  sprite.fillSprite(TFT_BLACK);
  sprite.setTextDatum(5);  // centre droit

  // affichage couleurs par rapport à la temperature exterieure
  sprite.setFreeFont(&FreeSerifBold24pt7b);
  if (TEMPExt.toInt() < -8) couleurT = color10;
  if (TEMPExt.toInt() < -4) couleurT = color11;
  if (TEMPExt.toInt() < -2) couleurT = color12;
  if (TEMPExt.toInt() < 0) couleurT = color13;
  if (TEMPExt.toInt() >= 0) couleurT = color14;
  if (TEMPExt.toInt() > 2) couleurT = color15;
  if (TEMPExt.toInt() > 5) couleurT = color16;
  if (TEMPExt.toInt() > 8) couleurT = color17;
  if (TEMPExt.toInt() > 10) couleurT = color18;
  if (TEMPExt.toInt() > 13) couleurT = color19;
  if (TEMPExt.toInt() > 16) couleurT = color20;
  if (TEMPExt.toInt() > 18) couleurT = color21;
  if (TEMPExt.toInt() > 19) couleurT = color22;
  if (TEMPExt.toInt() > 20) couleurT = color23;
  if (TEMPExt.toInt() > 22) couleurT = color24;
  if (TEMPExt.toInt() > 24) couleurT = color25;
  if (TEMPExt.toInt() > 26) couleurT = color26;
  if (TEMPExt.toInt() > 28) couleurT = color27;
  if (TEMPExt.toInt() > 30) couleurT = color28;
  if (TEMPExt.toInt() > 34) couleurT = color29;
  if (TEMPExt.toInt() > 37) couleurT = color30;
  if (TEMPExt.toInt() > 40) couleurT = TFT_WHITE;
  sprite.setTextColor(couleurT, TFT_BLACK);

  tx = TEMPExt;
  tx.replace(',', '.');         // on met un point à la place de la virgule
  if (abs(temperature-tx.toDouble())<1.00  || (lastMSunPV < 28000 )) { 
  temperature = tx.toDouble(); // on convertit en numérique
  }
  
    t1 = String(temperature + 0.5, 1);      // On convertit la valeur numérique en chaîne avec un seul chiffre après la virgule
    t1.replace('.', ',');                   // on met une virgule à la place du point
    sprite.drawString(t1, 308, 27);
  
  sprite.drawCircle(315, 16, 3, couleurT);  // pour °

  // affichage couleurs par rapport à la temperature piscine
  sprite.setFreeFont(&FreeSerifBold24pt7b);
  
  if (TEMPPisc.toInt() < 0) couleurP = color10;
  if (TEMPPisc.toInt() >= 0) couleurP = color13;
  if (TEMPPisc.toInt() > 2) couleurP = color14;
  if (TEMPPisc.toInt() > 5) couleurP = color16;
  if (TEMPPisc.toInt() > 8) couleurP = color17;
  if (TEMPPisc.toInt() > 10) couleurP = color18;
  if (TEMPPisc.toInt() > 13) couleurP = color19;
  if (TEMPPisc.toInt() > 16) couleurP = color21;
  if (TEMPPisc.toInt() > 19) couleurP = color23;
  if (TEMPPisc.toInt() > 20) couleurP = color25;
  if (TEMPPisc.toInt() > 22) couleurP = color26;
  if (TEMPPisc.toInt() > 24) couleurP = color27;
  if (TEMPPisc.toInt() > 26) couleurP = color28;
  if (TEMPPisc.toInt() > 28) couleurP = color29;
  if (TEMPPisc.toInt() > 30) couleurP = color30;
  
  sprite.setTextColor(couleurP, TFT_BLACK);

  tp = TEMPPisc;
  Debug.println(TEMPPisc);
  tp.replace(',', '.');         // on met un point à la place de la virgule
  if ((abs(temperaturep-tp.toDouble())<1.00 && ((temperaturep > 0.01) || (temperaturep < -0.01)))  || (lastMSunPV < 28000 ) && (temperaturep =! 0.00)) { 
  temperaturep = tp.toDouble(); // on convertit en numérique
  }
  
    t2 = String(temperaturep, 1);      // On convertit la valeur numérique en chaîne avec un seul chiffre après la virgule
    t2.replace('.', ',');                   // on met une virgule à la place du point
    sprite.drawString(t2, 308, 83);
    sprite.drawCircle(315, 72, 3, couleurP);  // pour °

  // affichage couleurs par rapport à la temperature cumulus
  sprite.setFreeFont(&FreeSerifBold12pt7b);
  if (TEMPCU.toInt() > 0) couleurC = color10;
  if (TEMPCU.toInt() > 10) couleurC = color11;
  if (TEMPCU.toInt() > 20) couleurC = color13;
  if (TEMPCU.toInt() > 25) couleurC = color15;
  if (TEMPCU.toInt() > 30) couleurC = color17;
  if (TEMPCU.toInt() > 35) couleurC = color19;
  if (TEMPCU.toInt() > 40) couleurC = color21;
  if (TEMPCU.toInt() > 45) couleurC = color23;
  if (TEMPCU.toInt() > 50) couleurC = color25;
  if (TEMPCU.toInt() > 55) couleurC = color27;
  if (TEMPCU.toInt() >= 60) couleurC = color29;
  sprite.setTextColor(couleurC, TFT_BLACK);

  tc = TEMPCU;
  tc.replace(',', '.');         // on met un point à la place de la virgule
  //if ((abs(temperaturec-tc.toDouble())<1.00 && ((temperaturec > 0.01) || (temperaturec < -0.01)))  || (lastMSunPV < 28000 ) && (temperaturec =! 0.00)) { 
  temperaturec = tc.toDouble(); // on convertit en numérique
  Debug.println(temperaturec);
  //}
  t3 = String(round(temperaturec),0); 
  Debug.println(t3);     // On convertit la valeur numérique en chaîne sans virgule
  sprite.setFreeFont(&FreeSerifBold18pt7b);
  sprite.drawString(t3, 172, 83);
  sprite.drawCircle(174, 72, 3, couleurC);  // pour °

  sprite.setTextDatum(4);  // centre milieu

  // Affichage valeur PV
  sprite.setTextColor(color17, TFT_BLACK);
  sprite.drawString(PV, 112, 28, 7);
  // Affichage valeur Cumulus
  sprite.setTextColor(color18, TFT_BLACK);
  sprite.setFreeFont(&FreeSerifBold24pt7b);
  sprite.drawString(CU, 84, 84);
  // Affichage valeur Consommation
  sprite.setTextColor(color29, TFT_BLACK);
  sprite.drawString(CO, 165, 140, 7);
  
  //  Dessin fenêtre principale
  sprite.setTextColor(TFT_WHITE, TFT_BLACK);

  // Panneaux principaux
  sprite.drawRoundRect(2, 0, 183, 56, 3, TFT_WHITE);
  sprite.drawString("PV", 23, 30, 4);
  sprite.drawRoundRect(2, 56, 183, 56, 3, TFT_WHITE);
  sprite.setFreeFont(&FreeSerifBold9pt7b);
  sprite.drawString("CE", 19, 83);
  sprite.drawString("Ext", 204, 33);
  sprite.drawString("Pisc", 205, 87);
  sprite.drawRoundRect(2, 112, 235, 60, 3, TFT_WHITE);
  sprite.drawString("CONSO", 52, 142, 4);

  // Affichage couleurs jours bleus et rouges Tempo aujourd'hui
    if (bouton == true && (JourJJ.equals("BLUE"))) {
      tempo.pushImage(0,0,80,55,BtnBEJ);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("bleuJ");
    }
    if (bouton == true && (JourJJ.equals("WHITE"))) {
      tempo.pushImage(0,0,80,55,BtnBLJ);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("blancJ");
    }
    if (bouton == true && (JourJJ.equals("RED"))) {
      tempo.pushImage(0,0,80,55,BtnROJ);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("rougeJ");
    }
    
// Affichage couleurs jours bleus et rouges Tempo lendemain
    if (bouton == false && (JourJJ1.equals("BLUE"))) {
      tempo.pushImage(0,0,80,55,BtnBEJ1);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("bleuJ1");
    }
    if (bouton == false && (JourJJ1.equals("WHITE"))) {
      tempo.pushImage(0,0,80,55,BtnBLJ1);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("blancJ1");
    }  
    if (bouton == false && (JourJJ1.equals("RED"))) {
      tempo.pushImage(0,0,80,55,BtnROJ1);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("rougeJ1");
      dim = 255;
      ledcWrite(ledChannel, dim);
    }
    if (bouton == false && (JourJJ1.equals("UNKNOWN"))) {
      tempo.pushImage(0,0,80,55,BtnIndefini);
      tempo.pushToSprite(&sprite,242,113,TFT_BLACK);
  Debug.println("Indefini");
    }

   
      //rafraichissement();
    
  
  esp_task_wdt_reset();

  rafraichissement();

}

/*******************************************************************
**          Decryptage des valeurs lues dans le xml               **
*******************************************************************/
void decrypte() {

delay(1000);
    // Mise en mémoire des consos du fichier xml
    int startValue = matchString.indexOf("<inAns>");
    int endValue = matchString.indexOf("</inAns>");
    MsgContent = matchString.substring(startValue + 7, endValue - 27);// + 7 depart index après la valeur du tag <InAns>  // -15 fin index avant la valeur du tag </InAns>

    int startOut = matchString.indexOf("<outStat>");
    int endOut = matchString.indexOf("</outStat>");
    MsgContent2 = matchString.substring(startOut + 9, endOut - 20);  // + 9 depart index après la valeur du tag <outStat>  // - 20 fin index avant la valeur du tag </outStat>

    // MsgContent : chaine avec toutes les valeurs recherchées
  Debug.println("Entrées >> " + MsgContent);
    split(MsgSplit, 7, MsgContent, ';');
    Debug.println("Sorties >> " + MsgContent2);
    split(MsgSplit2, 9, MsgContent2, ';');

/*****************************************************************
**                 MODIFICATION DES INDEX                       **
******************************************************************
**   Suivant les modifications que vous avez apporté au MSunPV
**   il est possible que les valeurs souhaitées ne soient pas
**   celles affichées. Vérifiez sur le moniteur série le bon index 
*****************************************************************/
CO = MsgSplit[0];       // Consommation
Debug.println("MsgSplit[0]:");
Debug.println(MsgSplit[0]);
  PV = MsgSplit[1];       // Panneaux PV
Debug.println("MsgSplit[1]:");
Debug.println(MsgSplit[1]);
  CU = MsgSplit[3];       // Cumulus
  TEMPCU = MsgSplit[5];   // Sonde température cumulus
  TEMPExt = MsgSplit[4];  // Sonde température exterieure
  TEMPPisc = MsgSplit[6];  // Sonde température piscine
  PAC = MsgSplit2[3];     // Sortie PAC
                          /**************************************/

  // Formatage des valeurs pour affichage sur l'écran
  PV = String(abs(PV.toInt()));  // (avec prod en + ou en -)

  // Affichage en entiers si demandé dans perso.h
  if (nbrentier) {
    CO = String(CO.toInt());
    PV = String(PV.toInt());
    CU = String(CU.toInt());
  }

  // hysteresis des panneaux et cumulus
  if (PV.toInt() <= residuel) PV = "0";  // Légère consommation due aux onduleurs
  if (CU.toInt() <= residuel) CU = "0";  // Légère consommation due au thermostat du cumulus

  esp_task_wdt_reset();
}

/*******************************************************************
**               Relancement du cycle de lecture                  **
*******************************************************************/
void getArrivals() {

  // Use WiFiClient class to create TLS connection
  Debug.println("\nInitialisation de la connexion au serveur...");
    // if you get a connection, report back via serial.connect(server, 80))
    if (client.connect(Afficheur, 80)) {
  Debug.println("Connecté au serveur");
    }

    // Make a HTTP request:
    client.print("GET ");
    client.print(path);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(Afficheur);
    client.println();

    while (!client.available())
      ;  //wait for client data to be available
  Debug.println("Attente de la réponse serveur...");

    while (client.available()) {
      String line = client.readStringUntil('\r');
      matchString = line;  // Mise en mémoire du xml complet
    }
  Debug.println("requete validée");
    awaitingArrivals = false;
    client.stop();
    
esp_task_wdt_reset();

}

void rafraichissement() {

sprite.pushSprite(0, 0);

}

void resetCycle() {
    awaitingArrivals = true;
    arrivalsRequested = false;
  Debug.println("et montre l'écran...");
  
}
// recuperation date, annee, mois, jour et heure, jours Tempo
void printLocalTime() {
    struct tm timeinfo;
    if (!getLocalTime(&timeinfo)) {
Debug.println("Failed to obtain time");
    return;
  }

//recuperation date et heure
  char timeHour[8];
  strftime(timeHour, 8, "%R", &timeinfo);
  heure = String(timeHour);
  heureJour = heure.toDouble();

  char DayMonth[15];
  strftime(DayMonth, 15, "%d/%m", &timeinfo);
  date = String(DayMonth);
  Debug.println("date:");
  Debug.println(date);

  char timeDay[3];
  strftime(timeDay, 3, "%d", &timeinfo);
  jour = String(timeDay);
  
  char timeMonth[4];
  strftime(timeMonth, 4, "%m", &timeinfo);
  mois = String(timeMonth);
 
  char timeYear[6];
  strftime(timeYear, 6, "%Y", &timeinfo);
  an = String(timeYear);
  Annee = an.toInt();
     
  char dayYear[4];
  strftime(dayYear, 4, "%j", &timeinfo);
  jourAn = String(dayYear);
  jourAnnee = jourAn.toDouble();

  esp_task_wdt_reset();
     
}

/**************************************************************************
**  Découpe la partie du xml voulue en autant de valeurs que trouvées    **
***************************************************************************/
void split(String* vecSplit, int dimArray, String content, char separator) {
  if (content.length() == 0)
    return;
  content = content + separator;
  int countVec = 0;
  int posSep = 0;
  int posInit = 0;
  while (countVec < dimArray) {
    posSep = content.indexOf(separator, posSep);
    if (posSep < 0) return;
    String splitStr = content.substring(posInit, posSep);
    posSep = posSep + 1;
    posInit = posSep;
    vecSplit[countVec] = splitStr;
    countVec++;
  }

  esp_task_wdt_reset();
}

OK oui avec ces 2 bibliothèques ça devrait aller donc le souci est dans le réseau probablement.

L’OTA utilise le port 3232 et Telnet utilise le port 23. Comment votre réseau est-il paramétré pour ces ports, via port forwarding ou VPN ?

Telnet est sur le port 23, le port 3232 n’est pas ouvert

Capture d’écran_2025-11-26_09-57-40

Vérifiez aussi qu’aucun pare-feu du routeur ou de votre fournisseur n’interdit le trafic entrant sur le port 23. Même avec tout cela, certains FAI bloquent le port 23 par défaut, donc vous pourriez devoir utiliser un port externe différent (par exemple 2323) et rediriger ce port vers le 23 interne de l’ESP32.

Notez que RemoteDebug n’est pas sécurisé pour un accès public - il n’inclut pas d’authentification robuste donc vous avez éventuellement un risque de ce côté là...

Le pare-feu ne bloque pas le port.

Comment fait-on pour rediriger le port 2323 vers le port 23?

Mais comment expliquer que j’arrive à communiquer avec l’ESP32 de mon ami par OTA?

Il trouve bien l’ESP et me permet de telecharger un binaire.

Pourquoi je n’arrive pas à monitorer ce même ESP?

Vous avez mis l’ESP dans la DMZ chez vous ?
Plus d’info sur le réseau serait utile.

Quelle box ? Avez vous un router séparé ? …

Je ne cherche pas à monitorer un ESP chez moi, j’y arrive très bien sur mon afficheur ESP.

Je cherche à monitorer de chez moi le même afficheur ESP chez un ami.

L’OTA fonctionne mais je n’arrive pas le monitorer…

ça reste la même question : comment est configuré le réseau chez votre ami ?

Je ne me rappelle pas comment il est configuré.

J’ai connecté un autre PC à mon portable ( donc comme si je me connectais à distance ), ce qui devrait me permettre de faire des essais sur mon ESP puisque je suis sûr que ça fonctionne.

Mais je ne sais toujours pas configurer Putty. Que dois-je mettre dans ces onglets?

Bon j’y suis parvenu. Il suffit de mettre dans putty l’adresse IP de la box, Telnet port 23.

Et bien sûr d’ouvrir le port Telnet 23 sur la box…

Il ne faut pas juste ouvrir le port 23, il faut dire à la box où envoyer une communication qui rentre sur le port 23 pour qu'elle aille sur l'ESP32 aussi sur le port 23.

oui bien sûr, c’est ce que j’ai fait également

Capture d’écran_2025-11-27_09-56-06

oui - ça reste fragile car certains fournisseurs internet bloque par défaut ce trafic mais si ça fonctionne pour vous, pas de souci.

(si c'est bloqué il faut que votre changer le N° du port entrant pour que putty fasse du telnet par exemple en 2323 et dans le routeur dire que si une communication arrive sur 2323 à la box, alors il est routé sur le port 23 à l'ESP).

c’était une de mes questions.

ça se fait comment? Il faut mettre port internet 23 et externe 2323 comme ceci: