Les Carnets de Byfeel domotique , Objets connectĂ©s , DIY , Programmation, Nouvelles Technologies ….

DIY Horloge et Notification Domotique ( Matrix LED ) avec Jeedom

Le but de cet article , est d’amĂ©liorer le projet Horloge Arduino.

en apportant les plus suivants :

  • Mise Ă  jour en WIFI
  • Envoi des notification en WIFI
  • Gestion de la luminositĂ©
  • Gestion et mise Ă  jour de l’heure via service NTP
  • Ecran plus grand
  • ParamĂ©trable via interface Web
  • InteropĂ©rabilitĂ© domotique

Pour cela nous aurons besoin de :

  • Wemos d1
  • Deux matrices LED de quatre Ă©lĂ©ments
  • Une photorĂ©sistance et une rĂ©sistance

On va partir du sketch final de l’article : WIFI et OTA

Afin de gĂ©rer , l’affichage des diffĂ©rentes fonctionnalitĂ©s ( horloge , notification , message information …. ) nous allons utiliser deux matrices LED ( composĂ©es de 4 matrices LED 8×8 ( basĂ©es sur Max7219 ).

Vue arriĂšre
Vue cÎté
Matrice led – vue Avant

Il suffira de souder les deux modules , ce qui amĂšne un affichage sur 8 x 64.

Une fois les deux modules assemblés ( soudures entre les deux circuits , à prévoir ).Nous allons relier la matrice au Wemos de la façon suivante :

  • Vcc -> 5v
  • Gnd -> Gnd
  • DIN -> D7
  • CS  -> D6
  • CLK -> D5

Nous allons maintenant intĂ©grer au Sketch , les bibliothĂšques permettant de piloter la matrice  ( ne pas hĂ©siter Ă  se reporter Ă  l’article horloge Arduino , pour plus de dĂ©tails ).

// gestion de l’affichage matricielle
#include <MD_Parola.h>
#include <MD_MAX72xx.h>

Puis Ă  dĂ©finir les PIN sur lesquels sont reliĂ©s cette derniĂšre , ainsi que le nombre d’afficheur. Puis Ă  Initialiser la matrice.

// Parametrage matrice ( Pin Arduino oĂč est branchĂ©e la matrice )
#define MAX_DEVICES 8 // ( nombre de matrice )
#define CLK_PIN D5
#define DATA_PIN D7
#define CS_PIN D6

// initialisation de la matrice
MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

Afin de pouvoir afficher des messages il faut dĂ©marrer le service d’affichage , dans la fonction Setup.

//démarrage Display
P.begin();

A partir de maintenant , nous sommes en mesure de pouvoir afficher un message sur la matrice avec la fonction :  P.print(« votre message« );

Le message Ă  afficher peut ĂȘtre soit de type String ou Char(buffer).

Si vous aves des soucis d’affichage , des caractĂšres Ă  l’envers , des effets miroir ou autres ( penser Ă  configurer dans la  bibliothĂšque master  : le fichier src/MD_MAX72xx_lib.h , comme expliquĂ© dans cet article )

Ce qui donne :

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// WIFI Manager , afin de gérer la connexion au WIFI de façon plus intuitive
#include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager

///includes nécessaires au fonctionnement de l'OTA :
#include <WiFiUdp.h>
#include <ArduinoOTA.h>


// gestion de l'affichage matricielle
#include <MD_Parola.h>
#include <MD_MAX72xx.h>


ESP8266WebServer server(80);         // serveur WEB sur port 80

// définition du numéro de LED interne 
int led = 2; // led built IN

// ParamĂ©trage matrice  ( Pin Arduino oĂč est branchĂ©e la matrice )
#define MAX_DEVICES 8 // ( nombre de matrice )
#define CLK_PIN   D5
#define DATA_PIN  D7
#define CS_PIN    D6
// initialisation de la matrice
MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); 

//variable systemes
#define  BUF_SIZE  60
char Notif[BUF_SIZE];

// fonction callback Wifimanager quand Mode AP en fonction
void configModeCallback (WiFiManager *myWiFiManager) {
  P.print("Choisir AP..");
  delay(3000);
  P.print(WiFi.softAPIP().toString());
    delay(3000);
    P.print(myWiFiManager->getConfigPortalSSID());
  //Serial.println(WiFi.softAPIP());
  //if you used auto generated SSID, print it
  //Serial.println(myWiFiManager->getConfigPortalSSID());
}

void setup() {
   //démarrage Display
   P.begin();

      //******** WiFiManager ************
    //Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wifiManager;

     //Si besoin de fixer une adresse IP
    //wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
    
    //Forcer à effacer les données WIFI dans l'eprom , permet de changer d'AP à chaque démarrage ou effacer les infos d'une AP dans la mémoire ( à valider , lors du premier lancement  )
    //wifiManager.resetSettings();
    //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
     wifiManager.setAPCallback(configModeCallback);
    
    //RecupĂšre les identifiants   ssid et Mot de passe dans l'eprom  et essaye de se connecter
    //Si pas de connexion possible , il demarre un nouveau point d'accés avec comme nom , celui defini dans la commande autoconnect ( ici : AutoconnectAP )
    // wifiManager.autoConnect("AutoConnectAP");
    //Si rien indiqué le nom par défaut est  ESP + ChipID
    //wifiManager.autoConnect();
      if(!wifiManager.autoConnect("AP_ESP")) {
              P.print("erreur AP");;
              delay(3000);
              //reset and try again, or maybe put it to deep sleep
              ESP.reset();
              delay(5000);
        } 
    
// ****** Fin config WIFI Manager ************



 //******* OTA ***************
// Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("EspTestOTA");

  // 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";
    digitalWrite(led, HIGH); // allume led au début du transfert
      P.print("Update ..."); 
    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    //Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
     P.print("Reboot ..."); 
    digitalWrite(led, LOW); // éteint à la fin de la mise à jour
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    sprintf(Notif,"Upload  %u%%", (progress / (total / 100)));
     P.print(Notif); 
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    //Serial.printf("Error[%u]: ", error);
  });
  ArduinoOTA.begin();
  //********* Fin OTA ***************
   
 

  // on attend d'ĂȘtre connectĂ© au WiFi avant de continuer
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  P.print("Wait ..."); 
  }
  // on affiche l'adresse IP attribuée pour le serveur DSN
  //Serial.print("IP address: ");
  //Serial.println(WiFi.localIP());
  P.print("Wifi Ready ...");
  delay(300);
  P.print(WiFi.localIP().toString());
  delay(2000);
  
  // on définit les points d'entrée (les URL à saisir dans le navigateur web) et on affiche un simple texte 
  server.on("/", [](){
    server.send(200, "text/plain", "Page d'accueil");
  });

 server.on("/led", []() {
  String Etat=server.arg("etat");
  if (Etat == "on") digitalWrite(led, LOW);
  else if (Etat == "off") digitalWrite(led, HIGH);
  server.send(200, "text/plain", "la led est  " + Etat);
});

  // on démarre le serveur web 
  server.begin();
  pinMode(led, OUTPUT);     // Initialise la broche "led" comme une sortie 
  digitalWrite(led, HIGH);
   P.print("OK ..."); 
}
 

