#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet3.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp3.h>
#include <Key.h>               // Bibliothèque pour le clavier
#include <Keypad.h>            // Bibliothèque pour le clavier
#include <EEPROM.h>            // Bibliothèque pour enregistrer dans l'eeprom
#include <SPI.h>
#include <max6675.h>           // Bibliothèque pour les capteur thermocouple
#include <PID_v1_bc.h>         // Bibliothèque pour la gestion PID
#include <LiquidCrystal_I2C.h> // Bibliothèque pour LCD I2C
#include <RTClib.h>            // Bibliothèque pour l'horloge
#include <Arduino.h>
// ******************************paramètres stockés dans l'eeprom**********************************************
//const byte modeaut=EEPROM.read(4); // mode auto ou off(0 mode off->1 mode auto)
const byte p5=EEPROM.read(16);     //(p5) vitesse d'alimentation de la vis sans fin
const byte p6=EEPROM.read(17);     //(p6) Période de nettoyage du brûleur
const byte p7=EEPROM.read(18);     //(p7) Fenêtre de modulation
const byte p8=EEPROM.read(19);     //(p8) Hysteresis
const byte p9=EEPROM.read(20);     //(p9) Période d'alimentation
const byte p10=EEPROM.read(21);    //(p10) Vitesse du ventilateur à faible puissance
const byte p11=EEPROM.read(22);    //(p11) Vitesse du ventilateur à haut rendement
const byte p17=EEPROM.read(23);    //(p17) Limite de temperature de gaz d'échappement en °c
const byte p29=EEPROM.read(1);     //(p29) temps d'alimentation pellet au demarrage en secondes defaut:40
const byte p30=EEPROM.read(2);     //(p30) temps d'allumage résistance au demarrage en minutes defaut:20
const byte P31=EEPROM.read(0);     //(P31) vitesse du ventilateur des gaz au demarrage du bruleur defaut:140
const byte p32=EEPROM.read(3);     //(p32) difference de temperature pendant phase d'allumage
const byte p33=EEPROM.read(6);     //(p33) temps de rodage pendant allumage pellets
const byte p34=EEPROM.read(7);     //(p34) Vitesse du ventilateur pendant le rodage
const byte p35=EEPROM.read(8);     //(p35) temps d'extinction de flammes
const byte p36=EEPROM.read(9);     //(p36) detection temperature echappement en phase d'arrêt
const byte p37=EEPROM.read(5);     //(p37) temperature minimum pour demarrage pompe de circulation chaidière
const byte p38=EEPROM.read(10);    //(p38) hysteresis de la pompe de circulation
const byte p39=EEPROM.read(11);    //(p39) P Gain du contrôleur PID
const byte p40=EEPROM.read(12);    //(p40) I Gain du contrôleur PID
const byte p41=EEPROM.read(13);    //(p41) D Gain du contrôleur PID
const byte p42=EEPROM.read(14);    //(p42) Temps d'échantillonnage PID
const byte p53=EEPROM.read(15);    //(p53) reset du bruleur
const byte p60=EEPROM.read(24);    //(p60) temperature de reference eau chaudière

//********************************* parametrage carte ethernet-************************************************
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED  };
IPAddress ip(192,168,1,143);
EthernetServer local_server(49152);
char *url = (char *)malloc(100); 
//char url[100];

//***************************Initialiser les écrans LCD I2C 20x4***********************************************
LiquidCrystal_I2C lcd1(0x27, 20, 4); // Adresse 0x27, écran 20x4 (1)
LiquidCrystal_I2C lcd2(0x3F, 20, 4); // Adresse 0x27, écran 20x4 (2)

//***********************Définir les lignes et les colonnes du clavier 4x4*************************************
const byte ROWS    = 4; 
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
// Pins du clavier (L1, L2, L3, L4 pour les lignes et C1, C2, C3, C4 pour les colonnes)
byte rowpins[ROWS] = {28, 29, 30, 31}; // Les broches des lignes
byte colpins[COLS] = {32, 33, 34, 35}; // Les broches des colonnes
// Créer un objet Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowpins, colpins, ROWS, COLS );

