Bonjour et bienvenue dans une autre partie de la série ESP Captive Portal.
Dans la partie d'aujourd'hui, nous élargissons notre portail captif avec un serveur de fichiers intégré par une autre application de suivi très intéressante: nous connectons une matrice 8x8 WS1812 à l'ESP32 et affichons des fichiers BMP 8x8 pixels stockés sur le serveur de fichiers! Actuellement, il y a une limitation que le fichier BMP doit être exactement 8x8 pixels pour être affiché. Tous les autres formats ou tailles ne sont pas proposés pour la sélection d'affichage. La sélection du fichier BMP à afficher se fait sur le site principal:
Tout d'abordoui nous devons ajouter un affichage matriciel 8x8 au matériel et le câbler. La structure est très simple grâce au bus monofil des LED WS2812:
*** Veuillez également noter les consignes de sécurité de notre e-book pour la mise en service de la matrice 8x8 ***
Nous téléchargeons le code étendu sur l'ESP 32:
#include <WiFi.h> #include <WiFiClient.h> #include <Serveur Web.h> #include <ESPmDNS.h> #include <SPIFFS.h> #include <Serveur DNS.h> #include <EEPROM.h> #include <FastLED.h> #define GPIO_OUT_W1TS_REG (DR_REG_GPIO_BASE + 0x0008) #define GPIO_OUT_W1TC_REG (DR_REG_GPIO_BASE + 0x000c) #define LED_PIN 17 #define COLOR_ORDER GRB #define CHIPSET WS2812 statique const octet WiFiPwdLen = 25; statique const octet APSTANAMELEN = 20; struct WiFiEEPromData { bool APSTA = vrai; // Mode point d'accès ou station - véritable mode AP bool PwDReq = faux; // PasswordRequired bool CapPortal = vrai ; // CaptivePortal activé en mode AP char APSTAName[APSTANAMELEN]; // Nom du point STATION / AP À CONNECTER, si défini char WiFiPwd[WiFiPwdLen]; // WiFiPAssword, si défini char ConfigValid[3]; // Si Config est Vaild, le tag "TK" est requis " }; struct BMPHeader // BitMapStucture { uint32_t fileSize; // uint32_t creatorBytes; // uint32_t imageOffset; // Début des données d'image "Décalage d'image: uint32_t headerSize; // uint32_t largeur; uint32_t hauteur; uint16_t avions; uint16_t profondeur; // bits par pixel uint32_t format; }; / * nom d'hôte pour mDNS. Devrait fonctionner au moins sur les fenêtres. Essayez http://esp8266.local */ const char *ESPHostname = "ESP32"; // Serveur DNS const octet DNS_PORT = 53; Serveur DNS dnsServer; // Conmmon Paramenters bool SoftAccOK = faux; // serveur web Serveur Web serveur(80); / * Paramètres réseau Soft AP * / IPAddress apIP(172, 20, 0, 1); IPAddress netMsk(255, 255, 255, 0); non signé longue currentMillis = 0; non signé longue startMillis; / ** État WLAN actuel * / court statut = WL_IDLE_STATUS; Fichier fsUploadFile; // un objet File pour stocker temporairement le fichier reçu WiFiEEPromData MyWiFiConfig; String getContentType(String nom de fichier); // convertir l'extension de fichier au type MIME bool handleFileRead(String chemin); // envoie le bon fichier au client (s'il existe) nul handleFileUpload(); // télécharger un nouveau fichier sur le SPIFFS String temp =""; octet LUMINOSITÉ = 100; // PresetBrightness // Paramètres pour LED const uint8_t kMatrixWidth = 8; const uint8_t kMatrixHeight = 8; // const bool kMatrixSerpentineLayout = false; #define NUM_LEDS (kMatrixWidth * kMatrixHeight) CRGB leds_plus_safety_pixel[ NUM_LEDS + 1]; CRGB* const leds( leds_plus_safety_pixel + 1); nul configuration() { REG_WRITE(GPIO_OUT_W1TS_REG, BIT(GPIO_NUM_16)); // Ensemble de correction d'erreurs de méditation Guru retard(1); REG_WRITE(GPIO_OUT_W1TC_REG, BIT(GPIO_NUM_16)); // Correction d'erreur de méditation Guru effacée bool ConnectSuccess = faux; bool CreateSoftAPSucc = faux; bool Système CInitFS = faux; bool CInitHTTPServer = faux; octet len; Série.commencer(9600); tout (!Série) { ; // attend que le port série se connecte. Nécessaire pour USB natif } En série.println(F("Interface série initalisée à 9600 bauds.")); FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypiqueSMD5050); FastLED.setBrightness(LUMINOSITÉ); FastLED.spectacle(); Wifi.setAutoReconnect (faux); Wifi.persistant(faux); Wifi.déconnecter(); Wifi.setHostname(ESPHostname); // Définissez le nom d'hôte DHCP attribué à la station ESP. si (loadCredentials()) // Charger les informations d'identification WLAN pour les paramètres WiFi { En série.println(F("Informations d'identification valides trouvées.")); si (MyWiFiConfig.APSTA == vrai) // Mode AP { En série.println(F("Mode point d'accès sélectionné.")); len = strlen(MyWiFiConfig.APSTAName); MyWiFiConfig.APSTAName[len+1] = '\0'; len = strlen(MyWiFiConfig.WiFiPwd); MyWiFiConfig.WiFiPwd[len+1] = '\0'; CreateSoftAPSucc = CreateWifiSoftAP(); } autre { En série.println(F("Mode Station sélectionné.")); len = strlen(MyWiFiConfig.APSTAName); MyWiFiConfig.APSTAName[len+1] = '\0'; len = strlen(MyWiFiConfig.WiFiPwd); MyWiFiConfig.WiFiPwd[len+1] = '\0'; len = ConnectWifiAP(); si ( len == 3 ) { ConnectSuccess = vrai; } autre { ConnectSuccess = faux; } } } autre { // Définir la configuration par défaut - Créer un AP En série.println(F("AUCUNE information d'identification valide n'a été trouvée.")); SetDefaultWiFiConfig (); CreateSoftAPSucc = CreateWifiSoftAP(); saveCredentials(); // Cligner retard(500); } // Initaliser le système de fichiers CInitFSSystem = InitalizeFileSystem(); si (!(CInitFSSystem)) {En série.println(F("Système de fichiers non initialisé!")); } si ((ConnectSuccess ou CreateSoftAPSucc)) { En série.impression (F("Adresse IP: ")); si (CreateSoftAPSucc) { En série.println(Wifi.softAPIP());} si (ConnectSuccess) { En série.println(Wifi.localIP());} InitalizeHTTPServer(); } autre { En série.setDebugOutput(vrai); // Sortie de débogage pour WLAN sur l'interface série. En série.println(F("Erreur: impossible de se connecter au WLAN. Définissez la configuration par défaut.")); SetDefaultWiFiConfig(); CreateSoftAPSucc = CreateWifiSoftAP(); InitalizeHTTPServer(); SetDefaultWiFiConfig(); saveCredentials(); } pour ( int je = 0; je < NUM_LEDS; je++) // Affichage LED clair { leds[je]= 0x000000; } FastLED.spectacle(); // Effacer l'affichage :) } néant InitalizeHTTPServer() { bool initok = faux; / * Configurer les pages Web: racine, pages de configuration wifi, détecteurs de portail captifs SO et non trouvés. * / serveur.sur("/", handleRoot); serveur.sur("/Wifi", handleWifi); serveur.sur("/système de fichiers", HTTP_GET,handleDisplayFS); serveur.sur("/télécharger", HTTP_POST, []() { serveur.envoyer(200, "texte simple", ""); }, handleFileUpload); // if (MyWiFiConfig.CapPortal) {server.on ("/ generate_204", handleRoot); } // Portail captif Android. Peut-être pas nécessaire. Peut être géré par le gestionnaire notFound. // if (MyWiFiConfig.CapPortal) {server.on ("/ favicon.ico", handleRoot); } // Un autre portail captif Android. Peut-être pas nécessaire. Peut être géré par le gestionnaire notFound. Vérifié sur Sony Handy // if (MyWiFiConfig.CapPortal) {server.on ("/ fwlink", handleRoot); } // Portail captif Microsoft. Peut-être pas nécessaire. Peut être géré par le gestionnaire notFound. serveur.sur("/ generate_204", handleRoot); // Portail captif Android. Peut-être pas nécessaire. Peut être géré par le gestionnaire notFound. serveur.sur("/favicon.ico", handleRoot); // Un autre portail captif Android. Peut-être pas nécessaire. Peut être géré par le gestionnaire notFound. Vérifié sur Sony Handy serveur.sur("/ fwlink", handleRoot); // Portail captif Microsoft. Peut-être pas nécessaire. Peut être géré par le gestionnaire notFound. serveur.onNotFound ( handleNotFound ); serveur.commencer(); // Démarrage du serveur Web } booléen InitalizeFileSystem() { bool initok = faux; initok = SPIFFS.commencer(); retard(200); si (!(initok)) { En série.println(F("Format SPIFFS")); SPIFFS.format(); initok = SPIFFS.commencer(); } revenir initok; } booléen CreateWifiSoftAP() { Wifi.déconnecter(); En série.impression(F("Initaliser SoftAP")); si (MyWiFiConfig.PwDReq) { SoftAccOK = Wifi.softAP(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); // Passwortlänge mindestens 8 Zeichen! } autre { SoftAccOK = Wifi.softAP(MyWiFiConfig.APSTAName); // Point d'accès SANS mot de passe // Fonction de surcharge :; WiFi.softAP (ssid, mot de passe, canal, caché) } retard(2000); // Sans tarder, j'ai vu l'adresse IP vide Wifi.softAPConfig(apIP, apIP, netMsk); si (SoftAccOK) { / * Configurez le serveur DNS redirigeant tous les domaines vers l'apIP * / Serveur dns.setErrorRhnessCode(DNSRhnessCode::Pas d'erreur); Serveur dns.début(DNS_PORT, "*", apIP); En série.println(F("réussi.")); } autre { En série.println(F("Erreur Soft AP.")); En série.println(MyWiFiConfig.APSTAName); En série.println(MyWiFiConfig.WiFiPwd); } revenir SoftAccOK; } octet ConnectWifiAP() { En série.println(F("Client Wifi initalisant.")); octet connRes = 0; octet je = 0; Wifi.déconnecter(); Wifi.softAPdisconnect(vrai); // La fonction définira le SSID et le mot de passe actuellement configurés du soft-AP sur des valeurs nulles. Le paramètre est facultatif. S'il est défini sur true, il désactivera le mode soft-AP. retard(500); Wifi.commencer(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); connRes = Wifi.waitForConnectResult(); tandis que (( connRes == 0 ) et (je != 10)) // if connRes == 0 "IDLE_STATUS - change Statius" { connRes = Wifi.waitForConnectResult(); retard(2000); je++; En série.impression(F(".")); // instruction (s) } tandis que (( connRes == 1 ) et (je != 10)) // si connRes == 1 NO_SSID_AVAILin - SSID ne peut pas être atteint { connRes = Wifi.waitForConnectResult(); retard(2000); je++; En série.impression(F(".")); // instruction (s) } si (connRes == 3 ) { Wifi.setAutoReconnect(vrai); // Définit si le module tentera de se reconnecter à un point d'accès au cas où il serait déconnecté. // Configuration du répondeur MDNS si (!MDNS.commencer(ESPHostname)) { En série.println(F("Erreur: MDNS")); } autre { MDNS.addService("http", "tcp", 80); } } tandis que (( connRes == 4 ) et (je != 10)) // si connRes == 4 Mot de passe incorrect. Cela arrive parfois avec PWD corrct { Wifi.commencer(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); connRes = Wifi.waitForConnectResult(); retard(2000); je++; En série.impression(F(".")); } si (connRes == 4 ) { En série.println(F("STA Pwd Err")); En série.println(MyWiFiConfig.APSTAName); En série.println(MyWiFiConfig.WiFiPwd); Wifi.déconnecter(); } En série.println(F("")); revenir connRes; } uint16_t read16(Fichier F) { // Les données BMP sont stockées en petit bout, comme Arduino. uint16_t résultat; ((uint8_t *)&résultat)[0] = F.lis(); // LSB ((uint8_t *)&résultat)[1] = F.lis(); // MSB revenir résultat; } uint32_t read32(Fichier F) { // Les données BMP sont stockées en petit bout, comme Arduino. uint32_t résultat; ((uint8_t *)&résultat)[0] = F.lis(); // LSB ((uint8_t *)&résultat)[1] = F.lis(); ((uint8_t *)&résultat)[2] = F.lis(); ((uint8_t *)&résultat)[3] = F.lis(); // MSB revenir résultat; } BMPHeader ReadBitmapSpecs(Chaîne nom de fichier) { Fichier fichier; BMPHeader BMPData; fichier =SPIFFS.ouvert(nom de fichier, "r"); si (!fichier) { fichier.proche(); revenir BMPData; } // Analyser l'en-tête BMP si (read16(fichier) == 0x4D42) // Signature BMP { BMPData.taille du fichier = read32(fichier); BMPData.creatorBytes = read32(fichier); BMPData.imageOffset = read32(fichier); // Début des données d'image BMPData.headerSize = read32(fichier); BMPData.largeur = read32(fichier); BMPData.la taille = read32(fichier); BMPData.Avions = read16(fichier); BMPData.profondeur = read16(fichier); // bits par pixel BMPData.format = read32(fichier); } fichier.proche(); revenir BMPData; } #définir SD_BUFFER_PIXELS 20 néant drawBitmap_SPIFFS(Chaîne nom de fichier, uint8_t X, uint8_t y) { Fichier fichier; uint8_t tampon[3 * SD_BUFFER_PIXELS]; // tampon de pixels, taille pour r, g, b bool valide = faux; // format valide à manipuler bool retourner = vrai; // le bitmap est stocké de bas en haut uint32_t pos = 0; fichier =SPIFFS.ouvert(nom de fichier, "r"); si (!fichier) { En série.impression(F("Erreur de système de fichiers")); revenir; } // Analyser l'en-tête BMP si (read16(fichier) == 0x4D42) // Signature BMP { uint32_t taille du fichier = read32(fichier); uint32_t creatorBytes = read32(fichier); uint32_t imageOffset = read32(fichier); // Début des données d'image uint32_t headerSize = read32(fichier); uint32_t largeur = read32(fichier); uint32_t la taille = read32(fichier); uint16_t Avions = read16(fichier); uint16_t profondeur = read16(fichier); // bits par pixel uint32_t format = read32(fichier); si ((Avions == 1) && (format == 0)) // non compressé est géré { En série.impression(F("Taille du fichier: ")); En série.println(taille du fichier); En série.impression(F("Décalage d'image:")); En série.println(imageOffset); En série.impression(F("Taille de l'en-tête:")); En série.println(headerSize); En série.impression(F("Peu profond: ")); En série.println(profondeur); En série.impression(F("Taille de l'image: ")); En série.impression(largeur); En série.impression('X'); En série.println(la taille); uint32_t rowSize = (largeur * profondeur / 8 + 3) & ~3; si (la taille < 0) { la taille = -la taille; retourner = faux; } uint16_t w = largeur; uint16_t h = la taille; taille_t buffidx = taille de(tampon); // force la charge du tampon pour (uint16_t rangée = 0; rangée < h; rangée++) // pour chaque ligne { si (retourner) // Bitmap est stocké de bas en haut (BMP normal) pos = imageOffset + (la taille - 1 - rangée) * rowSize; autre // Le bitmap est stocké de haut en bas pos = imageOffset + rangée * rowSize; si (fichier.position() != pos) { // Besoin de chercher? fichier.chercher(pos,SeekSet); // si le mode est SeekSet, la position est définie pour décaler les octets depuis le début. // si le mode est SeekCur, la position actuelle est déplacée par des octets décalés. // si le mode est SeekEnd, la position est définie pour décaler les octets de la fin du buffidx = taille de(tampon); // forcer le rechargement du tampon } uint8_t morceaux; pour (uint16_t col = 0; col < w; col++) // pour chaque pixel { // Il est temps de lire plus de données en pixels? si (buffidx >= taille de(tampon)) { fichier.lis(tampon, taille de(tampon)); buffidx = 0; // Mettre l'index au début } commutateur (profondeur) { Cas 1: // un bit par pixel format n / b { valide = vrai; si (0 == col % 8) { morceaux = tampon[buffidx++]; } uint16_t bw_color = morceaux & 0x80; uint16_t PixelNum = (rangée*8)+col; leds[PixelNum].rouge = bw_color; leds[PixelNum].vert = bw_color; leds[PixelNum].bleu = bw_color; morceaux <<= 1; } Pause; Cas 24: // format BMP standard { valide = vrai; uint16_t b = tampon[buffidx++]; uint16_t g = tampon[buffidx++]; uint16_t r = tampon[buffidx++]; uint16_t PixelNum = (rangée*8)+col; leds[PixelNum].rouge = r; leds[PixelNum].vert = g; leds[PixelNum].bleu = b; } Pause; } } // pixel de fin } // fin de ligne FastLED.spectacle(); // Montrer les résultats :) } } fichier.proche(); si (!(valide)) { En série.println(F("Err: BMP")); } } néant handleFileUpload() { si (serveur.uri() != "/télécharger") revenir; HTTPUpload& télécharger = serveur.télécharger(); si (télécharger.statut == UPLOAD_FILE_START) { Chaîne nom de fichier = télécharger.nom de fichier; si (télécharger.nom de fichier.longueur() > 30) { télécharger.nom de fichier = télécharger.nom de fichier.sous-chaîne(télécharger.nom de fichier.longueur() - 30, télécharger.nom de fichier.longueur()); // Dateinamen auf 30 Zeichen kürzen } En série.println("Nom FileUpload:" + télécharger.nom de fichier); si (!nom de fichier.commence avec("/")) nom de fichier = "/" + nom de fichier; fsUploadFile = SPIFFS.ouvert("/" + serveur.urlDecode(télécharger.nom de fichier), "w"); nom de fichier = Chaîne(); } autre si (télécharger.statut == UPLOAD_FILE_WRITE) { si (fsUploadFile) fsUploadFile.écrire(télécharger.buf, télécharger.la taille actuelle); } autre si (télécharger.statut == UPLOAD_FILE_END) { si (fsUploadFile) fsUploadFile.proche(); handleDisplayFS(); } } néant handleDisplayFS() { //HTML le système de fichier //Page :/filesystem temp =""; //HTML Header serveur.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); serveur.sendHeader("Pragma", "no-cache"); serveur.sendHeader("Expires", "-1"); serveur.setContentLength(CONTENT_LENGTH_UNKNOWN); //HTML Content serveur.envoie ( 200, "texte / html", temp ); temp += "<!DOCTYPE HTML><html longtemps ='de'><head><meta charset le nom ='UTF-8'><meta = viewport content ='width=device-width, initial scale=1.0, '>"; serveur.sendContent(temp); temp = ""; temp += "<style type ='text / css'><! - DIV.container {min-height : 10em em; display : table-cell; vertical-align : middle}.button {height:35px; width:90px; font-size:16px}"; serveur.sendContent(temp); temp = ""; temp += "body {background-color : powderblue;} </style><head><title>File le système Manager</title></head>"; temp += "<h2>Serial Peripheral l'interface le flash Filesystem</h2><body><left>"; serveur.sendContent(temp); temp = ""; if (serveur.args() > 0) //Des paramètres devenaient ubergeben { if (serveur.hasArg("delete")) { Chaîne FToDel = serveur.méchamment("delete"); if (SPIFFS.exists(FToDel)) { SPIFFS.remove(FToDel); temp += "Fichier" + FToDel + " successfully deleted."; } else { temp += "Fichier" + FToDel + " cannot deleted."; } serveur.sendContent(temp); temp = ""; } if (serveur.hasArg("format") et serveur.méchamment("on")) { SPIFFS.format(); temp += "Le fichier SPI le système successfully formatted."; serveur.sendContent(temp); temp = ""; } //server.client ().stop ();//l'arrêt is needed because we sent no content length } temp += "<table border=2 bgcolor = white width = 400 ><td><h4>Current SPIFFS Status : </h4>"; temp += octets de format(SPIFFS.usedBytes() * 1.05) + "of" + octets de format(SPIFFS.octets totaux()) + " used. <br>"; temp += octets de format((SPIFFS.octets totaux() - (SPIFFS.usedBytes() * 1.05)))+ " free. <br>"; temp += "</td></table><br>"; serveur.sendContent(temp); temp = ""; //Chèque for le site du paramètre temp += "<table border=2 bgcolor = white width = 400><tr><th><br>"; temp += "<h4>Available des fichiers on SPIFFS:</h4><table border=2 bgcolor = white ></tr></th><td>Filename</td><td>Size</td><td>Action </td></tr></th>"; serveur.sendContent(temp); temp = ""; Fichier root = SPIFFS.open("/"); Fichier fichier = root.openNextFile(); while (fichier) { temp += "<td> <a title = \"le téléchargement \" href = \"" + Chaîne(fichier.nom()) + "\" le téléchargement = \"" + Chaîne(fichier.nom()) + "\">" + Chaîne(fichier.nom()) + "</a> <br></th>"; temp += "<td>"+ octets de format(fichier.size())+ "</td>"; temp += "<td><a href =filesystem ? delete =" + Chaîne(fichier.nom()) + "> Delete </a></td>"; temp += "</tr></th>"; fichier = racine.openNextFile(); } temp += "</tr></th>"; temp += "</td></tr></th></th></th><br></th></tr></table></table></table><br>"; temp += "<table border=2 bgcolor = white width = 400 ><td><h4>Upload</h4>; temp += "<label> Choose File: </label>"; temp += "<form method='POST' action='/upload' enctype='multipart/form-data' style='height:35px;'><input type='file' name='upload' style='height:35px; font-size:13px;' required>\r \n<input type='submit' value='Upload' class='button'></form>"; temp += " </table><br>"; serveur.sendContent(temp); temp = ""; temp += "<td><a href =filesystem?format=on> Format SPIFFS Filesystem. (Takes up to 30 Seconds) </a></td>"; temp += "<table border=2 bgcolor = white width = 500 cellpadding =5 ><caption><p><p><h3>Gauche système:</h2></p></caption><tr><th><br>"; temp += " <a href="/fr">Main Page</a><br><br></th></tr></table><br><br>"; serveur.sendContent(temp); temp = ""; temp += "<footer><p>Programmed and designed by: Tobias Kuch</p><p>Contact information: <a href='mailto:tobias.kuch@googlemail.com'>tobias.kuch@googlemail.com</a></p></p></footer></footer></html></body></html>; // server.send (200, "", temp) ; serveur.sendContent(temp); serveur.client().stop(); // Stop is needed needed because we no content length temp = ""; } /** Load WLAN credentials from EEPROM */ bool loadCredentials() { bool RetValue; EEPROM.begin(512); EEPROM.get(0, MyWiFiConfig); EEPROM.end(); if (Chaîne(MyWiFiConfig.ConfigValid) == Chaîne("TK")) { RetValue = vrai; } else { RetValue = false; // Les paramètres WLAN ne sont pas found. } return RetValue; } /** Store WLAN Credentials to EEPROM */ bool saveCredentials() { bool RetValue; // Check logical Errors RetValue = vrai; if (MyWiFiConfig.APSTA == vrai ) // AP Mode { if (MyWiFiConfig.PwDReq and (sizeof(Chaîne(MyWiFiConfig.WiFiPwd)) < 8)) { RetValue = false; // Config Invalid Config } if (sizeof(Chaîne(MyWiFiConfig.APSTAName)) < 1) { RetValue = false; // Config Invalid Config } } if (RetValue) { EEPROM.begin(512); pour (int i = 0 ; i < sizeof(MyWiFiConfig) ; i++) { EEPROM.write(i, 0); } strncpy( MyWiFiConfig.ConfigValid , "TK", sizeof(MyWiFiConfig.ConfigValid) ); EEPROM.put(0, MyWiFiConfig); EEPROM.commit(); EEPROM.end(); } return RetValue; } void SetDefaultWiFiConfig() { octets len; MyWiFiConfig.APSTA = vrai; MyWiFiConfig.PwDReq = vrai; // default PW required MyWiFiConfig.CapPortal = vrai; strncpy( MyWiFiConfig.APSTAName, "ESP_Config", sizeof(MyWiFiConfig.APSTAName) ); len = strlen(MyWiFiConfig.APSTAName); MyWiFiConfig.APSTAName[len+1] = '\0'; strncpy( MyWiFiConfig.WiFiPwd, "12345678", sizeof(MyWiFiConfig.WiFiPwd) ); len = strlen(MyWiFiConfig.WiFiPwd); MyWiFiConfig.WiFiPwd[len+1] = '\0'; strncpy( MyWiFiConfig.ConfigValid, "TK", sizeof(MyWiFiConfig.ConfigValid) ); len = strlen(MyWiFiConfig.ConfigValid); MyWiFiConfig.ConfigValid[len+1] = '\0'; Serial.println(F("Reset WiFi Credentials.")); } void handleRoot() { //Main la page : temp = ""; short PicCount = 0; octet ServArgs = 0; //Building la page //HTML Header serveur.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); serveur.sendHeader("Pragma", "no-cache"); serveur.sendHeader("Expires", "-1"); serveur.setContentLength(CONTENT_LENGTH_UNKNOWN); //HTML Content serveur.envoie ( 200, "texte / html", temp ); //Speichersparen - déjà au client envoient temp = ""; temp += "<!DOCTYPE HTML><html longtemps ='de'><head><meta charset le nom ='UTF-8'><meta = viewport content ='width=device-width, initial scale=1.0, '>"; temp += "<style type ='text / css'><! - DIV.container {min-height : 10em em; display : table-cell; vertical-align : middle}.button {height:35px; width:90px; font-size:16px}"; serveur.sendContent(temp); temp = ""; temp += "body {background-color : powderblue;} </style>"; temp += "<head><title>Tobi 's LED Display</title></head>"; temp += "<h2>LED Display</h2>"; temp += "<body>"; serveur.sendContent(temp); temp = ""; //Processing l'utilisateur Request if (serveur.args() > 0) //Des paramètres devenaient ubergeben { temp += "<br>Eingaben sont traités. S'il vous plaît, warten..<br><br>";; serveur.sendContent(temp); temp = ""; //Version modernisée Background Paper if (serveur.méchamment("PicSelect") == "off") //Clear le display LED { temp = ""; for ( int i = 0; i < NUM_LEDS; i++) { leds[i]= 0x000000; } FastLED.show(); } else { temp = serveur.méchamment("PicSelect"); //Image choisi. Display le contenu par Picselect hergstellt drawBitmap_SPIFFS(temp,0,0); temp = ""; } } temp += "<table border=2 bgcolor = white ><caption><p><h3>Available Pictures in SPIIFS for 8x8 Display</h2></p></caption>"; temp += "<form>"; temp += Nom de "<tr><th><input type ='radio" du ='PicSelect' value = 'off' checked> Clear LED Display<br></th></tr>"; temp += "<tr><th>"; //Ruse les fichiers de BMP available dans SPIFFS Fichier root = SPIFFS.open("/"); Fichier fichier = root.openNextFile(); PicCount = 1; while (fichier) { if (Chaîne(fichier.nom()).endsWith(".bmp") or Chaîne(fichier.nom()).endsWith(".BMP")) { BMPHeader PicData = ReadBitmapSpecs(fichier.nom()); if ((PicData.width < kMatrixWidth + 1) et (PicData.height < kMatrixHeight +1 )) //Display only dans la ruse, when Bitmap exceeding le display la résolution. Bigger des images are listed. { temp += "<label for ='radio1'><img src =""+ Chaîne(fichier.nom())+"' vieux ='"+ Chaîne(fichier.nom())+"' border = '3' bordercolor=green> image"+ PicCount+"</label><input type ='radio" value ='"+ Chaîne(fichier.nom())+"' le name ='PicSelect'/> <br>"; temp += Chaîne(fichier.nom())+ "Res :"+ Chaîne(PicData.width) + "x" + Chaîne(PicData.height) + "px Filesize :"+ octets de format(fichier.size()) + "</th></tr><tr><th>"; PicCount ++; } } fichier = root.openNextFile(); } serveur.sendContent(temp); temp = ""; temp = Le nom de "<button type ='submit" du ='action' value = '0' donne un look ='height : 50px; width : 280px'>Show l'image on Led Display</button>"; temp += "</form>"; temp += "<br><table border=2 bgcolor = white width = 280 cellpadding =5 ><caption><p><h3>Systemlinks:</h2></p></caption>"; temp += "<tr><th><br>"; temp += "<a href="/fr/ wifi">WIFI Settings</a><br><br>"; temp += "<a href="/fr/ filesystem">Filemanager</a><br><br>"; temp += "</th></tr></table><br><br>"; temp += "<footer><p>Programmed et designed by : Tobias Kuch</p><p>Contact l'information : <a href ='mailto:tobias.kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer>"; temp += "</body></html>"; serveur.sendContent(temp); temp = ""; serveur.client().arrêt(); //Arrêt is needed because we sent no content length } void handleNotFound() { if (captivePortal()) { //If le portail caprive redirect instead of displaying the error la page. return; } if (!handleFileRead(serveur.Uri())) { temp = ""; //HTML Header serveur.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); serveur.sendHeader("Pragma", "no-cache"); serveur.sendHeader("Expires", "-1"); serveur.setContentLength(CONTENT_LENGTH_UNKNOWN); //HTML Content temp += "<!DOCTYPE HTML><html longtemps ='de'><head><meta charset le nom ='UTF-8'><meta = viewport content ='width=device-width, initial scale=1.0, '>"; temp += "<style type ='text / css'><! - DIV.container {min-height : 10em em; display : table-cell; vertical-align : middle}.button {height:35px; width:90px; font-size:16px}"; temp += "body {background-color : powderblue;} </style>"; temp += "<head><title>File found</title></head>"; temp += "<h2> 404 fichiers la nécessité Found</h2><br>"; temp += "<h4>Debug Information:</h4><br>"; temp += "<body>"; temp += "URI :"; temp += serveur.Uri(); temp += "\nMethod :"; temp+= ( serveur.method() == HTTP_GET ) ? "GET" : "POSTE"; temp += "<br>Arguments :"; temp += serveur.args(); temp += "\n"; for ( uint8_t i = 0; i < serveur.args(); i++ ) { temp += " " + serveur.nom mauvais ( i ) + ": " + serveur.méchamment ( i ) + "\n"; } temp += "<br>Server Hostheader :"+ serveur.hostHeader(); for ( uint8_t i = 0; i < serveur.headers(); i++ ) { temp += " " + serveur.headerName ( i ) + ": " + serveur.header ( i ) + "\n<br>"; } temp += "</table></form><br><br><table border=2 bgcolor = white width = 500 cellpadding =5 ><caption><p><h2>You may want to browse to:</h2></p></caption>"; temp += "<tr><th>"; temp += "<a href="/fr">Main Page</a><br>"; temp += "<a href="/fr/ wifi">WIFI Settings</a><br>"; temp += "<a href="/fr/ filesystem">Filemanager</a><br>"; temp += "</th></tr></table><br><br>"; temp += "<footer><p>Programmed et designed by : Tobias Kuch</p><p>Contact l'information : <a href ='mailto:tobias.kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer>"; temp += "</body></html>"; serveur.envoie ( 404, "", temp ); serveur.client().arrêt(); //Arrêt is needed because we sent no content length temp = ""; } } / ** Redirect to le portail captive if we got a request for du domaine another. Return true dans that case la page si the le jeu handler try to agit the request again. */ boolean captivePortal() { if (!isIp(serveur.hostHeader()) && serveur.hostHeader() != (Chaîne(ESPHostname)+".local")) { //Serial.println ("Request redirected to captive portal"); serveur.sendHeader("Location", Chaîne("http://") + toStringIp(serveur.client().localIP()), true); serveur.envoie ( 302, "texte / plain", ""); //Empty content inhibits Content-length header ainsi we have to close the socket ourselves. serveur.client().arrêt(); //Arrêt is needed because we sent no content length return true; } return false; } / ** Wifi config la page handler */ void handleWifi() { //Page :/wifi octet i; octet len ; temp = ""; //Chèque for le site du paramètre if (serveur.hasArg("Reboot") ) //Reboot le système { temp = "Rebooting le système dans 5 Seconds."; serveur.envoie ( 200, "texte / html", temp ); delay(5000); serveur.client().arrêt(); WiFi.disconnect(); delay(1000); } if (serveur.hasArg("WiFiMode") et (serveur.méchamment("WiFiMode") == "1") ) //Station STA le mode Connect to another la station WIFI { startMillis = millis(); //Reset Time Up le compteur to avoid Idle Mode whiole operating //Connect to existing la STATION if ( sizeof(serveur.méchamment("WiFi_Network")) > 0 ) { Serial.println("Le mode STA"); MyWiFiConfig.APSTA = false; //Point d'Access or la station le mode - la station false le mode temp = ""; for ( i = 0; i < APSTANameLen;i++) { MyWiFiConfig.APSTAName[i] = 0; } temp = serveur.méchamment("WiFi_Network"); len = temp.length(); for ( i = 0; i < len;i++) { MyWiFiConfig.APSTAName[i] = temp[i]; } //MyWiFiConfig. APSTAName [len 1] = '\0'; temp = ""; for ( i = 0; i < WiFiPwdLen;i++) { MyWiFiConfig.WiFiPwd[i] = 0; } temp = serveur.méchamment("STAWLanPW"); len = temp.length(); for ( i = 0; i < len;i++) { if (temp[i] > 32) //Signes d'impôt dehors { MyWiFiConfig.WiFiPwd[i] = temp[i]; } } //MyWiFiConfig. WiFiPwd [len 1] = '\0'; temp = "WiFi Connect to AP :-"; temp += MyWiFiConfig.APSTAName; temp += "-<br>WiFi PW :-"; temp += MyWiFiConfig.WiFiPwd; temp += "-<br>"; temp += "Connecting to le mode STA dans 2 Seconds..<br>"; serveur.envoie ( 200, "texte / html", temp ); serveur.sendContent(temp); delay(2000); serveur.client().arrêt(); serveur.arrêt(); temp = ""; WiFi.disconnect(); WiFi.softAPdisconnect(true); delay(500); //ConnectWifiAP bool SaveOk = saveCredentials(); i = ConnectWifiAP(); delay(700); if (i != 3) //4 : WL_CONNECT_FAILED - Word de passeport is incorrect 1 : WL_NO_SSID_AVAILin - Configured SSID cannot reached { Serial.print(F("Cannot Connect to specified Network. Reason :")); Serial.println(i); serveur.client().arrêt(); delay(100); WiFi.setAutoReconnect (false); delay(100); WiFi.disconnect(); delay(1000); SetDefaultWiFiConfig(); CreateWifiSoftAP(); return; } else { //Coffre-forts Config bool SaveOk = saveCredentials(); InitalizeHTTPServer(); return; } } } if (serveur.hasArg("WiFiMode") et (serveur.méchamment("WiFiMode") == "2") ) //Change le mode AP { startMillis = millis(); //Reset Time Up le compteur to avoid Idle Mode whiole operating //Configure Access Point temp = serveur.méchamment("APPointName"); len = temp.length(); temp =serveur.méchamment("APPW"); if (serveur.hasArg("PasswordReq")) { i = temp.length(); } else { i = 8; } if ( ( len > 1 ) et (serveur.méchamment("APPW") == serveur.méchamment("APPWRepeat")) et ( i > 7) ) { temp = ""; Serial.println(F("APMode")); MyWiFiConfig.APSTA = true; //Point d'Access or le Sation le mode - true le mode AP if (serveur.hasArg("CaptivePortal")) { MyWiFiConfig.CapPortal = true ; //CaptivePortal on dans le mode AP } else { MyWiFiConfig.CapPortal = false ; } if (serveur.hasArg("PasswordReq")) { MyWiFiConfig.PwDReq = true ; //Word de passeport Required dans le mode AP } else { MyWiFiConfig.PwDReq = false ; } for ( i = 0; i < APSTANameLen;i++) { MyWiFiConfig.APSTAName[i] = 0; } temp = serveur.méchamment("APPointName"); len = temp.length(); for ( i = 0; i < len;i++) { MyWiFiConfig.APSTAName[i] = temp[i]; } MyWiFiConfig.APSTAName[len+1] = '\0'; temp = ""; for ( i = 0; i < WiFiPwdLen;i++) { MyWiFiConfig.WiFiPwd[i] = 0; } temp = serveur.méchamment("APPW"); len = temp.length(); for ( i = 0; i < len;i++) { MyWiFiConfig.WiFiPwd[i] = temp[i]; } MyWiFiConfig.WiFiPwd[len+1] = '\0'; temp = ""; if (saveCredentials()) //Save AP ConfigCongfig { temp = "Des données d'AP Modes avec succès sauvegardé. Reboot nécessairement."; } else { temp = "Des données d'AP Modes faussement."; } } else if (serveur.méchamment("APPW") != serveur.méchamment("APPWRepeat")) { temp = ""; temp = "WLAN le mot de passe non de la même façon. De manière interrompue."; } else { temp = ""; temp = "WLAN le mot de passe ou le nom AP trop brièvement. De manière interrompue."; } //WifiAP } //HTML Header serveur.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); serveur.sendHeader("Pragma", "no-cache"); serveur.sendHeader("Expires", "-1"); serveur.setContentLength(CONTENT_LENGTH_UNKNOWN); //HTML Content temp += "<!DOCTYPE HTML><html longtemps ='de'><head><meta charset le nom ='UTF-8'><meta = viewport content ='width=device-width, initial scale=1.0, '>"; serveur.envoie ( 200, "texte / html", temp ); temp = ""; temp += "<style type ='text / css'><! - DIV.container {min-height : 10em em; display : table-cell; vertical-align : middle}.button {height:35px; width:90px; font-size:16px}"; temp += "body {background-color : powderblue;} </style><head><title>Smartes Tuerschild - WiFi Settings</title></head>"; serveur.sendContent(temp); temp = ""; temp += "<h2>WiFi Settings</h2><body><left>"; temp += "<table border=2 bgcolor = white width = 500 ><td><h4>Current WiFi Settings : </h4>"; if (serveur.client().localIP() == apIP) { temp += "Le mode : Soft Access Point (AP) <br>"; temp += "SSID :" + Chaîne (MyWiFiConfig.APSTAName) + "<br><br>"; } else { temp += "Le mode : La station (STA) <br>"; temp += "SSID :"+ Chaîne (MyWiFiConfig.APSTAName) + "<br>"; temp += "BSSID :" + WiFi.BSSIDstr()+ "<br><br>"; } temp += "</td></table><br>"; serveur.sendContent(temp); temp = ""; temp += "<form action = '/ wifi' method ='post'>"; temp += "<table border=2 bgcolor = white width = 500><tr><th><br>"; if (MyWiFiConfig.APSTA == 1) { temp += "<input type ='radio" value = '1' nom du ='WiFiMode' > WiFi la station Mode<br>"; } else { temp += "<input type ='radio" value = '1' nom du ='WiFiMode' checked > WiFi la station Mode<br>"; } temp += "Available WiFi Networks:<table border=2 bgcolor = white ></tr></th><td>Number </td><td>SSID </td><td>Encryption </td><td>WiFi Strength </td>"; serveur.sendContent(temp); temp = ""; WiFi.scanDelete(); int n = WiFi.scanNetworks(false, false); //WiFi.scanNetworks (async, show_hidden) if (n > 0) { for (int i = 0; i < n; i++) { temp += "</tr></th>"; Chaîne Nrb = Chaîne(i); temp += "<td>" + Nrb + "</td>"; temp += "<td>" + WiFi.SSID(i) +"</td>"; Nrb = GetEncryptionType(WiFi.encryptionType(i)); temp += "<td>"+ Nrb + "</td>"; temp += "<td>" + Chaîne(WiFi.RSSI(i)) + "</td>"; } } else { temp += "</tr></th>"; temp += "<td>1 </td>"; temp += "<td>No WLAN found</td>"; temp += "<td>---</td>"; temp += "<td>---</td>"; } temp += "</table><table border=2 bgcolor = white ></tr></th><td>Connect to WiFi SSID : </td><td><select name ='WiFi_Network" >"; if (n > 0) { for (int i = 0; i < n; i++) { temp += "<option value = '" + WiFi.SSID(i) +"'>" + WiFi.SSID(i) +"</option>"; } } else { temp += "<option value ='No_WiFi_Network'>No WiFiNetwork found !/option>"; } serveur.sendContent(temp); temp = ""; temp += "</select></td></tr></th></tr></th><td>WiFi Word de passeport : </td><td>"; temp += Nom de "<input type ='text" du ='STAWLanPW' maxlength = en '40' size = '40'>"; temp += "</td></tr></th><br></th></tr></table></table><table border=2 bgcolor = white width = 500 ><tr><th><br>"; serveur.sendContent(temp); temp = ""; if (MyWiFiConfig.APSTA == true) { temp += Nom de "<input type ='radio" du ='WiFiMode' value = '2' checked> WiFi Access Point le mode <br>"; } else { temp += Nom de "<input type ='radio" du ='WiFiMode' value = '2' > WiFi Access Point le mode <br>"; } temp += "<table border=2 bgcolor = white ></tr></th> <td>WiFi Access Point Name : </td><td>"; serveur.sendContent(temp); temp = ""; if (MyWiFiConfig.APSTA == true) { temp += Nom de "<input type ='text" du ='APPointName' maxlength = '"+Chaîne(APSTANameLen-1)+"' size = en '30' value = '" + Chaîne(MyWiFiConfig.APSTAName) + "'></td>"; } else { temp += Nom de "<input type ='text" du ='APPointName' maxlength = '"+Chaîne(APSTANameLen-1)+"' size = en '30' ></td>"; } serveur.sendContent(temp); temp = ""; if (MyWiFiConfig.APSTA == true) { temp += "</tr></th><td>WiFi Word de passeport : </td><td>"; temp += Nom de "<input type ='password" du ='APPW' maxlength = '"+Chaîne(WiFiPwdLen-1)+"' size = en '30' value = '" + Chaîne(MyWiFiConfig.WiFiPwd) + "'> </td>"; temp += "</tr></th><td>Repeat WiFi Password : </td>"; temp += Nom de "<td><input type ='password" du ='APPWRepeat' maxlength = '"+Chaîne(WiFiPwdLen-1)+"' size = en '30' value = '" + Chaîne(MyWiFiConfig.WiFiPwd) + "'> </td>"; } else { temp += "</tr></th><td>WiFi Word de passeport : </td><td>"; temp += Nom de "<input type ='password" du ='APPW' maxlength = '"+Chaîne(WiFiPwdLen-1)+"' size = '30'> </td>"; temp += "</tr></th><td>Repeat WiFi Password : </td>"; temp += Nom de "<td><input type ='password" du ='APPWRepeat' maxlength = '"+Chaîne(WiFiPwdLen-1)+"' size = '30'> </td>"; } temp += "</table>"; serveur.sendContent(temp); temp = ""; if (MyWiFiConfig.PwDReq) { temp += Nom de "<input type ='checkbox" du ='PasswordReq' checked> Word de passeport for Login required."; } else { temp += Nom de "<input type ='checkbox" du ='PasswordReq' > Word de passeport for Login required."; } serveur.sendContent(temp); temp = ""; if (MyWiFiConfig.CapPortal) { temp += Nom de "<input type ='checkbox" du ='CaptivePortal' checked> Activate Captive le portail"; } else { temp += Nom de "<input type ='checkbox" du ='CaptivePortal' > Activate Captive le portail"; } serveur.sendContent(temp); temp = ""; temp += "<br></tr></th></table><br> <button type le nom de ='submit' du ='Settings' value = '1' donne un look ='height : 50px; width : 140px' autofocus>Set WiFi Settings</button>"; temp += Le nom de "<button type ='submit" du ='Reboot' value = '1' donne un look ='height : 50px; width : 200px' >Reboot System</button>"; serveur.sendContent(temp); temp = ""; temp += Le nom de "<button type ='reset" du ='action' value = '1' donne un look ='height : 50px; width : 100px' >Reset</button></form>"; temp += "<table border=2 bgcolor = white width = 500 cellpadding =5 ><caption><p><h3>Systemlinks:</h2></p></caption><tr><th><br>"; serveur.sendContent(temp); temp = ""; temp += "<a href="/fr">Main Page</a><br><br></th></tr></table><br><br>"; temp += "<footer><p>Programmed et designed by : Tobias Kuch</p><p>Contact l'information : <a href ='mailto:tobias.kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer>"; temp += "</body></html>"; serveur.sendContent(temp); serveur.client().arrêt(); //Arrêt is needed because we sent no content length temp = ""; } void handleUploadSave() { Chaîne FileData ; temp = ""; for (octet i = 0; i < serveur.args(); i++) { temp += "Méchamment" + (Chaîne)i + " –> "; //Include the current iteration value temp += serveur.nom mauvais(i) + ": "; //Get le nom the of les paramètres the temp += serveur.méchamment(i) + "\n"; //Get the value of les paramètres the } //server.send (200, "le texte / plain", temp);//des réponses to the HTTP request FileData = serveur.méchamment("fichier"); serveur.sendHeader("Location", "système de fichier", true); serveur.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); serveur.sendHeader("Pragma", "no-cache"); serveur.sendHeader("Expires", "-1"); serveur.envoie ( 302, "texte / plain", ""); //Empty content inhibits Content-length header ainsi we have to close the socket ourselves. serveur.client().arrêt(); //Arrêt is needed because we sent no content length } / ** Is this à IP ? */ boolean isIp(Chaîne str) { for (int i = 0; i < str.length(); i++) { int c = str.charAt(i); if (c != '.' && (c < '0' || c > '9')) { return false; } } return true; } Chaîne GetEncryptionType(octet thisType) { Chaîne Sortie = ""; //read the encryption type et print le nom the out : switch (thisType) { case 5: Sortie = "WEP"; return Sortie; break; case 2: Sortie = "WPA"; return Sortie; break; case 4: Sortie = "WPA2"; return Sortie; break; case 7: Sortie = "None"; return Sortie; break; case 8: Sortie = "Voiture"; return Sortie; break; } } / ** IP to la chaîne ? */ Chaîne toStringIp(IPAddress ip) { Chaîne res = ""; for (int i = 0; i < 3; i++) { res += Chaîne((ip >> (8 * i)) & 0xFF) + "."; } res += Chaîne(((ip >> 8 * 3)) & 0xFF); return res; } Chaîne octets de format(size_t octets) { //annonce lisible des grandeurs d'entrepôt if (octets < 1024) { return Chaîne(octets) + "Octet"; } else if (octets < (1024 * 1024)) { return Chaîne(octets / 1024.0) + "KBIT"; } else if (octets < (1024 * 1024 * 1024)) { return Chaîne(octets / 1024.0 / 1024.0) + "MO"; } } Chaîne getContentType(Chaîne nom de fichier) { //convert le fichier the l'extension to les codages MIME the type if (nom de fichier.endsWith(".htm")) return "texte / html"; else if (nom de fichier.endsWith(".css")) return "texte / css"; else if (nom de fichier.endsWith(".js")) return "application/javascript"; else if (nom de fichier.endsWith(".ico")) return "image / x-icon"; else if (nom de fichier.endsWith(".gz")) return "application/x-gzip"; else if (nom de fichier.endsWith(".bmp")) return "image / bmp"; else if (nom de fichier.endsWith(".tif")) return "image / tiff"; else if (nom de fichier.endsWith(".pbm")) return "l'image / le x portable bitmap"; else if (nom de fichier.endsWith(".jpg")) return "image / jpeg"; else if (nom de fichier.endsWith(".gif")) return "image / gif"; else if (nom de fichier.endsWith(".png")) return "image / png"; else if (nom de fichier.endsWith(".svg")) return "image/svg xml"; else if (nom de fichier.endsWith(".html")) return "texte / html"; else if (nom de fichier.endsWith(".wav")) return "audio / x-wav"; else if (nom de fichier.endsWith(".zip")) return "application/zip"; else if (nom de fichier.endsWith(".rgb")) return "image / x-rg"; //Complete la ruse on https://wiki.selfhtml.org/wiki/MIME-Type/Aperçu return "texte / plain"; } bool handleFileRead(Chaîne path) { //envoie the right le fichier to le client the (if it exists) if (path.endsWith("/")) path += "index.html"; //If a le dossier is requested, envoie l'index the au fichier Chaîne contentType = getContentType(path); //Get les codages MIME the type Chaîne pathWithGz = path + ".gz"; if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { //If le fichier the exists, l'as either a compressed des archives, or normalement if (SPIFFS.exists(pathWithGz)) //If there's a compressed la version available path += ".gz"; //Use the compressed verion Fichier fichier = SPIFFS.open(path, "r"); //Open le fichier the size_t sent = serveur.streamFile(fichier, contentType); //Envoie it to le client the fichier.close(); //Close le fichier the again return true; } return false; } void loop() { if (SoftAccOK) { dnsServer.processNextRequest(); //DNS } //HTTP serveur.handleClient(); }
J'ai produit quelques 8x8 BMP des graphiques dans la profondeur de couleur différente pour vous au test :
Téléchargement BMP des graphiques
Dans la prochaine partie, nous nous occupons d'une résolution plus haute de notre display LED. Jusque là souhaite beaucoup de plaisir avec l'annonce des propres fichiers de BMP sur le display LED.
3 commentaires
aschommer
Es hat doch etwas länger gedauert, aber jetzt habe ich “meinen Fork” erstellt: https://github.com/a-schommer/Tobis-General-Display
Rückmeldungen würden mich freuen – ich habe (noch) keine Routine damit, Software zu “veröffentlichen”, also glaube ich selbst nicht so ganz, dass es fehlerfrei ist.
Tobias
Hallo aschommer
Sämtliche Codes hier von mir stehen unter der GPL 3, wenn nicht anders im Code angegeben. Die Codes werden zuätzlich von mir auf GitHub unter https://github.com/kuchto zeitverzögert veröffentlich. Gerne kann für die einzelnen Projekte ein Fork angelegt werden.
Viele Grüße
aschommer
Unter welcher Lizenz stehen die Programme hier eigentlich? Ich würde gerne eine Variante für SSD1306-OLEDs (via u8g2-Library) beisteuern.