void loop() {
  // Ă  chaque iteration, la fonction handleClient traite les requĂȘtes 
  server.handleClient();
   // Surveillance des demandes de mise Ă  jour en OTA
  ArduinoOTA.handle();
             
}

Qu’apporte ce script , par rapport Ă  la version prĂ©cĂ©dente : Des messages d’informations sur les diffĂ©rentes Ă©tapes de sketch.

  • Phase WifiManager : Une fonction de callback Ă  Ă©tĂ© ajoutĂ©e , afin d’informer l’utilisateur de configurer son module en allant sur l’AP créé par le module ( le nom de l’AP et l’adresse IP du module s’affiche sur le Display ).
    P.print(WiFi.softAPIP().toString());
    P.print(myWiFiManager->getConfigPortalSSID());
  • Phase OTA : Une information sur chaque Ă©tape : Start , End et Progress qui permet d’afficher un compteur en pourcentage sur le tĂ©lĂ©chargement en cours .
    sprintf(Notif, »Upload %u%% », (progress / (total / 100)));
    P.print(Notif);
  • Phase 3 : Information sur la connexion Ă  votre reseau WIFI , affichage de l’adresse IP obtenue.
    P.print(« Wifi Ready … »);
    delay(300);
    P.print(WiFi.localIP().toString());
  • Phase 4 : Fin de la boucle setup
[adsense]

Fonction Temps et affichage de l’heure

Nous pourrions utiliser un module RTC , comme dans le premier article , sur la conception de l’horloge avec le module Arduino. Mais Ă©tant donnĂ© que ce module dispose d’une connexion WIFI permanente , nous allons synchroniser l’heure systĂšme sur un serveur de temps afin de rĂ©cupĂ©rer l’heure universelle rĂ©guliĂšrement , et ainsi permettre d’ĂȘtre toujours Ă  l’heure.

Pour cela nous allons utiliser , les deux librairies suivantes :

time et NTPclient . A ajouter par l’intermĂ©diaire du gestionnaire de bibliothĂšque ou Ă  tĂ©lĂ©charger directement sur leurs github associĂ©s.

On définit ensuite les paramÚtres NTP suivants :

// ParamĂštre NTP
// Serveur NTP
const char ntpserver[] = « pool.ntp.org »;
// TimeZone
int8_t timeZone = 1;
// Le fuseau utilise les horaires été / hiver
bool DLS = true;

Dans la boucle Setup() , on va démarrer le service NTP avec les instructions suivantes :

//******* Service NTP ********
// Démarrage du processus NTP
NTP.begin(ntpserver, timeZone, DLS);
// Intervalle de  synchronisation en seconde , 10 s au départ pour forcer une mise à jour rapide dÚs le démarrage.
NTP.setInterval (10);

Dans la boucle loop() , on dĂ©finit la fonction de callback dĂ©diĂ©e au process NTP , afin d’agir en fonction des diffĂ©rents Ă©vĂšnements.

NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
processNtpEvent(event);
});

La fonction processNTPEvent , est définie en dehors des deux boucles :

void processNtpEvent (NTPSyncEvent_t ntpEvent) {
if (ntpEvent) {
         if (ntpEvent == noResponse)
// action à définir si aucune réponse ou réponse erronée en retour
else if (ntpEvent == invalidAddress)
// action Ă  definir si adresse serveur invalide
         }      else  {
// RĂ©ponse valide et serveur accessible  — Tout est OK
NTP.setInterval (1800);  // Apres premiĂšre synchro , le temps de synchronisation est augmentĂ© Ă  30 mn , afin d’Ă©viter d’envoyer trop de requĂȘte )
         }
}

Une fois le service NTP synchronisĂ© , l’heure peut ĂȘtre affichĂ©e Ă  l’aide de la librairie Time.

par le biais des fonctions suivantes :

hour();            // L'heure (0-23)
minute();          // Minute (0-59)
second();          // Seconde (0-59)
day();             // Le jour(1-31)
weekday();         // Numéro de jour (1-7), Dimanche est le jour 1
month();           // Numéro du mois (1-12)
year();            // l'année sur 4 digit: (2017,2018 , etc )

Pour afficher l’heure , nous allons inclure dans la boucle loop , les instructions suivantes :

if (P.displayAnimate())   // Boucle pour contrĂŽler les animations de l’afficheur
{
digitalClockDisplay().toCharArray(Notif,BUF_SIZE); // fonction pour rĂ©cupĂ©rer l’heure et la formater.
P.displayText(Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
 // affichage de l’horloge sur le display avec effet central 

}

Pour le formatage de l’heure , on utilise la fonction suivante :

// Fonction clockformat
String digitalClockDisplay()
     {
String message;
// si date pas rĂ©cupĂ©rĂ©e affiche init …
if ( year() == 1970) {    message= »Init.. »;
    }
else {
message=hour();
message+=printDigits(minute());
// Affiche les secondes si variable DisSec sur true
if ( DisSec ) { message+=printDigits(second()); }
}
return message;
}

Fonction qui permet d’ajouter les deux points et le zĂ©ro avant les minutes et les secondes.

String printDigits(int digits)
{
String Digital;
Digital= »: »;
if (digits < 10) Digital+= »0″;
Digital+=digits;
return Digital;
}

Ce qui donne le script complet suivant :

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// WIFI Manager , afin de gérer la connexion au WIFI de façon plus intuitive
#include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager

///includes nécessaires au fonctionnement de l'OTA :
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// gestion de l'affichage matricielle
#include <MD_Parola.h>
#include <MD_MAX72xx.h>

// librairie temps
#include <TimeLib.h>
#include <NtpClientLib.h>

ESP8266WebServer server(80);         // serveur WEB sur port 80

// définition du numéro de LED interne 
int led = 2; // led built IN

// ParamĂ©trage matrice  ( Pin Arduino oĂč est branchĂ©e la matrice )
#define MAX_DEVICES 8 // ( nombre de matrice )
#define CLK_PIN   D5
#define DATA_PIN  D7
#define CS_PIN    D6
// initialisation de la matrice
MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); 

//variable systemes
#define  BUF_SIZE  60
char Notif[BUF_SIZE];
boolean DisSec = true;

// Parametre NTP
// Serveur NTP
const char ntpserver[] = "pool.ntp.org";
// TimeZone
int8_t timeZone = 1;
// Le fuseau utilise les horaires été / hiver
bool DLS = true;


void configModeCallback (WiFiManager *myWiFiManager) {
  P.print("Choisir AP..");
  delay(3000);
  P.print(WiFi.softAPIP().toString());
    delay(3000);
    P.print(myWiFiManager->getConfigPortalSSID());
  //Serial.println(WiFi.softAPIP());
  //if you used auto generated SSID, print it
  //Serial.println(myWiFiManager->getConfigPortalSSID());
}


void processNtpEvent (NTPSyncEvent_t ntpEvent) {
  if (ntpEvent) {
    if (ntpEvent == noResponse)
      P.print ("Serveur NTP injoignable");
    else if (ntpEvent == invalidAddress)
      P.print ("Adresse du serveur NTP invalide");
  } else {
    //P.print ("Récupération du temps NTP: ");
    //P.print (NTP.getTimeDateString (NTP.getLastNTPSync ()));
    NTP.setInterval (1800);
  }
}