//*************************************************************************************************************
byte degc[8] = {B11100,B10100,B11100,B00000,B00111,B00100,B00100,B00111};
byte tedegc[8] = {B10011,B10011,B10000,B11100,B10000,B10011,B10010,B10011};
//***************************initialisation horloge RTC_DS1307*************************************************
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
boolean ecran=0;
//************************** Déclaration des broches de relais**********-**************************************
int relaisPin[3] = {11,12,13};//  11  résistance, 12  au moteur de l'auge, 13  pompe circulation eau chaudière
bool relais3=false;  // etat du relais de pompe de circulation activé ou desactivé
//*************************************************************************************************************
int modeauto=1;//  1->arret, 2->auto, 3->perso, 4->h/gel
boolean defautbrul = 0;          //permet de boucle une seul fois sur demarrage bruleur si echoué
//************************declaration des variables pour le capteur hc-sr04************************************
const int trigPin = 6;  // Pin pour le signal Trigger
const int echoPin = 7;  // Pin pour le signal Echo
long duration;          // Durée du signal Echo
float distance;         // Distance mesurée en cm
float distanceMin = 0;  // Distance minimale en cm
float distanceMax = 50; // Distance maximale en cm
float pourcentage;      // Pourcentage calculé
float pourcentage2;
//**********************************Déclaration des pins SPI***************************************************
//pin thermocouple temperature sortie cheminee
const int pinCLK = 22;    // Pin horloge (SCK)
const int pinCS = 24;     // Pin CS (Chip Select)
const int pinSO = 23;     // Pin MISO (SO)
// pin thermocouple temperature eau chaudiere
const int pinCLK2 = 25;   // Pin horloge (SCK)
const int pinCS2 = 26;    // Pin CS (Chip Select)
const int pinSO2 = 27;    // Pin MISO (SO)
// Déclaration des broches 
MAX6675 thermocouple1( pinCLK, pinCS, pinSO ); // Initialiser le capteur MAX6675 1 temperature fumée
MAX6675 thermocouple2( pinCLK2, pinCS2, pinSO2 ); // Initialiser le capteur MAX6675 2 temperature eau chaudière

//***************************declaration pin pwm ventilateur de tirage*****************************************
const byte FAN_PIN = 4;             // Pin PWM pour contrôler la vitesse ventilateur tirage
byte vitesse = 0;                   // Valeur initiale de la vitesse (0 = éteint)

char index = 0;                     // index indiquant où l'on est rendu dans la chaîne
boolean etats[3] = {LOW, LOW, LOW}; // L'état des 3 sorties
unsigned char pwm = 0;              // La valeur de la pwm

//************************Variables de gestion de la température pour demarrage bruleur************************
float tempInitiale =0;  
float tempActuelle = 0;
unsigned long startTime=0; 
unsigned long elapsedTime = 0;
float seuildifference=EEPROM.read(3); //difference de temperature mini pendant la phase de demarrage du bruleur 

//************************variable PID pour gestion du bruleur pendant une chauffe*****************************
double temperaturepid; //température mesuré
double setPoint = p60; //température cible (en°c)
double input, output;  // entree PID(temperature mesuré), sortie PID(valeur de commande pour le chauffage)

double Kp = 2.0, Ki = 5.0, Kd = 1.0; // Gain P, I et D // PID constants (à ajuster en fonction de votre système)

PID myPID(&input, &output, &setPoint, Kp, Ki, Kd, DIRECT); // Création d'un objet PID

//*************************************************************************************************************
int tempSansVirgule1=0;
int tempSansVirgule2=0;
//float temp1=0;
//float temp2=0;
// ****************Définir les caractères personnalisés pour le ventilateur************************************
byte ventilateur2[8] = {B00000,B00110,B10100,B11111,B00101,B01100,B00000,B00000};
byte ventilateur3[8] = {B00000,B11001,B01011,B00100,B11010,B10011,B00000,B00000};	
	
bool exitLoop=0;

int consigne=40; // consigne temperature eau chaudière
//****************************************SETUP****************************************************************
int consacc=0;
//*************************************************************************************************************
//*****************************Variables pour la navigation du menu********************************************
int menuLevel = 0;  // Niveau du menu : 0 - Menu principal, 1 - Sous-menu 1, etc.
int menuIndex = 0;  // Index de la sélection dans le menu
// --------------------------------------Menu principal--------------------------------------------------------
const char* mainMenu[] = {"Mode", "Parametres"};
const int mainMenuSize = 2;
// ---------------------------------------Sous-menu(mode)------------------------------------------------------
const char* subMenu1[] = {"Arret", "Auto", "Perso", "Hors/Gel"};
const int subMenu1Size = 4;
//----------------------------------------Sous-menu(parametres)------------------------------------------------
const char* subMenu3[] = {"1-Valeurs usine", "2-modif valeurs", "3-Planning", "4-Consigne (fin)"};
const int subMenu3Size = 4;
//-------------------------------------Sous menu(parametres/planning)------------------------------------------
int jourIndex = 0;
const char* subsubMenu1[] = {"Lundi", "Mardi","Mercredi" , "Jeudi", "Vendredi", "Samedi", "Dimanche"};
const int subsubMenu1Size = 7;
//-------------------------------------Sous menu(parametres/planning/jours)------------------------------------------

const char* temps[] = {"Matin", "Apres-Midi"};
const int tempsSize = 2;





