Écran connecté

Tout sur Domoticz
Répondre
Avatar du membre
Alain
Administrateur du site
Messages : 204
Enregistré le : 11 févr. 2021 11:55
Localisation : Gradignan - Gironde
Contact :

Écran connecté

Message par Alain »

Mon nouvel objet connecté
Mon nouvel objet connecté
Voici ma nouvelle solution pour afficher de façon permanente (sans PC, sans tablette et sans smartphone) la situation sur ma consommation électrique et mes productions photovoltaïques (auto-consommation et vente).

Article sur le blog

La solution peut être déclinée pour faire une station météo, un autre suivi, ...
Avatar du membre
Alain
Administrateur du site
Messages : 204
Enregistré le : 11 févr. 2021 11:55
Localisation : Gradignan - Gironde
Contact :

Re: Écran connecté

Message par Alain »

Après la version décrite sur le Blog qui était un PoC (Proof of Concept) et qui a fait ses preuves pendant une semaine, place à la version 2 qui améliore la cohérence du projet.
Les données étaient en partie gérées sur l'ESP32 (unité et libellé de chaque case) et l'autre partie sur Domoticz (valeur et heure). Maintenant toutes les données sont gérées dans les scripts dzVents sur Domoticz ce qui simplifie le programme sur l'ESP32 qui passe de plus de 800 lignes à moins de 600. Cela ne se fait pas au dépend des scripts car eux aussi ont été rendus plus cohérents et plus simples à paramètrer.
Au passage le format des messages mqtt a été réorganisé et harmonisé (par exemple les valeurs sont toujours dans la même zone alors que dans la version initiale il y avait plusieurs champs en fonction de la nature de la valeur) :
Format pour les IDX

Code : Tout sélectionner

{
"IDX":"5526",
"Nomidx":"Tempo Total",
"Cellule":"L1C1",
"Libelle":"Conso EDF",
"Unite":"Watt",
"Heure":"11:19",
"Valeur":"526"
}
Format pour les Variables utilisateur

Code : Tout sélectionner

{
"VAR":"530",
"Nomvar":"ConsoTempo_hp",
"Cellule":"L4C2",
"Libelle":"H Pleines",
"Unite":"",
"Heure":"11:20",
"Valeur":"3.59"
}
J'ai rajouté le nom des IDX et des Variables utilisateur qui ne sont pas utilisés mais qui sont utiles pour la mise au point.
Avatar du membre
Alain
Administrateur du site
Messages : 204
Enregistré le : 11 févr. 2021 11:55
Localisation : Gradignan - Gironde
Contact :

Re: Écran connecté

Message par Alain »

Nouvelle version des dzVents pour les IDX, il n'y a plus que la table MyDevices à mettre à jour, le nom du topic et la périodicité :

Code : Tout sélectionner

-- Envoi vers ESP32 epaper via mqtt depuis Domoticz
-- pour les dispositifs de suivi de Consommation et Production (chaque minute)

-- 10/11/2023 : Modification pour que les informations soient gérées en dehors de l"ESP32

-- Zone à renseigner -----------------
-- table des informations - format : {Idx,Cellule,Libellé,Unité,Valeur}
-- Idx 		= IDX à envoyer vers l'ESP32 epaper
-- Cellule	= Cellule de l'écran dans laquelle les données de l'IDX seront affichées
-- Libellé	= Libellé à afficher dans la cellule
-- Unité	= Unité à afficher dans la cellule pour la valeur
-- Valeur	= Valeur qui doit être affichée dans la cellule
--		  souvent c'est la valeur identifiée dans le Json (usage, counter, counterToday, temperature, ...)
--		  il faut conserver le format exact du libellé Json
local MyDevices  = {{5526,"L1C1","Conso EDF","Watt","usage"},
		    {3327,"L3C4","Auto-Conso","Watt","usage"},
		    {3327,"L4C4","Fronius","kWh","counterToday"},
		    {3814,"L3C5","Vente","W","usage"},
		    {3814,"L4C5","Enphase","kW","counterToday"}}
local MQTTTopic  = 'domoticz/epaper'		-- nom du topic MQTT
local logtext	 = 'MQTT epaper Idx minute : '	-- libellé identifiant les messages dans les logs
-- Fin de la Zone à renseigner -------

return
{
-- Indiquer la périodicité d'exécution du script
--  on		=	{timer = {'at 12:05','every 15 minutes'},},	
    on 		=	{timer = {'every minute',},},
-- change to LOG_ERROR when ok or LOG_DEBUG pour tester
--  logging 	=	{level = domoticz.LOG_DEBUG,},
    logging	=	{level = domoticz.LOG_ERROR,},

-- Si possible - Ne pas modifier la partie du script ci-dessous
execute = function(dz)
    local function osCommand(cmd)
    dz.log('Executing Command: ' .. cmd,dz.LOG_DEBUG)
    local fileHandle = assert(io.popen(cmd .. ' 2>&1 || echo ::ERROR::', 'r'))
    local commandOutput = assert(fileHandle:read('*a'))
    local returnTable = {fileHandle:close()}
    if commandOutput:find '::ERROR::' then     -- something went wrong
	dz.log('Error ==>> ' .. tostring(commandOutput:match('^(.*)%s+::ERROR::') or ' ... but no error message ' ) ,dz.LOG_DEBUG)
    else -- all is fine!!
	dz.log('ReturnCode: ' .. returnTable[3] .. '\ncommandOutput:\n' .. commandOutput, dz.LOG_DEBUG)
    end
    return commandOutput,returnTable[3] -- rc[3] contains returnCode
    end
    local function sendMQTT(message)
	 osCommand ( 'mosquitto_pub  -u user -P fireport68 ' ..  ' -t '  .. MQTTTopic .. " -m '" .. message .. "'")
    end
    for i,j in ipairs(MyDevices) do
	local Idx	= tostring(dz.devices(MyDevices[i][1]).id)
	local Nom 	= tostring(dz.devices(MyDevices[i][1]).name)
	local Cell 	= tostring(MyDevices[i][2])
	local Lib 	= tostring(MyDevices[i][3])
	local Unit 	= tostring(MyDevices[i][4])	    	    
	local lastUh	= tonumber(dz.devices(MyDevices[i][1]).lastUpdate.hour)
	    if lastUh < 10 then lastUh = "0"..lastUh end
	local lastUm	= tonumber(dz.devices(MyDevices[i][1]).lastUpdate.minutes)
	    if lastUm < 10 then lastUm = "0"..lastUm end
	local LastU	= lastUh..":"..lastUm
	local lastUM	= tonumber(dz.devices(MyDevices[i][1]).lastUpdate.month)
	    if lastUM < 10 then lastUM = "0"..lastUM end	    
	local lastUd	= tonumber(dz.devices(MyDevices[i][1]).lastUpdate.day)
	    if lastUd < 10 then lastUd = "0"..lastUd end
	local timed	= tonumber(dz.time.day)
	    if timed < 10 then timed = "0"..timed end	    
	if lastUd ~= timed then LastU = lastUd.."/"..lastUM end
	local Val
	if MyDevices[i][5] == "usage" then
		Val = tostring(dz.devices(MyDevices[i][1]).usage)
	elseif MyDevices[i][5] == "counterToday" then
		Val = tonumber(dz.devices(MyDevices[i][1]).counterToday)
		Val = dz.utils.round(Val, 2)
	elseif MyDevices[i][5] == "counter" then
		Val = tostring(dz.devices(MyDevices[i][1]).counter)
	elseif MyDevices[i][5] == "text" then
		Val = tostring(dz.devices(MyDevices[i][1]).text)
	elseif MyDevices[i][5] == "temperature" then
		Val = tostring(dz.devices(MyDevices[i][1]).temperature)
		Val = string.sub(Val,1,4)
	end
	myMessage	= '{"IDX":"'..Idx..'","Nomidx":"'..Nom..'","Cellule":"'..Cell..'","Libelle":"'..Lib..'","Unite":"'..Unit..'","Heure":"'..LastU..'","Valeur":"'..Val..'"}'
	dz.log(logtext..myMessage,dz.LOG_FORCE)
	sendMQTT(myMessage)
    end
end
}
Avatar du membre
Alain
Administrateur du site
Messages : 204
Enregistré le : 11 févr. 2021 11:55
Localisation : Gradignan - Gironde
Contact :

