/**********************************************************************************************
** 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();
}