Cet article vous présente comment configurer , la version V2.6 pour se fabriquer une horloge connectée avec Notification , et comment la relier facilement à votre domotique.
Etant sous jeedom , je ne vais parler que de cette solution , sachant que toute les requêtes passent par du http , cela devrait facilement être adaptable à toutes les autres box.
J’ai réalisé cette petite vidéo , pour vous monter les différentes options possibles.
Liste des courses :
Minimum requis ( 10 € ) :
- Un module ESP8266 ( j’utilise le WEMOS D1 , très simple à utiliser et surtout possédant une alimentation +5v ) Environ 5 € sur
- Une matrice led de type MAX72xx ( minimum 4 modules ) , par exemple la matrice de 4 modules MAX7219 sur Gearbest à 5 €
En option :
- Une Photo résistance ( pour gérer la luminosité en automatique ) – le pack de 20 à 0,59 € sur amazon.
Un bouton poussoir ( pour gérer différentes options directement depuis l’horloge ) – quelques centimes d’euro à 1 € en fonction des modèles.
Autres options possible : ( le code est ouvert , il est modifiable facilement pour adapter selon vos envies )
- Un capteur température / humidité type DHT
- Un autre bouton poussoir
- Un capteur de présence …..
Pré-requis logiciel
- Le logiciel IDE Arduino ( dans cet article en version 1.8.5 ) , disponible pour la plupart des plateformes.
- Configurer pour gérer les modules ESP8266 et avec les bibliothèques adéquates. ( Voir mes précédents articles , pour la configuration de l’interface Arduino ). Si vous avez des soucis de versions , avec les bibliothèques , ci joint un lien vers mon drive pour récupérer les bibliothèques utilisées .
- J’utilise les dernières versions des bibliothèques MD_Parola et MD_MAX en version 3 minimum.
- Pour la partie OTA ( si vous voulez pouvoir uploader avec ide arduino) , il faut que python soit installé.
Les Sources
Les sources sont récupérables sur mon github , elles sont composées de 3 fichiers à déposer dans le même dossier de travail.
- Notifeur vx.x.ino ( qui est le sketch qui sera déployé depuis l’interface Arduino )
- Parola_font_data.h ( qui est la police de caractère UTF 8 )
- font_byfeel.h ( qui est la police de caractère pour l’horloge )
La compilation
Au début du programme , avant l’inclusion des bibliothèques.
....... #define Ver 2.6-2 #define NOMMODULE "NotifHeure_nom" // nom module #define NTPSERVER "pool.ntp.org" // Serveur NTP #define ACTIVBOUTON false // Si bouton installé #define ACTIVCAPTLUM true // Si capteur luminosité installé #define BUF_SIZE 60 // Taille max des notification ( nb de caractéres max ) // Options horloge ( valeur par defaut ) boolean AutoIn=true; // Auto / manu intensite boolean TimeOn=true; // ON - off Affichage horloge boolean DisSec=true; // on-off secondesboolean Alert=false; #define DEBUG false ......
A modifier si besoin :
NOMMODULE : Le nom que vous souhaitez donner à votre Notif’Heure
ACTIVBOUTON et ACTIVCAPTLUM servent à indiquer si vous avez monté les options ( photo resistor et bouton poussoir ) .
Si pas utilisé laisser les sur « false »
Les variables AutoIn , TimeOn et DisSec servent à définir une valeur par défaut , lors du premier lancement . Par la suite, on récupére les valeurs enregistrées dans l’EEPROM.
DEBUG , me sert lors des différents tests. ( Laisser sur false ).Si vous souhaitez l’utiliser , brancher le module en USB , et ouvrir le moniteur série.
Suite aux inclusions des différentes bibliothèques , il faudra définir le type de matrice utilisée et comment elle est connectée .
// Définition des matrices // Define the number of devices we have in the chain and the hardware interface // NOTE: These pin numbers will probably not work with your hardware and may // need to be adapted #define HARDWARE_TYPE MD_MAX72XX::FC16_HW #define MAX_DEVICES 8 // nombre de matrice #define MAX_ZONES 1 // 1 ou 2 zones #if (MAX_ZONES == 1 ) #define ZONE_TIME (MAX_DEVICES) #else #define ZONE_TIME 4 // taille de l'horloge Si Zone = 2 #endif #define ZONE_MSG (MAX_DEVICES-ZONE_TIME) #define CLK_PIN D5 #define DATA_PIN D7 #define CS_PIN D6 // Hardware SPI connection MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // Si probleme avec detection auto SPI // MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); #define SPEED_TIME 30 #define PAUSE_TIME 1000
Dans l’ordre :
- HARDWARE_TYPE : Le type de matrice utilisé ( voir mon article sur les types de matrices , pour plus de précisions ). Mes matrices correspondent au type FC16.
- MAX_DEVICES : Le nombre de module de votre matrice
- MAX_ZONES : 1 pour utiliser tout l’affichage pour l’horloge et les notifications , 2 pour partager la matrice ( horloge et notification sur un écran séparé)
- ZONE_TIME : Si le paramètre 2 a été défini sur MAX_ZONES , il est possible de donner le nombre de module que l’on souhaite utiliser pour l’affichage de l’horloge.
- ZONE_MSG : est défini automatiquement
Exemple 1 :
j’ai un module de 4 Matrices et je souhaite un affichage commun pour l’heure et les notifications.
Les valeurs à indiquer sont MAX_devices = 4 et Max_zones = 1
Exemple 2 :
J’ai un module composé de 8 matrices ( 2 blocs de quatre ) et je souhaite avoir une Zone de 4 pour l’heure et une deuxième zone de 4 pour les messages.
Les valeurs à indiquer : MAX_devices = 8 , MAX_Zones = 2 et Zone_time = 4
Puis indiquer les PIN où la matrice est branchée : ( notation WEMOS , ou GPIO)
- CLK_PIN , DATA_PIN et CS_PIN
Et enfin SPEED_TIME , PAUSE_TIME permettent de jouer sur les effets des notifications. SPEED_TIME est la vitesse d’exécution de l’animation et PAUSE_TIME est le temps de pause à la fin de l’animation.
[adsense]Interaction avec box Domotique : Jeedom
Dans le cas où vous désirez vous connecter à votre box domotique jeedom , les paramétrages se font ici.
//**********************// //interaction Jeedom #define JEEDOM false // Activation interaction avec Jeedom ( veuillez renseigner tous les champs ) String ApiKey = ""; // cle API Jeedom ex :mVuQikcXm620321DMYZiCsLj0wamT0HsCcrBCuXRxntJDO1kn String IPJeedom = "192.168.x.x"; String PortJeedom = "80"; // ID equipement a modifier // id SDJ String idHor = "10821"; String idLum ="10822"; String idSec = "10823";
Mettre JEEDOM à True , si on désire remonter les infos à Jeedom . ( Pas obligatoire , si vous désirez seulement communiquer dans un sens . Jeedom vers i-Notif’Heure ).
Pré-requis jeedom :
- Création d’un équipement SCRIPT qui servira à envoyer les requêtes pour commander les différentes options du Notif’Heure.
- Création d’un Virtuel , pour gérer les états (retour d’information jeedom, Activation JEEDOM=true nécessaire )
Puis renseigner les champs suivants , en fonction de votre virtuel
- ApiKey : La clé Jeedom pour le connecteur Virtuel
- IPJeedom : L’adresse IP de votre box
- PortJeedom : Le numéro de port
- idHor , idLum et idSec : correspondent aux numéros id des commandes virtuels à renseigner.
Plus d’information dans mon article précédent.
Une fois tous ces paramètres renseignés , il ne vous reste plus qu’à compiler votre sketch et l’envoyer via USB dans votre module.
Lors de vos prochaines mises à jour , le transfert , pourra se faire via OTA.
Les Nouveautés de cette version
- La gestion des ZONES , voir l’article précédent
- La mémorisation des Options en mémoire EEPROM.
Il suffit d’intégrer la bibliothèque suivante :
//********** eeprom
#include <EEPROM.h>
Dans la boucle Setup , initialiser par la commande : EEPROM.begin(512); Qui indique d’utiliser les 512 premières adresses.
Pour lire une valeur en mémoire EEPROM , il suffit d’utiliser la fonction : valEPROM = EEPROM.read(100), qui permet de lire la valeur située à l’adresse 100.
Pour enregistrer , il suffit d’utiliser la fonction : EEPROM.write(100,valEPROM); qui permet d’écrire la valeur valEPROM à l’adresse 100 .
Puis pour valider tous les enregistrements la commande : EEPROM.commit();
Chaque adresse est de type Byte ( valeur de 0 à 255 ) codés sur 8 bits. Dans mon programme les options sont de type Boolean ( soit 0 ou 1 ) , je me sers donc de la commande : bitWrite(valEPROM, 7, true) , pour ne bouger qu’un seul bit sur ma valeur sauvegardée.
Ansi valEprom stocke la valeur des trois options boolean sur les 4 derniers bits
le bit 7 : Sert à indiquer qu’un enregistrement existe
le bit 4 : Sert à indiquer l’état des secondes
le bit 5 : Sert à indiquer si horloge est sur off ou non
le bit 6 : Sert à indiquer si mode Manuel ou Auto
Les bits ( 0 à 3 ) servent à stocker la valeur de l’intensité en mode Manuel.
Ansi si valEPROM vaut : 175 , cela équivaut en binaire à : 1010 1111 qui signifie un enregistrement existe , Secondes désactivées , horloge allumée, mode Manuel et intensité sur 15.
Exemple code pour lecture de la mémoire
...... .... // init systéme - lecture Eeprom si existe et envoie info à jeedom valEPROM = EEPROM.read(100); if (bitRead(valEPROM, 7)) // Si Enregistrement existe { DisSec=bitRead(valEPROM, 4); TimeOn=bitRead(valEPROM, 5); AutoIn=bitRead(valEPROM, 6); if (!AutoIn) Intensite=valEPROM&15; // masque sur les 4 derniers bits , pour recuperer valeur intensite en mode manuel if (DEBUG) { Serial.println(" Valeur lu en Memoire : "); Serial.println(" valeur intensite : "+String(Intensite)); } } ... .....
l’enregistrement s’effectue dans la fonction Options().
- Modifier les polices de caractères :
Pour l’affichage de l’horloge , j’ai modifié la police utilisée , afin d’avoir tous les chiffres de même largeur et ainsi éviter les déplacements de l’affichage lorsque le 1 s’affiche.
Le choix de la police s’effectue par la commande : P.setFont(0,ExtASCII); 0 indique la zone où utiliser la police , ExtASCII indique le nom de la police utilisée.
Pour la Police de l’horloge , je me suis basé sur la police existante dans la bibliothèque MAX ( numeric7Seg ).
/ Data file for user example user defined fonts #ifndef FONTDATA_H #define FONTDATA_H MD_MAX72XX::fontType_t numeric7Seg[] PROGMEM = { 0, // 0 0, // 1 0, // 2 0, // 3 0, // 4 0, // 5 0, // 6 0, // 7 0, // 8 0, // 9 0, // 10 0, // 11 0, // 12 0, // 13 0, // 14 0, // 15 0, // 16 0, // 17 0, // 18 0, // 19 0, // 20 0, // 21 0, // 22 0, // 23 0, // 24 0, // 25 0, // 26 0, // 27 0, // 28 0, // 29 0, // 30 0, // 31 1, 0, // 32 - 'Space' 0, // 33 - '!' 0, // 34 - '"' 0, // 35 - '#' 0, // 36 - '
j’ai modifié les codes ASCII allant de 48 à 57 ( chiffre 0 à 9 ) , afin de resserrer légèrement les chiffres pour que tout rentre en un écran de 4 modules.
La modification est assez simple à faire :
Chaque Module est codé sur 8 lignes x 8 colonnes .
Dans cette exemple , pour coder le 2 sur 4 colonnes seulement , il faudra définir les valeurs décimales suivantes : 121,73,73,79
Si on regarde la colonne 1 du 2 :
0111 1001 ( en binaire ) soit 121 en décimal ou 79 en Hexa.
4, 127, 65, 65,127, // 48 - '0' 4, 0, 0, 127, 0, // 49 - '1' 4, 121, 73, 73, 79, // 50 - '2' 4, 73, 73, 73, 127, // 51 - '3' 4, 15, 8, 8, 127, // 52 - '4' 4, 79, 73, 73, 121, // 53 - '5' 4, 127, 73, 73, 121, // 54 - '6' 4, 1, 1, 1, 127, // 55 - '7' 4, 127, 73, 73, 127, // 56 - '8' 4, 79, 73, 73, 127, // 57 - '9'
le premier nombre désigne le nombre de colonne , les suivants correspondent aux valeurs de ces colonnes.
Pour les petits chiffres , j’ai agis sur le même principe , mais codé sur 3 colonnes seulement.
Ce qui donne :
3, 124, 68, 124, // 71 - '0' petit caractere pour secondes 3, 0, 124, 0, // 72 - '1' 3, 116,84,92, // 76 - '2' 3, 84, 84, 124, // 74 - '3' 3, 28,16,124, // 75 - '4' 3, 92,84, 116, // 73 - '5' 3, 124,84,116, // 77 - '6' 3, 4,4,124, // 78 - '7' 3, 124,84,124, // 79 - '8' 3, 92,84,124, // 80 - '9'
Pou vos aider à calculer automatiquement les bonnes valeurs , vous pouvez utiliser un fichier Excel fournis avec la bibliothèque MAX . Parola-font_builder.xls
Mes deux jeux de caractères sont codés mais comment utiliser les mini chiffres pour les secondes ?
Car si je demande d’afficher le 2 , c’est le grand chiffre qui s’affiche. Pour afficher le mini 2 il faut écrire la lettre I ( i majuscule ) . Afin de pouvoir utiliser la même police de caractère dans l’affichage de l’horloge , j’ai dû décaler les mini chiffres dans la table ASCII ( ils sont positionnés entre le code 71 et 80 , qui correspondent aux lettres G à P.
D’où la petite translation de code ASCII , dans la fonction digitalClockDisplay() , par l’instruction secondes[0]=secondes[0]+23;
23 correspondant au décalage entre le chiffre 0 et le G.
// Fonction clockformat ( ajoute les zeros devant les unités ) void digitalClockDisplay(char *heure,bool flash) { // Si affichage de l'heure if (TimeOn) { P.setIntensity(Intensite); if ( DisSec ) { // si affichage des Secondes 00:00 (secondes en petit ) char secondes[2]; // pour affichage des secondes sprintf(secondes,"%02d",second()); secondes[0]=secondes[0]+23; // permutation codes AScci 71 à 80 secondes[1]=secondes[1]+23; if (DEBUG) { Serial.println("debug des secondes : "); Serial.println(second()); Serial.println(secondes[0]); Serial.println(secondes[1]); } sprintf(heure,"%02d:%02d %c%c",hour(),minute(),secondes[0],secondes[1]); //sprintf(heure,"%02d%c%02d%c%c",hour(),(flash ? ':' : ' '),minute(),secondes[0],secondes[1]); } // Affichage 00:00 avec : Clignottant ( flasher ) else sprintf(heure,"%02d%c%02d",hour(),(flash ? ':' : ' '),minute()); } else // sinon point clignottant uniquement { P.setIntensity(0); sprintf(heure,"%c",(flash ? '.' : ' ')); } }
A vous maintenant , d’imaginez votre police d’affichage.
- optimisation du code , ainsi que de quelques fonctions .
Ci-dessous le code complet :
//**************************
// **** i-Notif'Heure
// Hotloge / notification
// OTA + Interface Web + Connecté
// Gestion Zone + enregistrement eeprom
// Juin 2018
// Byfeel
// *************************
String Ver="2.632";
#define NTPSERVER "pool.ntp.org" // Serveur NTP
#define ACTIVBOUTON false // Si bouton installé
#define ACTIVCAPTLUM true // Si capteur luminosité installé
#define BUF_SIZE 60 // Taille max des notification ( nb de caractéres max )
#define NOMMODULE "NotifHeure_salon" // nom module
// Options horloge à définir avant programmation
boolean AutoIn=true; // Auto / manu intensite
boolean TimeOn=true; // ON - off Affichage horloge
boolean DisSec=false; // on-off secondesboolean Alert=false;
#define DEBUG false
// ******************************//
//******** Bibliotheque *********//
//******************************//
//***** Gestion reseau
#include <EthernetClient.h>
#include <Ethernet.h>
#include <Dhcp.h>
#include <EthernetServer.h>
#include <Dns.h>
#include <EthernetUdp.h>
//****** Gestion WIFI
#include <ESP8266WiFi.h>
//****** Serveur WEB
#include <ESP8266WebServer.h>
//****** Client WEB
#include <ESP8266HTTPClient.h>
// WIFI Manager , afin de gerer la connexion au WIFI de façon plus intuitive
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
// ***** OTA
///includes necessaires au fonctionnement de l'OTA :
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
// **** Bibliotheque Matrice LED
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Parola_Fonts_data.h"
#include "Font_Byfeel.h"
// **** Temps
// librairie temps
#include <TimeLib.h>
#include <NtpClientLib.h>
//********** eeprom
#include <EEPROM.h>
//*************************
#if (ACTIVBOUTON)
//librairies click bouton
#include <ClickButton.h>
#endif
// ******************************//
// Definir le nombre de module
//la taille de la zone time si plus de deux modules
// et les PINS ou sont branches les modules
// ***************************************
// ***** Doit etre verifié avant chaque compilation
//**********************************************
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4 // nombre de matrice
#define MAX_ZONES 1 // 1 ou 2 zones
#if (MAX_ZONES == 1 )
#define ZONE_TIME (MAX_DEVICES)
#else
#define ZONE_TIME 4 // taille de l'horloge Si Zone = 2
#endif
#define ZONE_MSG (MAX_DEVICES-ZONE_TIME)
#define CLK_PIN D5
#define DATA_PIN D7
#define CS_PIN D6
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Si probleme avec detection auto SPI
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 30
#define PAUSE_TIME 1000
//**********************//
//interaction Jeedom
#define JEEDOM false // Activation interaction avec Jeedom ( veuillez renseigner tous les champs )
String ApiKey = ""; // cle API Jeedom ex :mVuQikcXm620321DMYZiCsLj0wamT0HsCcrBCuXRxntJDO1kn
String IPJeedom = "192.168.x.x";
String PortJeedom = "80";
// ID equipement a modifier // id SDJ
String idHor = "10821";
String idLum ="10822";
String idSec = "10823";
String idAuto ="10834";
// id salon
//base URL jeedom Virtuel
String BaseUrlJeedom ="http://"+IPJeedom+":"+PortJeedom+"/core/api/jeeApi.php?apikey=" + ApiKey + "&type=virtual&id=";
//**************************
//**** Varaible & service ***
// *************************
ESP8266WebServer server(80); // serveur WEB sur port 80
#if (JEEDOM)
HTTPClient http; // init client WEB
#endif
// definition du numero de LED interne
#define led 2 // led built IN
// Bouton
#if (ACTIVBOUTON)
#define bouton 0 // GPIO0 ( pullup integré - D8 pour R1 ou D3 pour R2 )
ClickButton boutonClick(bouton, LOW, CLICKBTN_PULLUP);
#endif
// variable pour stocker la valeur du photoresistor
#if (ACTIVCAPTLUM)
int sensorValue;
#endif
//variable systemes
char Notif[BUF_SIZE];
char Horloge[BUF_SIZE];
boolean Alert=false;
boolean FinMsg=false;
byte Intensite=5;
byte BkIntensite=Intensite;
const long interval = 20000; // interval pour mesure luminosite réglé sur 20 s
unsigned long previousMillis=0 ;
byte clic=0;
byte clicstate=1;
String message="";
String type="";
int httpCode=200;
byte NTPcount=0;
byte valEPROM;
//******** fx *******
textEffect_t effect[] =
{
PA_RANDOM,
PA_PRINT,
PA_SCAN_HORIZ,
PA_SCROLL_LEFT,
PA_NO_EFFECT,
PA_WIPE,
PA_SCAN_VERTX,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_FADE,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_SPRITE,
PA_CLOSING,
PA_GROW_DOWN,
PA_SCAN_VERT,
PA_SCROLL_DOWN_LEFT,
PA_WIPE_CURSOR,
PA_SCAN_HORIZX,
PA_DISSOLVE,
PA_MESH,
PA_OPENING,
PA_CLOSING_CURSOR,
PA_SCROLL_DOWN_RIGHT,
PA_SCROLL_RIGHT,
PA_SLICE,
PA_SCROLL_DOWN,
};
byte fx_in=3;
byte fx_out=3;
bool fx_center;
//*****************************************
// UTF8 - Ascii etendu
//*****************************************
uint8_t utf8Ascii(uint8_t ascii)
// Convert a single Character from UTF8 to Extended ASCII according to ISO 8859-1,
// also called ISO Latin-1. Codes 128-159 contain the Microsoft Windows Latin-1
// extended characters:
// - codes 0..127 are identical in ASCII and UTF-8
// - codes 160..191 in ISO-8859-1 and Windows-1252 are two-byte characters in UTF-8
// + 0xC2 then second byte identical to the extended ASCII code.
// - codes 192..255 in ISO-8859-1 and Windows-1252 are two-byte characters in UTF-8
// + 0xC3 then second byte differs only in the first two bits to extended ASCII code.
// - codes 128..159 in Windows-1252 are different, but usually only the €-symbol will be needed from this range.
// + The euro symbol is 0x80 in Windows-1252, 0xa4 in ISO-8859-15, and 0xe2 0x82 0xac in UTF-8.
//
// Modified from original code at http://playground.arduino.cc/Main/Utf8ascii
// Extended ASCII encoding should match the characters at http://www.ascii-code.com/
//
// Return "0" if a byte has to be ignored.
{
static uint8_t cPrev;
uint8_t c = '\0';
if (ascii < 0x7f) // Standard ASCII-set 0..0x7F, no conversion
{
cPrev = '\0';
c = ascii;
}
else
{
switch (cPrev) // Conversion depending on preceding UTF8-character
{
case 0xC2: c = ascii; break;
case 0xC3: c = ascii | 0xC0; break;
case 0x82: if (ascii==0xAC ) c = 0x80; // Euro symbol special case
}
cPrev = ascii; // save last char
}
return(c);
}
void utf8Ascii(char* s)
// In place conversion UTF-8 string to Extended ASCII
// The extended ASCII string is always shorter.
{
uint8_t c, k = 0;
char *cp = s;
while (*s != '\0')
{
c = utf8Ascii(*s++);
if (c != '\0')
*cp++ = c;
}
*cp = '\0'; // terminate the new string
}
//*****************************************
// **************************
// Parametre NTP
// Serveur NTP
// **************************
// 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 {
// dateNum2 = datenum(dateStr2,'dd-mmm-yyyy HH:MM:SS');
if ( NTPcount>14 ) {
NTP.setInterval (1200);
}
else ++NTPcount;
}
}
// **************************************
void luminosite() {
#if (ACTIVCAPTLUM)
// fonction reglage auto luminosite
byte bkint = Intensite;
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;
if (bkint != Intensite ) ToJeedom( idLum ,Intensite);
#endif
}
// ******************
// Gestion page WEB
//******************
void handleRoot(){
if ( server.hasArg("SEC") || server.hasArg("LUM") || server.hasArg("HOR")) {
handleSubmit();
}
else {
server.send ( 200, "text/html", getPage() );
}
}
void handleSubmit() {
String SEC = server.arg("SEC");
String LUM = server.arg("LUM");
String HOR = server.arg("HOR");
if ( LUM =="manu" ) {
if (server.arg("INT") !="") Intensite=server.arg("INT").toInt();
ToJeedom(idLum , Intensite);
Option(&AutoIn,false);
} else if ( LUM == "auto")
{
Option(&AutoIn,true);
}
if ( HOR =="off" ) Option(&TimeOn,false);
else if ( HOR =="on") Option(&TimeOn,true);
if ( SEC == "on" ) Option(&DisSec,true);
else if ( SEC == "off" ) Option(&DisSec,false);
if ( server.arg("RAZ") =="1" ) {
P.print("reboot");
delay(3000);
ESP.reset();
}
server.send ( 200, "text/html", getPage() );
}
// *****************************
// ANIMATION
// SPRITE DEFINITION (PAC MAn )
// *****************************
const uint8_t F_PMAN1 = 6;
const uint8_t W_PMAN1 = 8;
static uint8_t pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
};
const uint8_t F_PMAN2 = 6;
const uint8_t W_PMAN2 = 18;
static uint8_t pacman2[F_PMAN2 * W_PMAN2] = // ghost pursued by a pacman
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe,
};
// ***************************
// Fonction gestion des Options
// TimeOn , DisSec / AutoIn
//*****************************
void Option(boolean *Poption, boolean valeur) {
String *Pid = NULL ;
int value=valeur;
// afectation de la valeur à l'option ( via pointeur )
*Poption = valeur;
byte UpVal = valEPROM;
if ( Poption == &DisSec ) {
Pid = &idSec ;
bitWrite(valEPROM, 4, valeur);
}
else if ( Poption == &AutoIn ) {
Pid = &idAuto ;
if (!bitRead(UpVal,6) && valeur ) NotifMsg("Auto",Intensite,true);
bitWrite(valEPROM, 6, valeur);
if ( !valeur ) {
if ( Intensite == 0 ) message="Min";
else if ( Intensite == 15 ) message="Max";
else message="LUM :"+String(Intensite);
NotifMsg(message,Intensite,true);
valEPROM=valEPROM&240; // masque sur les 4 derniers bits
valEPROM+=Intensite;
P.setIntensity(Intensite);
if (DEBUG) {
Serial.println(" Menu Option");
Serial.println("valeur enregistrement EPROM " + String(valEPROM) );
}
}
}
else if ( Poption == &TimeOn ) {
Pid = &idHor ;
bitWrite(valEPROM, 5, valeur);
if (!valeur)
{
NotifMsg("OFF",Intensite,true);
}
}
if (UpVal != valEPROM ) {
// enregistre en EEprom les options si changement
bitWrite(valEPROM, 7, true);
EEPROM.write(100,valEPROM);
EEPROM.commit();
}
// envoie a jeedom des modifications effectués en fonction de l 'option
ToJeedom(*Pid,value);
}
void NotifMsg(String Msg,byte lum,boolean Info)
{
P.setFont(0,ExtASCII);
Alert=true;
Msg.toCharArray(Notif,BUF_SIZE);
if (Info) {
//P.displayZoneText(0,Notif,PA_CENTER,SPEED_TIME, PAUSE_TIME,PA_PRINT,PA_NO_EFFECT);
fx_center=true;
fx_in=1;
fx_out=4;
}
else
{
P.setTextAlignment(0,PA_LEFT) ;
// P.displayZoneText(0, Notif, PA_LEFT, SPEED_TIME, PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
fx_in=3;
fx_out=3;
}
}
//***********************
// Boucle SETUP
// *********************
void setup(void)
{
//init demmarrage
P.begin();
if (DEBUG) {
Serial.begin(9600);
}
EEPROM.begin(512);
P.print("Start ...");
//******** WiFiManager ************
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 ************
P.print( "OTA ...");
//******* OTA ***************
// Port defaults to 8266
// ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname(NOMMODULE);
// 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([]() {
digitalWrite(led, HIGH); // allume led au debut du transfert
P.begin();
P.setFont(0,ExtASCII);
});
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) {
if (MAX_DEVICES<5) sprintf(Notif,"Up %u%%", (progress / (total / 100)));
else 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
while (WiFi.status() != WL_CONNECTED) {
}
// on affiche l'adresse IP attribuee pour le serveur DSN et on affecte le nom reseau
WiFi.hostname(NOMMODULE);
//*************************
// on definit les points d'entree (les URL a saisir dans le navigateur web) : Racine du site est géré par la fonction handleRoot
server.on("/", handleRoot);
server.on("/Notification", [](){
// on recupere les parametre dans l'url dans la partie /Notification?msg="notification a affiocher"&type="PAC"
if ( server.hasArg("msg")) {
message=server.arg("msg");
if (message ) {
// message.toCharArray(Notif,BUF_SIZE);
if (server.hasArg("intnotif") && server.arg("intnotif").length() > 0 ) {
BkIntensite=Intensite;
Intensite = server.arg("intnotif").toInt();
if (Intensite < 1 ) Intensite = 0 ;
if (Intensite > 14 ) Intensite = MAX_INTENSITY;
}
if (server.arg("type")) {
type=server.arg("type");
}
P.setIntensity(Intensite); // intensité pour les notifs si pas de valeur Intensité par defaut
// on repond au client
NotifMsg(message,Intensite,false);
server.send(200, "text/plain", "message :" + message + " & Animation : "+server.arg("type") + " & Intensite : "+Intensite);
}
}
});
// on demarre le serveur web
server.begin();
//******* Service NTP ********
NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
ntpEvent = event;
syncEventTriggered = true;
});
P.print("init");
// 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);
//************************************
// init systéme - lecture Eeprom si existe et envoie info à jeedom
valEPROM = EEPROM.read(100);
if (bitRead(valEPROM, 7)) // Si Enregistrement existe
{
DisSec=bitRead(valEPROM, 4);
TimeOn=bitRead(valEPROM, 5);
AutoIn=bitRead(valEPROM, 6);
if (!AutoIn) Intensite=valEPROM&15; // masque sur les 4 derniers bits , pour recuperer valeur intensite mode manuel
if (DEBUG) {
Serial.println(" Valeur lu en Memoire : ");
Serial.println(" valeur intensite : "+String(Intensite));
}
}
ToJeedom(idSec,DisSec);
ToJeedom(idHor,TimeOn);
ToJeedom(idAuto,AutoIn);
// *********************************
//************ Initialisation des Zones
P.begin(MAX_ZONES);
P.setSpriteData(pacman1, W_PMAN1, F_PMAN1,pacman2, W_PMAN2, F_PMAN2); // chargement animation en memoire
P.setInvert(false);
#if (MAX_ZONES >1 && ZONE_MSG >0 )
P.setZone(0, 0, (ZONE_MSG-1));
P.setZone(1, ZONE_MSG,(MAX_DEVICES -1));
//P.setZone(1, 1,3);
#else
P.setZone(0, 0, MAX_DEVICES);
#endif
P.displayZoneText(0, "", PA_LEFT, SPEED_TIME, PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
if (MAX_ZONES > 1 ) P.displayZoneText(1, Horloge, PA_CENTER, 0,0, PA_PRINT, PA_NO_EFFECT);
// Fin de Setup
message = " Systeme OK - Adresse ip : ";
message += WiFi.localIP().toString();
//message.toCharArray(Notif,BUF_SIZE);
//Alert=true;
NotifMsg(message,Intensite,false);
}
//***********************************
//***********************************
//********* Boucle loop *************
//***********************************
//**********************************
void loop(void)
{
static uint32_t lastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
// ******** Gestion luminosite
// Si Horloge activé
if (TimeOn) {
// Si gestion Auto luminositée activé
if (AutoIn) {
#if (ACTIVCAPTLUM)
if( millis() - previousMillis >= interval) {
previousMillis = millis();
luminosite();
}
#endif
}
//P.setIntensity(Intensite);
}
// if (DEBUG) Serial.println("valeur luminosité "+ String(Intensite));
// ********** Fin gestion luminosite
// *********** Gestion bouton
#if (ACTIVBOUTON)
// etat bouton
boutonClick.Update();
// Sauvegarde de la valeur dans la variable click
if (boutonClick.clicks != 0) clic = boutonClick.clicks;
if (DEBUG && clic ) Serial.print("valeur clic : "+ String(clic));
switch (clic) {
case 1: // double clic - Affiche ou non les secondes
Option(&DisSec,!DisSec);
clic=0;
break;
case 2: // double clic - ON / OFF horloge
Option(&TimeOn,!TimeOn);
clic=0;
break;
case 3: // Simple clic - boucle : Manuel intensite à 0 / Manu Intensite MAX / Auto
if (clicstate==1) {
Intensite = 0;
Option(&AutoIn,false);
}
if (clicstate==2) {
Intensite = 15;
Option(&AutoIn,false);
}
if (clicstate==3) {
Option(&AutoIn,true);
clicstate=0;
}
ToJeedom(idLum , Intensite);
P.setIntensity(Intensite);
++clicstate;
clic=0;
break;
case 255: // simple clic mais long sur dernier - diminue
--Intensite;
if (Intensite<0) Intensite=0;
NotifMsg("LUM :"+String(Intensite),Intensite,true);
clic=0;
break;
case 254: // double clic mais long sur dernier - Augmente
++Intensite;
if (Intensite>15) Intensite=MAX_INTENSITY;
NotifMsg("LUM :"+String(Intensite),Intensite,true);
clic=0;
break;
default:
// default is optional
break;
}
#endif
// ******** Fin gestion bouton
// ********* Gestion Reseau : Pages WEB , NTP et OTA
// ********* Service NTP
if (syncEventTriggered) {
processSyncEvent (ntpEvent);
syncEventTriggered = false;
}
// ****** Page WEb : a chaque iteration, la fonction handleClient traite les requetes
server.handleClient();
// ******* OTA
// Surveillance des demandes de mise a jour en OTA
ArduinoOTA.handle();
// ******** Fin gestion reseau
//********** flasher
if (millis() - lastTime >= 1000)
{
lastTime = millis();
flasher = !flasher;
}
if (P.displayAnimate())
{
if (Alert) {
if (P.getZoneStatus(0))
{
P.setFont(0,ExtASCII); // chargement caractere etendue
// Type de demande
if (type=="PAC" ) { // animation PAC MAn
P.displayZoneText(0,"Notif", PA_LEFT, 40, 1, PA_SPRITE, PA_SPRITE);
type="";
}
else if (type=="BLINDS" ) { // animation de type volet
P.displayZoneText(0,"", PA_CENTER, 40, 1, PA_BLINDS, PA_BLINDS);
type="";
}
else if (type=="OPENING" ) { // animation Ouverture
P.displayZoneText(0,"Notif", PA_CENTER, 60, 100, PA_OPENING_CURSOR, PA_OPENING_CURSOR);
type="";
}
else {
P.displayClear(0);
P.displayZoneText(0, Notif, PA_LEFT,SPEED_TIME, PAUSE_TIME, effect[fx_in], effect[fx_out]);
if (fx_center) {
P.setTextAlignment(0,PA_CENTER);
fx_center=false;
}
else FinMsg=true;
Alert=false;
//Intensite=BkIntensite; // reviens a intensite avant notif
if (DEBUG) Serial.println("valeur de intensite : "+String(Intensite) +" Valeur de bk : "+String(BkIntensite));
}
}
}
else {
if (MAX_ZONES == 1) {
P.setFont(0, numeric7Seg_Byfeel);
digitalClockDisplay(Notif,flasher);
P.displayZoneText(0, Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
}
if (MAX_ZONES > 1) {
if (P.getZoneStatus(0)) P.displayClear(0);
P.setFont(1, numeric7Seg_Byfeel);
digitalClockDisplay(Horloge,flasher);
P.displayZoneText(1, Horloge, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
}
// Check for individual zone completion. Note that we check the status of the zone rather than use the
// return status of the displayAnimate() method as the other unused zones are completed, but we
// still need to call it to run the animations.
//while (!P.getZoneStatus(MAX_ZONES-1))
} // fin displayanimate
}
//********************** fin boucle
// Fonction envoie requete vers Jeedom
void ToJeedom( String id , byte valeur){
#if (JEEDOM)
String url;
String value;
if (id=="idSec" || id=="idHor") {
if (valeur==0) value="off";
else value="on";
}
else if ( id=="idAuto" ) {
if (valeur==0) value="manu";
else value="auto";
}
else {
value=valeur;
}
url = BaseUrlJeedom;
url +=id;
url +="&value="+value;
http.begin(url);
httpCode = http.GET();
http.end();
#endif
}
// Fonction clockformat ( ajoute les zeros devant les unités )
void digitalClockDisplay(char *heure,bool flash)
{
// Si affichage de l'heure
if (TimeOn) {
if (FinMsg) {
Intensite=BkIntensite;
FinMsg=false;
}
P.setIntensity(Intensite);
if ( DisSec )
{ // si affichage des Secondes 00:00 (secondes en petit )
char secondes[2]; // pour affichage des secondes
sprintf(secondes,"%02d",second());
secondes[0]=secondes[0]+23; // permutation codes AScci 71 à 80
secondes[1]=secondes[1]+23;
if (DEBUG) {
//Serial.println("debug des secondes : ");
//Serial.println(second());
//Serial.println(secondes[0]);
//Serial.println(secondes[1]);
}
sprintf(heure,"%02d:%02d %c%c",hour(),minute(),secondes[0],secondes[1]);
//sprintf(heure,"%02d%c%02d%c%c",hour(),(flash ? ':' : ' '),minute(),secondes[0],secondes[1]);
}
// Affichage 00:00 avec : Clignottant ( flasher )
else sprintf(heure,"%02d%c%02d",hour(),(flash ? ':' : ' '),minute());
}
else // sinon point clignottant uniquement
{
P.setIntensity(0);
sprintf(heure,"%c",(flash ? '.' : ' '));
}
}
//************************************
// Page WEB Accueil
// ***********************************
String getPage(){
char ddj[30];
sprintf(ddj,"%02d:%02d:%02d - Date : %02d/%02d/%4d",hour(),minute(),second(),day(),month(),year());
String page = "<html lang=fr-FR><head><meta http-equiv='content-type' content='text/html;charset=ISO-8859-15' /><meta http-equiv='refresh' content='120'/>";
page += "<title>i-Notif'Heure - 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;'>i-Notif\'Heure</span></h1>";
page += "<h3><span style='background-color: #398AA4; color: #ffffff; padding: 0 5px;'> Heure : ";
page += ddj;
page += "</span></h3>";
page += "<div class='bloc'><form action='/Notification' method='GET' accept-charset='ISO-8859-1'>";
page +="<fieldset><legend>Envoyer une Notification :</legend>";
page +="<label for='msg'>Message </label><br />";
page += "<INPUT type='text' name='msg' id='msg'maxlength='59' style='width:400px;' placeholder='Votre Message - "+String(BUF_SIZE) +" caracteres max -'/>";
page +="<label for='type'>type : </label>";
page +="<select name='type' id='type'>";
page +="<option value=''>Defaut</option>";
page +="<option value='PAC'>PAC MAN</option>";
page +="<option value='BLINDS'>BLINDS</option>";
page +="<option value='OPENING'>Opening</option>";
page +="</select><br />";
page +="<label for='intnotif'>Intensite : </label><br />";
page += "<p><input id='sliderINT' type='range' min='0' max='15' step='1' name='intnotif' list='tickmarks' />";
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='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>Version </td><td>";
page += Ver;
page +="</td></tr>";
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='on' id='on'";
if (DisSec==true) page +=" checked ";
page += "><label for='on'>ON</label>";
page +="<INPUT type='radio' name='SEC' value='off' 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='on' id='horon'";
if (TimeOn==true) page +=" checked ";
page += "><label for='horon'>ON</label>";
page +="<INPUT type='radio' name='HOR' value='off' id='horoff'";
if (TimeOn==false) page +=" checked ";
page += "><label for='horoff'>OFF</label></fieldset>";
page +="<fieldset><legend>Gestion de la luminositée ( ";
page +=Intensite;
page +=" ) : </legend>";
page += "<INPUT type='radio' name='LUM' value='auto' id='auto'";
if (AutoIn==true) page +=" checked ";
page += "><label for='auto'>AUTO</label>";
page +="<INPUT type='radio' name='LUM' value='manu' id='manu'";
if (AutoIn==false) page +=" checked ";
page += "><label for='manu'>Manuel</label></P>";
if (AutoIn==false) {
page +="<p>Valeur luminositée : ";
page +=Intensite;
page +="</p>";
page += "<p><input id='slider1' type='range' min='0' max='15' step='1' name='INT' 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 +="<fieldset><legend>Redemarrage Module :</legend>";
page += "<INPUT type='radio' name='RAZ' value='1' id='reset'";
page += "><label for='reset'>Redemmarage</label>";
page += "</fieldset>";
page +="</fieldset>";
page += "<INPUT type='submit' value='Actualiser'name='parametres'/></div>";
page += "</form>";
page += "<br><br>";
page += "</body></html>";
return page;
}
[adsense]Code complet script font numeric7 modifié.
// Definition des polices de caractéres pour affichage
// Horloge avec notif.
// Modification du fichier Font.h de la bibliotheque Parola
// Byfeel : Juin 2018
// Definition des chiffres principaux sur 4 rangées , definition de 7 led en hauteur / et 4 led en largeur
// Definition des mini chiffres ( pour affichage secondes
// Sur 5 led en hauteur / 3 led en largeur
// Espaces caracteres de 3 , pour les petits chiffres.
// Mini chiffre : definit à la place des lettres G à P.
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t numeric7Seg_Byfeel[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
1, 0, // 32 - 'Space'
0, // 33 - '!'
0, // 34 - '"'
0, // 35 - '#'
0, // 36 -
0, // 37 - '%'
0, // 38 - '&'
0, // 39 - '''
0, // 40 - '('
0, // 41 - ')'
0, // 42 - '*'
0, // 43 - '+'
0, // 44 - ','
0, // 45 - '-'
1, 64, // 46 - '.'
0, // 47 - '/'
4, 127, 65, 65,127, // 48 - '0'
4, 0, 0, 127, 0, // 49 - '1'
4, 121, 73, 73, 79, // 50 - '2'
4, 73, 73, 73, 127, // 51 - '3'
4, 15, 8, 8, 127, // 52 - '4'
4, 79, 73, 73, 121, // 53 - '5'
4, 127, 73, 73, 121, // 54 - '6'
4, 1, 1, 1, 127, // 55 - '7'
4, 127, 73, 73, 127, // 56 - '8'
4, 79, 73, 73, 127, // 57 - '9'
1, 20, // 58 - ':'
0, // 59 - ';'
0, // 60 - '<'
0, // 61 - '='
0, // 62 - '>'
0, // 63 - '?'
0, // 64 - '@'
5, 127, 9, 9, 9, 127, // 65 - 'A'
5, 127, 73, 73, 73, 54, // 66 - 'B'
5, 127, 65, 65, 65, 65, // 67 - 'C'
5, 127, 65, 65, 65, 62, // 68 - 'D'
5, 127, 73, 73, 73, 73, // 69 - 'E'
5, 127, 9, 9, 9, 9, // 70 - 'F'
3, 124, 68, 124, // 71 - '0' petit caractere pour secondes
3, 0, 124, 0, // 72 - '1'
3, 116,84,92, // 76 - '2'
3, 84, 84, 124, // 74 - '3'
3, 28,16,124, // 75 - '4'
3, 92,84, 116, // 73 - '5'
3, 124,84,116, // 77 - '6'
3, 4,4,124, // 78 - '7'
3, 124,84,124, // 79 - '8'
3, 92,84,124, // 80 - '9'
0, // 81 - 'Q'
0, // 82 - 'R'
0, // 83 - 'S'
0, // 84 - 'T'
0, // 85 - 'U'
0, // 86 - 'V'
0, // 87 - 'W'
0, // 88 - 'X'
0, // 89 - 'Y'
0, // 90 - 'Z'
0, // 91 - '['
0, // 92 - '\'
0, // 93 - ']'
0, // 94 - '^'
0, // 95 - '_'
0, // 96 - '`'
5, 127, 9, 9, 9, 127, // 97 - 'a'
5, 127, 73, 73, 73, 54, // 98 - 'b'
5, 127, 65, 65, 65, 65, // 99 - 'c'
5, 127, 65, 65, 65, 62, // 100 - 'd'
5, 127, 73, 73, 73, 73, // 101 - 'e'
5, 127, 9, 9, 9, 9, // 102 - 'f'
0, // 103 - 'g'
0, // 104 - 'h'
0, // 105 - 'i'
0, // 106 - 'j'
0, // 107 - 'k'
0, // 108 - 'l'
0, // 109 - 'm'
0, // 110 - 'n'
0, // 111 - 'o'
0, // 112 - 'p'
0, // 113 - 'q'
0, // 114 - 'r'
0, // 115 - 's'
0, // 116 - 't'
0, // 117 - 'u'
0, // 118 - 'v'
0, // 119 - 'w'
0, // 120 - 'x'
0, // 121 - 'y'
0, // 122 - 'z'
0, // 123 - '{'
1, 127, // 124 - '|'
0, // 125
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
0, // 161
0, // 162
0, // 163
0, // 164
0, // 165
0, // 166
0, // 167
0, // 168
0, // 169
0, // 170
0, // 171
0, // 172
0, // 173
0, // 174
0, // 175
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
0, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
37 commentaires sur “DIY : i-Notif’Heure ou comment mettre en place une horloge connectée avec Notification”
Merci pour ce tuto génial, tout fonctionne bien, cela aussi avec jeedom, juste un petit souci d’apostrophe qui ne s’affiche pas en passant par Jeedom, problème que je n’ai pas en passant par l’interface Web. Est-ce normal, chez vous aussi, il y a ce problème ? y’a t’il une astuce ?
je viens de tester , c’est pareil , il doit y avoir un probleme avec le script jeedom en PHP , je vais regarder du coté de la fonction urlencode .
JE repasse encore une fois par ici te dire MERCI et BRAVO car j’utilise le système depuis des mois et c’est vraiment génial !
J’ai reçu récement des matrices leds ws2812b, penses tu qu’on pourrais faire pareil ?
Merci pour tes encouragements. Pas eu l occasion de tester avec d autres leds pour l instant. Je suis en train de finaliser une nouvelle version.
Bonjour,
Lors de la compilation j’obtiens cette erreur :
FC16_HW’ is not a member of ‘MD_MAX72XX’
Une idée ?
Merci
bonjour ,
vous devez , sans doute ne pas utiliser les dernières versions de la bibliothèque MD_max et md_Parola.
Vous devez être en version 3 minimum pour les deux.
Bonjour à tous,
Bravo pour le travail sur ce superbe projet que je découvre.
Je viens de me lancer et sur la version 2.631 j’ai un problème d’intensité.
Je n’utilise pas la photocellule, suis en manu. Lorsque je change l’intensité (sur la page web ou dans jeedom), l’afficheur indique bien le changement, mais l’intensité elle ne bouge pas.
Lors de l’envoi d’un message de notif, seule l’animation avant message « PAC » Blind » etc… voit son intensité modifiée, le message lui etant toujours à une intensité intermédiaire.
Bonjour ,
je vais regarder ça .
Merci pour l’info
Une ligne était inversé , pb de copier/coller.
ça devrait aller.
Hello,
je viens de recevoir les photo résistance mais je n’ai pas trouvé où la connecter sur le WEMOS D1 .???
et une 2eme question est-il possible d’utiliser d’autres polices de caractère pour les messages celle par défaut est « énorme »
bonjour ,
la photo resistance , se branche sur la seule entrée analogique du WEMOS . La A0.
Tout est expliqué dans cet article :
https://byfeel.info/diy-horloge-et-notification-domotique-matrix-led-avec-jeedom/
Attention l’entrée A0 ne supporte pas le 5V !!! MAX 3,3 V sous peine de griller son wemos.
il faut faire un pont diviseur avec une retissante de 10K , et brancher le tout entre le 0 et 3,3V
Il est tout a fait possible de redessiner les polices de caractères , comme expliqué dans ce tuto . Il faut que tu modifie le fichier Parola_font_data ( qui sert a afficher le texte ), qui définit tous les codes ascii .
le font_byfeel sert a afficher les heures.
Merci encore ByFeel pour ton super boulot et pour le temps que tu passes à partager avec nous
mon boitier est parti à l’imprimante 3D
Hello,
Pourquoi ne pas partager aussi ce boitier ?
merci
Fabrice
Bonjour Byfeel,
Merci pour tout ton travail qui va me permettre de réaliser des afficheurs sympa à connecter à Jeedom.
J’ai fait un proto qui fonctionne en 2.6 avec les mises à jour OTA.
J’ai juste eu un problème pour le téléversement en OTA, il faut avoir installé Python (en version 2.7 et coche « ajouter au PATH » à l’installation) que je n’avais pas. Je ne crois pas l’avoir vu dans tes tutos. Peut-être peux-tu l’ajouter…
J’ai un autre petit soucis, j’ai du mal à créer les scripts Jeedom nécessaires à toutes les commandes. Pas de soucis avec celui des notif que tu as décris mais pour ceux des paramètres, j’ai retrouvé les noms des arguments dans le code mais j’ai du mal à les construire (je n’avais encore jamais utilisé plugin Script de Jeedom). Si tu peux rajouter ça quelque part …
Merci d’avance.
Fabrice
bonjour fabrice ,
merci pour ton retour 🙂
En ce qui concerne OTA , je suis sur Mac , et python etait effectivement installé depuis longtemps. Merci pour l’info , il faudra que je l’intègre , car je n’ai pas fait attention que python devait être installé pour OTA.
Pour les script Jeedom , j’en ai écrit deux :
Un pour les notifications et un autres pour les options , tous les détails dans cet article :
https://byfeel.info/diy-horloge-et-notification-v2-interaction-avec-jeedom/
exemple appel script depuis jeedom , si ip horloge = 192.168.80.156
Pour les notifications :
/var/www/html/core/php/../../plugins/script/core/ressources/notifHorloge.php 192.168.80.156 #message# #title#
ou message est le texte a envoyer
et title les options : par exemple type=PAC,lum=15 ( luminosité à 15 et animation PacMan )
Pour les options : Eteints les Secondes
/var/www/html/core/php/../../plugins/script/core/ressources/SetupHorloge.php 192.168.80.156 SEC off
Merci Byfeel pour la rapidité de la réponse.
J’ai lu et relu tes articles plusieurs fois avec parfois difficulté malgré leur niveau de détail et de pédagogie car la programmation C remonte à loin pour moi. et celui-ci je l’avais mis de côté car je ne voulais pas me compliquer les choses avec les caractères spéciaux en première approche et je n’avais pas vu qu’il contenait ce que je cherchais.
Je vais tester ça tout de suite.
Dans mes projets, n’ayant pas de système sonos ou équivalent, j’envisage d’ajouter un buzzer au NotifHeur pour attirer l’attention en cas d’alerte ou réveiller.
si tu veux plus d’info sur l’install de Python sur Windows, j’ai trouvé l’info ici :
http://esp8266.github.io/Arduino/versions/2.0.0/doc/ota_updates/ota_updates.html
Bonne journée
Fabrice
Bonjour Byfeel,
Grace à tes articles j’ai bien avancé dans ma mise au point de mon horloge.
J’arrive maintenant à envoyer mes notifications et gérer l’horloge mais tout n’est pas encore parfait :
– L’intensité lumineuse de l’horloge ne revient pas à son niveau précédent après une notification en surbrillance.
– Depuis Jeedom (pas de soucis avec la page web) seul le premier mot de la page est pris en compte.
– J’ai remarqué aussi que contrairement à ce que tu indiques, les options de notifications ne fonctionnent qu’avec une virgule (et pas le 😉 et sans espace. Peut-être est-ce lié au pb précédent ?
Merci d’avance de ton aide.
Fabrice
Salut Fabrice, tu peux peux être te simplifier la vie en utilisant des scenarios jeedom non ?
Rebonjour à tous,
en relisant mon message, je vois quelques coquilles, je devais être fatigué.
Il faut lire :
– « seul le premier mot de la !notification! page est pris en compte »
– et remplacer le smiley par un ;
Pour DCJona, peux-tu préciser ta remarque sur les scénarios ? J’imagine pouvoir gérer mon premier problème avec mais pas les autres…
Dans ta vidéo ci-dessous c’est une plaque de verre que tu as mis devant les matrices ?
Fabrice
En fait pour plus de flexibilité et ne pas modifié le code et réuploader sur le wemos a chauqe fois j’ai mis en place 3 scénarios ( 1-2 et 3 clics), on peut en imagine bien plus mais j’en avais pas l’utilité et je modifie les scénarios jeedom au lieu de modifier le code, ce qui me parait plus simple pour l’affichage de notification… et comme cela je peux ajouter plusieurs actions au simple clic par exemple dans mon scenario.
Pour mon mur en bois c’est une plaque de plexi translucide auquel je suis venu collé un film miroir 🙂
Bonjour fabrice ,
en effet , après verification ,il y a un petit bug , avec la gestion de la luminosité .
Des infos , qui ne remonté pas correctement et des commentaires , que j’avais oublié d’enlever dans mon script.
Je corrige tout ça et fait une mise a jour en 2.631 sur le Github.
En ce qui concerne le problème de notification , cela est peut etre du au script PHP sous jeedom .
J’ai corrigé le script dans l’article .
il faut modifier le debut
$IP=$argv[1];
$notif=iconv(« UTF-8 », « CP1252 », $argv[2]); // conversion utf8 en ISO 8859-15 – gestion de €
$notif=urlencode($notif);
// Decoupage des options transmis dans titre sous la forme type =
….
L’intégralité à été corrigé , dans l’article original.
Pour les options pas de soucis de séparateur chez moi
voici les séparateurs autorisés , ; . : –
// Decoupage des options transmis dans titre sous la forme type =
$Options=preg_split(« /[\,\;\.\:\-]/ », str_replace(‘ ‘, », $argv[3]));
Pour finir devant l’affichage j’ai collé une plaque de Plexiglas fumée. ( entre 3 et 6 € dans les magasins de bricolage selon la taille )
Bonsoir Byfeel,
Merci encore pour ton aide.
C’est bizarre, je ne peux pas répondre à ton dernier message, seulement à celui là.
J’ai fait la modif du PHP que tu préconises pour mon pb de notification coupée, mais j’ai maintenant un message d’erreur de Jeedom quand le lance la commande script :
Erreur dans l’exécution du terminal, la valeur retournée est : 255. Détails : Array ( [0] => PHP Parse error: syntax error, unexpected ‘UTF’ (T_STRING), expecting ‘,’ or ‘)’ in /var/www/html/plugins/script/core/ressources/ScriptNotification.php on line 3 )
ci-dessous mon script :
Pour le github je n’ai pas trouvé la nouvelle version mais peut-être ne l’as tu pas encore faite. PAs de soucis, y’a pas le feu.
Pour ta question sur la mise à jour du blog, un truc cool serait de pouvoir mieux mettre en forme les commentaires, mais je sais pas si c’est possible. En tout cas bravo pour tout ton travail.
Fabrice
mon script a été viré de mon message (peut-être pour des raisons de sécu). Je ne remet sans la balise php initiale pour voir si ça passe :
$IP=$argv[1];
$notif=iconv(« UTF-8 », « CP1252 », $argv[2]); // conversion utf8 en ISO 8859-15 – gestion de €
$notif=urlencode($notif);
// Decoupage des options transmis dans titre sous la forme type = Animation ; lum = intensite de la lumiére
//$Options = explode(« ; »,str_replace(‘ ‘, », $argv[3]));
$Options=preg_split(« /[\,\;\.\:\-]/ », str_replace(‘ ‘, », $argv[3]));
foreach ( $Options as $Value ){
list($k, $v) = explode(« = »,$Value);
$k = strtolower($k);
$v = strtoupper($v);
$result[ $k ] = $v;
}
// Affectation des differents index
$type=$result[« type »];
$lum=$result[« lum »];
/* Lit un fichier distant sur le serveur http://www.example.com avec le protocole HTTP */
$url= »http:// ».$IP. »/Notification?msg= ».$notif. »&type= ».$type. »&intnotif= ».$lum;
$httpfile = file_get_contents($url);
Fabrice
Je pense qu’il doit y avoir un problème de syntaxe , j’ai mis sur mon github , les scipt jeedom que j’utilise .
Si tu as fait un copié collé depuis le blog , tu as peut etre récupéré des caractères de formatage ?
Dans le message d’erreur , c’est bizarre qu’il t’indique la valeur $IP , au lieu de l’adresse ip : 192.168.x.x , aucune variable n’a été remplacé par l’appel de ton script sous jeedom ? bizarre ?
il faut bien créer une commande de type script ( avec type action message ) , puis dans le champs de la requête bien renseigner tous les éléments : /var/www/html/core/php/../../plugins/script/core/ressources/notifHorloge.php 192.168.x.x « #message# » « #title# »
Bonjour,
Peut-être bien un pb de formatage. J’ai récupéré le script et le nouveau .ino.
Plus de pb de luminosité et plus d’erreur Jeedom, mais j’ai toujours que le 1er mot de ma notification qui passe aucun pb depuis la page web.
Sais-tu comment je pourrais visualiser l’URL qui est émise par jeedom (par le script) ?
Fabrice
tu met bien la balise #message# entre guillemet ?
Tu peux activer les log dans le plug in script .
ajoute ces commandes à ton script aprés notif urlencode ….
include(‘/var/www/html/core/class/scenario.class.php’);
log::add(‘script’,’error’,’Argument transmis par message :’.$argv[2]);
log::add(‘script’,’error’,’valeur notif envoyé :’.$notif );
tu auras deux infos bulles dans jeedom qui te donnera les infos récupérés et les infos envoyés ( formatés en html codé iso )
Si tu constate que les infos sont bonnes , il faut que tu verifie que tu n’as pas modifié la page web du module :
String page = «
Hello, bon et bien je crois que tu as trouvé. Je n’avais pas vu les guillemets ! Par contre je viens de partir en vacances et je ne pourrai pas tester avant plusieurs jours. Mais à mon avis ça devrait y faire. Il me restera plus qu’à ajouter le bouton et la ldr…
Merci encore.
Fabrice
bonne vacances 🙂
J’en ai profité aussi pour adapté mon afficheur dans mon panneau en bois du coup avec l’ajout de 2 boutons ..
https://www.youtube.com/watch?v=WqiudSwDc8E
Superbe intégration , ça me donne des idées.
Merci, ah ben si je peux donner des idées en retour 🙂
Finalisation de mon radio réveil en cours, j’ai opté pour le bois finalement, juste passer un produit de teinte et protection :
[url=https://www.noelshack.com/2018-29-1-1531743352-img-20180716-135845.jpg][img]https://image.noelshack.com/minis/2018/29/1/1531743352-img-20180716-135845.png[/img][/url]
[url=https://www.noelshack.com/2018-29-1-1531743352-img-20180716-135935.jpg][img]https://image.noelshack.com/minis/2018/29/1/1531743352-img-20180716-135935.png[/img][/url]
[url=https://www.noelshack.com/2018-29-1-1531743352-img-20180716-135947.jpg][img]https://image.noelshack.com/minis/2018/29/1/1531743352-img-20180716-135947.png[/img][/url]
[url=https://www.noelshack.com/2018-29-1-1531743351-img-20180716-140040.jpg][img]https://image.noelshack.com/minis/2018/29/1/1531743351-img-20180716-140040.png[/img][/url]
Excellent, beau boulot.
J’ai mis aussi le nouveau code, ca en jette + avec la police :p
oui il est superbe comme çà
Merci pour toutes c’est news 😀
T’a modifiée pas mal ton code par rapport au précédent, va falloir que je regarde pour l’ajout du second bouton, un copier collé ne va pas forcement fonctionner.
L’idée de couper la matrice est top MAIS (y a toujours un mais :D) il serait intéressent d’aller encore plus loin et de pouvoir afficher en permanence la température issu de Jeedom par ex..
En gros pouvoir faire plusieurs configuration avec un bouton qui te permet de sélectionner
. heure centrée
. heure à gauche – température à droite
. Nombre de mail non lu à droite – Heure à gauche
. réveil à droite – heure à gauche
. Heure à droite – notif facebook à gauche
Quand on vois le code de départ et le code de maintenant y a pas photos on frôle la perfection, merci Byfeel
C’est vrai que la on serait au top si on pouvait faire cela.
J’ai modifié le bouton comme ceci moi Thyer car marchait plus non plus avec le sendtojeedomscenario :
void ToJeedomScenario( String id){
#if (JEEDOM)
String url;
url = BaseUrlJeedomScenario;
url +=id;
url += »&action=start »;
http.begin(url);
httpCode = http.GET();
http.end();
#endif
}
une nouvelle fonction reprise du tojeedom
et pour le bouton :
switch (clic2) {
case 1: // double clic – eteind radio
NotifMsg(« Snooze »,Intensite,true);
ToJeedomScenario(idsnooze);
clic2=0;
break;
case 2: // double clic – allume led
NotifMsg(« Led ON »,Intensite,true);
ToJeedomScenario(idLedON);
clic2=0;
break;
case 3: // …….
et ca fonctionne bien 🙂