void setup() {
   //démarrage Display
   P.begin();

      //******** WiFiManager ************
    //Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wifiManager;

     //Si besoin de fixer une adresse IP
    //wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
    
    //Forcer à effacer les données WIFI dans l'eprom , permet de changer d'AP à chaque démarrage ou effacer les infos d'une AP dans la mémoire (à valider , lors du premier lancement)
    //wifiManager.resetSettings();
    //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
     wifiManager.setAPCallback(configModeCallback);
    
    //RécupÚre les identifiants   ssid et Mot de passe dans l'eprom et essaye de se connecter
    //Si pas de connexion possible , il démarre un nouveau point d'accÚs avec comme nom , celui définit dans la commande autoconnect ( ici : AutoconnectAP )
    // wifiManager.autoConnect("AutoConnectAP");
    //Si rien indiqué le nom par défaut est  ESP + ChipID
    //wifiManager.autoConnect();
      if(!wifiManager.autoConnect("AP_ESP")) {
              P.print("erreur AP");;
              delay(3000);
              //reset and try again, or maybe put it to deep sleep
              ESP.reset();
              delay(5000);
        } 
    
// ****** Fin config WIFI Manager ************



 //******* OTA ***************
// Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("EspTestOTA");

  // 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";
    digitalWrite(led, HIGH); // allume led au début du transfert
      P.print("Update ..."); 
    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    //Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
     P.print("Reboot ..."); 
    digitalWrite(led, LOW); // éteint à la fin de la mise à jour
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    sprintf(Notif,"Upload  %u%%", (progress / (total / 100)));
     P.print(Notif); 
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    //Serial.printf("Error[%u]: ", error);
  });
  ArduinoOTA.begin();
  //********* Fin OTA ***************
   
 

  // on attend d'ĂȘtre connectĂ© au WiFi avant de continuer
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  P.print("Wait ..."); 
  }
  // on affiche l'adresse IP attribuée pour le serveur DSN
  //Serial.print("IP address: ");
  //Serial.println(WiFi.localIP());
  P.print("Wifi Ready ...");
  delay(300);
  P.print(WiFi.localIP().toString());
  delay(2000);

 

  //*************************
  
  // on définit les points d'entrée (les URL à saisir dans le navigateur web) et on affiche un simple texte 
  server.on("/", [](){
    server.send(200, "text/plain", "Page d'accueil");
  });

 server.on("/led", []() {
  String Etat=server.arg("etat");
  if (Etat == "on") digitalWrite(led, LOW);
  else if (Etat == "off") digitalWrite(led, HIGH);
  server.send(200, "text/plain", "la led est  " + Etat);
});

  // on démarre le serveur web 
  server.begin();


    //******* Service NTP ********
// Démarrage du processus NTP  
NTP.begin(ntpserver, timeZone, DLS);
// Intervalle de synchronisation en seconde , 10 s au départ pour forcer une mise à jour rapide
NTP.setInterval (10);


  pinMode(led, OUTPUT);     // Initialise la broche "led" comme une sortie 
  digitalWrite(led, HIGH);
   P.print("OK ...");
}

 

void loop() {
  NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
  processNtpEvent(event);
});
  // Ă  chaque iteration, la fonction handleClient traite les requĂȘtes 
  server.handleClient();
   // Surveillance des demandes de mise Ă  jour en OTA
  ArduinoOTA.handle();

  if (P.displayAnimate())
{
         digitalClockDisplay().toCharArray(Notif,BUF_SIZE);
  
    P.displayText(Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);    
}
}


// Fonction clockformat
String digitalClockDisplay()
    {
      String message;
      if ( year() == 1970) {
             message="Init..";
            }
        else {
          message=hour();
          message+=printDigits(minute());
          if ( DisSec ) { message+=printDigits(second()); }
          }
  return message;
  }

String printDigits(int digits)
{
  String Digital;
  Digital=":";
  if (digits < 10) Digital+="0";
  Digital+=digits;
  return Digital;
}

Avec la variable suivante :

boolean DisSec = true;

vous pouvez afficher les secondes ( true ) ou ne pas les afficher ( false ).

Ajout des Notifications

Les messages vont ĂȘtre envoyĂ©s par le biais du Wifi , en appelant l’adresse Web du serveur de notre module.

Sous la forme : http://ip_module/Notification?msg=test

Pour cela, nous allons mettre en place une page Web , dans notre programme sous la forme suivante :

server.on(« /Notification », [](){
// on rĂ©cupĂšre le paramĂštre msg dans l’url
message=server.arg(« msg »);
// on affecte le message Ă   l’Ă©cran et on passe la variable Alert a true , afin de signaler une demande d’affichage
message.toCharArray(Notif,BUF_SIZE);
Alert=true;
// on répond au client , en affichant le message récupéré
server.send(200, « text/plain », « message received: » + message);
});

Dans la boucle loop , au niveau de la boucle qui contrĂŽle l’affichage du display , on va apporter les modifications suivantes :

