
#include <Arduino.h>

// ==================================
	String version="2026-08-10";
// ==================================


/*---------------------------------------------------------------------------------------
	SW.ino  - Gestion de boutons (switches) pour ESP32
	numéro de version doit être identique à celui du PFD (Primary Flight Display)	
	
	par Silicium628
	Ce logiciel est libre et gratuit sous licence GNU GPL
	
	Pour les #includes issus de l'univers Arduino (que je ne fournis pas), il faut voir au cas par cas.
---------------------------------------------------------------------------------------

Notes :

- ce SW envoi toutes les données par WiFi. Il n'est donc pas nécessaire de le connecter
sur un port USB, il peut être simplement alimenté par un adaptateur 5V.
*/

#include <stdint.h>

#include "SPI.h"


#include <WiFi.h>
#include <HTTPClient.h> // Remarque: les fonctions WiFi consomment 50% de la mémoire flash (de programme)

const char* ssid = "PFD_srv"; // nous nous connectons en tant que client au même serveur (le PFD) que le ND.
const char* password = "72r4TsJ28"; // doit être identique à celui du serveur du PFD


//IP address with URL path
const char* srvName_sw = "http://192.168.4.1/switch";


String recp_1;

char var_array[5];	// 4 char + zero terminal - pour envoi par WiFi

uint16_t v_switches=0; // états des boutons

uint32_t memo_micros = 0;
uint32_t temps_ecoule;
uint16_t nb_100ms=0;
uint16_t nb_secondes=0;


//-------------------------------------------------------------------------------------------
// j'attribue les ports dans l'ordre des pins de la platine ESP32, voir schéma
// Le SW (panel des boutons) peut être positionné soit à l'horizontale soit à la verticale.
// Il faut cofigurer ci-dessous les pins des boutons en conséqence.
// j'indique en colonne dans les commentaires les différents paramètrages utilisés au fil des versions...

uint16_t bouton0=1; // (2^0) -> positionnera 1 bit dans le mot "v_switches"
const int GPIO_bouton0 = 27; // 14 ; 13 pour la version horizontale du SW
bool bouton0_etat;
bool memo_bouton0_etat;

uint16_t bouton1=2; // (2^1)
const int GPIO_bouton1 = 14; // 27 ; 12 pour la version horizontale du SW
bool bouton1_etat;
bool memo_bouton1_etat;

uint16_t bouton2=4; // (2^2)
const int GPIO_bouton2 = 13; // 12 ; 14 pour la version horizontale du SW
bool bouton2_etat;
bool memo_bouton2_etat;

uint16_t bouton3=8; // (2^3)
const int GPIO_bouton3 = 12; // 13 ; 27 pour la version horizontale du SW
bool bouton3_etat;
bool memo_bouton3_etat;

uint16_t bouton4=64; // 16 (2^4)
const int GPIO_bouton4 = 25; // 26 pour la version horizontale du SW
bool bouton4_etat;
bool memo_bouton4_etat;

uint16_t bouton5=128; // 32 (2^5)
const int GPIO_bouton5 = 26; //25 pour la version horizontale du SW
bool bouton5_etat;
bool memo_bouton5_etat;

uint16_t bouton6=16; // 64 (2^6) 
const int GPIO_bouton6 = 33; // 33
bool bouton6_etat;
bool memo_bouton6_etat;

uint16_t bouton7=32; // 128 (2^7) 
const int GPIO_bouton7= 32; // 32
bool bouton7_etat;
bool memo_bouton7_etat;

/*
uint16_t bouton8=256; // (2^7) 
const int GPIO_bouton8= 35; // 32
bool bouton8_etat;
bool memo_bouton8_etat;
*/


uint16_t potar1;
uint16_t memo_potar1;
const int GPIO_potar1= 35;



//-------------------------------------------------------------------------------------------


//const int led1 = 25;


#define TEMPO 20 // tempo anti-rebond pour l'acquisition des encodeurs rotatifs
volatile uint32_t timer1 = 0;
volatile uint32_t timer2 = 0;

uint16_t compteur1;
uint8_t premier_passage=1;