Re: Écran connecté

Message par Alain »

Version pour les Variables utilisateur sur le même principe :

Code : Tout sélectionner

-- Envoi vers ESP32 epaper via mqtt depuis Domoticz
-- pour les variables utilisateur mises à jour à 22:00

-- 11/11/2023 : Modification pour que les informations soient gérées en dehors de l"ESP32

-- Zone à renseigner -----------------
-- table des informations - format : {Idx,Cellule,Libellé,Unité,Valeur}
-- Idx 		= IDX de la variable à envoyer vers l'ESP32 epaper
-- Cellule	= Cellule de l'écran dans laquelle les données de l'IDX seront affichées
-- Libellé	= Libellé à afficher dans la cellule
-- Unité	= Unité à afficher dans la cellule pour la valeur
-- Valeur	= Valeur qui doit être affichée dans la cellule
--		  souvent c'est la valeur identifiée dans le Json (usage, counter, counterToday, temperature, ...)
--		  il faut conserver le format exact du libellé Json

local MyVar	  = {{559,"L4C1","Conso EDF","","Value"},
		     {530,"L4C2","H Pleines","","Value"},
		     {560,"L5C1","EDF Jour","","Value"},
		     {531,"L5C2","HP EDF","","Value"},
    		     {307,"L5C4","","","Value"},
    		     {536,"L3C3","Tarif en Cours","","Value"},		     
		     {252,"L5C5","Vente aujourd'hui (Enphase)","","Value"}}
local MQTTTopic  = 'domoticz/epaper'		-- nom du topic MQTT
local logtext	 = 'MQTT epaper Var 22:05 : '	-- libellé identifiant les messages dans les logs
-- Fin de la Zone à renseigner -------

return
{
-- Indiquer la périodicité d'exécution du script
--  on		=	{timer = {'at 12:05','every 15 minutes'},},	
--  on 		=	{timer = {'every minute',},},
    on 		=    	{timer = {'at 22:05','every 15 minutes'},},
-- change to LOG_ERROR when ok or LOG_DEBUG pour tester
--  logging 	=	{level = domoticz.LOG_DEBUG,},
    logging	=	{level = domoticz.LOG_ERROR,},

-- Si possible - Ne pas modifier la partie du script ci-dessous
execute = function(dz)
    local function osCommand(cmd)
    dz.log('Executing Command: ' .. cmd,dz.LOG_DEBUG)
    local fileHandle = assert(io.popen(cmd .. ' 2>&1 || echo ::ERROR::', 'r'))
    local commandOutput = assert(fileHandle:read('*a'))
    local returnTable = {fileHandle:close()}
    if commandOutput:find '::ERROR::' then     -- something went wrong
	dz.log('Error ==>> ' .. tostring(commandOutput:match('^(.*)%s+::ERROR::') or ' ... but no error message ' ) ,dz.LOG_DEBUG)
    else -- all is fine!!
	dz.log('ReturnCode: ' .. returnTable[3] .. '\ncommandOutput:\n' .. commandOutput, dz.LOG_DEBUG)
    end
    return commandOutput,returnTable[3] -- rc[3] contains returnCode
    end
    local function sendMQTT(message)
	osCommand ( 'mosquitto_pub  -u user -P fireport68 ' ..  ' -t '  .. MQTTTopic .. " -m '" .. message .. "'")
    end
    for i,j in ipairs(MyVar) do
	local Var 	= tostring(dz.variables(MyVar[i][1]).id)
	local Nom 	= tostring(dz.variables(MyVar[i][1]).name)
	local Cell 	= tostring(MyVar[i][2])
	local Lib 	= tostring(MyVar[i][3])
	local Unit 	= tostring(MyVar[i][4])
	local lastUh	= tonumber(dz.variables(MyVar[i][1]).lastUpdate.hour)
	    if lastUh < 10 then lastUh = "0"..lastUh end
	local lastUm	= tonumber(dz.variables(MyVar[i][1]).lastUpdate.minutes)
	    if lastUm < 10 then lastUm = "0"..lastUm end
	local LastU	= lastUh..":"..lastUm
	local lastUM	= tonumber(dz.variables(MyVar[i][1]).lastUpdate.month)
	    if lastUM < 10 then lastUM = "0"..lastUM end	    
	local lastUd	= tonumber(dz.variables(MyVar[i][1]).lastUpdate.day)
	    if lastUd < 10 then lastUd = "0"..lastUd end
	local timed	= tonumber(dz.time.day)
	    if timed < 10 then timed = "0"..timed end	    
	if lastUd ~= timed then LastU = lastUd.."/"..lastUM end
	local Val	= tonumber(dz.variables(MyVar[i][1]).value)
	Val 		= dz.utils.round(Val, 2)
	myMessage	= '{"VAR":"'..Var..'","Nomvar":"'..Nom..'","Cellule":"'..Cell..'","Libelle":"'..Lib..'","Unite":"'..Unit..'","Heure":"'..LastU..'","Valeur":"'..Val..'"}'
 	dz.log(logtext..myMessage,dz.LOG_FORCE)
	sendMQTT(myMessage)
    end
end
}
Avatar du membre
Alain
Administrateur du site
Messages : 204
Enregistré le : 11 févr. 2021 11:55
Localisation : Gradignan - Gironde
Contact :