void setup() {

  // démarre le port série pour déboguer
  Serial.begin(9600);Ethernet.begin(mac, ip);local_server.begin();   
 
 capteur_niveau_pellets(); 
  //delay(1000);
  accueil();  

// Créer les caractères personnalisés pour le ventilateur
 //lcd2.init();lcd2.backlight(); 
 lcd1.createChar(3, ventilateur2);
 lcd1.createChar(4, ventilateur3);
   
   // rtc.begin();
   // rtc.adjust(DateTime(2023, 6, 31, 14, 21, 0));
   //lcd2.init();     

//----------------------- Initialisation des broches de relais en tant que sortie------------------------------
  for (byte i = 0; i < 3; i++)
   {
    pinMode(relaisPin[i], OUTPUT);
    digitalWrite(relaisPin[i], LOW); // Éteindre tous les relais au départ
} 
// Configure la broche PWM comme une sortie
    pinMode(FAN_PIN, OUTPUT); 

    //configure pins echo hc-sr04
     pinMode(trigPin, OUTPUT);
     pinMode(echoPin, INPUT);
      delay(3000);      

    myPID.SetMode(AUTOMATIC); // Mettre le PID en mode automatique
    myPID.SetOutputLimits(0, 255); // La sortie du PID sera entre 0 et 255 (contrôle du chauffage)

    pinMode(trigPin, OUTPUT); // Configurer le pin Trigger comme sortie
    pinMode(echoPin, INPUT); // Configurer le pin Echo comme entrée
}
//*********************************************LOOP************************************************************
void loop() {

//-----------------------------------------gestion du menu-----------------------------------------------------
   char key = keypad.getKey();  // Lire la touche du clavier 
   ecran=0;
  if (key) {
       
    if ((key=='*') && (ecran==0)){
      lcd2.init();lcd2.backlight();
      lcd1.backlight();           
      afficherMenuPrincipal();
      switch_menu();    
    } 
//--------------------- apuyer sur la touche 1 pour demarrer le mode auto--------------------------------------
    if (key=='1'){
      lcd2.init();lcd2.backlight();
      modeauto=2;
      menu_mode(2,1);
    } 
    if(key=='C'){
      lcd2.init();lcd2.backlight();
      consacc=1;
      consigne1();    
    }  
    if(key=='3'){
      cycle_chauffe ();
    }
  } 
  //ventilateur(); 
 } 
//******************************mise en route circulateur chaudiere********************************************
void fonctionnement_pompe(){

//float temp2 = thermocouple2.readCelsius();
liretemp2();
if (tempSansVirgule2>=p37 && !relais3){
   digitalWrite(relaisPin[3],HIGH);
   relais3 = true;
    Serial.println("pompe en fonction");
   }
if (tempSansVirgule2<(p37-p38) && relais3){
    digitalWrite(relaisPin[3],LOW);
    relais3=false;
    Serial.println("pompe arrete");
}    
}
//************************lecture des temperatures eau chaudière et temperature fumées*************************
void liretemp1(){// lecture température des fumées
    
    float temp1=0;
    temp1  = thermocouple1.readCelsius();  // Lire la température en °C  
    tempSansVirgule1 = int(temp1);
    Serial.print("Température fumée : ");
    Serial.print(tempSansVirgule1);  // Afficher la température
    Serial.println(" °C");
   }
  
void liretemp2()// lecture temperature eau chaudière
    {
      float temp2=0;
      temp2 = thermocouple2.readCelsius();  // Lire la température en °C  
      tempSansVirgule2 = int(temp2);    
     //delay(60000);  // Attendre 1 seconde avant la prochaine lecture
    }
//*************************************************************************************************************
void ventilateur(){// Affichage du ventilateur tournant
 
 lcd1.setCursor(3, 16);lcd1.write(byte(3)); // Ventilateur 2
 delay(500);
lcd1.setCursor(3, 16);lcd1.write(byte(4)); // Ventilateur 3 
 delay(500); 
}
//*************************************************************************************************************
mega:SCL
mega:SDA
mega:AREF
mega:GND.1
mega:13
mega:12
mega:11
mega:10
mega:9
mega:8
mega:7
mega:6
mega:5
mega:4
mega:3
mega:2
mega:1
mega:0
mega:14
mega:15
mega:16
mega:17
mega:18
mega:19
mega:20
mega:21
mega:5V.1
mega:5V.2
mega:22
mega:23
mega:24
mega:25
mega:26
mega:27
mega:28
mega:29
mega:30
mega:31
mega:32
mega:33
mega:34
mega:35
mega:36
mega:37
mega:38
mega:39
mega:40
mega:41
mega:42
mega:43
mega:44
mega:45
mega:46
mega:47
mega:48
mega:49
mega:50
mega:51
mega:52
mega:53
mega:GND.4
mega:GND.5
mega:IOREF
mega:RESET
mega:3.3V
mega:5V
mega:GND.2
mega:GND.3
mega:VIN
mega:A0
mega:A1
mega:A2
mega:A3
mega:A4
mega:A5
mega:A6
mega:A7
mega:A8
mega:A9
mega:A10
mega:A11
mega:A12
mega:A13
mega:A14
mega:A15
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
lcd2:GND
lcd2:VCC
lcd2:SDA
lcd2:SCL
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4
ultrasonic1:VCC
ultrasonic1:TRIG
ultrasonic1:ECHO
ultrasonic1:GND
GND5VSDASCLSQWRTCDS1307+
rtc1:GND
rtc1:5V
rtc1:SDA
rtc1:SCL
rtc1:SQW
NOCOMNCVCCGNDINLED1PWRRelay Module
relay1:VCC
relay1:GND
relay1:IN
relay1:NC
relay1:COM
relay1:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay2:VCC
relay2:GND
relay2:IN
relay2:NC
relay2:COM
relay2:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay3:VCC
relay3:GND
relay3:IN
relay3:NC
relay3:COM
relay3:NO