void httpGet1()
{
	String s1;
	String s2;
	String s3;
	String s4;
/**
 envoie requete au serveur, avec position des switches en argument.
 il s'agit donc ici d'un envoi de données de ce SW vers le PFD. (voir la fonction "setup()" du PFD)
 dans une adresse (URL) html, le 1er argument se place à droite après un signe '?'
 les arguments suivants (éventuels) se placent à la suite, précédés cette fois par le signe '&'
 sur le web, la méthode n'est pas sécurisée à priori, mais ici il s'agit d'un réseau WiFi privé à courte portée
 et les données ne sont ni confidentielles ni critiques :
 (pas d'action sur un objet réel, chauffage, voiture, drône, Ariane5, bombe atomique etc...) 
**/
	HTTPClient http;
	char c1[4];

	s1= "?sw1=";  // sw1 (nom arbitraire..) pour désigner l'argument n°1 envoyé dans l'URL de la requête
	s2= String(v_switches);
	s1+= s2;

	s1+= "&pot1=";  // pot1 (nom arbitraire..) pour désigner l'argument n°3 envoyé dans l'URL de la requête
	s4= String(potar1);
	s1+= s4; // valeur à transmettre
	
	
	http.begin(srvName_sw+s1);
	int httpResponseCode = http.GET();
	if (httpResponseCode>0)	{ recp_1 = http.getString();}
	http.end();
}



void int_to_array(uint16_t valeur_i)
{
// prépare la chaine de caract à zéro terminal pour l'envoi
	String s1= (String) valeur_i;
	var_array[0]=s1[0];
	var_array[1]=s1[1];
	var_array[2]=s1[2];
	var_array[3]=s1[3];
	var_array[4]=0;  // zéro terminal  -> chaine C
}



void setup()
{
    Serial.begin(19200);
    delay(300);
   // Serial.println("");
   // Serial.println("Ici le SW");

	WiFi.persistent(false);
	WiFi.begin(ssid, password);

	
	delay(100);


	pinMode(GPIO_bouton0, INPUT_PULLUP);
	pinMode(GPIO_bouton1, INPUT_PULLUP);
	pinMode(GPIO_bouton2, INPUT_PULLUP);
	pinMode(GPIO_bouton3, INPUT_PULLUP);
	pinMode(GPIO_bouton4, INPUT_PULLUP);
	pinMode(GPIO_bouton5, INPUT_PULLUP);
	pinMode(GPIO_bouton6, INPUT_PULLUP);
	pinMode(GPIO_bouton7, INPUT_PULLUP);
	
//	pinMode(GPIO_bouton8, INPUT);

	pinMode(GPIO_potar1, INPUT);
	

	//pinMode(led1, OUTPUT);

	delay(100);


	bouton0_etat = digitalRead(bouton0);
	memo_bouton0_etat = bouton0_etat;

	bouton1_etat = digitalRead(bouton1);
	memo_bouton1_etat = bouton1_etat;

	bouton2_etat = digitalRead(bouton2);
	memo_bouton2_etat = bouton2_etat;

	bouton3_etat = digitalRead(bouton3);
	memo_bouton3_etat = bouton3_etat;

	bouton4_etat = digitalRead(bouton4);
	memo_bouton4_etat = bouton4_etat;

	bouton5_etat = digitalRead(bouton5);
	memo_bouton5_etat = bouton5_etat;

	bouton6_etat = digitalRead(bouton6);
	memo_bouton6_etat = bouton6_etat;

	bouton7_etat = digitalRead(bouton7);
	memo_bouton7_etat = bouton7_etat;

}


uint16_t L=0;
uint16_t C=0;
uint16_t x, y;
uint16_t i1 = 0;

uint8_t p1;

int32_t number = 0;

String parametre;
String s1;
String s2;



void requete_WiFi()
{
// voir les "server.on()" dans la fonction "setup()" du code du PFD pour la source des données
	recp_1 = "";
	if(WiFi.status()== WL_CONNECTED )
	{
		httpGet1(); // envoie requete au serveur, avec position des switch en argument.
		// il s'agit donc ici d'un envoi de données de ce SW vers le PFD.
		// les arguments dans les requetes permettent en effet à un client d'envoyer des data au serveur.
	}
}


void toutes_les_10s()
{
}


void toutes_les_1s()
{
	nb_secondes++;

	if(nb_secondes>10)
	{
		nb_secondes=0;
		toutes_les_10s();
	}
}