Re: Écran connecté

Message par Alain »

Et la nouvelle version du sketch pour l'ESP32 - Attention il faut aussi rajouter GxEPD2_display_selection_new_style.h pour que le fonctionnement soit correct (disponible sur demande) ;) :

Code : Tout sélectionner

// Programme qui permet l'affichage des informations liées à la consommation électrique sur un écran e-paper
// sur la base d'exemples de Jean-Marc Zingg (pour la gestion de l'écran) et Cyril Poissonnier (pour Domoticz via JSON)
// et avec modification du transfert depuis Domoticz en utilisant mqtt
// écran e-paper 800x480 3 couleurs (noir/blanc/rouge) de Waveshare + ESP32 Driver Board
//
// Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
//
// Author: Jean-Marc Zingg
//
// Library: https://github.com/ZinggJM/GxEPD2

// Supporting Arduino Forum Topics:
// Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0

// NOTE for use with Waveshare ESP32 Driver Board:
// **** also need to select the constructor with the parameters for this board in GxEPD2_display_selection_new_style.h ****
//
// The Wavehare ESP32 Driver Board uses uncommon SPI pins for the FPC connector. It uses HSPI pins, but SCK and MOSI are swapped.
// To use HW SPI with the ESP32 Driver Board, HW SPI pins need be re-mapped in any case. Can be done using either HSPI or VSPI.
// Other SPI clients can either be connected to the same SPI bus as the e-paper, or to the other HW SPI bus, or through SW SPI.
// The logical configuration would be to use the e-paper connection on HSPI with re-mapped pins, and use VSPI for other SPI clients.
// VSPI with standard VSPI pins is used by the global SPI instance of the Arduino IDE ESP32 package.

// Bibliothèques
#include <WiFi.h>
#include <WiFiClient.h>
#include <ArduinoOTA.h>           // Librairie pour permettre les mises à jour en wifi (Over The Air)
#include <PubSubClient.h>         // Librairie pour la gestion du protocole mqtt
#include <time.h> 
#include <ArduinoJson.h>          // https://github.com/bblanchon/ArduinoJson    
#include <SoftTimer.h>            // Librairie SoftTimer.h (pour le lancement périodique de taches)
//#include "RemoteDebug.h"          // Librairie RemoteDebug.h (pour mise au point en wifi)
//#include "RemoteDebugger.h"       // Librairie RemoteDebugger.h (pour mise au point en wifi) 

// Initialisation de WiFiClient, PubSubClient et RemoteDebug
WiFiClient espClient;
PubSubClient MQTTclient(espClient);
//RemoteDebug Debug;

// uncomment next line to use HSPI for EPD (and e.g VSPI for SD), e.g. with Waveshare ESP32 Driver Board
#define USE_HSPI_FOR_EPD

// base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
// enable or disable GxEPD2_GFX base class
#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_3C.h>
// Utilisation des polices Adafruit GFX
// https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
#include <Fonts/FreeMono9pt7b.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSansBold18pt7b.h>
#include <Fonts/FreeSansBold24pt7b.h>

// select the display class and display driver class in the following file (new style):
#include "GxEPD2_display_selection_new_style.h"

#if !defined(__AVR) && !defined(STM32F1xx)
// comment out unused bitmaps to reduce code space used
#include "bitmaps/Bitmaps800x480.h" // 7.5"  b/w
// 3-color
#include "bitmaps/Bitmaps3c400x300.h" // 4.2"  b/w/r
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_RP2040)
#include "bitmaps/Bitmaps3c648x480.h" // 5.83" b/w/r
#include "bitmaps/Bitmaps3c800x480.h" // 7.5"  b/w/r
#endif
#else
// select only one to fit in code space
// 3-color
#include "bitmaps/Bitmaps3c400x300.h" // 4.2"  b/w/r // not enough code space
#endif

#if defined(ESP32) && defined(USE_HSPI_FOR_EPD)
SPIClass hspi(HSPI);
#endif

// Paramétres WIFI à modifier en fonction des paramètres locaux
#define wifi_ssid     "votre SSID"
#define wifi_password "votre mot de passe"
#define host_name     "votre hostname"

// Paramétres MQTT Broker à modifier en fonction des paramètres locaux
const char *mqtt_broker         = "192.168.1.XXX";
char       *topic               = "votre topic";
const char *mqtt_username       = "";
const char *mqtt_password       = "";
const int   mqtt_port           = 1883;
const int   mqtt_keepalive      = 120;
const int   mqtt_sockettimeout  = 120;
// Variables pour la lecture des messages mqtt sur le topic
byte *payload;
int  length;

// Définition de l'adresse IP fixe pour l'ESP32
IPAddress local_IP(192, 168, 1, XXX); // Définition de l'adresse IP fixe pour l'ESP32 
IPAddress gateway(192, 168, 1, 1);    // Indication de l'adresse de la passerelle (la box)
IPAddress subnet(255, 255, 255, 0);   // Indication du subnet du réseau local
IPAddress primaryDNS(192, 168, 1, 1); // facultatif - Indication du serveur DNS primaire à utiliser (ici DNS de Google)
IPAddress secondaryDNS(8, 8, 8, 8);   // facultatif - Indication du serveur DNS secondaire à utiliser (ici DNS de Google)

// Paramétres pour la synchro NTP
const char* ntpServer = "fr.pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 0; // pendant l'heure d'été mettre à 3600 sinon à zéro

// Variables pour la connexion à Domoticz en http
char* host    = "192.168.1.XX";
int httpPort  = 8080; 