if (Alert) {
P.print(«  »);
P.setIntensity(MAX_INTENSITY); // intensité au max
P.displayText(Notif, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
Alert=false;
}
else {
// Affichage heure
P.setIntensity(Intensite);
digitalClockDisplay().toCharArray(Notif,BUF_SIZE);
P.displayText(Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

Si Alert est a True , on ajuste l’intensitĂ© de l’Ă©cran au Max, et on fait dĂ©filer le texte vers la gauche Ă  une vitesse de dĂ©filement de 40 et une pause de 1000 Millisecondes.

Puis le paramĂštre Alert passe Ă  False , afin d’afficher l’heure Ă  la prochaine boucle. L’intensitĂ© du display , rĂ©cupĂšre sa valeur d’origine.

Gestion de la luminosité

Afin d’Ă©viter que l’Ă©cran soit trop lumineux le soir , j’ai ajoutĂ© une fonction qui permet toutes les 5 secondes de contrĂŽler la luminositĂ© ambiante ( via une rĂ©sistance sensible Ă  la lumiĂšre ) et ajuster ainsi l’intensitĂ© des leds.

int Intensite=5;
const long interval = 5000;  // intervalle pour mesure luminosite réglé sur 5 s
unsigned long previousMillis=0 ;


// fonction réglage auto luminosité
void luminosite() {
  sensorValue = analogRead(A0); // read analog input pin 0
  Intensite =round((sensorValue*1.5)/100);
  if (Intensite < 1 ) Intensite = 1 ;
  if (Intensite > 15 ) Intensite = MAX_INTENSITY;
}


void loop () {
...........

 if( millis() - previousMillis >= interval) {
    previousMillis = millis();
  luminosite();
  }

..........
}

 

Pour mesurer l’intensitĂ© lumineuse , on utilise une rĂ©sistance sensible Ă  la lumiĂšre ( Photo rĂ©sistance ). Cette rĂ©sistance varie en fonction de la luminositĂ© ambiante.

Photo résistance , résistance sensible à la lumiÚre

Pour lire cette variation , on va réaliser le branchement suivant :

Schéma de montage du photoresistor . ( attention à bien brancher sur le 3,3 V et non sur le 5V , sous peine de détruire votre module )

Attention l’entrĂ©e Analogique A0 du module ESP8266 , ne doit pas dĂ©passer 3,3 V .

Pour lire la valeur A0 , on utilise la fonction analogRead(A0) , qui en fonction de la variation de la Photo-résistance donnera une valeur comprise entre 0 ( Nuit ) et 1023 ( en pleine lumiÚre ).

Sachant que l’intensitĂ© du display , varie de 0 Ă  15 ( 0 Ă©tant Ă©teint ) , on applique la formule suivante :

round((sensorValue*1.5)/100);

Qui permet de rĂ©cupĂ©rer une valeur entre 0 et 15. Afin d’Ă©viter d’Ă©teindre le display ou d’envoyer une valeur trop haute , le retour est compris entre 1 et 15 par les deux conditions if.

Ce qui donne le script final complet :

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// WIFI Manager , afin de gerer la connexion au WIFI de façon plus intuitive
#include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager

///includes nécessaires au fonctionnement de l'OTA :
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// gestion de l'affichage matricielle
#include <MD_Parola.h>
#include <MD_MAX72xx.h>

// librairie temps
#include <TimeLib.h>
#include <NtpClientLib.h>

ESP8266WebServer server(80);         // serveur WEB sur port 80

// définition du numéro de LED interne 
int led = 2; // led built IN
// variable pour stocker la valeur du photoresistor
int sensorValue;

// ParamĂ©trage matrice  ( Pin Arduino oĂč est branchĂ©e la matrice )
#define MAX_DEVICES 8 // ( nombre de matrice )
#define CLK_PIN   D5
#define DATA_PIN  D7
#define CS_PIN    D6
// initialisation de la matrice
MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); 

//variable systemes
#define  BUF_SIZE  60
char Notif[BUF_SIZE];
boolean DisSec = true;
boolean Alert=false;
int Intensite=5;
const long interval = 5000;  // interval pour mesure luminosite réglé sur 5 s
unsigned long previousMillis=0 ;
String message="";

// ParamĂštre NTP
// Serveur NTP
const char ntpserver[] = "pool.ntp.org";
// TimeZone
int8_t timeZone = 1;
// Le fuseau utilise les horaires été / hiver
bool DLS = true;


void configModeCallback (WiFiManager *myWiFiManager) {
  P.print("Choisir AP..");
  delay(3000);
  P.print(WiFi.softAPIP().toString());
    delay(3000);
    P.print(myWiFiManager->getConfigPortalSSID());
  //Serial.println(WiFi.softAPIP());
  //if you used auto generated SSID, print it
  //Serial.println(myWiFiManager->getConfigPortalSSID());
}


void processNtpEvent (NTPSyncEvent_t ntpEvent) {
  if (ntpEvent) {
    if (ntpEvent == noResponse)
      P.print ("Serveur NTP injoignable");
    else if (ntpEvent == invalidAddress)
      P.print ("Adresse du serveur NTP invalide");
  } else {
    //P.print ("Récupération du temps NTP: ");
    //P.print (NTP.getTimeDateString (NTP.getLastNTPSync ()));
    NTP.setInterval (1800);
  }
}


// fonction réglage auto luminosité
void luminosite() {
  sensorValue = analogRead(A0); // read analog input pin 0
  Intensite =round((sensorValue*1.5)/100);
  if (Intensite < 1 ) Intensite = 1 ;
  if (Intensite > 15 ) Intensite = MAX_INTENSITY;
}

void setup() {
   //démarrage Display
   P.begin();

      //******** WiFiManager ************
    //Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wifiManager;

     //Si besoin de fixer une adresse IP
    //wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
    
    //Forcer à effacer les données WIFI dans l'eprom , permet de changer d'AP à chaque démarrage ou effacer les infos d'une AP dans la mémoire (à valider , lors du premier lancement  )
    //wifiManager.resetSettings();
    //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
     wifiManager.setAPCallback(configModeCallback);
    
    //RécupÚre les identifiants   ssid et Mot de passe dans l'eprom  et essaye de se connecter
    //Si pas de connexion possible , il démarre un nouveau point d'accÚs avec comme nom , celui défini dans la commande autoconnect ( ici : AutoconnectAP )
    // wifiManager.autoConnect("AutoConnectAP");
    //Si rien indiqué le nom par défaut est  ESP + ChipID
    //wifiManager.autoConnect();
      if(!wifiManager.autoConnect("AP_ESP")) {
              P.print("erreur AP");;
              delay(3000);
              //reset and try again, or maybe put it to deep sleep
              ESP.reset();
              delay(5000);
        } 
    
// ****** Fin config WIFI Manager ************



 //******* OTA ***************
// Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("EspTestOTA");

  // 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";
    digitalWrite(led, HIGH); // allume led au début du transfert
      P.print("Update ..."); 
    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    //Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
     P.print("Reboot ..."); 
    digitalWrite(led, LOW); // éteint à la fin de la mise à jour
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    sprintf(Notif,"Upload  %u%%", (progress / (total / 100)));
     P.print(Notif); 
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    //Serial.printf("Error[%u]: ", error);
  });
  ArduinoOTA.begin();
  //********* Fin OTA ***************
   
 

  // on attend d'ĂȘtre connectĂ© au WiFi avant de continuer
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  P.print("Wait ..."); 
  }
  // on affiche l'adresse IP attribuée pour le serveur DSN
  //Serial.print("IP address: ");
  //Serial.println(WiFi.localIP());
  P.print("Wifi Ready ...");
  delay(300);
  P.print(WiFi.localIP().toString());
  delay(2000);

 

  //*************************
  
  // on définit les points d'entrée (les URL à saisir dans le navigateur web) et on affiche un simple texte 
  server.on("/", [](){
    server.send(200, "text/plain", "Page d'accueil");
  });

 server.on("/Notification", [](){
    // on récupÚre le paramÚtre msg dans l'url
    message=server.arg("msg");
    message.toCharArray(Notif,BUF_SIZE); 
    Alert=true;
    //P.print(message);
    // on repond au client
    server.send(200, "text/plain", "message received:" + message);
  });
  
 server.on("/led", []() {
  String Etat=server.arg("etat");
  if (Etat == "on") digitalWrite(led, LOW);
  else if (Etat == "off") digitalWrite(led, HIGH);
  server.send(200, "text/plain", "la led est  " + Etat);
});

  // on demarre le serveur web 
  server.begin();


    //******* Service NTP ********
// Démarrage du processus NTP  
NTP.begin(ntpserver, timeZone, DLS);
// Intervalle de synchronisation en seconde , 10 s au départ pour forcer une mise à jour rapide
NTP.setInterval (10);


  pinMode(led, OUTPUT);     // Initialise la broche "led" comme une sortie 
  digitalWrite(led, HIGH);
   P.print("OK ...");
}

 