void toutes_les_100ms()
{
	nb_100ms++;

	if(nb_100ms>10)
	{
		nb_100ms=0;
		toutes_les_1s();
	}
}



void teste_boutons()
{
	bouton0_etat = digitalRead(GPIO_bouton0);
	if (bouton0_etat != memo_bouton0_etat)
	{
		memo_bouton0_etat = bouton0_etat;
		if (bouton0_etat==1) { v_switches &= ~bouton0;} else { v_switches |=  bouton0;}
		requete_WiFi();
	}

	bouton1_etat = digitalRead(GPIO_bouton1);
	if (bouton1_etat != memo_bouton1_etat)
	{
		memo_bouton1_etat = bouton1_etat;
		if (bouton1_etat==1){ v_switches &= ~bouton1;} else { v_switches |=  bouton1;}
		requete_WiFi();
	}

	bouton2_etat = digitalRead(GPIO_bouton2);
	if (bouton2_etat != memo_bouton2_etat)
	{
		memo_bouton2_etat = bouton2_etat;
		if (bouton2_etat==1) { v_switches &= ~bouton2;} else { v_switches |=  bouton2;}
			requete_WiFi();
	}

	bouton3_etat = digitalRead(GPIO_bouton3);
	if (bouton3_etat != memo_bouton3_etat)
	{
		memo_bouton3_etat = bouton3_etat;
		if (bouton3_etat==1) { v_switches &= ~bouton3;} else { v_switches |=  bouton3;}
		requete_WiFi();
	}
	
	bouton4_etat = digitalRead(GPIO_bouton4);
	if (bouton4_etat != memo_bouton4_etat)
	{
		memo_bouton4_etat = bouton4_etat;
		if (bouton4_etat==1) { v_switches &= ~bouton4;} else { v_switches |=  bouton4;}
		requete_WiFi();
	}

	bouton5_etat = digitalRead(GPIO_bouton5);
	if (bouton5_etat != memo_bouton5_etat)
	{
		memo_bouton5_etat = bouton5_etat;
		if (bouton5_etat==1) { v_switches &= ~bouton5;} else { v_switches |=  bouton5;}
		requete_WiFi();
	}

	bouton6_etat = digitalRead(GPIO_bouton6);
	if (bouton6_etat != memo_bouton6_etat)
	{
		memo_bouton6_etat = bouton6_etat;
		if (bouton6_etat==1) { v_switches &= ~bouton6;} else { v_switches |=  bouton6;}
		requete_WiFi();
	}

	bouton7_etat = digitalRead(GPIO_bouton7);
	if (bouton7_etat != memo_bouton7_etat)
	{
		memo_bouton7_etat = bouton7_etat;
		if (bouton7_etat==1) { v_switches &= ~bouton7;} else { v_switches |=  bouton7;}
		requete_WiFi();
	}

/*
	bouton8_etat = digitalRead(GPIO_bouton8);
	Serial.println(bouton8_etat);
	if (bouton8_etat != memo_bouton8_etat)
	{
		memo_bouton8_etat = bouton8_etat;
		if (bouton8_etat==1) { v_switches &= ~bouton8;} else { v_switches |=  bouton8;}
		requete_WiFi();
	}
*/

	potar1 = analogRead(GPIO_potar1)/16; // 0..255
	potar1 += 14; // en fonction de MON potentiomètre, qui du fait de son encoche sur l'axe, ne permet pas le règlage de son bouton
	if (abs(potar1 - memo_potar1) >1) // et pas '!=' pour éviter de faire des requetes intempestives lorsque le read hésite entre deux valeurs
	{
		memo_potar1 = potar1;
		//Serial.println(potar1);			
		requete_WiFi();
	}
}



uint16_t t=0; // temps -> rebouclera si dépassement    
void loop()
{
	teste_boutons();
	
	temps_ecoule = micros() - memo_micros;

	if (temps_ecoule  >= 1E5)  // (>=) et pas strictement égal (==) parce qu'alors on rate l'instant en question
	{
		memo_micros = micros();
		toutes_les_100ms();
	}
	
	compteur1+=1;
	if (compteur1 >= 100)  // tous les 1000 passages dans la boucle 
	{
		compteur1=0;
	}
		

	delay(30);
}