// Variables pour l'affichage initial
// char timeWeekDay[10];
char jjsem[2];   // Jour de la semaine (de 1 à 7) 1 = Lundi
char jjmois[3];  // Jour du mois
char mois[3];    // Mois (de 1 à 12)
char annee[5];   // Année
char heure[9];   // Heure
String L0Z1;     // Jour 
String L0Z5;     // Heure
String L0Z8 = "votre identification du projet";
// Variables principales des zones d'affichage (7 lignes et 5 colonnes)
// première cellule double (2 lignes sur 2 colonnes)
String L1C1; String L1C3; String L1C4; String L1C5;
String L2C3; String L2C4; String L2C5;
String L3C1; String L3C2; String L3C3; String L3C4; String L3C5;
String L4C1; String L4C2; String L4C3; String L4C4; String L4C5;
String L5C1; String L5C2; String L5C3; String L5C4; String L5C5;
String L6C1; String L6C2; String L6C3; String L6C4; String L6C5;
String L7C1; String L7C2; String L7C3; String L7C4; String L7C5;
// Libellé des zones d'affichage (7 lignes et 5 colonnes)
// qui indique la nature de valeur affichée au dessus dans la case
String L1C1l; String L1C3l; String L1C4l; String L1C5l;
String L2C3l; String L2C4l; String L2C5l;
String L3C1l; String L3C2l; String L3C3l; String L3C4l; String L3C5l;
String L4C1l; String L4C2l; String L4C3l; String L4C4l; String L4C5l;
String L5C1l; String L5C2l; String L5C3l; String L5C4l; String L5C5l;
String L6C1l; String L6C2l; String L6C3l; String L6C4l; String L6C5l;
String L7C1l; String L7C2l; String L7C3l; String L7C4l; String L7C5l;
// Unité dans les zones d'affichage (7 lignes et 5 colonnes)
// elle indique l'unité de la valeur affichée dans la case
String L1C1u; String L1C3u; String L1C4u; String L1C5u;
String L2C3u; String L2C4u; String L2C5u;
String L3C1u; String L3C2u; String L3C3u; String L3C4u; String L3C5u;
String L4C1u; String L4C2u; String L4C3u; String L4C4u; String L4C5u;
String L5C1u; String L5C2u; String L5C3u; String L5C4u; String L5C5u;
String L6C1u; String L6C2u; String L6C3u; String L6C4u; String L6C5u;
String L7C1u; String L7C2u; String L7C3u; String L7C4u; String L7C5u;
// Variables utilisées pour l'affichage des heures de mises à jour
// des valeurs contenues dans chaque case
String L1C1h; String L1C3h; String L1C4h; String L1C5h;
String L2C3h; String L2C4h; String L2C5h;
String L3C1h; String L3C2h; String L3C3h; String L3C4h; String L3C5h;
String L4C1h; String L4C2h; String L4C3h; String L4C4h; String L4C5h;
String L5C1h; String L5C2h; String L5C3h; String L5C4h; String L5C5h;
String L6C1h; String L6C2h; String L6C3h; String L6C4h; String L6C5h;
String L7C1h; String L7C2h; String L7C3h; String L7C4h; String L7C5h;

void loop(Task* me) { // Boucle du programme qui s'exécute perpétuellement
  if (!MQTTclient.connected()) {
    MQTTconnect();
  }
  MQTTclient.loop();
  ArduinoOTA.handle();
}

void epaper(Task* me) {      // Envoi des valeurs de Domoticz vers l'écran epaper (valeur fixée dans la commande Task t1(60000, TempMesure))
  Serial.println("Appel à affichage");  
  affichage();
  Serial.println("Retour de affichage");
}

// Paramètres pour SoftTimer
// Périodicité pour la boucle principale (ex loop)
Task t0(0, loop);                 // Boucle permanente
// Périodicité pour la récupération des valeurs sur Domoticz et leur affichage sur l'écran
Task t1(60000, epaper);           // Lancement epaper toutes les minutes

void setup() {
  Serial.begin(115200);
  Serial.println("----- Lancement du Setup -----");
  // Connexion au réseau WiFi
  setup_wifi();           // appel de la fonction setup_wifi sans paramètre
  initOTA();              // initialisation OTA
  // Connexion mqtt à Mosquitto
  MQTTclient.setKeepAlive(mqtt_keepalive);
  MQTTclient.setSocketTimeout(mqtt_sockettimeout);  
  MQTTclient.setServer(mqtt_broker, mqtt_port);
  MQTTclient.setCallback(MQTTcallback);
  MQTTconnect();         // appel de la fonction MQTTconnect sans paramètre
  #if defined(ESP32) && defined(USE_HSPI_FOR_EPD)
    hspi.begin(13, 12, 14, 15); // remap hspi for EPD (swap pins)
    display.epd2.selectSPI(hspi, SPISettings(4000000, MSBFIRST, SPI_MODE0));
  #endif
  // first update should be full refresh
  display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
//  display.cp437(true);  // Use correct CP437 character codes
  affichage_init();
  delay(1000);
  SoftTimer.add(&t0);
  SoftTimer.add(&t1);
  Serial.println("----- Setup terminé -----");
}

