#include "WiFiEsp.h" // https://github.com/bportaluri/WiFiEsp
#include "WiFiEspUdp.h" // est inclus dan la librairie WiFiEsp
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
#include <Ephemeris.h> // https://github.com/MarScaper/ephemeris
// on défini une 2eme com serie en D2 et D8 pour communiquer avec l'ESP
HardwareSerial ESP(D2, D8); // RX, TX
char ssid[] = "XXXX"; // Votre réseau wifi
char pass[] = "YYYY"; // Votre mdp du réseau wifi
int status = WL_IDLE_STATUS; // l'état du réseau wifi
char timeServer[] = "fr.pool.ntp.org"; // le pool de serveur ntp interrogé
unsigned int localPort = 8888; // port d'écoute des packets UDP
const int NTP_PACKET_SIZE = 48; // L'horodatage NTP se trouve dans les 48 premiers octets du message
const int UDP_TIMEOUT = 2000; // délai d'attente pour l'arrivée d'un paquet UDP
const int timeZone = 1; // la timezone pour UTC vers GMT (+1 paris)
byte packetBuffer[NTP_PACKET_SIZE]; // tampon pour contenir les paquets entrants et sortants
// on instance l'UDP
WiFiEspUDP Udp;
// variable pour stocker l'heure précédente
time_t prevDisplay = 0;
// flag pour lancer le calcule du lever et coucher du soleil après chaque synchronisation au serveur NTP
bool flag_ephemeride = false; // en position desactivé
// variable pour stocker les heures et minutes du lever et coucher de soleil
int heure_lever, minute_lever, heure_coucher, minute_coucher;
// fonction pour afficher l'heure et la date
void digitalClockDisplay() {
// digital clock display of the time
printDigits(hour());
Serial.print(":");
printDigits(minute());
Serial.print(":");
printDigits(second());
Serial.print(" ");
printDigits(day());
Serial.print("/");
printDigits(month());
Serial.print("/");
Serial.print(year());
Serial.println();
}
// fonction qui met en forme les chiffres de 0 à 9 sur 2 digits
void printDigits(int digits) {
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void setup() {
Serial.begin(115200); // On démmarre la com série avec le pc a 115200 baud
ESP.begin(115200); // On démmarre la com série avec l'ESP a 115200 baud
WiFi.init(&ESP); // On initialisle la connection au réseau
// On test si on a le réseau à travers l'esp
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("Je tourve pas l'ESP");
while (true); // On ne continue pas
}
// On essaye de se connécter au réseau wifi
while ( status != WL_CONNECTED) {
Serial.print("J'essaye de me connecter au réseau wifi : ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
}
// On affiche les infos de connexions
Serial.print("Connécté à : ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("Mon ip est : ");
Serial.println(ip);
// On demarre l'udp
Udp.begin(localPort);
// on configure la synchronisation (toutes les 30s on interrogera le serveur NTP)
setSyncProvider(getNtpTime);
setSyncInterval(30); // 30 secondes pour les tests sinon 300 secondes ou plus
}
void loop() {
if (timeStatus() != timeNotSet) { // si le temps est configuré
if (now() != prevDisplay) { // ne met à jour l'affichage que si l'heure a changé
prevDisplay = now(); // l'ancienne heure devient celci
digitalClockDisplay(); // on affiche l'heure dans la com serie avec le pc
if (flag_ephemeride) { // si le flag est activé on calcul l'ephemeride avec la date et heure actuelle
printRiseAndSet("Varages", 43.6, 5.9667, timeZone, day(),month(),year());
}
}
}
}
time_t getNtpTime() {
// on attend que l'udp reponde
unsigned long startMs = millis();
while (!Udp.available() && (millis() - startMs) < UDP_TIMEOUT) {}
Serial.println(Udp.parsePacket());
while (Udp.parsePacket() > 0) ;
// Envoie de la requète NTP
Serial.println("Envoie de la requète NTP !!!");
sendNTPpacket(timeServer);
// on récupère la réponse (1500 ms pour recevoir)
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Reponse du serveur NTP reçu :");
Udp.read(packetBuffer, NTP_PACKET_SIZE);
// l'horodatage commence à l'octet 40 du paquet reçu et fait quatre octets,
// ou deux mots soit 2 octets par mot. On extraye les deux mots:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// on combine les quatre octets (les deux mots) en un entier long
// c'est l'heure NTP en secondes depuis le 1er janvier 1900
unsigned long secsSince1900 = highWord << 16 | lowWord;
// on affiche cette heure en timstamp dans la comme serie
Serial.print("Temps en secondes depuis le 1er janvier 1900 = ");
Serial.println(secsSince1900);
// on calcule le temps en ajoutant la time zone et le formate pour la librairie timelib (2208988800UL année 2000)
unsigned long Date_heure_courante = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
// on active le flag pour calculer l'ephemeride
flag_ephemeride = true;
// on retourne la date et heure pour la synchro
return Date_heure_courante;
}
}
// si rien n'arrive au bout de 1500ms on sort de la boucle while et on retourne 0
Serial.println("Pas de reponse du serveur NTP !!!");
return 0;
}
// fonction qui envoie une requête NTP au serveur de temps à l'adresse indiquée en argument
void sendNTPpacket(char *ntpSrv) {
// on met tous les octets du tampon à 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// On initialise les valeurs nécessaires pour former la requête NTP (j'ai pas trouver d'infos sur ces valeurs, pourquoi celle-ci, est ce modifiable ?)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes à zero de packetBuffer[4] à packetBuffer[11] puis
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// tous les champs tampon ont reçu les valeurs nécéssaire à la requète de temps sur le serveur NTP
// on ouvre la com au serveur (adresse et port de la requete tj 123)
Udp.beginPacket(ntpSrv, 123);
// on ecrit la demande (le tampon)
Udp.write(packetBuffer, NTP_PACKET_SIZE);
// on ferme la com
Udp.endPacket();
}
void printRiseAndSet(char *city, FLOAT latitude, FLOAT longitude, int UTCOffset, int day, int month, int year)
{
Ephemeris::setLocationOnEarth(latitude,longitude);
Serial.print(city);
Serial.print(" (UTC");
if( UTCOffset >= 0 ) { Serial.print("+"); }
Serial.print(UTCOffset);
Serial.print(")");
Serial.println(":");
SolarSystemObject sun = Ephemeris::solarSystemObjectAtDateAndTime(Sun,day,month,year,0,0,0);
// si le calcul est bon on stock les heures et minutes du lever et coucher dans les variables
if( sun.riseAndSetState == RiseAndSetOk ) {
float seconds;
// on converit et heure minute et seconde
Ephemeris::floatingHoursToHoursMinutesSeconds(Ephemeris::floatingHoursWithUTCOffset(sun.rise,UTCOffset), &heure_lever, &minute_lever, &seconds);
// on converit et heure minute et seconde
Ephemeris::floatingHoursToHoursMinutesSeconds(Ephemeris::floatingHoursWithUTCOffset(sun.set,UTCOffset), &heure_coucher, &minute_coucher, &seconds);
}
// si le calcul sont mauvais on affiche l'erreur
else if( sun.riseAndSetState == LocationOnEarthUnitialized )
{
Serial.println("Vous devez d'abord définir votre Longitude et Latitude");
}
else if( sun.riseAndSetState == ObjectAlwaysInSky )
{
Serial.println("Soleil toujours dans le ciel pour votre emplacement");
}
else if( sun.riseAndSetState == ObjectNeverInSky )
{
Serial.println("Soleil jamais dans le ciel pour votre emplacement");
}
// on ecrit dans la com serie avec le pc les infos
Serial.println();
Serial.print("A Varages le soleil se levera à ");
printDigits(heure_lever);
Serial.print("H");
printDigits(minute_lever);
Serial.print(" et se couchera à ");
printDigits(heure_coucher);
Serial.print("H");
printDigits(minute_coucher);
Serial.println();
// on desactive le flag
flag_ephemeride = false;
}