void loop() {
  if( millis() - previousMillis >= interval) {
    previousMillis = millis();
  luminosite();
  }
  
  NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
  processNtpEvent(event);
});
  // Ă  chaque iteration, la fonction handleClient traite les requĂȘtes 
  server.handleClient();
   // Surveillance des demandes de mise Ă  jour en OTA
  ArduinoOTA.handle();

  if (P.displayAnimate())
{
  if (Alert) {
    
    P.setIntensity(MAX_INTENSITY); // intensité au max
   P.displayText(Notif, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
   Alert=false;
  }
  else {
  // Affichage heure
   P.setIntensity(Intensite); 
    digitalClockDisplay().toCharArray(Notif,BUF_SIZE);
    //P.print(Intensite); Debug pour afficher valeur luminosité
    P.displayText(Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
  }
}
}


// Fonction clockformat
String digitalClockDisplay()
    {
      message;
      if ( year() == 1970) {
             message="Init..";
            }
        else {
          message=hour();
          message+=printDigits(minute());
          if ( DisSec ) { message+=printDigits(second()); }
          }
  return message;
  //Serial.print(day());
  //Serial.print(".");
  //Serial.print(month());
  //Serial.print(".");
  //Serial.print(year());
  //Serial.println();
  }

String printDigits(int digits)
{
  String Digital;
  Digital=":";
  if (digits < 10) Digital+="0";
  Digital+=digits;
  return Digital;
}
[adsense]

Integration Jeedom

Afin de permettre Ă  Jeedom ( ou toute autre solution domotique ) , d’envoyer des notifications sur notre horloge . Nous allons crĂ©er un nouvel Ă©lĂ©ment Ă  l’aide du plugin Script de jeedom.

Aller dans Scipt , et ajouter . Choisisser un nom.

Puis dans l’onglet commande , ajouter une commande script.

Cette commande sera de type HTTP

commande notif jeedom
Commande de type http , dans le module Script de jeedom

Choisissez dans type : Action et type d’action : message.
Dans le champs requĂȘte :
 Ip_de_votre_module/Notification?msg=#message#

Sauvegarder puis tester , vous devriez voir défiler sur votre écran : Ceci est un test de message pour la commande notification.

exemple depuis Widget jeedom

 

test depuis le Widget Jeedom.

L’info titre n’est pas utilisĂ© dans cet exemple.

Dans le script j’ai ajoutĂ© une variable type , qui peut ĂȘtre utilisĂ©e avec le mot clĂ© « alert » afin de mettre l’intensitĂ© au max.

Il suffit alors de modifier la requĂȘte http de la commande script créée :

IP_Module_horloge/Notification?msg=#message#&type=#title#

Les notifications peuvent ĂȘtre appelĂ©es depuis un scĂ©nario.

Cela se présente sous la forme suivante :

Exemple appel depuis un scénario jeedom

Dans jeedom , il n’y a pas de limite aux types de notification. Elles peuvent servir Ă  afficher :

  • Un message d’information
  • Un message d’alerte ( en indiquant alert dans l’onglet titre )
  • la date du jour et la saint du jour  ( #sjour# , #jour# #smois# #annee# Saint du jour : #[Admin / Info][INFO][Saint du jour]# )
  • des flash news
  • la mĂ©tĂ©o du jour
  • etc ……

 

pour terminer cet article , il ne reste plus qu’a dĂ©crire , comment implanter une interface web pour le paramĂ©trage du module

Paramétrage depuis interface WEB

Dans le cadre de cet article , nous allons mettre une page WEB , qui affichera les informations suivantes :

  • Etat du systĂšme
  • Parametrage de l’affichage des secondes
  • Parametrage IntensitĂ©

Avec ces diffĂ©rents exemples , vous serez en mesure d’apporter des paramĂštres supplĂ©mentaires , que vous jugerez utile , dans le cas d’une amĂ©lioration de l’horloge.

Voici la page WEB qui sera dédié aux réglages :

Parametrage du module ESP et Information

Pour cela nous allons modifier le script de la maniĂšre suivante :

..........
// dans la partie definition de notre serveur web
server.on("/", handleRoot);  // on ajoute la fonction handleRoot

server.on("/Notification", [](){
    // on recupere les parametre dans l'url
    message=server.arg("msg");
    message.toCharArray(Notif,BUF_SIZE);
    if (server.arg("type")=="alert") {
      P.setIntensity(MAX_INTENSITY); // intensité au max
    }
    Alert=true;
    //P.print(message);
    // on repond au client
    server.send(200, "text/plain", "message received:" + message + server.arg("type"));
  });
........

La fonction handleroot sera en charge d’intercepter tous les appels effectuĂ© Ă  la racine du site WEB du module.

Avant la section setup() , nous allons insérerez les deux nouvelles fonctions :

handleRoot : qui sera en charge d’afficher la page HTML du formulaire ou de rediriger vers handleSubmit , si des donnĂ©es sont prĂ©sentes dans le formulaire.
handleSubmit : Qui sera en charge de récupérer les variables soumis dans le formulaire et de les traiter.

// ******************
// Gestiuon page WEB
//******************

void handleRoot(){ 
  if ( server.hasArg("SEC") ) {
    handleSubmit();
  } 
  else {
    server.send ( 200, "text/html", getPage() );
  }  
}
 
void handleSubmit() {
  String SEC;
  SEC = server.arg("SEC");
  if ( server.arg("Autolum") =="manu" ) {
  AutoIn=false;
  Intensite=server.arg("ReglageInt").toInt();
  } else { AutoIn=true;}
  if ( server.arg("HOR") =="1" ) {
  TimeOn=true;
  } else { TimeOn=false;}
  
  if ( SEC == "1" ) {
    DisSec=true;
    server.send ( 200, "text/html", getPage() );
  } else if ( SEC == "0" ) {
    DisSec=false;
    server.send ( 200, "text/html", getPage() );
  } else {
   // Serial.println("Err Led Value");
  }
}

//***********************

Dans cette exemple , j’ai mis en place un formulaire permettant de :

  • Afficher les secondes
  • GĂ©rer la luminositĂ©
  • Afficher l’horloge ( Ă©cran vide , juste un point indique que l’horloge est active )

Quand Ă  la fonction getPage , elle me permet d’aller chercher ma page WEB.

La fonction est écrite en fin de script , aprÚs la fonction loop().

........
//************************************
// Page WEB
// ***********************************
String getPage(){
  String page = "<html lang=fr-FR><head><meta http-equiv='refresh' content='120'/>";
  page += "<title>Horloge / Notification - Byfeel.info</title>";
  page += "<style> table.steelBlueCols { border: 3px solid #555555;background-color: #555555;width: 95%;text-align: left;border-collapse: collapse;}";
  page +="table.steelBlueCols td, table.steelBlueCols th { border: 1px solid #555555;padding: 4px 9px;}";
  page +="table.steelBlueCols tbody td {font-size: 1em;font-weight: bold;color: #FFFFFF;} table.steelBlueCols td:nth-child(even) {background: #398AA4;}";
  page +="fieldset { padding:0 20px 20px 20px; margin-bottom:10px;border:1px solid #398AA4;width:95%;} div.bloc {float:left;width:450px}";
  //page +="table.steelBlueCols tfoot .links a{display: inline-block;background: #FFFFFF;color: #398AA4;padding: 2px 8px;border-radius: 5px;"
  page +="}</style>";
  page += "</head><body><h1><span style='background-color: #398AA4; color: #ffffff; padding: 0 5px;'>Horloge - Notification</span></h1>";
   page += "<div class='bloc'><form action='/Notification' method='GET'>";
  page +="<fieldset><legend>Envoyer une Notification :</legend>";
  page += "<INPUT type='text' name='msg' id='msg'maxlength='59' style='width:400px;' placeholder='Votre Message - 60 caracteres max -'/>";
  page +="</fieldset>";
  page += "<INPUT type='submit' value='Envoyer Message' /></div>";
  page += "</form></div>";
  page +="<div style='clear:both;'></div>";
  page += "<div class='bloc'><h3>Systeme</h3>";
  page += "<table class='steelBlueCols'><tbody>";
  page += "<tr><td>Mise en Marche </td><td>"+ NTP.getUptimeString() + "</td></tr>";
  page += "<tr><td>Serveur NTP </td><td>";
  page += ntpserver;
  page +="</td></tr>";
  page += "<tr><td>Premiere synchro NTP </td><td>"+NTP.getTimeDateString(NTP.getFirstSync())+"</td></tr>";
  page += "<tr><td>Derniere synchro NTP </td><td>"+NTP.getTimeDateString(NTP.getLastNTPSync())+"</td></tr>";
  page +="</tbody></table></div>";
  page += "<div class='bloc'><h3>Resau</h3>";
  page += "<table class='steelBlueCols'><tbody>";
  page += "<tr><td>mac adress : </td><td>";
  page += WiFi.macAddress().c_str();
  page +="</td></tr>";
  page += "<tr><td>IP</td><td>"+ WiFi.localIP().toString() + "</td></tr>";
  page += "<tr><td>Masque </td><td>"+ WiFi.subnetMask().toString() + "</td></tr>";
  page += "<tr><td>Passerelle</td><td>"+ WiFi.gatewayIP().toString() + "</td></tr>";
  page += "<tr><td>DNS primaire</td><td>"+ WiFi.dnsIP().toString() + "</td></tr>";
  page += "<tr><td>DNS secondaire</td><td>"+ WiFi.dnsIP(1).toString() + "</td></tr>";
  page +="</tbody></table></div>";
  page +="<div class='bloc'><h3>Wifi</h3>";
  page += "<table class='steelBlueCols'><tbody>";
  page += "<tr><td>Hostname</td><td>"+ WiFi.hostname() + "</td></tr>";
  page += "<tr><td>SSID</td><td>"+ WiFi.SSID() + "</td></tr>";
  page += "<tr><td>Signal WIFI</td><td>";
  page += WiFi.RSSI();
  page +=" dBm</td></tr>";
  page += "<tr><td>BSSID </td><td>";
  page += WiFi.BSSIDstr().c_str();
  page +="</td></tr>";
  page +="</tbody></table></div>";
  page +="<div style='clear:both;'></div>";
  page += "<div class='bloc'><h3>Parametres :</h3>";
  page += "<form action='/' method='POST'>";
  page +="<fieldset><legend>Affichage des Secondes :</legend>";
  page += "<INPUT type='radio' name='SEC' value='1' id='on'";
  if (DisSec==true) page +=" checked ";
  page += "><label for='on'>ON</label>";
  page +="<INPUT type='radio' name='SEC' value='0' id='off'";
  if (DisSec==false) page +=" checked ";
  page += "><label for='off'>OFF</label></fieldset>";
  page +="<fieldset><legend>Affichage Horloge :</legend>";
  page += "<INPUT type='radio' name='HOR' value='1' id='horon'";
  if (TimeOn==true) page +=" checked ";
  page += "><label for='horon'>ON</label>";
  page +="<INPUT type='radio' name='HOR' value='0' id='horoff'";
  if (TimeOn==false) page +=" checked ";
  page += "><label for='horoff'>OFF</label></fieldset>";
  page +="<fieldset><legend>Gestion de la luminosit&eacute;e : </legend>";
  page += "<INPUT type='radio' name='Autolum' value='auto' id='auto'";
  if (AutoIn==true) page +=" checked ";
  page += "><label for='auto'>AUTO</label>";
  page +="<INPUT type='radio' name='Autolum' value='manu' id='manu'";
  if (AutoIn==false) page +=" checked ";
  page += "><label for='manu'>Manuel</label></P>";
  if (AutoIn==false) {
  page +="<p>Valeur luminosit&eacute;e : ";
  page +=Intensite;
  page +="</p>";
  page += "<p><input id='slider1' type='range' min='0' max='15' step='1' name='ReglageInt' list='tickmarks' value='";
  page +=Intensite;
  page +="'/>";
  page +="<datalist id='tickmarks'>";
  page +="<option value='0' label='0'>";
  page +="<option value='1'>";
  page +="<option value='2'>";
  page +="<option value='3'>";
  page +="<option value='4'>";
  page +="<option value='5' label='5'>";
  page +="<option value='6'>";
  page +="<option value='7'>";
  page +="<option value='8'>";
  page +="<option value='9'>";
  page +="<option value='10' label='10'>";
  page +="<option value='11'>";
  page +="<option value='12'>";
  page +="<option value='13'>";
  page +="<option value='14'>";
  page +="<option value='15' label='15'>";
  page +="</datalist></p>";
  };
  page +="</fieldset>";
  page += "<INPUT type='submit' value='Actualiser'name='parametres'/></div>";
  page += "</form>";
  page += "<br><br>";
  page += "</body></html>";
  return page;
}
........

Pour , vous aider Ă  Ă©crire votre page WEB , vous pouvez vous aider d’Ă©diteurs en ligne comme Online HTML Editor .

Dans cette page , je gére deux formulaires :

  • le premier : Envoie d’une notification avec le formulaire « <form action=’/Notification’ method=’GET’> » , par la methode Get et appelle de la page /Notification ( celle utilisĂ© par jeedom , pour l’envoie des notifications ).
  • Le second : ParamĂštres , utilise la mĂ©thode POST, « <form action=’/’ method=’POST’> »  , afin d’ĂȘtre traitĂ© par la fonction hndleSubmit .

Le script final au complet :

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// WIFI Manager , afin de gerer la connexion au WIFI de façon plus intuitive
#include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager

///includes necessaires au fonctionnement de l'OTA :
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// gestion de l'affichage matricielle
#include <MD_Parola.h>
#include <MD_MAX72xx.h>

// librairie temps
#include <TimeLib.h>
#include <NtpClientLib.h>

ESP8266WebServer server(80);         // serveur WEB sur port 80

// definition du numero de LED interne 
int led = 2; // led built IN
// variable pour stocker la valeur du photoresistor
int sensorValue;

// Parametrage matrice  ( Pin Arduino ou est branché la matrice )
#define MAX_DEVICES 8 // ( nombre de matrice )
#define CLK_PIN   D5
#define DATA_PIN  D7
#define CS_PIN    D6
// initialisation de la matrice
MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); 

//variable systemes
const char nom_module[] ="ESP_tuto-horloge";
#define  BUF_SIZE  60
char Notif[BUF_SIZE];
boolean DisSec = true;
boolean Alert=false;
boolean AutoIn=true;
boolean TimeOn=true;
int Intensite=5;
const long interval = 5000;  // interval pour mesure luminosite réglé sur 5 s
unsigned long previousMillis=0 ;
String message="";

// Parametre NTP
// Serveur NTP
const char ntpserver[] = "pool.ntp.org";
// TimeZone
int8_t timeZone = 1;
// Le fuseau utilise les horaires été / hiver
bool DLS = true;
boolean syncEventTriggered = false; // True if a time even has been triggered
NTPSyncEvent_t ntpEvent; // Last triggered event


void configModeCallback (WiFiManager *myWiFiManager) {
  P.print("Choisir AP..");
  delay(3000);
  P.print(WiFi.softAPIP().toString());
    delay(3000);
    P.print(myWiFiManager->getConfigPortalSSID());
  //Serial.println(WiFi.softAPIP());
  //if you used auto generated SSID, print it
  //Serial.println(myWiFiManager->getConfigPortalSSID());
}


//void processNtpEvent (NTPSyncEvent_t ntpEvent) {
 void processSyncEvent (NTPSyncEvent_t ntpEvent) {
  if (ntpEvent) {
    if (ntpEvent == noResponse)
      P.print ("Serveur NTP injoignable");
    else if (ntpEvent == invalidAddress)
      P.print ("Adresse du serveur NTP invalide");
  } else {
     if ( year() != 1970 or year() != 2036 ) {
             NTP.setInterval (1200);
            }
    
  }
  
}



// fonction reglage auto luminosite
void luminosite() {
  sensorValue = analogRead(A0); // read analog input pin 0
  Intensite =round((sensorValue*1.5)/100);
  if (Intensite < 1 ) Intensite = 0 ;
  if (Intensite > 15 ) Intensite = MAX_INTENSITY;
}


// ******************
// Gestiuon page WEB
//******************

void handleRoot(){ 
  if ( server.hasArg("SEC") ) {
    handleSubmit();
  } 
  else {
    server.send ( 200, "text/html", getPage() );
  }  
}
 
void handleSubmit() {
  String SEC;
  SEC = server.arg("SEC");
  if ( server.arg("Autolum") =="manu" ) {
  AutoIn=false;
  Intensite=server.arg("ReglageInt").toInt();
  } else { AutoIn=true;}
  if ( server.arg("HOR") =="1" ) {
  TimeOn=true;
  } else { TimeOn=false;}
  
  if ( SEC == "1" ) {
    DisSec=true;
    server.send ( 200, "text/html", getPage() );
  } else if ( SEC == "0" ) {
    DisSec=false;
    server.send ( 200, "text/html", getPage() );
  } else {
   // Serial.println("Err Led Value");
  }
}

//***********************

void setup() {
   //demarrage Display
   P.begin();

      //******** WiFiManager ************
    //Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wifiManager;

     //Si besoin de fixer une adresse IP
    //wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
    
    //Forcer Ă  effacer les donnees WIFI dans l'eprom , permet de changer d'AP Ă  chaque demmarrage ou effacer les infos d'une AP dans la memoire ( a valider , lors du premier lancement  )
    //wifiManager.resetSettings();
    //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
     wifiManager.setAPCallback(configModeCallback);
    
    //Recupere les identifiants   ssid et Mot de passe dans l'eprom  et essayes de se connecter
    //Si pas de connexion possible , il demarre un nouveau point d'accés avec comme nom , celui definit dans la commande autoconnect ( ici : AutoconnectAP )
    // wifiManager.autoConnect("AutoConnectAP");
    //Si rien indiqué le nom par defaut est  ESP + ChipID
    //wifiManager.autoConnect();
      if(!wifiManager.autoConnect("AP_ESP")) {
              P.print("erreur AP");;
              delay(3000);
              //reset and try again, or maybe put it to deep sleep
              ESP.reset();
              delay(5000);
        } 
    
// ****** Fin config WIFI Manager ************



 //******* OTA ***************
// Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname(nom_module);

  // 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";
    digitalWrite(led, HIGH); // allume led au debut du transfert
      P.print("Update ..."); 
    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    //Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
     P.print("Reboot ..."); 
    digitalWrite(led, LOW); // eteint a la fin de la mise a jour
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    sprintf(Notif,"Upload  %u%%", (progress / (total / 100)));
     P.print(Notif); 
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    //Serial.printf("Error[%u]: ", error);
  });
  ArduinoOTA.begin();
  //********* Fin OTA ***************
   
 

  // on attend d'etre connecte au WiFi avant de continuer
  P.print("Wait ..."); 
  while (WiFi.status() != WL_CONNECTED) {
  }
  // on affiche l'adresse IP attribuee pour le serveur DSN et on affecte le nom reseau
   WiFi.hostname(nom_module);
  P.print("Wifi Ready ...");
  delay(300);
  P.print(WiFi.localIP().toString());
  delay(2000);

 

  //*************************
  
  // on definit les points d'entree (les URL a saisir dans le navigateur web) et on affiche un simple texte 
  server.on("/", handleRoot);

 server.on("/Notification", [](){
    // on recupere les parametre dans l'url
    message=server.arg("msg");
    message.toCharArray(Notif,BUF_SIZE);
    if (server.arg("type")=="alert") {
      P.setIntensity(MAX_INTENSITY); // intensité au max
    }
    Alert=true;
    //P.print(message);
    // on repond au client
    server.send(200, "text/plain", "message received:" + message + server.arg("type"));
  });
  

  // on demarre le serveur web 
  server.begin();


    //******* Service NTP ********
    NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
        ntpEvent = event;
        syncEventTriggered = true;
    });

    