// Récupération des valeurs en format json dans le payload mqtt
void MQTTcallback(char *topic, byte *payload, unsigned int length) {
//  Serial.print("MQTTcallback - Message arrivant dans le topic : "); Serial.println(topic);
    for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
    }
    Serial.println();
    DynamicJsonDocument docmqtt(512);
    deserializeJson(docmqtt, payload, length);
    String idx, var, cel, lib, uni, heu, val;
    idx=docmqtt["IDX"]|"";            Serial.println("IDX = "+idx);
    var=docmqtt["VAR"]|"";            Serial.println("VAR = "+var);
    cel=docmqtt["Cellule"]|"";        Serial.println("Cellule = "+cel); 
    lib=docmqtt["Libelle"]|"";        Serial.println("Libelle = "+lib);  
    uni=docmqtt["Unite"]|"";          Serial.println("Unite = "+uni);  
    heu=docmqtt["Heure"]|"";          Serial.println("Heure = "+heu);
    val=docmqtt["Valeur"]|"";         Serial.println("Valeur = "+val);
    // Envoi des données Domoticz dans les zones d'affichage
    if (cel=="L1C1") {L1C1=val;L1C1u=uni;L1C1h=heu;L1C1l=lib;}
    if (cel=="L1C3") {L1C3=val;L1C3u=uni;L1C3h=heu;L1C3l=lib;}
    if (cel=="L1C4") {L1C4=val;L1C4u=uni;L1C4h=heu;L1C4l=lib;}
    if (cel=="L1C5") {L1C5=val;L1C5u=uni;L1C5h=heu;L1C5l=lib;}
    if (cel=="L2C3") {L2C3=val;L2C3u=uni;L2C3h=heu;L2C3l=lib;}
    if (cel=="L2C4") {L2C4=val;L2C4u=uni;L2C4h=heu;L2C4l=lib;}
    if (cel=="L2C5") {L2C5=val;L2C5u=uni;L2C5h=heu;L2C5l=lib;}
    if (cel=="L3C1") {L3C1=val;L3C1u=uni;L3C1h=heu;L3C1l=lib;}
    if (cel=="L3C2") {L3C2=val;L3C2u=uni;L3C2h=heu;L3C2l=lib;}
    if (cel=="L3C3") {L3C3=val;L3C3u=uni;L3C3h=heu;L3C3l=lib;}
    if (cel=="L3C4") {L3C4=val;L3C4u=uni;L3C4h=heu;L3C4l=lib;}
    if (cel=="L3C5") {L3C5=val;L3C5u=uni;L3C5h=heu;L3C5l=lib;}
    if (cel=="L4C1") {L4C1=val;L4C1u=uni;L4C1h=heu;L4C1l=lib;}
    if (cel=="L4C2") {L4C2=val;L4C2u=uni;L4C2h=heu;L4C2l=lib;}
    if (cel=="L4C3") {L4C3=val;L4C3u=uni;L4C3h=heu;L4C3l=lib;}
    if (cel=="L4C4") {L4C4=val;L4C4u=uni;L4C4h=heu;L4C4l=lib;}
    if (cel=="L4C5") {L4C5=val;L4C5u=uni;L4C5h=heu;L4C5l=lib;}
    if (cel=="L5C1") {L5C1=val;L5C1u=uni;L5C1h=heu;L5C1l=lib;}
    if (cel=="L5C2") {L5C2=val;L5C2u=uni;L5C2h=heu;L5C2l=lib;}
    if (cel=="L5C3") {L5C3=val;L5C3u=uni;L5C3h=heu;L5C3l=lib;}
    if (cel=="L5C4") {L5C4=val;L5C4u=uni;L5C4h=heu;L5C4l=lib;}
    if (cel=="L5C5") {L5C5=val;L5C5u=uni;L5C5h=heu;L5C5l=lib;}
    if (cel=="L6C1") {L6C1=val;L6C1u=uni;L6C1h=heu;L6C1l=lib;}
    if (cel=="L6C2") {L6C2=val;L6C2u=uni;L6C2h=heu;L6C2l=lib;}
    if (cel=="L6C3") {L6C3=val;L6C3u=uni;L6C3h=heu;L6C3l=lib;}
    if (cel=="L6C4") {L6C4=val;L6C4u=uni;L6C4h=heu;L6C4l=lib;}
    if (cel=="L6C5") {L6C5=val;L6C5u=uni;L6C5h=heu;L6C5l=lib;}
    if (cel=="L7C1") {L7C1=val;L7C1u=uni;L7C1h=heu;L7C1l=lib;}
    if (cel=="L7C2") {L7C2=val;L7C2u=uni;L7C2h=heu;L7C2l=lib;}
    if (cel=="L7C3") {L7C3=val;L7C3u=uni;L7C3h=heu;L7C3l=lib;}
    if (cel=="L7C4") {L7C4=val;L7C4u=uni;L7C4h=heu;L7C4l=lib;}
    if (cel=="L7C5") {L7C5=val;L7C5u=uni;L7C5h=heu;L7C5l=lib;}
}

void dateheure() {
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  struct tm timeinfo;
  char jj_sem[7][12] = {"Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"};
  char mm_an[12][12] = {"Janvier", "Fevrier", "Mars", "Avril", "Mai", "Juin", "Juillet",
                        "Aout", "Septembre", "Octobre", "Novembre", "Decembre"};
  if(!getLocalTime(&timeinfo)){
    Serial.println("Impossible de récupérer la Date et l'Heure");
    return;
  }
  // Serial.println(&timeinfo, "%u %d %m %Y %T");
  strftime(jjsem,  2, "%u", &timeinfo);
  strftime(jjmois, 3, "%d", &timeinfo);
  strftime(mois,   3, "%m", &timeinfo);
  strftime(annee,  5, "%Y", &timeinfo);
  strftime(heure,  9, "%T", &timeinfo);
  String jjj(jjsem);      // conversion char to string
  int jj = jjj.toInt();   // conversion string to int
  String mmm(mois);       // conversion char to string
  int mm = mmm.toInt();   // conversion string to int
  L0Z1 = " ";             L0Z1.concat(jj_sem[jj-1]);
  L0Z1.concat(" ");       L0Z1.concat(jjmois);
  L0Z1.concat(" ");       L0Z1.concat(mm_an[mm-1]);
  L0Z1.concat(" ");       L0Z1.concat(annee);       // Serial.printf("L0Z1 = "); Serial.println(L0Z1);
  L0Z5=heure;                                       // Serial.printf("L0Z5 = "); Serial.println(L0Z5);
}

void affichage_dateheure() {
  dateheure();
  // Affichage Date-Heure
  // Ligne 0 Date-Heure-Titre
  display.setFont(&FreeSansBold9pt7b);
  display.setTextColor(GxEPD_BLACK);                // Couleur du Texte en Blanc
  display.setCursor(30, 18); display.print(L0Z1);   // Jour de la semaine
  display.setCursor(690, 18); display.print(L0Z5);  // Heure
}

void affichage_init() {
  Serial.println("----- Début void affichage_init -----");
  display.setFullWindow();
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);                  // Remplissage initial du fond de l'écran en blanc
    display.drawRect(1, 1, 800, 480, GxEPD_WHITE);    // Traçage du rectangle avec couleur du trait
    display.setFont(&FreeSansBold24pt7b);
    display.fillRect(1, 1, 800, 480, GxEPD_WHITE);    // Remplissage du rectangle en Blanc
    display.setFont(&FreeSansBold24pt7b);
    display.setTextColor(GxEPD_BLACK);                  // Message en Rouge
    display.setCursor(135, 220); display.print(L0Z8);
    delay(3000);
  }
  while (display.nextPage());
  Serial.println("----- Fin void affichage_init -----");
}

// note for partial update window and setPartialWindow() method:
// partial update window size and position is on byte boundary in physical x direction
// the size is increased in setPartialWindow() if x or w are not multiple of 8 for even rotation, y or h for odd rotation
// see also comment in GxEPD2_BW.h, GxEPD2_3C.h or GxEPD2_GFX.h for method setPartialWindow()

