Suite à mon précédent article ( que vous pouvez retrouver ici ) , et aux remontées d’infos de DCjona et Thyer voici une nouvelle version de cette horloge / Notification connectée.
- Correction du bug OTA
- Ajout du support des caractères étendus
- Ajout d’un bouton et gestion des clics.
- Quelques nouveautés
Mise en jour en 2.34 ( gestion luminosité et divers correctifs ) – 04/06/2018
Cet article fait suite à une série , sur la programmation et la mise en place d’une horloge connectée à l’aide d’un WEMOS .
Je vous conseille néanmoins de lire les articles suivants, avant de commencer par celui-ci :
- Intérêt du Wemos / Specificité
- Travailler en WIFI avec WEMOS
- OTA ( ou comment mettre à jour ses modules à distance )
- DIY Horloge / Notification
Correction Bug OTA
DCjona et Thyer , m’ont indiqué tous deux , une problématique avec la partie OTA , dans mon script.
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); });
Cette partie a été mise en place dans le cas où je serais amené à flasher l’espace file system ( SPIFFS ) au lieu du sketch , cela indique simplement si la mise à jour est un sketch ou si elle se situe dans le File System.
Pour info , ci dessous une illustration de la répartition de la mémoire
|--------------|-------|---------------|--|--|--|--|--|
^ ^ ^ ^ ^
Sketch OTA update File system EEPROM WiFi config (SDK)
La taille dépend des différentes cartes existantes dans le commerce.
Carte ESP8266 | Flash chip size, bytes | File system size, bytes |
---|---|---|
Generic module | 512k | 64k |
Generic module | 1M | 64k, 128k, 256k, 512k |
Generic module | 2M | 1M |
Generic module | 4M | 3M |
Adafruit HUZZAH | 4M | 1M, 3M |
NodeMCU 0.9 | 4M | 1M, 3M |
NodeMCU 1.0 | 4M | 1M, 3M |
Olimex MOD-WIFI-ESP8266(-DEV) | 2M | 1M |
SparkFun Thing | 512k | 64k |
SweetPea ESP-210 | 4M | 1M, 3M |
WeMos D1 & D1 mini | 4M | 1M, 3M |
Il faut voir l’espace FileSystem ( SPIFFS ) comme une sorte de carte SD interne , dans laquelle il est possible de venir écrire ou lire des données qui resteraient en mémoire même après l’extinction du module.
Finalement , pour ce module , seul le sketch est mis à jour . J’ai donc simplifié cette partie ( qui bug , chez certains de mes lecteurs ) par cette version :
ArduinoOTA.onStart([]() { digitalWrite(led, HIGH); // allume led au debut du transfert P.print("Update ..."); });
Pour que la partie OTA fonctionne , il est impératif que le module soit démarré , avant de lancer l’interface IDE Arduino. Après le premier flashage ( en USB ) , redémarrer votre interface IDE , afin que le port OTA apparaisse dans la liste des ports disponibles.
[adsense]Caractères accentués et caractères spéciaux
Afin de prendre en compte , les caractéres accentués ainsi que les caractéres spéciaux , il faut ajouter le fichier suivant « Parola_Fonts_data.h » , dans le dossier de votre sketch. Ce fichier se trouve dans le dossier libraries de votre logiciel ide arduino.
arduino/libraries/MD_Parola/examples/Parola_UTF8_display
Ci dessous , le contenu du fichier :
// Data file for UTF-8 example user defined fonts #ifndef FONTS_DATA_H #define FONTS_DATA_H MD_MAX72XX::fontType_t ExtASCII[] PROGMEM = { 0, // 0 - 'Unused' 0, // 1 - 'Unused' 0, // 2 - 'Unused' 0, // 3 - 'Unused' 0, // 4 - 'Unused' 0, // 5 - 'Unused' 0, // 6 - 'Unused' 0, // 7 - 'Unused' 0, // 8 - 'Unused' 0, // 9 - 'Unused' 0, // 10 - 'Unused' 0, // 11 - 'Unused' 0, // 12 - 'Unused' 0, // 13 - 'Unused' 0, // 14 - 'Unused' 0, // 15 - 'Unused' 0, // 16 - 'Unused' 0, // 17 - 'Unused' 0, // 18 - 'Unused' 0, // 19 - 'Unused' 0, // 20 - 'Unused' 0, // 21 - 'Unused' 0, // 22 - 'Unused' 0, // 23 - 'Unused' 0, // 24 - 'Unused' 0, // 25 - 'Unused' 0, // 26 - 'Unused' 0, // 27 - 'Unused' 0, // 28 - 'Unused' 0, // 29 - 'Unused' 0, // 30 - 'Unused' 0, // 31 - 'Unused' 2, 0, 0, // 32 - 'Space' 1, 95, // 33 - '!' 3, 7, 0, 7, // 34 - '"' 5, 20, 127, 20, 127, 20, // 35 - '#' 5, 36, 42, 127, 42, 18, // 36 - '$' 5, 35, 19, 8, 100, 98, // 37 - '%' 5, 54, 73, 86, 32, 80, // 38 - '&' 2, 4, 3, // 39 3, 28, 34, 65, // 40 - '(' 3, 65, 34, 28, // 41 - ')' 5, 42, 28, 127, 28, 42, // 42 - '*' 5, 8, 8, 62, 8, 8, // 43 - '+' 2, 128, 96, // 44 - ',' 5, 8, 8, 8, 8, 8, // 45 - '-' 2, 96, 96, // 46 - '.' 5, 32, 16, 8, 4, 2, // 47 - '/' 5, 62, 81, 73, 69, 62, // 48 - '0' 3, 66, 127, 64, // 49 - '1' 5, 114, 73, 73, 73, 70, // 50 - '2' 5, 33, 65, 73, 77, 51, // 51 - '3' 5, 24, 20, 18, 127, 16, // 52 - '4' 5, 39, 69, 69, 69, 57, // 53 - '5' 5, 60, 74, 73, 73, 49, // 54 - '6' 5, 65, 33, 17, 9, 7, // 55 - '7' 5, 54, 73, 73, 73, 54, // 56 - '8' 5, 70, 73, 73, 41, 30, // 57 - '9' 1, 20, // 58 - ':' 2, 128, 104, // 59 - ';' 4, 8, 20, 34, 65, // 60 - '<' 5, 20, 20, 20, 20, 20, // 61 - '=' 4, 65, 34, 20, 8, // 62 - '>' 5, 2, 1, 89, 9, 6, // 63 - '?' 5, 62, 65, 93, 89, 78, // 64 - '@' 5, 124, 18, 17, 18, 124, // 65 - 'A' 5, 127, 73, 73, 73, 54, // 66 - 'B' 5, 62, 65, 65, 65, 34, // 67 - 'C' 5, 127, 65, 65, 65, 62, // 68 - 'D' 5, 127, 73, 73, 73, 65, // 69 - 'E' 5, 127, 9, 9, 9, 1, // 70 - 'F' 5, 62, 65, 65, 81, 115, // 71 - 'G' 5, 127, 8, 8, 8, 127, // 72 - 'H' 3, 65, 127, 65, // 73 - 'I' 5, 32, 64, 65, 63, 1, // 74 - 'J' 5, 127, 8, 20, 34, 65, // 75 - 'K' 5, 127, 64, 64, 64, 64, // 76 - 'L' 5, 127, 2, 28, 2, 127, // 77 - 'M' 5, 127, 4, 8, 16, 127, // 78 - 'N' 5, 62, 65, 65, 65, 62, // 79 - 'O' 5, 127, 9, 9, 9, 6, // 80 - 'P' 5, 62, 65, 81, 33, 94, // 81 - 'Q' 5, 127, 9, 25, 41, 70, // 82 - 'R' 5, 38, 73, 73, 73, 50, // 83 - 'S' 5, 3, 1, 127, 1, 3, // 84 - 'T' 5, 63, 64, 64, 64, 63, // 85 - 'U' 5, 31, 32, 64, 32, 31, // 86 - 'V' 5, 63, 64, 56, 64, 63, // 87 - 'W' 5, 99, 20, 8, 20, 99, // 88 - 'X' 5, 3, 4, 120, 4, 3, // 89 - 'Y' 5, 97, 89, 73, 77, 67, // 90 - 'Z' 3, 127, 65, 65, // 91 - '[' 5, 2, 4, 8, 16, 32, // 92 - '\' 3, 65, 65, 127, // 93 - ']' 5, 4, 2, 1, 2, 4, // 94 - '^' 5, 64, 64, 64, 64, 64, // 95 - '_' 2, 3, 4, // 96 - '`' 5, 32, 84, 84, 120, 64, // 97 - 'a' 5, 127, 40, 68, 68, 56, // 98 - 'b' 5, 56, 68, 68, 68, 40, // 99 - 'c' 5, 56, 68, 68, 40, 127, // 100 - 'd' 5, 56, 84, 84, 84, 24, // 101 - 'e' 4, 8, 126, 9, 2, // 102 - 'f' 5, 24, 164, 164, 156, 120, // 103 - 'g' 5, 127, 8, 4, 4, 120, // 104 - 'h' 3, 68, 125, 64, // 105 - 'i' 4, 64, 128, 128, 122, // 106 - 'j' 4, 127, 16, 40, 68, // 107 - 'k' 3, 65, 127, 64, // 108 - 'l' 5, 124, 4, 120, 4, 120, // 109 - 'm' 5, 124, 8, 4, 4, 120, // 110 - 'n' 5, 56, 68, 68, 68, 56, // 111 - 'o' 5, 252, 24, 36, 36, 24, // 112 - 'p' 5, 24, 36, 36, 24, 252, // 113 - 'q' 5, 124, 8, 4, 4, 8, // 114 - 'r' 5, 72, 84, 84, 84, 36, // 115 - 's' 4, 4, 63, 68, 36, // 116 - 't' 5, 60, 64, 64, 32, 124, // 117 - 'u' 5, 28, 32, 64, 32, 28, // 118 - 'v' 5, 60, 64, 48, 64, 60, // 119 - 'w' 5, 68, 40, 16, 40, 68, // 120 - 'x' 5, 76, 144, 144, 144, 124, // 121 - 'y' 5, 68, 100, 84, 76, 68, // 122 - 'z' 3, 8, 54, 65, // 123 - '{' 1, 119, // 124 - '|' 3, 65, 54, 8, // 125 - '}' 5, 2, 1, 2, 4, 2, // 126 - '~' 0, // 127 - 'Unused' 6, 20, 62, 85, 85, 65, 34, // 128 - 'Euro sign' 0, // 129 - 'Not used' 2, 128, 96, // 130 - 'Single low 9 quotation mark' 5, 192, 136, 126, 9, 3, // 131 - 'f with hook' 4, 128, 96, 128, 96, // 132 - 'Single low 9 quotation mark' 8, 96, 96, 0, 96, 96, 0, 96, 96, // 133 - 'Horizontal ellipsis' 3, 4, 126, 4, // 134 - 'Dagger' 3, 20, 126, 20, // 135 - 'Double dagger' 4, 2, 1, 1, 2, // 136 - 'Modifier circumflex' 7, 35, 19, 104, 100, 2, 97, 96, // 137 - 'Per mille sign' 5, 72, 85, 86, 85, 36, // 138 - 'S with caron' 3, 8, 20, 34, // 139 - '< quotation' 6, 62, 65, 65, 127, 73, 73, // 140 - 'OE' 0, // 141 - 'Not used' 5, 68, 101, 86, 77, 68, // 142 - 'z with caron' 0, // 143 - 'Not used' 0, // 144 - 'Not used' 2, 3, 4, // 145 - 'Left single quote mark' 2, 4, 3, // 146 - 'Right single quote mark' 4, 3, 4, 3, 4, // 147 - 'Left double quote marks' 4, 4, 3, 4, 3, // 148 - 'Right double quote marks' 4, 0, 24, 60, 24, // 149 - 'Bullet Point' 3, 8, 8, 8, // 150 - 'En dash' 5, 8, 8, 8, 8, 8, // 151 - 'Em dash' 4, 2, 1, 2, 1, // 152 - 'Small ~' 7, 1, 15, 1, 0, 15, 2, 15, // 153 - 'TM' 5, 72, 85, 86, 85, 36, // 154 - 's with caron' 3, 34, 20, 8, // 155 - '> quotation' 7, 56, 68, 68, 124, 84, 84, 8, // 156 - 'oe' 0, // 157 - 'Not used' 5, 68, 101, 86, 77, 68, // 158 - 'z with caron' 5, 12, 17, 96, 17, 12, // 159 - 'Y diaresis' 2, 0, 0, // 160 - 'Non-breaking space' 1, 125, // 161 - 'Inverted !' 5, 60, 36, 126, 36, 36, // 162 - 'Cent sign' 5, 72, 126, 73, 65, 102, // 163 - 'Pound sign' 5, 34, 28, 20, 28, 34, // 164 - 'Currency sign' 5, 43, 47, 252, 47, 43, // 165 - 'Yen' 1, 119, // 166 - '|' 4, 102, 137, 149, 106, // 167 - 'Section sign' 3, 1, 0, 1, // 168 - 'Spacing diaresis' 7, 62, 65, 93, 85, 85, 65, 62, // 169 - 'Copyright' 3, 13, 13, 15, // 170 - 'Feminine Ordinal Ind.' 5, 8, 20, 42, 20, 34, // 171 - '<<' 5, 8, 8, 8, 8, 56, // 172 - 'Not sign' 0, // 173 - 'Soft Hyphen' 7, 62, 65, 127, 75, 117, 65, 62, // 174 - 'Registered Trademark' 5, 1, 1, 1, 1, 1, // 175 - 'Spacing Macron Overline' 3, 2, 5, 2, // 176 - 'Degree' 5, 68, 68, 95, 68, 68, // 177 - '+/-' 3, 25, 21, 19, // 178 - 'Superscript 2' 3, 17, 21, 31, // 179 - 'Superscript 3' 2, 2, 1, // 180 - 'Acute accent' 4, 252, 64, 64, 60, // 181 - 'micro (mu)' 5, 6, 9, 127, 1, 127, // 182 - 'Paragraph Mark' 2, 24, 24, // 183 - 'Middle Dot' 3, 128, 128, 96, // 184 - 'Spacing sedilla' 2, 2, 31, // 185 - 'Superscript 1' 4, 6, 9, 9, 6, // 186 - 'Masculine Ordinal Ind.' 5, 34, 20, 42, 20, 8, // 187 - '>>' 6, 64, 47, 16, 40, 52, 250, // 188 - '1/4' 6, 64, 47, 16, 200, 172, 186, // 189 - '1/2' 6, 85, 53, 31, 40, 52, 250, // 190 - '3/4' 5, 48, 72, 77, 64, 32, // 191 - 'Inverted ?' 5, 120, 20, 21, 22, 120, // 192 - 'A grave' 5, 120, 22, 21, 20, 120, // 193 - 'A acute' 5, 122, 21, 21, 21, 122, // 194 - 'A circumflex' 5, 120, 22, 21, 22, 121, // 195 - 'A tilde' 5, 120, 21, 20, 21, 120, // 196 - 'A diaresis' 5, 120, 20, 21, 20, 120, // 197 - 'A ring above' 6, 124, 10, 9, 127, 73, 73, // 198 - 'AE' 5, 30, 161, 161, 97, 18, // 199 - 'C sedilla' 4, 124, 85, 86, 68, // 200 - 'E grave' 4, 124, 86, 85, 68, // 201 - 'E acute' 4, 126, 85, 85, 70, // 202 - 'E circumflex' 4, 124, 85, 84, 69, // 203 - 'E diaresis' 3, 68, 125, 70, // 204 - 'I grave' 3, 68, 126, 69, // 205 - 'I acute' 3, 70, 125, 70, // 206 - 'I circumplex' 3, 69, 124, 69, // 207 - 'I diaresis' 6, 4, 127, 69, 65, 65, 62, // 208 - 'Capital Eth' 5, 124, 10, 17, 34, 125, // 209 - 'N tilde' 5, 56, 68, 69, 70, 56, // 210 - 'O grave' 5, 56, 70, 69, 68, 56, // 211 - 'O acute' 5, 58, 69, 69, 69, 58, // 212 - 'O circumflex' 5, 56, 70, 69, 70, 57, // 213 - 'O tilde' 5, 56, 69, 68, 69, 56, // 214 - 'O diaresis' 5, 34, 20, 8, 20, 34, // 215 - 'Multiplication sign' 7, 64, 62, 81, 73, 69, 62, 1, // 216 - 'O slashed' 5, 60, 65, 66, 64, 60, // 217 - 'U grave' 5, 60, 64, 66, 65, 60, // 218 - 'U acute' 5, 58, 65, 65, 65, 58, // 219 - 'U circumflex' 5, 60, 65, 64, 65, 60, // 220 - 'U diaresis' 5, 12, 16, 98, 17, 12, // 221 - 'Y acute' 4, 127, 18, 18, 12, // 222 - 'Capital thorn' 4, 254, 37, 37, 26, // 223 - 'Small letter sharp S' 5, 32, 84, 85, 122, 64, // 224 - 'a grave' 5, 32, 84, 86, 121, 64, // 225 - 'a acute' 5, 34, 85, 85, 121, 66, // 226 - 'a circumflex' 5, 32, 86, 85, 122, 65, // 227 - 'a tilde' 5, 32, 85, 84, 121, 64, // 228 - 'a diaresis' 5, 32, 84, 85, 120, 64, // 229 - 'a ring above' 7, 32, 84, 84, 124, 84, 84, 8, // 230 - 'ae' 5, 24, 36, 164, 228, 40, // 231 - 'c sedilla' 5, 56, 84, 85, 86, 88, // 232 - 'e grave' 5, 56, 84, 86, 85, 88, // 233 - 'e acute' 5, 58, 85, 85, 85, 90, // 234 - 'e circumflex' 5, 56, 85, 84, 85, 88, // 235 - 'e diaresis' 3, 68, 125, 66, // 236 - 'i grave' 3, 68, 126, 65, // 237 - 'i acute' 3, 70, 125, 66, // 238 - 'i circumflex' 3, 69, 124, 65, // 239 - 'i diaresis' 4, 48, 75, 74, 61, // 240 - 'Small eth' 4, 122, 9, 10, 113, // 241 - 'n tilde' 5, 56, 68, 69, 70, 56, // 242 - 'o grave' 5, 56, 70, 69, 68, 56, // 243 - 'o acute' 5, 58, 69, 69, 69, 58, // 244 - 'o circumflex' 5, 56, 70, 69, 70, 57, // 245 - 'o tilde' 5, 56, 69, 68, 69, 56, // 246 - 'o diaresis' 5, 8, 8, 42, 8, 8, // 247 - 'Division sign' 6, 64, 56, 84, 76, 68, 58, // 248 - 'o slashed' 5, 60, 65, 66, 32, 124, // 249 - 'u grave' 5, 60, 64, 66, 33, 124, // 250 - 'u acute' 5, 58, 65, 65, 33, 122, // 251 - 'u circumflex' 5, 60, 65, 64, 33, 124, // 252 - 'u diaresis' 4, 156, 162, 161, 124, // 253 - 'y acute' 4, 252, 72, 72, 48, // 254 - 'small thorn' 4, 157, 160, 160, 125, // 255 - 'y diaresis' }; #endif
Ce fichier définit , tous les caractères Ascii Etendu.
Une fois ce fichier copié , il suffira de l’inclure dans notre sketch :
#include « Parola_Fonts_data.h »
Puis, on ajoute ces deux fonctions avant la fonction setup()
.... ... //***************************************** // UTF8 - Ascii etendu //***************************************** uint8_t utf8Ascii(uint8_t ascii) // Convertit un caractere UTF8 en caractére etendu ASCII selon la norme // ISO 8859-1 , aussi appellé ISO Latin-1 // Codes 128-159 contient les codes Microsoft Windows Latin-1 // // - codes 0..127 sont identiques entre ASCII et 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. // 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 } //***************************************** ....
Plus de détails , sur les codes ASCCI , à cette adresse ( table ASCII ).
Enfin dans la partie Setup() , j’ enregistrer en mémoire la nouvelle table ASCII étendue .
..... .. void setup() { //demarrage Display P.begin(); P.setFont(ExtASCII); // Chargement table ASCII Etendu ..... ....
J’ ajoute aussi , dans la définition de la page WEB du module ( en fin de script ) , que je travaille sur une table étendue de type Latin.
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’/> »;
Par l’ajout de la balise meta charset=iso-8859-15.
En testant depuis l’interface WEB du module , avec la phrase suivante :
« ça fonctionne avec les é et même les degrés : 23°C »
Je remarque que dans la page suivante l’url du site WEB a été modifié avec les bons codes :
msg=%E7a+fonctionne+avec+les+%E9+et+m%EAme+les+degr%E9s+%3A+23%B0C
Et surtout que l’affichage led indique bien : ça fonctionne avec les é et même les degrés : 23°C
Super, mais je viens d’essayer sous jeedom et cela ne fonctionne pas ? Tous mes caractères accentués ne sont pas affichés.
Le problème , c’est que lors de l’envoi de la requête http via le module Script de jeedom , cette dernière est codée en UTF8.
Il va falloir passer par un script , qui sera en charge de convertir l’UTF8 en ISO 8859.
Pour cela , dans le module Script de jeedom , nous allons créer une commande de type Script .
Dans le champs requête , cliquer sur nouveau, choisir un nom de fichier par exemple : notifhorloge.php
Puis, dans la fenêtre qui s’ouvre copier le script suivant :
Modification du SCRIPT : Ajout gestion luminosité et options
<?php $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 www.example.com avec le protocole HTTP */ $url="http://".$IP."/Notification?msg=".$notif."&type=".$type."&intnotif=".$lum; $httpfile = file_get_contents($url); ?>
Ce script , permet de récupérer trois arguments passés en ligne de commande :
Modification : gestion luminosité ( 04/06/18 )
L’adresse IP du module , le Message et l’info Titre , qui réunit les différentes options : une info type ( qui permet des petits effets sur les notifications envoyées ) et une info lum , pour la valeur de la luminosité.
Le champ message est dans un premier temps decodés de l’utf8 ( utf8_decode ) , puis encodés dans un format url afin d’encapsuler les caractères qui peuvent poser soucis ( avec urlencode ).
Le champ titre est découpé en fonction des séparateurs ( ; , : -.) , dans un tableau Option , qui est ensuite traitée pour récuperer les bonnes valeurs à transmettre à votre horloge.
Le champ titre peut être de la forme suivante :
type=PAC,lum=15 ( animation PacMan avec intensité au max )
lum = 9 ; type=OPENING ( animation Opening avec intensité à 9 )
L’ordre des options dans le champ titre n’a pas d’importance . Les options
peuvent être ignorées ( le champ titre vide = notification avec luminosité par défaut )
Afin de passer les paramètres aux script PHP , dans le champs requête à la suite de notre fichier script , nous indiquons les champs suivants :
adresse_ip « #message# » « #title# » , ou adresse_ip est l’adresse de votre module.
Une fois votre commande créée , il ne vous reste plus qu’à sauvegarder le tout et à tester votre nouvel équipement.
[adsense]Pour aller plus loin , avec Jeedom , je vais expliquer comment envoyer une requête de type POST sous jeedom , afin de pouvoir activer depuis l’interface de notre box domotique , toutes les configurations que permet l’interface WEB du module.
Voici , à quoi peut ressembler l’équipement au complet sous JEEDOM.
Pour créer les commandes , permettant d’afficher ou non l’horloge , les secondes ou encore régler manuellement l’intensité, il suffit de créer une nouvelle commande qui sera basée sur un nouveau script php.
- Commencer par ajouter une nouvelle commande
- Donner par exemple un nom : Horloge OFF
- Type de script : script
- Nouveau , donner un nom à son script , par exemple SetupHorloge.php
- Puis coller ce script
<?php $IP=$argv[1]; $commande=urlencode(utf8_decode($argv[2])); $etat=urlencode(utf8_decode($argv[3])); $url = 'http://'.$IP; if ($commande =="INT") $data = array("LUM" => "manu" , $commande => $etat); else $data = array($commande => $etat); // use key 'http' even if you send the request to https://... $options = array( 'http' => array( 'header' => "Content-type: application/x-www-form-urlencoded\r\n", 'method' => 'POST', 'content' => http_build_query($data), ), ); $context = stream_context_create($options); $result = file_get_contents($url, false, $context); //var_dump($result); ?>
Comme sur le script précédent , il nous servira à appeler les différentes commandes passées en argument. IP_du_Module Commande Etat
exemple : /var/www/html/core/php/../../plugins/script/core/ressources/SetupHorloge.php 192.168.80.156 HOR off
Ce qui aura pour effet d’éteindre l’affichage de l’horloge.
Ici notre module a l’adresse IP : 192.168.80.156 , la commande est HOR ( pour Horloge ) et les deux états sont on ou off .
Les différentes commandes implantées sont :
HOR : ( on ou off ) pour afficher ou non l’horloge
SEC : ( on ou off ) pour afficher ou non les secondes
LUM : ( auto ou manu ) pour activer ou désactiver le mode auto pour la luminosité
INT : ( une valeur de 0 à 15 ) pour le réglage de la luminosité ( dans la commande j’ai utilisé le slider et indiqué #slider# pour état.
Un bouton pour tout commander
Il y a plusieurs façons d’installer un bouton sur un module WEMOS . Plutôt que de reprendre , ce qui existe déjà sur de nombreux autres sites , qui explique les différences entre un montage pull up , pull down , je vous invite à aller sur le site d’open classroom où est rédigé un article qui explique très bien tout cela .
Sur les modules Arduino , comme les Wemos , il existe des entrées Logique qui intègrent des résistances de type pull up .
Pour les activer nous disposons de la variable INPUT_PULLUP.
J’ai donc installé mon poussoir , entre le GND et la broche D8 de mon WEMOS D1 R1. Pourquoi la D8 , parce que celle-ci intègre une résistance de 10 K pullup ( voir article sur WEMOS ) . Si vous utilisez la version R2 , prenez la sortie D3.
Ces deux sorties correspondent à la GPIO0 .
On ajoute la constante bouton au programme :
const int bouton = 0; // GPIO0 ( pullup integré – D8 pour R1 ou D3 pour R2 )
Plutôt que de déclarer la fonction : pinMode(bouton,INPUT_PULLUP); je préfère utiliser la bibliothèque clickbutton de marco Brianza, qui permet de gérer très facilement les clicks , double click , triple click et même les appuis longs.
Vous pouvez récupérer cette bibliothèque sur le Github de marco Brianza .
Cette bibliothèque , permet de paramètrer les problèmes dus au rebond ( bounce ) et de renvoyer une valeur en fonction des différentes actions sur le bouton poussoir .
1 clic rapide = 1 , 2 clic rapide = 2 , 3 clic rapide = 3 , etc ……
1 clic long = -1 , 1 clic rapide suivi d’un clic long = -2 , 2 clic rapide suivi d’un clic long = -3 et ainsi de suite.
Une fois téléchargé , il suffit de copier le dossier décompressé « clickbutton-master » dans le dossier libraries de l’interface Arduino.
Il faudra donc inclure cette librairie , puis initier une instance Clickbutton .
Ce qui donne dans le script :
....... ..... ..... //librairies click bouton #include <ClickButton.h> ........ ....... const int bouton = 0; // GPIO0 ( pullup integré - D8 pour R1 ou D3 pour R2 ) ClickButton boutonClick(bouton, LOW, CLICKBTN_PULLUP); // GPIO , mode pressé du bouton ( haut ou bas ) ici bas quand on appuie sur le bouton ( la broche est mise a la masse ) , mode pullup activé ) ........... int clic=0; ..... ..... void setup() { .... // Setting click button : Setup button timers (all in milliseconds / ms) // (These are default if not set, but changeable for convenience) boutonClick.debounceTime = 20; // Debounce timer in ms boutonClick.multiclickTime = 250; // Time limit for multi clicks boutonClick.longClickTime = 1000; // time until "held-down clicks" register } void loop() { // etat bouton boutonClick.Update(); // Mise a jour du bouton , et récupère la nouvelle valeur if (boutonClick.clicks != 0) clic = boutonClick.clicks; // stockage de la valeur dans la variable clic ............. // traitement du clic en fonction de ce que l'on va definir switch (clic) { case 1: // Simple clic ....... ......
Dans mon script , voici les actions que j’ai choisis :
1 clic rapide ( valeur 1 ) : Une boucle de 3 états est mis en place qui permet de passer à tour de rôle de : Auto / mode manuel avec Intensité mini / Mode manuel avec Intensité Max , puis on reboucle.
2 clic rapide ( valeur 2 ) : ON / OFF Ecran horloge
3 clic rapide ( valeur 3 ) : ON / OFF Affichage des secondes
……
1 clic long ( valeur -1 ) : diminue luminosité d’un cran
1 clic rapide + 1 clic long ( valeur -2 ) : Augmentation luminosité d’un cran
j’ai essayé avec 4 clics et 5 clics , mais cela devient vite compliqué. Il vaut mieux rester raisonnable et ne pas dépasser 3 clics.
Maintenant , la bibliothèque est capable de gérer autant de clic que vous voulez , il faudra sûrement ajuster les valeurs par défaut afin que le comptage s’adapte à votre rapidité ( par exemple le timelimit pour les multiples click qui est par défaut de 0,25s entre chaque clic)
Dans ce cas là , dans la partie setup() , vous pouvez modifier ces trois valeurs :
// Setup button timers (all in milliseconds / ms) // (These are default if not set, but changeable for convenience) button1.debounceTime = 20; // Debounce timer in ms button1.multiclickTime = 250; // Time limit for multi clicks button1.longClickTime = 1000; // time until "held-down clicks" register
Ce qui donne pour le paramètrage de la fonction switch :
............ #if (ACTIVBOUTON) // etat bouton boutonClick.Update(); // Sauvegarde de la valeur dans la variable click if (boutonClick.clicks != 0) clic = boutonClick.clicks; switch (clic) { case 1: // Simple clic - boucle : Manuel intensite à 0 / Manu Intensite MAX / Auto if (clicstate==1) { AutoIn=false; Intensite = 0; P.print("Min"); } if (clicstate==2) { Intensite = 15; P.print("Max"); } if (clicstate==3) { AutoIn=true; P.print("Auto"); clicstate=0; } ++clicstate; delay(400); clic=0; break; case 2: // double clic - ON / OFF horloge TimeOn =!TimeOn; if (TimeOn) P.print("Time On"); else P.print("Time Off"); delay(400); clic=0; break; case 3: // double clic - Affiche ou non les secondes DisSec =!DisSec; clic=0; break; case -1: // simple clic mais long sur dernier - diminue --Intensite; if (Intensite<0) Intensite=0; P.print(Intensite); delay(400); clic=0; break; case -2: // double clic mais long sur dernier - Augmente ++Intensite; if (Intensite>15) Intensite=MAX_INTENSITY; P.print(Intensite); delay(400); clic=0; break; default: // default is optional break; } #endif
Par exemple , dans le cas du double click ( valeur : 2 ) , je réalise une bascule sur la variable TimeOn , qui passe de true à false , lors de chaque double clic grâce à la ligne : TimeOn =!TimeOn;
Puis, j’affiche une info à l’écran pour informer que la commande a bien été prise en compte. Avec un petit delay , afin d’avoir le temps de lire l’info.
Puis on remet la valeur de clic à zero.
Il est donc très facile , de pouvoir attribuer une action , en fonction de vos envies , il suffira pour cela de modifier chaque cas.
Si vous avez des idées de configuration plus pratique , je suis preneur. Pour l’instant , je ne me sers pas du bouton dans mon quotidien , donc je ne suis pas en mesure de dire quel est le mode le plus utilisé.
Quelques Nouveautés :
Script plus structuré :
Avant de vous livrer le script final , j’ai aéré le code , et mis un peu plus de commentaires , afin qu’il soit facilement modifiable , si vous désirez y apporter des modifs.
En entête du script , j’ai placé 5 variables à modifier si besoin , avant la compilation du sketch.
#define NOMMODULE « ESP-Horloge_testV2 » // nom module
#define NTPSERVER « pool.ntp.org » // Serveur NTP
#define ACTIVBOUTON true // Si bouton installé
#define ACTIVCAPTLUM true // Si capteur luminosité installé
#define BUF_SIZE 60 // Taille max des notification ( nb de caractéres max )
Option reboot :
J’ai ajouté une fonction depuis l’interface WEB , permettant de redémarrer le module à distance.
Options :
J’ai ajouté aussi , l’option « type » , lors de l’envoi d’une notification qui permet de choisir un effet avant de diffuser votre notification.
L’idée m’est venue de l’horloge installé e, dans la salle de jeux , qui me permet de notifier les enfants lors des heures de repas par exemple.
J’ai pu constater qu’il ne faisait pas toujours attention à la notification , j’ai donc décidé de mettre en place une petite animation , afin que leur attention soit fixée sur l’horloge.
J’ai donc intégré une animation avec PacMan qui passe , puis repasse poursuive par un fantôme. Pour la déclencher , il suffit d’indiquer l’option « PAC » dans le champ titre.
Ci-dessous le code pour l’animation PacMan
..... // ***************************** // 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, }; void setup { ......... P.setSpriteData(pacman1, W_PMAN1, F_PMAN1,pacman2, W_PMAN2, F_PMAN2); // chargement animation en memoire .......... } void loop { .......... // Gestion Affichage if (P.displayAnimate()) { // Si une demande de notification est arrivée if (Alert) { // Type de demande if (type=="PAC" ) { // animation PAC MAn P.displayText("Notif", PA_LEFT, 40, 1, PA_SPRITE, PA_SPRITE); // affiche l'animation PacMan type=""; } else if (type=="BLINDS" ) { // animation de type volet P.displayText("", PA_CENTER, 40, 1, PA_BLINDS, PA_BLINDS); type=""; } else if (type=="OPENING" ) { // animation Ouverture P.displayText("Notif", PA_CENTER, 60, 100, PA_OPENING_CURSOR, PA_OPENING_CURSOR); type=""; } else { P.displayText(Notif, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT); Alert=false; } } // Sinon affichage de l'heure } ......... .....
J’en ai profité , pour ajouter deux types d’animation inclus dans les animations de la bibliothèque Parola ( BLINDS et OPENING ), très facilement modifiable , si vous désirez mettre d’autres animations.
Bref , si le champs titre a pour valeur type= (PAC , BLINDS ou OPENING) , une animation sera jouée avant la notification , pour tous les autres cas il y aura juste l’animation.
Modification : 04/06/18
J’ai ajouté l’option luminosité ( Merci à Thyer ) , qui permet de jouer sur la luminosité de l’affichage ( valeur de 1 à 15 ).
Dans le champ titre , il suffit d’indiquer l’option : lum=6
Bien sur , il est tout a fait possible de combiner les deux en indiquant dans le champ titre : type=PAC,lum=4 par exemple.
Voila , je vous laisse vous amuser avec cette nouvelle mouture , il y a sûrement plein de modifications à apporter .
Je compte sur vos retours pour me donner des idées.
Voici le script complet :
//************************** // Hotloge / notification // OTA + Interface Web + Connecté // Mai 2018 // Byfeel // ************************* #define Ver 2.34 #define NOMMODULE "ESP-Horloge_Nom" // nom module #define NTPSERVER "fr.pool.ntp.org" // Serveur NTP #define ACTIVBOUTON true // Si bouton installé #define ACTIVCAPTLUM true // Si capteur luminosité installé #define BUF_SIZE 60 // Taille max des notification ( nb de caractéres max ) // Parametrage matrice ( Pin Arduino ou est branché la matrice ) #define MAX_DEVICES 8 // ( nombre de matr ice ) #define CLK_PIN D5 #define DATA_PIN D7 #define CS_PIN D6 // ******************************// //******** 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> #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 // ***** OTA ///includes necessaires au fonctionnement de l'OTA : #include <WiFiUdp.h> #include <ArduinoOTA.h> // **** Matrice // gestion de l'affichage matricielle #include <MD_Parola.h> #include <MD_MAX72xx.h> #include "Parola_Fonts_data.h" // **** Temps // librairie temps #include <TimeLib.h> #include <NtpClientLib.h> #if (ACTIVBOUTON) //librairies click bouton #include <ClickButton.h> #endif //************************** //**** Varaible & service *** // ************************* ESP8266WebServer server(80); // serveur WEB sur port 80 // 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 // initialisation de la matrice MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); //variable systemes char Notif[BUF_SIZE]; boolean DisSec = true; // on-off secondes boolean Alert=false; boolean AutoIn=true; // Auto / manu intensite boolean TimeOn=true; // ON - off Affichage horloge int Intensite=5; int BkIntensite; const long interval = 10000; // interval pour mesure luminosite réglé sur 5 s unsigned long previousMillis=0 ; int clic=0; int clicstate=1; String message=""; String type=""; //***************************************** // 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 if (ntpEvent == invalidAddress) P.print ("Adresse du serveur NTP invalide"); } else { if ( year() != 1970 or year() != 2036 ) { NTP.setInterval (1200); } } } // ************************************** #if (ACTIVCAPTLUM) // 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; } #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" ) { AutoIn=false; Intensite=server.arg("INT").toInt(); } else if ( LUM == "auto") { AutoIn=true;} if ( HOR =="off" ) { TimeOn=false; } else if ( HOR =="on") TimeOn=true; if ( SEC == "on" ) { DisSec=true; server.send ( 200, "text/html", getPage() ); } else if ( SEC == "off" ) { DisSec=false; server.send ( 200, "text/html", getPage() ); } else { server.send ( 200, "text/html", getPage() ); } if ( server.arg("RAZ") =="1" ) { P.print("reboot"); delay(3000); ESP.reset(); } } // ***************************** // 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, }; //*********************** //*********************** // Boucle SETUP // ********************* void setup() { //demarrage Display P.begin(); P.setFont(ExtASCII); // chargement caractere etendue P.setSpriteData(pacman1, W_PMAN1, F_PMAN1,pacman2, W_PMAN2, F_PMAN2); // chargement animation en memoire //******** 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 ************ //******* 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.print("Update ..."); }); 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 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(NOMMODULE); P.print("Ready ..."); delay(400); P.print(""); //************************* // 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")) { BkIntensite=Intensite; message=server.arg("msg"); if (message ) { message.toCharArray(Notif,BUF_SIZE); if (server.hasArg("intnotif") && server.arg("intnotif").length() > 0 ) { Intensite = server.arg("intnotif").toInt(); if (Intensite < 1 ) Intensite = 0 ; if (Intensite > 14 ) Intensite = MAX_INTENSITY; P.setIntensity(Intensite); // intensité pour les notifs si pas de valeur Intensité par defaut } if (server.arg("type")) { type=server.arg("type"); } Alert=true; P.print(""); // on repond au client server.send(200, "text/plain", "message :" + message + " & Animation : "+server.arg("type") + " & Intensite : "+server.arg("intnotif")); } } }); // 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); // Parametrage led interne pour indiquer fin de demmarrage pinMode(led, OUTPUT); // Initialise la broche "led" comme une sortie digitalWrite(led, LOW); #if (ACTIVBOUTON) // Setting click button : Setup button timers (all in milliseconds / ms) // (These are default if not set, but changeable for convenience) boutonClick.debounceTime = 20; // Debounce timer in ms boutonClick.multiclickTime = 250; // Time limit for multi clicks boutonClick.longClickTime = 1000; // time until "held-down clicks" register #endif message = " Systeme OK - Adresse ip de votre Module : "; message += WiFi.localIP().toString(); message.toCharArray(Notif,BUF_SIZE); Alert=true; } // ********* fin SETUP // ********** Boucle loop ******* void loop() { // *********** Gestion bouton #if (ACTIVBOUTON) // etat bouton boutonClick.Update(); // Sauvegarde de la valeur dans la variable click if (boutonClick.clicks != 0) clic = boutonClick.clicks; switch (clic) { case 1: // Simple clic - boucle : Manuel intensite à 0 / Manu Intensite MAX / Auto if (clicstate==1) { AutoIn=false; Intensite = 0; P.print("Min"); } if (clicstate==2) { Intensite = 15; P.print("Max"); } if (clicstate==3) { AutoIn=true; P.print("Auto"); clicstate=0; } ++clicstate; delay(400); clic=0; break; case 2: // double clic - ON / OFF horloge TimeOn =!TimeOn; if (TimeOn) P.print("On"); else P.print("Off"); delay(400); clic=0; break; case 3: // double clic - Affiche ou non les secondes DisSec =!DisSec; clic=0; break; case -1: // simple clic mais long sur dernier - diminue --Intensite; if (Intensite<0) Intensite=0; P.print(Intensite); delay(400); clic=0; break; case -2: // double clic mais long sur dernier - Augmente ++Intensite; if (Intensite>15) Intensite=MAX_INTENSITY; P.print(Intensite); delay(400); clic=0; break; default: // default is optional break; } #endif // ******** Fin gestion bouton // ******** Gestion luminosite #if (ACTIVCAPTLUM) // Si gestion Auto luminositée activé if (AutoIn) { if( millis() - previousMillis >= interval) { previousMillis = millis(); luminosite(); } } #endif // ********** Fin gestion luminosite // ********* 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 // Gestion Affichage if (P.displayAnimate()) { // Si une demande de notification est arrivée if (Alert) { // Type de demande if (type=="PAC" ) { // animation PAC MAn P.displayText("Notif", PA_LEFT, 40, 1, PA_SPRITE, PA_SPRITE); type=""; } else if (type=="BLINDS" ) { // animation de type volet P.displayText("", PA_CENTER, 40, 1, PA_BLINDS, PA_BLINDS); type=""; } else if (type=="OPENING" ) { // animation Ouverture P.displayText("Notif", PA_CENTER, 60, 100, PA_OPENING_CURSOR, PA_OPENING_CURSOR); type=""; } else { P.displayText(Notif, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT); Alert=false; Intensite=BkIntensite; } } // Sinon affichage de l'heure else { // Affichage heure if (TimeOn) { P.setIntensity(Intensite); digitalClockDisplay().toCharArray(Notif,BUF_SIZE); // P.print(clic); //Debug pour afficher valeur P.displayText(Notif, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT); } else { P.setIntensity(0); P.print("."); // Affichage d'un point si horloge etaind , peut etre remplaçé par "". Si on ne veut pas d'affichage } } } } // ********* Fin boucle // Fonction clockformat ( ajoute les zeros devant les unités ) String digitalClockDisplay() { message=printDigits(hour()); message+=":"; message+=printDigits(minute()); if ( DisSec ) { message+=":"; message+=printDigits(second()); } return message; } String printDigits(int digits) { String Digital; // Digital=":"; if (digits < 10) Digital+="0"; Digital+=digits; return Digital; } //************************************ // Page WEB Accueil // *********************************** String getPage(){ 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>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 += "<h3><span style='background-color: #398AA4; color: #ffffff; padding: 0 5px;'> Heure : "; page += printDigits(hour())+":"+printDigits(minute())+":"+printDigits(second()); page += " - Date : "+printDigits(day())+"/"+printDigits(month())+"/"+year()+"</span></h3>"; page += "<div class='bloc'><form action='/Notification' method='GET'>"; 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 - 60 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]
PS : Pour ceux qui ne disposent que d’un seul module de 4 led , le script est aussi fonctionnel , il suffira de modifier les lignes suivantes :
// Parametrage matrice ( Pin Arduino où est branchée la matrice )
#define MAX_DEVICES 4 // ( nombre de matrice ) au lieu de 8
#define CLK_PIN D5
#define DATA_PIN D7
#define CS_PIN D6
Il est conseillé de ne pas activer les secondes car l’afficheur ne dispose pas d’assez de place.
Les sources sont disponibles sur mon Github tout fraichement créé.
58 commentaires sur “DIY Horloge et Notification ( V2 ) – interaction avec Jeedom”
Hello c’est encore moi 🙂
j’y suis presque mais pas encore .. je reviens pour la gestion des boutons, bizarrement mon bouton sur D4 gpio 2 avec la builtin led fonctionne mais pas le D3 gpio0, je sais pas trop bien pourquoi..
Je voulais savoir pourquoi la nécessité du pullup? les autres gpio ne sont pas utilisables tels quels? sinon comment rendre une autre gpio pullup? uniquement en mettant une résistance de 10K entre D0 par exemple et le 5V?
Suis pas encore au point dans tout çà 🙂
Merci pour l’aide .. j’attends impatiemment la V2.5 avec la gestion des zones 😀
Bonjour jonathan ,
Mon bouton chez moi , est sur le GPIO 0 et cela fonctionne avec pullup intégré.
Effectivement , il y a aussi les broches GPIO 2 et 15 une résistance pull up intégré.
Pour la définition de tes boutons , je te conseille d’utiliser la référence GPIO , et pas celle de l’esp :
exemple : #define bouton 0 ( ni D3 ou D4 ) , car selon le compilateur utilisait dans l’interface arduino ( version R1 ou R2 ) , j’ai remarqué que c’est souvent la même table de translation qui est utilisé. ( D3 aura des fois comme valeur GPIO 5 ou GPIO 0 ).
Voir mon article , sur Projet DIY WEMOS ( pour les tables entre GPIO , R1 et R2 ).
Le pull up ou pull down , permet de s’assurer de la bonne valeur sur la patte du module , car sans résistance , il peut rester bloquer sur l’état haut ou bas .
Si tu utilise d’autres pattes , il est donc impératif de mettre une résistance , afin de t’assurer des retours fiables.
Pour la prochaine version ça avance bien .
J’ai modifié le script , en apportant pas mal de correctif , tout en incluant la gestion des zones . Les premiers test donnent satisfaction.
Il y a d’autres surprise , comme la mémorisation des variables , suite à une coupure secteur et une refonte de l’affichage de l’heure plus « Pro ».
Parfait je vais partir sur le 15 alors car bizarrement le 0 donne rien et testesur deux Émissions différents j’ai le même résultat. Je sais pas trop pourquoi. Tu me vends du rêve la ! Impatient de pouvoir tester ta nouvelle version. !!!!
bizarre ?
La nouvelle version arrive , je la teste depuis deux jours , tout à l’air de fonctionner ….
Je n’ai pas encore commencer le tuto qui va avec …
Il faut vraiment que je vérifie ce qui cloche avec mon pc alors car même en reprenant ta biblio j’ai des erreurs de compilation.
bon ben c’était un soucis matériel au niveau du bouton, j’ai changé le cable et la masse et tout est ok maintenant… réveil en test depuis hier soir .. ce matin il a sonné 🙂
Hello, j’avance bien sur la conception et j’attends avec impatience la livraison de mon HP, et donc je viens avec quelques doléances 😀
Petit aperçu d’ou j’en suis : http://www.youtube.com/watch?v=iM2dnL4VC18
J’aimerais donc si possible si tu le veux bien quand tu as un moment pour adapter le script car perso je sais pas si j’en suis capable.
J’ai pour le moment deux wemos et donc j’envisage deux boutons, peut on envisager plusieurs autre boutons pour des actions via http ( exemple allumer mes leds) car je vois que sur mon wemos d1 mini il semble y avoir plusieurs GPIO avec une résistance de 10K pull up, donc on pourrait les exploiter de la même façon que celui expliquer ici?
Je souhaiterai au total 3-4 boutons avec chacun clic rapide , lent et double soit au total 9 à 12 actions possibles…
Merci d’avance,
PS : Si Thyer peut détaillé l’action sur son bouton ca m’arrange aussi 😀
Bonjour jonathan ,
joli projet !!
Plusieurs réponses , tu pourra simplifier les deux wemos , avec un seul wemos , grâce à la gestion des Zones .
Je n’ai pas trop de dispo , ces derniers temps , mais je suis entrain de voir pour modifier le script en ajoutant la gestion des Zones . Ansi que la sauvegarde des Options en EEPROM.
Pour les boutons la seul limite , c’est le nombre d’entrée digital disponible. Le pullup interne , peut être remplacée par une résistance extérieur si plus de disponible.
Au niveau du script c’est assez simple à modifier , pour la gestion de plusieurs boutons:
dans la partie
// Bouton
#if (ACTIVBOUTON)
#define bouton 0 // GPIO0 ( pullup integré – D8 pour R1 ou D3 pour R2 )
ClickButton boutonClick(bouton, LOW, CLICKBTN_PULLUP);
#endif
ajouter une deuxième définition de bouton :
#define bouton2 2 // GPIO2 par exemple si dispo
ClickButton boutonClick2(bouton2, LOW, CLICKBTN_PULLUP);
et ainsi de suite pour un bouton3 , bouton4 …..
Puis dans la partie loop
// *********** Gestion bouton
#if (ACTIVBOUTON)
// etat bouton
boutonClick.Update();
boutonClick2.Update();
// Sauvegarde de la valeur dans la variable click
if (boutonClick.clicks != 0) clic = boutonClick.clicks;
if (boutonClick2.clicks != 0) clic2 = boutonClick2.clicks;
etc pour 3 ….
Puis faire un switch -> case en fonction de clic2 ….
Ne pas oublier de définir clic2 dans les variables systèmes au début.
byte clic=0;
byte clic2=0;
etc….
hate de voir ton projet final !!
Génial merci. Il faut que je teste pour ne laisser que deux wemos .un pour les matrices et le second pour les LEDs. Merci pour les explications je regarde à cela des dès que j’ai un peu de temps. Merci pour le boulot !
J’ai tenter de modifier les zones mais je constate bizarre des erreurs ,l’ecran reste bloqué sur WAIT comme si il ne parvenait pas à se connecter, j’ai du mal faire quelque chose mais je ne sais pas trop ou ca bloque, j’ai l’impression que dès que je défini les zone dans P.begin(2) ca bloque car si je laisse P;begin il se connecte… je ne vois pas trop le rapport car en partant sur le simple exemple dans la biblio MD_parole : hello ca passe tout seul… aurais tu une idée? je te joint un lien du fichier modifié si tu as le temps d’y jeter un oeil , sinon je patienterai pour la V2.43 😀
http://www.k-upload.fr/afficher-fichier-2018-06-23-1f8fe3f79horloge24dcj.txt.html
effectivement , la gestion des Zones n’est pas compatible avec la fonction P.print qui fait planter le module des la première itération trouvé . ( Ici P.print(‘wait’) ).
Je suis en train de revoir tout mon code , pour gérer aussi bien une Zone que plusieurs Zones , mais il y a un gros boulot de réécriture.
Des que l’on met un chiffre dans P.begin() , même 1 , cela active les Zones.
Voici donc le pourquoi du comment.. ok ben bon courage alors 🙂
Merci pour le taff en tout cas
Excellent :p
J’avais compris depuis le début l’ajout des boutons supplémentaires 😀
Le bouton de Byfeel pour gérer l’affichage est derrière la box
Le bouton pour gérer le réveil est au dessus
Un appuis lance un scénario de jeedom via son ID
Deux appuis lance un scénario de jeedom via son ID
Trois appuis… etc..
Voila une vidéo par Ex: https://www.youtube.com/watch?v=jvPOZDjPDbI
J’utilise le Tuto de Sarakha http://sarakha63-domotique.fr/synchroniser-son-reveil-avec-jeedom-et-tasker/ pour la gestion du radio réveil.
Je t’avouerais que c’est simple a mettre en oeuvre 🙂
Encore Merci Byfeel pour ton Code
Super boulot !
Excellent
https://image.noelshack.com/fichiers/2018/25/3/1529478320-35686835-10155404454801875-8689263656409497600-n.jpg
Petit aperçu du mien en cours de réalisation
Jolie DCJona
pour ma part J’ai entièrement revus le miens.
voila la bête
https://ibb.co/bB4tvT
Super travail !!
Joliii je préfère de loin cette V2 🙂 mais je vois pas le RPI ??
Effectivement il n’y est pas sur la Photo, mais il est bien dedans 🙂
Alors là je dis bravo… joli boulot.
Installé sur un Esp8266 Wiity sans (trop de problème).
J’ai du ajouter le type de mon module de led dans le paramétrage de la matrice
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
et donc
dans l’initialisation j’ai dù rajouter
MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
J’aimerais bien n’activer l’affichage qu’en présence (c’est le cas de le dire) d’un détecteur de présence… Faudrait que je me penche sur la question…
En tout cas merci
En effet depuis début juin , est sortie la nouvelle version de la bibliothèque MAX72xx ( en V3 ) . Il est indispensable , si on utilise cette version d’indiquer le type d’Hardware . Je suis en train de finaliser un article la dessus , justement .
Bien vu.
Salut,
Et il possible de rajouter un second Bouton, un peut comme un Dash Bouton ?
Le bouton envoi une requête à Jeedom qui la retourne sous forme de message, par Ex. un clic retourne la température intérieur. on peux même imaginer qu’un double clic allumer une lampe par ex.
En effet tout est imaginable . On sait aujourd’hui comment envoyer une info au module depuis jeedom et vice versa .
Donc avec un petit scenario jeedom :
Quand action sur dash button envoie notif module
Quand clic sur module , on fait tel action
etc …
Bravo pour le travail!! Marche Impec!!
Comment fait-on pour rajouter d’autres effets au niveau défilement (Entrée texte, sortie texte,vitesse,etc)?
A quel niveau faut-il faire des changements?
Merci
la partie affichage notification est géré par la ligne de code suivante :
P.displayText(Notif, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
dans la boucle loop .
Il est vrai , que pour l’instant , je suis sur des valeurs figés . Je suis en réflexion , sur les prochaines versions , d’intégrer la possibilité de modifier tout ça .
Mais , je ne voulais pas trop alourdir , le script a ce jour.
Petit aperçu de mon radio reveil
https://image.noelshack.com/fichiers/2018/23/7/1528636503-20180610-151246.jpg
https://image.noelshack.com/fichiers/2018/23/7/1528636562-20180604-174118.jpg
https://image.noelshack.com/fichiers/2018/23/7/1528636777-20180604-180118.jpg
https://image.noelshack.com/fichiers/2018/23/7/1528636805-20180604-182642.jpg
sympa la boite , il y a aussi une squeezebox dedans ?
Oui un RPi-Zero qui fait office de SB 😉
et comme haut parleur?
il est top!
tu as été trop rapide! moi j’en suis que là
https://image.noelshack.com/fichiers/2018/24/2/1528807463-img-20180612-143700.jpg
Y te manque encore l’emballage 😀
Pour le son j’ai démonté des HP de PC qui fonctionne avec une simple prise USB (son+courant), un Pi-zero avec Volumio d’installé dessus et le tour est jouer.
https://www.cdiscount.com/informatique/clavier-souris-webcam/logitech-enceintes-usb-2-0-s150/f-1070218-980000029.html
Ca manque de BASS, mais pour le réveil pas besoin de plus.
avant de faire l’emballage je dois encore finaliser le projet 🙂 ca sera en bois ca c’est sure mais après je comptais peut etre mettre un sr04 pour éteindre le reveil le matin 😀
Depuis l’ajout du Bouton avec le retour sous Jeedom, contrôler le radio réveil est facile.
EX:
1) Réveil est programmé à 7h00 avec mon téléphone
2) A 7h00 L’horloge s’affiche
3) La musique ce lance avec un petit message
4) Appuis sur le bouton 1fois (MODE SLEEP)
4.1) Lancement du scénario cotée Jeedom
4.2) Extinction de L’horloge et Mise en Pause de la Musique
5) A 7h09 L’horloge s’affiche
6) La musique reprend
7) Appuis sur le bouton 1fois (MODE REVEIL OFF)
7.1) Lancement du scénario cotée Jeedom
7.2) Extinction de la musique, Message, météo, etc..;
7.3) Passage de l’horloge en mode Auto. pour la journée.
Visu de mon Virtuel
https://image.noelshack.com/fichiers/2018/24/3/1528884763-virtuel-rv.jpg
Mhmmm il faudrait que tu ouvres un post sous jeedom pour présenter ca en détail car ca m’intéresse vraiment :;D
il faudrait que tu fasses un tuto de tout ton montage , cela pourrais intéressé d’autres lecteurs .
Moi en l’occurrence 🙂 , pour le montage a la limite ca va encore, c’est plutôt la partie jeedom et script qui m’intéresse…
Franchement génial, bravo!!!
Pour ma part, ca marche du 1er coup avec un node MCU et un module de 4 matrices.
Le seul soucis est un scintillement constant très désagréable, j’imagine due à la puissance du node MCU ou à un problème de timing.
Du coup, avec une petite modif c’est parfait :
SI heure à afficher différente de l’heure précédente ALORS affichage de la nouvelle heure SINON rien…
Il ne manque plus qu’une boite…
Super , merci de votre remontée.
Je n’ai pas eu encore l’occasion de tester les Node MCU , mais merci pour le correctif , que j’appliquerais dans les prochaines mises à jour.
je me permets de vous poster l’intégration chez moi
http://nsa39.casimages.com/img/2018/01/16/mini_180116083229776887.jpg
http://nsa39.casimages.com/img/2018/01/16/mini_180116084059643542.jpg
ça à l’air sympa …
ben c’est grace à toi car avant ton tuto je ne l’utilisais plus !
Vidéo : http://www.youtube.com/watch?v=GTpQLeofF78
Pour ma part j’ai moins de chance que Thyer 🙁
j’ai tenter de télécharger depuis ton Github et téléverser mais ca compile pas …
Voici les erreurs :
C:\Users\Jon\Documents\Arduino\horloge-et-Notification-master\Horloge_wemos_OTA_v2\Horloge_wemos_OTA_v2.ino: In function ‘void setup()’:
Horloge_wemos_OTA_v2:292: error: ‘class MD_Parola’ has no member named ‘setSpriteData’
P.setSpriteData(pacman1, W_PMAN1, F_PMAN1,pacman2, W_PMAN2, F_PMAN2); // chargement animation en memoire
^
C:\Users\Jon\Documents\Arduino\horloge-et-Notification-master\Horloge_wemos_OTA_v2\Horloge_wemos_OTA_v2.ino: In function ‘void loop()’:
Horloge_wemos_OTA_v2:530: error: ‘PA_SPRITE’ was not declared in this scope
P.displayText(« Notif », PA_LEFT, 40, 1, PA_SPRITE, PA_SPRITE);
il semblerait que ‘est la partie définissant les effets d’animations (Sprite ) , qui bloque. Peut être un problème de librairie ( version ? )
Ci joint un lien vers mon drive , pour télécharger le ZIP de ma bibliothèque complète. https://drive.google.com/file/d/1_AAZX5_u_3hSyiGkVpaEaqugf3N8dcIj/view?usp=sharing
super ca compile merciii
Nickel pour le correctif, tout fonctionne parfaitement, de mon coté.
Dans mon projet de radio reveil, je me trouve confronté à un problème au niveau des boutons, j’ai beau essayer de faire fonctionner les GPIO de mon PI-Zero mais je galère a faire ce que je veux.
Dans Jeedom chaque action est associer à une URL, est ce qu’il y a moyen dans faire quelques chose avec ton code BOUTON pour utiliser une URL en action ? j’appui une fois ça envoi l’ordre à Jeedom ?
Merci pour ton aide 😀
En effet cela doit être possible , il suffit d’envoyer une requête http depuis le module en utilisant l’API jeedom :
http://#IP_JEEDOM#/jeedom/core/api/jeeApi.php?apikey=#APIKEY#&type=variable&name=#NAME#&value=VALUE
Je vais jeter un coup d’oeil sur les bibliothèques existantes .
J’ai vus ce Tuto mais j’arrive a rien 🙁
https://projetsdiy.fr/envoyer-donnees-jeedom-api-json-http-esp8266/
je vais regarder , ça n’a pas l’air très complexe à faire …
C’est ok , pour les modifs et envoie info à jeedom.
Je corrige tout ça , pour l’apporter dans la version 2.4
Excellent, merci 🙂
!impatient de voir ton reveil Thyer! j’ai pas pu résister non plus a cette idée
Un petit aperçu
https://image.noelshack.com/fichiers/2018/23/7/1528636562-20180604-174118.jpg
https://image.noelshack.com/fichiers/2018/23/7/1528636503-20180610-151246.jpg
Suite à la remontée de Thyer , j’ai apporté quelques modifications aux script ( maintenant en version 2.32 .
Qui permet la gestion d’option à travers le champ Titre , par exemple :
lum=12 , type = PAC
Ajoute l’animation PACMAN + met la luminosité à 12.
ou encore simplement lum = 1 , pour une luminosité au plus bas.
Pensez a mettre à jour le code , et à modifier le script PHP dans jeedom .
Merci de votre soutien
Merci thyer , en effet il manque la gestion de la luminosité . Il faut que je rajoute cette fonction dans le champ titre du message.
Que dire… Merci beaucoup pour toutes les nouveautés de cette V2.
Installer et configurer hier soir (Tard) c’est passé comme une lettre à la poste :D.et sans erreur OTA.
Par contre si je peux me permettre :D, les notifs sont toutes avec une lum. à 100%, alors qu’avant on avait le choix.
Mise a part ça, du super boulot, encore merci 😉