// Démarrage du processus NTP  
NTP.begin(ntpserver, timeZone, DLS);
// Interval de synchronisation en seconde , 10 s au depart pour forcer une mise a jour rapide
NTP.setInterval (10);


  pinMode(led, OUTPUT);     // Initialise la broche "led" comme une sortie 
  digitalWrite(led, HIGH);
   P.print("OK ...");
}

 

void loop() {
  // Si gestion Auto luminositée activé
  if (AutoIn) {
  if( millis() - previousMillis >= interval) {
    previousMillis = millis();
  luminosite();
  }
  }
  
// NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
//  processNtpEvent(event);
//});
   if (syncEventTriggered) {
        processSyncEvent (ntpEvent);
        syncEventTriggered = false;
    }


  // a chaque iteration, la fonction handleClient traite les requetes 
  server.handleClient();
   // Surveillance des demandes de mise a jour en OTA
  ArduinoOTA.handle();

  if (P.displayAnimate())
{
  if (Alert) {
    
   P.displayText(Notif, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
   Alert=false;
  }
  else {
  // Affichage heure
  if (TimeOn) {
   P.setIntensity(Intensite); 
    digitalClockDisplay().toCharArray(Notif,BUF_SIZE);
    //P.print(Intensite); Debug pour afficher valeur luminosite
    P.displayText(Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
    } else  P.print(".");
  }
}
}


// Fonction clockformat
String digitalClockDisplay()
    {
          message=hour();
          message+=printDigits(minute());
          if ( DisSec ) { message+=printDigits(second()); }
  return message;
  //Serial.print(day());
  //Serial.print(".");
  //Serial.print(month());
  //Serial.print(".");
  //Serial.print(year());
  //Serial.println();
  }

String printDigits(int digits)
{
  String Digital;
  Digital=":";
  if (digits < 10) Digital+="0";
  Digital+=digits;
  return Digital;
}


//************************************
// Page WEB
// ***********************************
String getPage(){
  String page = "<html lang=fr-FR><head><meta http-equiv='refresh' content='120'/>";
  page += "<title>Horloge / Notification - Byfeel.info</title>";
  page += "<style> table.steelBlueCols { border: 3px solid #555555;background-color: #555555;width: 95%;text-align: left;border-collapse: collapse;}";
  page +="table.steelBlueCols td, table.steelBlueCols th { border: 1px solid #555555;padding: 4px 9px;}";
  page +="table.steelBlueCols tbody td {font-size: 1em;font-weight: bold;color: #FFFFFF;} table.steelBlueCols td:nth-child(even) {background: #398AA4;}";
  page +="fieldset { padding:0 20px 20px 20px; margin-bottom:10px;border:1px solid #398AA4;width:95%;} div.bloc {float:left;width:450px}";
  //page +="table.steelBlueCols tfoot .links a{display: inline-block;background: #FFFFFF;color: #398AA4;padding: 2px 8px;border-radius: 5px;"
  page +="}</style>";
  page += "</head><body><h1><span style='background-color: #398AA4; color: #ffffff; padding: 0 5px;'>Horloge - Notification</span></h1>";
   page += "<div class='bloc'><form action='/Notification' method='GET'>";
  page +="<fieldset><legend>Envoyer une Notification :</legend>";
  page += "<INPUT type='text' name='msg' id='msg'maxlength='59' style='width:400px;' placeholder='Votre Message - 60 caracteres max -'/>";
  page +="</fieldset>";
  page += "<INPUT type='submit' value='Envoyer Message' /></div>";
  page += "</form></div>";
  page +="<div style='clear:both;'></div>";
  page += "<div class='bloc'><h3>Systeme</h3>";
  page += "<table class='steelBlueCols'><tbody>";
  page += "<tr><td>Mise en Marche </td><td>"+ NTP.getUptimeString() + "</td></tr>";
  page += "<tr><td>Serveur NTP </td><td>";
  page += ntpserver;
  page +="</td></tr>";
  page += "<tr><td>Premiere synchro NTP </td><td>"+NTP.getTimeDateString(NTP.getFirstSync())+"</td></tr>";
  page += "<tr><td>Derniere synchro NTP </td><td>"+NTP.getTimeDateString(NTP.getLastNTPSync())+"</td></tr>";
  page +="</tbody></table></div>";
  page += "<div class='bloc'><h3>Resau</h3>";
  page += "<table class='steelBlueCols'><tbody>";
  page += "<tr><td>mac adress : </td><td>";
  page += WiFi.macAddress().c_str();
  page +="</td></tr>";
  page += "<tr><td>IP</td><td>"+ WiFi.localIP().toString() + "</td></tr>";
  page += "<tr><td>Masque </td><td>"+ WiFi.subnetMask().toString() + "</td></tr>";
  page += "<tr><td>Passerelle</td><td>"+ WiFi.gatewayIP().toString() + "</td></tr>";
  page += "<tr><td>DNS primaire</td><td>"+ WiFi.dnsIP().toString() + "</td></tr>";
  page += "<tr><td>DNS secondaire</td><td>"+ WiFi.dnsIP(1).toString() + "</td></tr>";
  page +="</tbody></table></div>";
  page +="<div class='bloc'><h3>Wifi</h3>";
  page += "<table class='steelBlueCols'><tbody>";
  page += "<tr><td>Hostname</td><td>"+ WiFi.hostname() + "</td></tr>";
  page += "<tr><td>SSID</td><td>"+ WiFi.SSID() + "</td></tr>";
  page += "<tr><td>Signal WIFI</td><td>";
  page += WiFi.RSSI();
  page +=" dBm</td></tr>";
  page += "<tr><td>BSSID </td><td>";
  page += WiFi.BSSIDstr().c_str();
  page +="</td></tr>";
  page +="</tbody></table></div>";
  page +="<div style='clear:both;'></div>";
  page += "<div class='bloc'><h3>Parametres :</h3>";
  page += "<form action='/' method='POST'>";
  page +="<fieldset><legend>Affichage des Secondes :</legend>";
  page += "<INPUT type='radio' name='SEC' value='1' id='on'";
  if (DisSec==true) page +=" checked ";
  page += "><label for='on'>ON</label>";
  page +="<INPUT type='radio' name='SEC' value='0' id='off'";
  if (DisSec==false) page +=" checked ";
  page += "><label for='off'>OFF</label></fieldset>";
  page +="<fieldset><legend>Affichage Horloge :</legend>";
  page += "<INPUT type='radio' name='HOR' value='1' id='horon'";
  if (TimeOn==true) page +=" checked ";
  page += "><label for='horon'>ON</label>";
  page +="<INPUT type='radio' name='HOR' value='0' id='horoff'";
  if (TimeOn==false) page +=" checked ";
  page += "><label for='horoff'>OFF</label></fieldset>";
  page +="<fieldset><legend>Gestion de la luminosit&eacute;e : </legend>";
  page += "<INPUT type='radio' name='Autolum' value='auto' id='auto'";
  if (AutoIn==true) page +=" checked ";
  page += "><label for='auto'>AUTO</label>";
  page +="<INPUT type='radio' name='Autolum' value='manu' id='manu'";
  if (AutoIn==false) page +=" checked ";
  page += "><label for='manu'>Manuel</label></P>";
  if (AutoIn==false) {
  page +="<p>Valeur luminosit&eacute;e : ";
  page +=Intensite;
  page +="</p>";
  page += "<p><input id='slider1' type='range' min='0' max='15' step='1' name='ReglageInt' list='tickmarks' value='";
  page +=Intensite;
  page +="'/>";
  page +="<datalist id='tickmarks'>";
  page +="<option value='0' label='0'>";
  page +="<option value='1'>";
  page +="<option value='2'>";
  page +="<option value='3'>";
  page +="<option value='4'>";
  page +="<option value='5' label='5'>";
  page +="<option value='6'>";
  page +="<option value='7'>";
  page +="<option value='8'>";
  page +="<option value='9'>";
  page +="<option value='10' label='10'>";
  page +="<option value='11'>";
  page +="<option value='12'>";
  page +="<option value='13'>";
  page +="<option value='14'>";
  page +="<option value='15' label='15'>";
  page +="</datalist></p>";
  };
  page +="</fieldset>";
  page += "<INPUT type='submit' value='Actualiser'name='parametres'/></div>";
  page += "</form>";
  page += "<br><br>";
  page += "</body></html>";
  return page;
}

 

Il ne reste plus qu’Ă  vous trouver une petite boĂźte , ou en fabriquer une pour mettre votre horloge dedans.

 

 

 

37 commentaires sur “DIY Horloge et Notification Domotique ( Matrix LED ) avec Jeedom”

Les commentaires sont fermés.