void affichage() {
  Serial.println("----- Début void affichage -----");
  display.setFullWindow();
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);                  // Remplissage initial du fond de l'écran en blanc
    affichage_dateheure();
    // affichage d'une ligne avec x,y de début, x,y de fin et couleur
    // lignes horizontales
    display.drawLine(1, 25, 800, 25, GxEPD_BLACK);
    display.drawLine(320, 90, 800, 90, GxEPD_BLACK);
    display.drawLine(1, 155, 800, 155, GxEPD_BLACK);
    display.drawLine(1, 220, 800, 220, GxEPD_BLACK);
    display.drawLine(1, 285, 800, 285, GxEPD_BLACK);
    display.drawLine(1, 350, 800, 350, GxEPD_BLACK);
    display.drawLine(1, 415, 800, 415, GxEPD_BLACK);
    // lignes verticales
    display.drawLine(160, 155, 160, 480, GxEPD_BLACK); 
    display.drawLine(320, 25, 320, 480, GxEPD_BLACK);  
    display.drawLine(480, 25, 480, 480, GxEPD_BLACK);
    display.drawLine(640, 25, 640, 480, GxEPD_BLACK);

    // Affichage des valeurs envoyées depuis Domoticz via mqtt
    display.setTextColor(GxEPD_BLACK);    // Couleur du Texte en Noir
    // ligne 1 cellule 1
    display.setTextSize(2);       // Multiplicateur de la taille du texte (de 1 à 3)
    display.setCursor(50, 120);   display.setFont(&FreeSansBold24pt7b); display.print(L1C1);    // Valeur
    display.setTextSize(1);       // Multiplicateur de la taille du texte (de 1 à 3)
    display.setCursor(270, 120);  display.setFont(&FreeSansBold9pt7b);  display.print(L1C1u);   // Unité 
    display.setCursor(270, 40);   display.setFont(&FreeSans9pt7b);      display.print(L1C1h);   // Heure
    display.setCursor(110, 148);  display.setFont(&FreeMonoBold9pt7b);  display.print(L1C1l);   // Libellé
// ligne 1 cellule 3
    display.setCursor(370, 65);   display.setFont(&FreeSansBold18pt7b); display.print(L1C3);    // Valeur
    display.setCursor(420, 65);   display.setFont(&FreeSans9pt7b);      display.print(L1C3u);   // Unité 
    display.setCursor(430, 40);   display.setFont(&FreeSans9pt7b);      display.print(L1C3h);   // Heure
    display.setCursor(355, 83);   display.setFont(&FreeMonoBold9pt7b);  display.print(L1C3l);   // Libellé
// ligne 1 cellule 4    
    display.setCursor(510, 65);   display.setFont(&FreeSansBold18pt7b); display.print(L1C4);    // Valeur
    display.setCursor(580, 55);   display.setFont(&FreeSans9pt7b);      display.print(L1C4u);   // Unité 
    display.setCursor(590, 40);   display.setFont(&FreeSans9pt7b);      display.print(L1C4h);   // Heure
    display.setCursor(515, 83);   display.setFont(&FreeMonoBold9pt7b);  display.print(L1C4l);   // Libellé
// ligne 1 cellule 5    
    display.setCursor(650, 65);   display.setFont(&FreeSansBold18pt7b); display.print(L1C5);    // Valeur
    display.setCursor(720, 55);   display.setFont(&FreeSans9pt7b);      display.print(L1C5u);   // Unité  
    display.setCursor(725, 40);   display.setFont(&FreeSans9pt7b);      display.print(L1C5h);   // Heure
    display.setCursor(675, 83);   display.setFont(&FreeMonoBold9pt7b);  display.print(L1C5l);   // Libellé
// ligne 2 cellule 3    
    display.setCursor(370, 130);  display.setFont(&FreeSansBold18pt7b); display.print(L2C3);    // Valeur
    display.setCursor(420, 130);  display.setFont(&FreeSans9pt7b);      display.print(L2C3u);   // Unité 
    display.setCursor(430, 105);  display.setFont(&FreeSans9pt7b);      display.print(L2C3h);   // Heure
    display.setCursor(355, 148);  display.setFont(&FreeMonoBold9pt7b);  display.print(L2C3l);   // Libellé
// ligne 2 cellule 4    
    display.setCursor(510, 130);  display.setFont(&FreeSansBold18pt7b); display.print(L2C4);    // Valeur
    display.setCursor(580, 120);  display.setFont(&FreeSans9pt7b);      display.print(L2C4u);   // Unité 
    display.setCursor(590, 105);  display.setFont(&FreeSans9pt7b);      display.print(L2C4h);   // Heure
    display.setCursor(515, 148);  display.setFont(&FreeMonoBold9pt7b);  display.print(L2C4l);   // Libellé
// ligne 2 cellule 5    
    display.setCursor(650, 130);  display.setFont(&FreeSansBold18pt7b); display.print(L2C5);    // Valeur
    display.setCursor(720, 120);  display.setFont(&FreeSans9pt7b);      display.print(L2C5u);   // Unité 
    display.setCursor(725, 105);  display.setFont(&FreeSans9pt7b);      display.print(L2C5h);   // Heure
    display.setCursor(660, 148);  display.setFont(&FreeMonoBold9pt7b);  display.print(L2C5l);   // Libellé
// ligne 3 cellule 1    
    display.setCursor(35, 195);   display.setFont(&FreeSansBold18pt7b); display.print(L3C1);    // Valeur
    display.setCursor(115, 195);  display.setFont(&FreeSans9pt7b);      display.print(L3C1u);   // Unité 
    display.setCursor(110, 170);  display.setFont(&FreeSans9pt7b);      display.print(L3C1h);   // Heure 
    display.setCursor(30, 213);   display.setFont(&FreeMonoBold9pt7b);  display.print(L3C1l);   // Libellé
// ligne 3 cellule 2    
    display.setCursor(195, 195);  display.setFont(&FreeSansBold18pt7b); display.print(L3C2);    // Valeur
    display.setCursor(275, 195);  display.setFont(&FreeSans9pt7b);      display.print(L3C2u);   // Unité  
    display.setCursor(270, 170);  display.setFont(&FreeSans9pt7b);      display.print(L3C2h);   // Heure
    display.setCursor(205, 213);  display.setFont(&FreeMonoBold9pt7b);  display.print(L3C2l);   // Libellé
// ligne 3 cellule 3    
    display.setCursor(350, 195);  display.setFont(&FreeSansBold18pt7b); display.print(L3C3);    // Valeur
    display.setCursor(435, 195);  display.setFont(&FreeSans9pt7b);      display.print(L3C3u);   // Unité 
    display.setCursor(430, 170);  display.setFont(&FreeSans9pt7b);      display.print(L3C3h);   // Heure
    display.setCursor(335, 213);  display.setFont(&FreeMonoBold9pt7b);  display.print(L3C3l);   // Libellé
// ligne 3 cellule 4    
    display.setCursor(510, 195);  display.setFont(&FreeSansBold18pt7b); display.print(L3C4);    // Valeur
    display.setCursor(595, 195);  display.setFont(&FreeSans9pt7b);      display.print(L3C4u);   // Unité 
    display.setCursor(590, 170);  display.setFont(&FreeSans9pt7b);      display.print(L3C4h);   // Heure
    display.setCursor(505, 213);  display.setFont(&FreeMonoBold9pt7b);  display.print(L3C4l);   // Libellé     
// ligne 3 cellule 5    
    display.setCursor(660, 195);  display.setFont(&FreeSansBold18pt7b); display.print(L3C5);    // Valeur
    display.setCursor(745, 195);  display.setFont(&FreeSans9pt7b);      display.print(L3C5u);   // Unité 
    display.setCursor(725, 170);  display.setFont(&FreeSans9pt7b);      display.print(L3C5h);   // Heure
    display.setCursor(685, 213);  display.setFont(&FreeMonoBold9pt7b);  display.print(L3C5l);   // Libellé
// ligne 4 cellule 1    
    display.setCursor(30, 260);   display.setFont(&FreeSansBold18pt7b); display.print(L4C1);    // Valeur
    display.setCursor(120, 260);  display.setFont(&FreeSans9pt7b);      display.print(L4C1u);   // Unité
    display.setCursor(110, 235);  display.setFont(&FreeSans9pt7b);      display.print(L4C1h);   // Heure
    display.setCursor(35, 278);   display.setFont(&FreeMonoBold9pt7b);  display.print(L4C1l);   // Libellé
// ligne 4 cellule 2    
    display.setCursor(180, 260);  display.setFont(&FreeSansBold18pt7b); display.print(L4C2);    // Valeur
    display.setCursor(280, 260);  display.setFont(&FreeSans9pt7b);      display.print(L4C2u);   // Unité 
    display.setCursor(270, 235);  display.setFont(&FreeSans9pt7b);      display.print(L4C2h);   // Heure
    display.setCursor(195, 278);  display.setFont(&FreeMonoBold9pt7b);  display.print(L4C2l);   // Libellé
// ligne 4 cellule 3    
    display.setCursor(350, 260);  display.setFont(&FreeSansBold18pt7b); display.print(L4C3);    // Valeur
    display.setCursor(440, 260);  display.setFont(&FreeSans9pt7b);      display.print(L4C3u);   // Unité 
    display.setCursor(430, 235);  display.setFont(&FreeSans9pt7b);      display.print(L4C3h);   // Heure
    display.setCursor(355, 278);  display.setFont(&FreeMonoBold9pt7b);  display.print(L4C3l);   // Libellé
// ligne 4 cellule 4    
    display.setCursor(510, 260);  display.setFont(&FreeSansBold18pt7b); display.print(L4C4);    // Valeur
    display.setCursor(600, 260);  display.setFont(&FreeSans9pt7b);      display.print(L4C4u);   // Unité 
    display.setCursor(590, 235);  display.setFont(&FreeSans9pt7b);      display.print(L4C4h);   // Heure
    display.setCursor(515, 278);  display.setFont(&FreeMonoBold9pt7b);  display.print(L4C4l);   // Libellé
// ligne 4 cellule 5    
    display.setCursor(660, 260);  display.setFont(&FreeSansBold18pt7b); display.print(L4C5);    // Valeur
    display.setCursor(745, 260);  display.setFont(&FreeSans9pt7b);      display.print(L4C5u);   // Unité 
    display.setCursor(725, 235);  display.setFont(&FreeSans9pt7b);      display.print(L4C5h);   // Heure
    display.setCursor(675, 278);  display.setFont(&FreeMonoBold9pt7b);  display.print(L4C5l);   // Libellé  
// ligne 5 cellule 1    
    display.setCursor(30, 325);   display.setFont(&FreeSansBold18pt7b); display.print(L5C1);    // Valeur
    display.setCursor(115, 325);  display.setFont(&FreeSans9pt7b);      display.print(L5C1u);   // Unité
    display.setCursor(110, 300);  display.setFont(&FreeSans9pt7b);      display.print(L5C1h);   // Heure
    display.setCursor(35, 343);   display.setFont(&FreeMonoBold9pt7b);  display.print(L5C1l);   // Libellé
// ligne 5 cellule 2    
    display.setCursor(180, 325);  display.setFont(&FreeSansBold18pt7b); display.print(L5C2);    // Valeur
    display.setCursor(275, 325);  display.setFont(&FreeSans9pt7b);      display.print(L5C2u);   // Unité 
    display.setCursor(270, 300);  display.setFont(&FreeSans9pt7b);      display.print(L5C2h);   // Heure
    display.setCursor(195, 343);  display.setFont(&FreeMonoBold9pt7b);  display.print(L5C2l);   // Libellé
// ligne 5 cellule 3    
    display.setCursor(350, 325);  display.setFont(&FreeSansBold18pt7b); display.print(L5C3);    // Valeur
    display.setCursor(435, 325);  display.setFont(&FreeSans9pt7b);      display.print(L5C3u);   // Unité 
    display.setCursor(430, 300);  display.setFont(&FreeSans9pt7b);      display.print(L5C3h);   // Heure
    display.setCursor(355, 343);  display.setFont(&FreeMonoBold9pt7b);  display.print(L5C3l);   // Libellé
// ligne 5 cellule 4    
    display.setCursor(510, 325);  display.setFont(&FreeSansBold18pt7b); display.print(L5C4);    // Valeur
    display.setCursor(595, 325);  display.setFont(&FreeSans9pt7b);      display.print(L5C4u);   // Unité 
    display.setCursor(590, 300);  display.setFont(&FreeSans9pt7b);      display.print(L5C4h);   // Heure
    display.setCursor(515, 343);  display.setFont(&FreeMonoBold9pt7b);  display.print(L5C4l);   // Libellé      
// ligne 5 cellule 5    
    display.setCursor(660, 325);  display.setFont(&FreeSansBold18pt7b); display.print(L5C5);    // Valeur
    display.setCursor(745, 325);  display.setFont(&FreeSans9pt7b);      display.print(L5C5u);   // Unité 
    display.setCursor(725, 300);  display.setFont(&FreeSans9pt7b);      display.print(L5C5h);   // Heure
    display.setCursor(675, 343);  display.setFont(&FreeMonoBold9pt7b);  display.print(L5C5l);   // Libellé
// ligne 6 cellule 1    
    display.setCursor(30, 390);   display.setFont(&FreeSansBold18pt7b); display.print(L6C1);    // Valeur
    display.setCursor(120, 390);  display.setFont(&FreeSans9pt7b);      display.print(L6C1u);   // Unité
    display.setCursor(110, 365);  display.setFont(&FreeSans9pt7b);      display.print(L6C1h);   // Heure
    display.setCursor(35, 408);   display.setFont(&FreeMonoBold9pt7b);  display.print(L6C1l);   // Libellé
// ligne 6 cellule 2    
    display.setCursor(180, 390);  display.setFont(&FreeSansBold18pt7b); display.print(L6C2);    // Valeur
    display.setCursor(280, 390);  display.setFont(&FreeSans9pt7b);      display.print(L6C2u);   // Unité 
    display.setCursor(270, 365);  display.setFont(&FreeSans9pt7b);      display.print(L6C2h);   // Heure
    display.setCursor(195, 408);  display.setFont(&FreeMonoBold9pt7b);  display.print(L6C2l);   // Libellé
// ligne 6 cellule 3    
    display.setCursor(350, 390);  display.setFont(&FreeSansBold18pt7b); display.print(L6C3);    // Valeur
    display.setCursor(440, 390);  display.setFont(&FreeSans9pt7b);      display.print(L6C3u);   // Unité 
    display.setCursor(430, 365);  display.setFont(&FreeSans9pt7b);      display.print(L6C3h);   // Heure
    display.setCursor(355, 408);  display.setFont(&FreeMonoBold9pt7b);  display.print(L6C3l);   // Libellé
// ligne 6 cellule 4    
    display.setCursor(510, 390);  display.setFont(&FreeSansBold18pt7b); display.print(L6C4);    // Valeur
    display.setCursor(600, 390);  display.setFont(&FreeSans9pt7b);      display.print(L6C4u);   // Unité 
    display.setCursor(590, 365);  display.setFont(&FreeSans9pt7b);      display.print(L6C4h);   // Heure
    display.setCursor(515, 408);  display.setFont(&FreeMonoBold9pt7b);  display.print(L6C4l);   // Libellé      
// ligne 6 cellule 5    
    display.setCursor(660, 390);  display.setFont(&FreeSansBold18pt7b); display.print(L6C5);    // Valeur
    display.setCursor(745, 390);  display.setFont(&FreeSans9pt7b);      display.print(L6C5u);   // Unité 
    display.setCursor(725, 365);  display.setFont(&FreeSans9pt7b);      display.print(L6C5h);   // Heure
    display.setCursor(660, 408);  display.setFont(&FreeMonoBold9pt7b);  display.print(L6C5l);   // Libellé
// ligne 7 cellule 1    
    display.setCursor(30, 455);   display.setFont(&FreeSansBold18pt7b); display.print(L7C1);    // Valeur
    display.setCursor(115, 455);  display.setFont(&FreeSans9pt7b);      display.print(L7C1u);   // Unité
    display.setCursor(110, 430);  display.setFont(&FreeSans9pt7b);      display.print(L7C1h);   // Heure
    display.setCursor(35, 473);   display.setFont(&FreeMonoBold9pt7b);  display.print(L7C1l);   // Libellé
// ligne 7 cellule 2    
    display.setCursor(180, 455);  display.setFont(&FreeSansBold18pt7b); display.print(L7C2);    // Valeur
    display.setCursor(275, 455);  display.setFont(&FreeSans9pt7b);      display.print(L7C2u);   // Unité 
    display.setCursor(270, 430);  display.setFont(&FreeSans9pt7b);      display.print(L7C2h);   // Heure
    display.setCursor(195, 473);  display.setFont(&FreeMonoBold9pt7b);  display.print(L7C2l);   // Libellé
// ligne 7 cellule 3    
    display.setCursor(350, 455);  display.setFont(&FreeSansBold18pt7b); display.print(L7C3);    // Valeur 
    display.setCursor(435, 455);  display.setFont(&FreeSans9pt7b);      display.print(L7C3u);   // Unité 
    display.setCursor(430, 430);  display.setFont(&FreeSans9pt7b);      display.print(L7C3h);   // Heure
    display.setCursor(355, 473);  display.setFont(&FreeMonoBold9pt7b);  display.print(L7C3l);   // Libellé
// ligne 7 cellule 4    
    display.setCursor(510, 455);  display.setFont(&FreeSansBold18pt7b); display.print(L7C4);    // Valeur
    display.setCursor(595, 455);  display.setFont(&FreeSans9pt7b);      display.print(L7C4u);   // Unité 
    display.setCursor(590, 430);  display.setFont(&FreeSans9pt7b);      display.print(L7C4h);   // Heure
    display.setCursor(515, 473);  display.setFont(&FreeMonoBold9pt7b);  display.print(L7C4l);   // Libellé    
// ligne 7 cellule 5    
    display.setCursor(660, 455);  display.setFont(&FreeSansBold18pt7b); display.print(L7C5);    // Valeur
    display.setCursor(745, 455);  display.setFont(&FreeSans9pt7b);      display.print(L7C5u);   // Unité 
    display.setCursor(725, 430);  display.setFont(&FreeSans9pt7b);      display.print(L7C5h);   // Heure
    display.setCursor(675, 473);  display.setFont(&FreeMonoBold9pt7b);  display.print(L7C5l);   // Libellé
  }
  while (display.nextPage());
  Serial.println("----- Fin void affichage -----");
}

void setup_wifi() { // Connexion au réseau WiFi et affichage de la connexion dans le moniteur série
  delay(10);
  Serial.println();
  Serial.print("----- setup_wifi ----- Connexion à ");
  Serial.println(wifi_ssid);
  WiFi.mode(WIFI_STA);      // configure le WIFI en mode station
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  char adr_ip[20];          // contient l’adresse IP fournit par le point d’accès WiFi
  IPAddress ip;             // définition de la variable ip qui est une adresse IP
  ip = WiFi.localIP();      // on récupère l’adresse IP
  Serial.println("");
  Serial.println("WiFi connexion OK ");
  Serial.print("=> Addresse IP : ");
  Serial.println(WiFi.localIP());
  // Configuration de l'adresse IP fixe (DNS facultatif)
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
     Serial.println("Erreur de configuration pour l'IP fixe ! ");
  }
  Serial.print("----- IP Fixe = "); Serial.println(WiFi.localIP());
  delay(100);
}

void MQTTconnect() {  // Connexion au broker mqtt (mosquitto)
  Serial.print("----- MQTTconnect -----"); Serial.println();
  while (!MQTTclient.connected()) {
    String MQTTclient_id = "esp32_epaper_";
    MQTTclient_id += String(WiFi.macAddress());
    Serial.printf("Le client %s est connecté à mosquitto domoticz\n", MQTTclient_id.c_str());
    if (MQTTclient.connect(MQTTclient_id.c_str(), mqtt_username, mqtt_password)) {
        Serial.println("Connexion mqtt à Mosquitto OK");
        // Souscription au topic domoticz/epaper
        MQTTclient.subscribe(topic);
        Serial.print("Souscription au topic : "); Serial.println(topic);
      } else {
        Serial.print("Connexion mqtt à Mosquitto impossible ! "); Serial.println(MQTTclient.state());
        delay(2000);
    }
  }
}

void initOTA() {
  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);
  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname("esp32_epaper");
  // 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()
    Serial.println("Start updating " + type);
  })
  .onEnd([]() {
    Serial.println("\nEnd");
  })
  .onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  })
  .onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
}
Répondre