Ciao e benvenuto in un'altra parte della serie Captive Portal di ESP.
Nella parte odierna, stiamo espandendo il nostro portale captive con un file server integrato da un'altra applicazione di follow-up molto interessante: colleghiamo una matrice WS1812 8x8 a ESP32 e visualizziamo file BMP da 8x8 pixel memorizzati sul file server! Attualmente esiste una limitazione per cui il file BMP deve essere esattamente 8x8 pixel per essere visualizzato. Tutti gli altri formati o dimensioni non sono disponibili per la selezione del display. La selezione del file BMP da visualizzare viene effettuata sul sito Web principale:
Prima di tuttoma dobbiamo aggiungere un display a matrice di punti 8x8 all'hardware e collegarlo. La struttura è molto semplice grazie al bus a filo singolo dei LED WS2812:
*** Si prega di notare anche le istruzioni di sicurezza del nostro e-book per la messa in servizio della matrice 8x8 ***
Carichiamo il codice esteso su ESP 32:
#include <WiFi.B> #include <WiFiClient.B> #include <Server Web.B> #include <ESPmDNS.B> #include <spiffs.B> #include <Server DNS.B> #include <EEPROM.B> #include <FastLED.B> #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 statica const byte WiFiPwdLen = 25; statica const byte APSTANameLen = 20; struct WiFiEEPromData { bool APSTA = vero; // Punto di accesso o modalità stazione - modalità AP reale bool PwDReq = falso; // Password obbligatoria bool CapPortal = vero ; // CaptivePortal attivo in modalità AP carbonizzare APSTAName[APSTANameLen]; // Nome punto STATION / AP TO cONNECT, se difeso carbonizzare WiFiPwd[WiFiPwdLen]; // WiFiPAssword, se difeso carbonizzare ConfigValid[3]; // Se Config è Vaild, è richiesto il tag "TK" " }; struct BMPHeader // BitMapStucture { uint32_t Dimensione del file; // uint32_t byte creatore; // uint32_t offset di immagine; // Inizio dei dati immagine "Offset immagine: uint32_t dimensione dell'intestazione; // uint32_t larghezza; uint32_t altezza; uint16_t piano; uint16_t profondità; // bit per pixel uint32_t formato; }; / * nome host per mDNS. Dovrebbe funzionare almeno su Windows. provare http://esp8266.local */ const carbonizzare *ESPHostname = "ESP32"; // server DNS const byte DNS_PORT = 53; Server DNS dnsserver; // Conmmon Paramenters bool SoftAccOK = falso; // server web Server Web server(80); / * Parametri di rete Soft AP * / IPAddress APIP(172, 20, 0, 1); IPAddress netMsk(255, 255, 255, 0); unsigned lungo millis attuali = 0; unsigned lungo millis inizio; / ** Stato WLAN corrente * / breve stato = WL_IDLE_STATUS; file fsUploadFile; // un oggetto File per memorizzare temporaneamente il file ricevuto WiFiEEPromData MyWiFiConfig; stringa getContentType(stringa filename); // converte l'estensione del file nel tipo MIME bool manico FileRead(stringa sentiero); // invia il file giusto al client (se esiste) vuoto manico FileUpload(); // carica un nuovo file su SPIFFS stringa Temp =""; byte LUMINOSITÀ = 100; // PresetBrightness // Param per 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); vuoto configurazione() { REG_WRITE(GPIO_OUT_W1TS_REG, BIT(GPIO_NUM_16)); // Set di correzione dell'errore di meditazione Guru ritardo(1); REG_WRITE(GPIO_OUT_W1TC_REG, BIT(GPIO_NUM_16)); // Eliminazione dell'errore di meditazione Guru bool Collegare Successo = falso; bool CreateSoftAPSucc = falso; bool Sistema CInitFS = falso; bool CInitHTTPServer = falso; byte len; serial.iniziare(9600); mentre (!serial) { ; // attendi che la porta seriale si connetta. Necessario per USB nativo } Seriale.println(F("Interfaccia seriale inizializzata a 9600 Baud.")); FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050); FastLED.SetBrightness(LUMINOSITÀ); FastLED.mostrare(); Wi-Fi.setAutoReconnect (falso); Wi-Fi.persistente(falso); Wi-Fi.disconnect(); Wi-Fi.SetHostName(ESPHostname); // Imposta il nome host DHCP assegnato alla stazione ESP. Se (loadCredentials()) // Carica credenziali WLAN per le impostazioni WiFi { Seriale.println(F("Trovate credenziali valide.")); Se (MyWiFiConfig.APSTA == vero) // Modalità AP { Seriale.println(F("Modalità punto di accesso selezionata.")); len = strlen(MyWiFiConfig.APSTAName); MyWiFiConfig.APSTAName[len+1] = '\0'; len = strlen(MyWiFiConfig.WiFiPwd); MyWiFiConfig.WiFiPwd[len+1] = '\0'; CreateSoftAPSucc = CreateWifiSoftAP(); } altro { Seriale.println(F("Modalità stazione selezionata.")); len = strlen(MyWiFiConfig.APSTAName); MyWiFiConfig.APSTAName[len+1] = '\0'; len = strlen(MyWiFiConfig.WiFiPwd); MyWiFiConfig.WiFiPwd[len+1] = '\0'; len = ConnectWifiAP(); Se ( len == 3 ) { ConnectSuccess = vero; } altro { ConnectSuccess = falso; } } } altro { // Imposta configurazione predefinita - Crea AP Seriale.println(F("Nessuna credenziale valida trovata.")); SetDefaultWiFiConfig (); CreateSoftAPSucc = CreateWifiSoftAP(); saveCredentials(); // Lampeggia ritardo(500); } // Inizializza il filesystem CInitFSSystem = InitalizeFileSystem(); Se (!(CInitFSSystem)) {Seriale.println(F("File system non inizializzato!")); } Se ((ConnectSuccess o CreateSoftAPSucc)) { Seriale.Stampa (F("Indirizzo IP: ")); Se (CreateSoftAPSucc) { Seriale.println(Wi-Fi.softAPIP());} Se (ConnectSuccess) { Seriale.println(Wi-Fi.LOCALIP());} InitalizeHTTPServer(); } altro { Seriale.setDebugOutput(vero); // Uscita di debug per WLAN su interfaccia seriale. Seriale.println(F("Errore: impossibile connettersi alla rete WLAN. Impostare la configurazione DEFAULT.")); SetDefaultWiFiConfig(); CreateSoftAPSucc = CreateWifiSoftAP(); InitalizeHTTPServer(); SetDefaultWiFiConfig(); saveCredentials(); } per ( int io = 0; io < NUM_LEDS; io++) // Display a LED chiaro { leds[io]= 0x000000; } FastLED.mostrare(); // Cancella display :) } vuoto InitalizeHTTPServer() { bool initok = falso; / * Imposta pagine web: root, pagine di configurazione wifi, rilevatori di portale captive SO e non trovati. * / server.su("/", handleRoot); server.su("/Wi-Fi", handleWifi); server.su("Filesystem /", HTTP_GET,handleDisplayFS); server.su("/caricare", HTTP_POST, []() { server.Spedire(200, "Text / plain", ""); }, handleFileUpload); // if (MyWiFiConfig.CapPortal) {server.on ("/ generate_204", handleRoot); } // Portale captive Android. Forse non è necessario. Potrebbe essere gestito da notFound handler. // if (MyWiFiConfig.CapPortal) {server.on ("/ favicon.ico", handleRoot); } // Un altro portale captive per Android. Forse non è necessario. Potrebbe essere gestito da notFound handler. Controllato su Sony Handy // if (MyWiFiConfig.CapPortal) {server.on ("/ fwlink", handleRoot); } // Portale captive di Microsoft. Forse non è necessario. Potrebbe essere gestito da notFound handler. server.su("/ generate_204", handleRoot); // Portale captive Android. Forse non è necessario. Potrebbe essere gestito da notFound handler. server.su("/Favicon.ico", handleRoot); // Un altro portale captive per Android. Forse non è necessario. Potrebbe essere gestito da notFound handler. Controllato su Sony Handy server.su("Fwlink /", handleRoot); // Portale captive Microsoft. Forse non è necessario. Potrebbe essere gestito da notFound handler. server.onNotFound ( handleNotFound ); server.inizio(); // Avvio del server Web } booleano InitalizeFileSystem() { bool initok = falso; initok = spiffs.inizio(); ritardo(200); Se (!(initok)) { Seriale.println(F("Formato SPIFFS")); spiffs.formato(); initok = spiffs.inizio(); } ritorno initok; } booleano CreateWifiSoftAP() { Wi-Fi.disconnect(); Seriale.Stampa(F("Inizializza SoftAP")); Se (MyWiFiConfig.PwDReq) { SoftAccOK = Wi-Fi.SofTap(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); // Passwortlänge mindestens 8 Zeichen! } altro { SoftAccOK = Wi-Fi.SofTap(MyWiFiConfig.APSTAName); // Punto di accesso SENZA password // Funzione di sovraccarico :; WiFi.softAP (ssid, password, canale, nascosto) } ritardo(2000); // Senza indugio ho visto vuoto l'indirizzo IP Wi-Fi.softAPConfig(APIP, APIP, netMsk); Se (SoftAccOK) { / * Imposta il server DNS reindirizzando tutti i domini su apIP * / dnsserver.setErrorReplyCode(DNSReplyCode::Nessun errore); dnsserver.inizio(DNS_PORT, "*", APIP); Seriale.println(F("riuscito.")); } altro { Seriale.println(F("Errore soft AP.")); Seriale.println(MyWiFiConfig.APSTAName); Seriale.println(MyWiFiConfig.WiFiPwd); } ritorno SoftAccOK; } byte ConnectWifiAP() { Seriale.println(F("Inizializzazione del client Wifi".)); byte connRes = 0; byte io = 0; Wi-Fi.disconnect(); Wi-Fi.softAPdisconnect(vero); // La funzione imposterà l'SSID e la password attualmente configurati dell'AP-soft su valori null. Il parametro è facoltativo Se impostato su true, disattiva la modalità soft-AP. ritardo(500); Wi-Fi.inizio(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); connRes = Wi-Fi.waitForConnectResult(); mentre (( connRes == 0 ) e (io != 10)) // se connRes == 0 "IDLE_STATUS - cambia Statius" { connRes = Wi-Fi.waitForConnectResult(); ritardo(2000); io++; Seriale.Stampa(F(".")); // istruzioni } mentre (( connRes == 1 ) e (io != 10)) // se connRes == 1 NO_SSID_AVAILin - SSID non può essere raggiunto { connRes = Wi-Fi.waitForConnectResult(); ritardo(2000); io++; Seriale.Stampa(F(".")); // istruzioni } Se (connRes == 3 ) { Wi-Fi.setAutoReconnect(vero); // Imposta se il modulo tenterà di riconnettersi a un punto di accesso nel caso in cui sia disconnesso. // Imposta il risponditore MDNS Se (!MDNS.inizio(ESPHostname)) { Seriale.println(F("Errore: MDNS")); } altro { MDNS.addService("Http", "Tcp", 80); } } mentre (( connRes == 4 ) e (io != 10)) // se connRes == 4 Password errata. A volte succede questo con PWD corrct { Wi-Fi.inizio(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); connRes = Wi-Fi.waitForConnectResult(); ritardo(2000); io++; Seriale.Stampa(F(".")); } Se (connRes == 4 ) { Seriale.println(F("STA Pwd Err")); Seriale.println(MyWiFiConfig.APSTAName); Seriale.println(MyWiFiConfig.WiFiPwd); Wi-Fi.disconnect(); } Seriale.println(F("")); ritorno connRes; } uint16_t read16(File f) { // I dati BMP sono archiviati little-endian, come Arduino. uint16_t risultato; ((uint8_t *)&risultato)[0] = f.leggere(); // LSB ((uint8_t *)&risultato)[1] = f.leggere(); // MSB ritorno risultato; } uint32_t read32(File f) { // I dati BMP sono archiviati little-endian, come Arduino. uint32_t risultato; ((uint8_t *)&risultato)[0] = f.leggere(); // LSB ((uint8_t *)&risultato)[1] = f.leggere(); ((uint8_t *)&risultato)[2] = f.leggere(); ((uint8_t *)&risultato)[3] = f.leggere(); // MSB ritorno risultato; } BMPHeader ReadBitmapSpecs(Corda nome del file) { File file; BMPHeader BMPData; file =spiffs.Aperto(nome del file, "R"); Se (!file) { file.vicino(); ritorno BMPData; } // Intestazione BMP di analisi Se (read16(file) == 0x4D42) // Firma BMP { BMPData.dimensione del file = read32(file); BMPData.creatorBytes = read32(file); BMPData.imageOffset = read32(file); // Inizio dei dati dell'immagine BMPData.headerSize = read32(file); BMPData.larghezza = read32(file); BMPData.altezza = read32(file); BMPData.aerei = read16(file); BMPData.profondità = read16(file); // bit per pixel BMPData.formato = read32(file); } file.vicino(); ritorno BMPData; } #definire SD_BUFFER_PIXELS 20 vuoto drawBitmap_SPIFFS(Corda nome del file, uint8_t X, uint8_t y) { File file; uint8_t buffer[3 * SD_BUFFER_PIXELS]; // buffer pixel, dimensione per r, g, b bool valido = falso; // formato valido da gestire bool Flip = vero; // bitmap è memorizzato dal basso verso l'alto uint32_t pos = 0; file =spiffs.Aperto(nome del file, "R"); Se (!file) { Seriale.Stampa(F("Errore Filesytem")); ritorno; } // Intestazione BMP di analisi Se (read16(file) == 0x4D42) // Firma BMP { uint32_t dimensione del file = read32(file); uint32_t creatorBytes = read32(file); uint32_t imageOffset = read32(file); // Inizio dei dati dell'immagine uint32_t headerSize = read32(file); uint32_t larghezza = read32(file); uint32_t altezza = read32(file); uint16_t aerei = read16(file); uint16_t profondità = read16(file); // bit per pixel uint32_t formato = read32(file); Se ((aerei == 1) && (formato == 0)) // non compresso viene gestito { Seriale.Stampa(F("Dimensione del file: ")); Seriale.println(dimensione del file); Seriale.Stampa(F("Offset immagine:")); Seriale.println(imageOffset); Seriale.Stampa(F("Dimensioni intestazione:")); Seriale.println(headerSize); Seriale.Stampa(F("Profondità bit:")); Seriale.println(profondità); Seriale.Stampa(F("Dimensione dell'immagine: ")); Seriale.Stampa(larghezza); Seriale.Stampa('X'); Seriale.println(altezza); uint32_t rowsize = (larghezza * profondità / 8 + 3) & ~3; Se (altezza < 0) { altezza = -altezza; Flip = falso; } uint16_t w = larghezza; uint16_t h = altezza; size_t buffidx = taglia di(buffer); // forza il caricamento del buffer per (uint16_t riga = 0; riga < h; riga++) // per ogni riga { Se (Flip) // Bitmap è memorizzato dal basso verso l'alto (BMP normale) pos = imageOffset + (altezza - 1 - riga) * rowsize; altro // Bitmap è memorizzata dall'alto verso il basso pos = imageOffset + riga * rowsize; Se (file.posizione() != pos) { // Hai bisogno di cercare? file.cercare(pos,SeekSet); // se mode è SeekSet, la posizione è impostata per compensare i byte dall'inizio. // se mode è SeekCur, la posizione corrente viene spostata di byte offset. // se mode è SeekEnd, position è impostata per compensare i byte dalla fine di buffidx = taglia di(buffer); // forza la ricarica del buffer } uint8_t bit; per (uint16_t col = 0; col < w; col++) // per ogni pixel { // È tempo di leggere più dati pixel? Se (buffidx >= taglia di(buffer)) { file.leggere(buffer, taglia di(buffer)); buffidx = 0; // Imposta l'indice all'inizio } interruttore (profondità) { Astuccio 1: // un bit per pixel in formato b / n { valido = vero; Se (0 == col % 8) { bit = buffer[buffidx++]; } uint16_t bw_color = bit & 0x80; uint16_t PixelNum = (riga*8)+col; leds[PixelNum].rosso = bw_color; leds[PixelNum].verde = bw_color; leds[PixelNum].blu = bw_color; bit <<= 1; } rompere; Astuccio 24: // formato BMP standard { valido = vero; uint16_t B = buffer[buffidx++]; uint16_t g = buffer[buffidx++]; uint16_t r = buffer[buffidx++]; uint16_t PixelNum = (riga*8)+col; leds[PixelNum].rosso = r; leds[PixelNum].verde = g; leds[PixelNum].blu = B; } rompere; } } // end pixel } // fine linea FastLED.mostrare(); // Mostra i risultati :) } } file.vicino(); Se (!(valido)) { Seriale.println(F("Err: BMP")); } } vuoto handleFileUpload() { Se (server.uri() != "/caricare") ritorno; HTTPUpload& caricare = server.caricare(); Se (caricare.stato == UPLOAD_FILE_START) { Corda nome del file = caricare.nome del file; Se (caricare.nome del file.lunghezza() > 30) { caricare.nome del file = caricare.nome del file.sottostringa(caricare.nome del file.lunghezza() - 30, caricare.nome del file.lunghezza()); // Dateinamen auf 30 Zeichen kürzen } Seriale.println("FileUpload Name:" + caricare.nome del file); Se (!nome del file.inizia con("/")) nome del file = "/" + nome del file; fsUploadFile = spiffs.Aperto("/" + server.urldecode(caricare.nome del file), "W"); nome del file = Corda(); } altro Se (caricare.stato == UPLOAD_FILE_WRITE) { Se (fsUploadFile) fsUploadFile.Scrivi(caricare.buf, caricare.currentSize); } altro Se (caricare.stato == UPLOAD_FILE_END) { Se (fsUploadFile) fsUploadFile.vicino(); handleDisplayFS(); } } vuoto handleDisplayFS() { File system HTML Pagina: /filesystem Temp =""; Intestazione HTML Server.sendHeader (Intestazione)("Cache-Control", "no-cache, no-store, must-revalidate"); Server.sendHeader (Intestazione)("Pragma", "no-cache"); Server.sendHeader (Intestazione)("Scadenza", "-1"); Server.setContentLength (lunghezza in cui è impostato)(CONTENT_LENGTH_UNKNOWN); Contenuto HTML Server.Invia ( 200, "testo/html", Temp ); Temp += "<! HTML DOCTYPE><html lang>'de'><head><meta charset''UTF-8'><meta name'viewport content''width'device-width, initial-scale'1.0,'>"; Server.sendContent(Temp); Temp = ""; Temp += "<tipo di stile>'testo/css'><!-- DIV.container : min-height: 10em; display:cella di tabella; vertical-align: middle .button : altezza:35px; width:90px; font-size:16px; Server.sendContent(Temp); Temp = ""; Temp += "corpo: colore di sfondo: powderblue; </style><head><title>Gestore file system</title></head>"; Temp += "<h2>Serial Peripheral Interface Flash System</h2><body><left>"; Server.sendContent(Temp); Temp = ""; Se (Server.Args() > 0) Parametro wurden ubergeben { Se (Server.hasArg("elimina")) { Stringa FToDel = Server.Arg("elimina"); Se (SPIFFS.Esiste(FToDel)) { SPIFFS.Rimuovere(FToDel); Temp += "File" + FToDel + " eliminato con successo."; } Altro { Temp += "File" + FToDel + " non può essere eliminato."; } Server.sendContent(Temp); Temp = ""; } Se (Server.hasArg("formato") E Server.Arg("On")) { SPIFFS.Formato(); Temp += "File system SPI formattato correttamente."; Server.sendContent(Temp); Temp = ""; } server.client().stop(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto } Temp += "<bordo tabella>2 bgcolor , larghezza del bianco , 400 ><td><h4>Stato SPIFFS corrente: </h4>"; Temp += formatBytes (Byte di formato)(SPIFFS.usedBytes (Byte usati)() * 1.05) + " di " di " + formatBytes (Byte di formato)(SPIFFS.totalBytes()) + " utilizzato. <br>"; Temp += formatBytes (Byte di formato)((SPIFFS.totalBytes() - (SPIFFS.usedBytes (Byte usati)() * 1.05)))+ " libero. <br>"; Temp += "</td></tabella><br>"; Server.sendContent(Temp); Temp = ""; Verificare la presenza di parametri del sito Temp += "<bordo tabella<2 bgcolor , larghezza del bianco , 400><tr><th><br>"; Temp += "<h4>File disponibili su SPIFFS:</h4><bordo tabella >2 bgcolor & bianco ></tr></th><td></td><td>Dimensioni</td><td>Azione </td></tr></th>"; Server.sendContent(Temp); Temp = ""; file Radice = SPIFFS.Aperto("/"); file file = Radice.openNextFile (filediopenNext)(); Mentre (file) { Temp += "<td> <un titolo"Download" href + Stringa(file.Nome()) + """ download""" + Stringa(file.Nome()) + "\">" + Stringa(file.Nome()) + "</a> <br></th>"; Temp += "<td>"+ formatBytes (Byte di formato)(file.Dimensione())+ "</td>"; Temp += "<td><a href &filesystem?delete>" + Stringa(file.Nome()) + "> Elimina </a></td>"; Temp += "</tr></th>"; file = Radice.openNextFile (filediopenNext)(); } Temp += "</tr></th>"; Temp += "</td></tr></th><br></th></tr></table></table><br>"; Temp += "<bordo tabella<2 bgcolor , larghezza bianca , 400 ><td><h4>Carica</h4>"; Temp += "<etichetta> Scegli file: </etichetta>"; Temp += "<metodo di forma''AZIONE''POST'''/upload' enctype'''multipart/form-data' style''height:35px;' ><tipo di input''nome'''caricamento' style''altezza:35px; font-size:13px;' obbligatorio>'r'n<tipo di input''submit' value''Carica' classe''pulsante'></form>"; Temp += " </table><br>"; Server.sendContent(Temp); Temp = ""; Temp += "<td><a href > filesystem?format>on> Format SPIFFS Filesystem. (Accetta fino a 30 secondi) </a></td>"; Temp += "<bordo tabella>2 bgcolor , larghezza bianca , 500 cellum, 5 ><didascalia><p><h3>Systemlinks:</h2></p></caption><tr><th><br>& lt;/br>"; Temp += " <a href>Pagina principale</a><br><br></th></tr></tabella><br><br>"; Server.sendContent(Temp); Temp = ""; Temp += "<piè di pagina><p>Programmato e progettato da: Tobias Kuch</p><p>Informazioni di contatto: <a href>'mailto:tobias.kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer></body></html>"; server.send ( 200, "", temp ); Server.sendContent(Temp); Server.Client().Fermare(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto Temp = ""; } /z: carica le credenziali WLAN da EEPROM Bool loadCredentials() { Bool RetValue (RetValue); Eeprom.Iniziare(512); Eeprom.Ottieni(0, MyWiFiConfig); Eeprom.Fine(); Se (Stringa(MyWiFiConfig.ConfigValid (Valido)) == Stringa("TK")) { RetValue (RetValue) = Vero; } Altro { RetValue (RetValue) = False; Impostazioni WLAN non trovate. } Ritorno RetValue (RetValue); } /z Memorizzare le credenziali WLAN in EEPROM Bool saveCredentials (informazioni in base alle credenziali del servizio() { Bool RetValue (RetValue); Controllare gli errori logici RetValue (RetValue) = Vero; Se (MyWiFiConfig.APSTA == Vero ) Modalità AP { Se (MyWiFiConfig.PwDReq E (Sizeof(Stringa(MyWiFiConfig.WiFiPwd)) < 8)) { RetValue (RetValue) = False; Configurazione non valida } Se (Sizeof(Stringa(MyWiFiConfig.Nome APSTA)) < 1) { RetValue (RetValue) = False; Configurazione non valida } } Se (RetValue (RetValue)) { Eeprom.Iniziare(512); Per (Int Ho = 0 ; Ho < Sizeof(MyWiFiConfig) ; Ho++) { Eeprom.Scrivere(Ho, 0); } Strncpy( MyWiFiConfig.ConfigValid (Valido) , "TK", Sizeof(MyWiFiConfig.ConfigValid (Valido)) ); Eeprom.Mettere(0, MyWiFiConfig); Eeprom.Commettere(); Eeprom.Fine(); } Ritorno RetValue (RetValue); } Vuoto SetDefaultWiFiConfig() { byte Len; MyWiFiConfig.APSTA = Vero; MyWiFiConfig.PwDReq = Vero; PW predefinito richiesto MyWiFiConfig.CapPortal = Vero; Strncpy( MyWiFiConfig.Nome APSTA, "ESP_Config", Sizeof(MyWiFiConfig.Nome APSTA) ); Len = Strlen(MyWiFiConfig.Nome APSTA); MyWiFiConfig.Nome APSTA[Len+1] = '\0'; Strncpy( MyWiFiConfig.WiFiPwd, "12345678", Sizeof(MyWiFiConfig.WiFiPwd) ); Len = Strlen(MyWiFiConfig.WiFiPwd); MyWiFiConfig.WiFiPwd[Len+1] = '\0'; Strncpy( MyWiFiConfig.ConfigValid (Valido), "TK", Sizeof(MyWiFiConfig.ConfigValid (Valido)) ); Len = Strlen(MyWiFiConfig.ConfigValid (Valido)); MyWiFiConfig.ConfigValid (Valido)[Len+1] = '\0'; Seriale.println(F("Reimposta credenziali WiFi.")); } Vuoto handleRoot() { Pagina principale: Temp = ""; Breve Conteggio PicCount = 0; byte ServArgs = 0; Pagina Edificio Intestazione HTML Server.sendHeader (Intestazione)("Cache-Control", "no-cache, no-store, must-revalidate"); Server.sendHeader (Intestazione)("Pragma", "no-cache"); Server.sendHeader (Intestazione)("Scadenza", "-1"); Server.setContentLength (lunghezza in cui è impostato)(CONTENT_LENGTH_UNKNOWN); Contenuto HTML Server.Invia ( 200, "testo/html", Temp ); Speichersparen - Schon mal dem Client senden Temp = ""; Temp += "<! HTML DOCTYPE><html lang>'de'><head><meta charset''UTF-8'><meta name'viewport content''width'device-width, initial-scale'1.0,'>"; Temp += "<tipo di stile>'testo/css'><!-- DIV.container : min-height: 10em; display:cella di tabella; vertical-align: middle .button : altezza:35px; width:90px; font-size:16px; Server.sendContent(Temp); Temp = ""; Temp += "corpo: colore di sfondo: powderblue; </style>"; Temp += "<head><title>Tobi's LED Display</title></head>"; Temp += "<h2>Visualizzazione LED</h2>"; Temp += "<corpo>"; Server.sendContent(Temp); Temp = ""; Elaborazione della richiesta utente Se (Server.Args() > 0) Parametro wurden ubergeben { Temp += "<br>Eingaben werden verarbeitet. Bitte Warten.. <br><br>";; Server.sendContent(Temp); Temp = ""; Aggiorna carta di sfondo Se (Server.Arg("PicSelect" (Selezione)) == "off") Schermo LED chiaro { Temp = ""; Per ( Int Ho = 0; Ho < NUM_LEDS; Ho++) { Led[Ho]= 0x000000; } Led veloce.Visualizza(); } Altro { Temp = Server.Arg("PicSelect" (Selezione)); Bild gew'hlt. Mostra inhalt per Picselect hergstellt drawBitmap_SPIFFS(Temp,0,0); Temp = ""; } } Temp += "<bordo tabella>2 bgcolor ><didascalia><p><h3>Immagini disponibili in SPIIFS per 8x8 Display</h2></p></caption>"; Temp += "<forma>"; Temp += "<tr><th><input type''radio' name'''PicSelect' value -'off' checked> Clear LED Display<br></th></tr>"; Temp += "<tr><th>"; Elenco dei file BMP disponibili in SPIFFS file Radice = SPIFFS.Aperto("/"); file file = Radice.openNextFile (filediopenNext)(); Conteggio PicCount = 1; Mentre (file) { Se (Stringa(file.Nome()).endsWith(".bmp") O Stringa(file.Nome()).endsWith(". BMP")) { BMPHeader (Informazioni in base a Un'intestazion Dati PicData = ReadBitmapSpecs(file.Nome()); Se ((Dati PicData.Larghezza < KMatrixWidth (LarghezzaMatrice) + 1) E (Dati PicData.Altezza < kMatrixHeight (altezza) +1 )) Visualizza solo nell'elenco, quando Bitmap non supera la risoluzione dello schermo. Le immagini più grandi non sono elencate. { Temp += "<etichetta per'radio1'><img src''+ Stringa(file.Nome())+"' alt'"+ Stringa(file.Nome())+"' border'3' bordercolor-green> Immagine"+ Conteggio PicCount+"</label><input type''radio' value'"+ Stringa(file.Nome())+"' name:'PicSelect'/> <br>"; Temp += Stringa(file.Nome())+ " Res: "+ Stringa(Dati PicData.Larghezza) + "x" + Stringa(Dati PicData.Altezza) + "px Filesize: "+ formatBytes (Byte di formato)(file.Dimensione()) + "</th></tr><tr><th>"; Conteggio PicCount ++; } } file = Radice.openNextFile (filediopenNext)(); } Server.sendContent(Temp); Temp = ""; Temp = "<tipo di pulsante''submit' name''''action' value''0' style''height: 50px; larghezza: 280px'>Mostra immagine sul display a Led</pulsante>"; Temp += "</form>"; Temp += "<br><bordo tabella'2 bgcolor'2 bgcolor '2 larghezza del bianco' 280 cellpadding 5 ><caption><p><h3>Systemlinks:</h2></p></>"; Temp += "<tr><th><br>"; Temp += "<a href>Impostazioni WIFI</a><br><br>"; Temp += "<a href>Filemanager'>Filemanager</a><br><br>"; Temp += "</th></tr></tabella><br><br>"; Temp += "<piè di pagina><p>Programmato e progettato da: Tobias Kuch</p><p>Informazioni di contatto: <a href>'mailto:tobias kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer>"; Temp += "</body></html>"; Server.sendContent(Temp); Temp = ""; Server.Client().Fermare(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto } Vuoto handleNotFound() { Se (captivePortal()) { Se caprive portale reindirizzare invece di visualizzare la pagina di errore. Ritorno; } Se (!handleFileRead(Server.Uri())) { Temp = ""; Intestazione HTML Server.sendHeader (Intestazione)("Cache-Control", "no-cache, no-store, must-revalidate"); Server.sendHeader (Intestazione)("Pragma", "no-cache"); Server.sendHeader (Intestazione)("Scadenza", "-1"); Server.setContentLength (lunghezza in cui è impostato)(CONTENT_LENGTH_UNKNOWN); Contenuto HTML Temp += "<! HTML DOCTYPE><html lang>'de'><head><meta charset''UTF-8'><meta name'viewport content''width'device-width, initial-scale'1.0,'>"; Temp += "<tipo di stile>'testo/css'><!-- DIV.container : min-height: 10em; display:cella di tabella; vertical-align: middle .button : altezza:35px; width:90px; font-size:16px; Temp += "corpo: colore di sfondo: powderblue; </style>"; Temp += "<capo><titolo>File non trovato</titolo></head>"; Temp += "<h2> 404 File non trovato</h2><br>"; Temp += "<h4>Informazioni di debug:</h4><br>"; Temp += "<corpo>"; Temp += "URI: "; Temp += Server.Uri(); Temp += "NMetodo: "; Temp+= ( Server.Metodo() == HTTP_GET ) ? "OTTIENI" : "Post" (Posta); Temp += "<br>Argomenti: "; Temp += Server.Args(); Temp += "N"; Per ( uint8_t Ho = 0; Ho < Server.Args(); Ho++ ) { Temp += " " + Server.argName (nome arg) ( Ho ) + ": " + Server.Arg ( Ho ) + "N"; } Temp += "<br>Intestazione host server: "+ Server.hostHeader (intestazione host)(); Per ( uint8_t Ho = 0; Ho < Server.Intestazioni(); Ho++ ) { Temp += " " + Server.Headername ( Ho ) + ": " + Server.Intestazione ( Ho ) + "<br>"; } Temp += "</tabella></form><br><br><bordo tabella 2 bgcolor lt;caption><p><h2>È possibile passare a:</h2></p></caption>"; Temp += "<tr><th>"; Temp += "<a href>Pagina principale</a><br>"; Temp += "<a href>Impostazioni WIFI</a><br>"; Temp += "<a href>'/filesystem'>Filemanager</a><br>"; Temp += "</th></tr></tabella><br><br>"; Temp += "<piè di pagina><p>Programmato e progettato da: Tobias Kuch</p><p>Informazioni di contatto: <a href>'mailto:tobias kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer>"; Temp += "</body></html>"; Server.Invia ( 404, "", Temp ); Server.Client().Fermare(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto Temp = ""; } } Se abbiamo ricevuto una richiesta per un altro dominio, reindirizza al portale captive. Restituisce true in questo caso in modo che il gestore di pagina non tenti di gestire nuovamente la richiesta. */ Boolean captivePortal() { Se (!isIp (isIp)(Server.hostHeader (intestazione host)()) && Server.hostHeader (intestazione host)() != (Stringa(Nome host ESP)+".local")) { Serial.println("Richiesta reindirizzata al portale captive"); Server.sendHeader (Intestazione)("Posizione", Stringa("http://") + toStringIp (Informazioni in base a toStringIp(Server.Client().localIP (informazioni in locale)()), Vero); Server.Invia ( 302, "testo/semplice", ""); Il contenuto vuoto inibisce l'intestazione Content-length, quindi dobbiamo chiudere il socket da soli. Server.Client().Fermare(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto Ritorno Vero; } Ritorno False; } /- Gestore di pagina di config Wifi . Vuoto handleWifi() { Pagina: /wifi byte Ho; byte Len ; Temp = ""; Verificare la presenza di parametri del sito Se (Server.hasArg("Riavvia") ) Riavvia il sistema { Temp = "Riavvio del sistema in 5 secondi."; Server.Invia ( 200, "testo/html", Temp ); Ritardo(5000); Server.Client().Fermare(); Wifi.Scollegare(); Ritardo(1000); } Se (Server.hasArg("WiFiMode" (Modalità WiFi)) E (Server.Arg("WiFiMode" (Modalità WiFi)) == "1") ) STA Station Mode Connettersi a un'altra stazione WIFI { startMillis = millis(); Reset Time Up Counter per evitare il funzionamento della modalità di inattività Connettersi a STATION esistente Se ( Sizeof(Server.Arg("WiFi_Network")) > 0 ) { Seriale.println("Modalità STA"); MyWiFiConfig.APSTA = False; Modalità punto di accesso o stazione - modalità stazione falsa Temp = ""; Per ( Ho = 0; Ho < NomeAPSTALen;Ho++) { MyWiFiConfig.Nome APSTA[Ho] = 0; } Temp = Server.Arg("WiFi_Network"); Len = Temp.Lunghezza(); Per ( Ho = 0; Ho < Len;Ho++) { MyWiFiConfig.Nome APSTA[Ho] = Temp[Ho]; } MyWiFiConfig.APSTAName[len'1] : ''0''; Temp = ""; Per ( Ho = 0; Ho < WiFiPwdLen;Ho++) { MyWiFiConfig.WiFiPwd[Ho] = 0; } Temp = Server.Arg("STAWLanPW"); Len = Temp.Lunghezza(); Per ( Ho = 0; Ho < Len;Ho++) { Se (Temp[Ho] > 32) Steuerzeichen Raus { MyWiFiConfig.WiFiPwd[Ho] = Temp[Ho]; } } MyWiFiConfig.WiFiPwd[len'1] : ''0''; Temp = "WiFi Connect to AP: -"; Temp += MyWiFiConfig.Nome APSTA; Temp += "-<br>WiFi PW: -"; Temp += MyWiFiConfig.WiFiPwd; Temp += "-<br>"; Temp += "Connessione alla modalità STA in 2 secondi.. <br>"; Server.Invia ( 200, "testo/html", Temp ); Server.sendContent(Temp); Ritardo(2000); Server.Client().Fermare(); Server.Fermare(); Temp = ""; Wifi.Scollegare(); Wifi.softAPdisconnect (softAPdisconnect)(Vero); Ritardo(500); ConnectWifiAP (Connessione WifiAP) Bool SaveOk (Ok) = saveCredentials (informazioni in base alle credenziali del servizio(); Ho = ConnectWifiAP (Connessione WifiAP)(); Ritardo(700); Se (Ho != 3) 4: WL_CONNECT_FAILED - Password non corretta 1: WL_NO_SSID_AVAILin - Impossibile raggiungere l'SSID configurato { Seriale.Stampare(F("Impossibile connettersi alla rete specificata. Motivo: ")); Seriale.println(Ho); Server.Client().Fermare(); Ritardo(100); Wifi.setAutoReconnect (False); Ritardo(100); Wifi.Scollegare(); Ritardo(1000); SetDefaultWiFiConfig(); CreateWifiSoftAP (Informazioni in base ai pulsanti di sè)(); Ritorno; } Altro { Configurazione sicura Bool SaveOk (Ok) = saveCredentials (informazioni in base alle credenziali del servizio(); InitalizeHTTPServer(); Ritorno; } } } Se (Server.hasArg("WiFiMode" (Modalità WiFi)) E (Server.Arg("WiFiMode" (Modalità WiFi)) == "2") ) Cambia modalità AP { startMillis = millis(); Reset Time Up Counter per evitare il funzionamento della modalità di inattività Configurare il punto di accesso Temp = Server.Arg("NomeAPPoint"); Len = Temp.Lunghezza(); Temp =Server.Arg("APPW"); Se (Server.hasArg("PasswordReq")) { Ho = Temp.Lunghezza(); } Altro { Ho = 8; } Se ( ( Len > 1 ) E (Server.Arg("APPW") == Server.Arg("APPWRipeti")) E ( Ho > 7) ) { Temp = ""; Seriale.println(F("APMode" (Modalità API))); MyWiFiConfig.APSTA = Vero; Punto di accesso o modalità di sonnia - vera modalità AP Se (Server.hasArg("CaptivePortal")) { MyWiFiConfig.CapPortal = Vero ; CaptivePortal in modalità AP } Altro { MyWiFiConfig.CapPortal = False ; } Se (Server.hasArg("PasswordReq")) { MyWiFiConfig.PwDReq = Vero ; Password richiesta in modalità AP } Altro { MyWiFiConfig.PwDReq = False ; } Per ( Ho = 0; Ho < NomeAPSTALen;Ho++) { MyWiFiConfig.Nome APSTA[Ho] = 0; } Temp = Server.Arg("NomeAPPoint"); Len = Temp.Lunghezza(); Per ( Ho = 0; Ho < Len;Ho++) { MyWiFiConfig.Nome APSTA[Ho] = Temp[Ho]; } MyWiFiConfig.Nome APSTA[Len+1] = '\0'; Temp = ""; Per ( Ho = 0; Ho < WiFiPwdLen;Ho++) { MyWiFiConfig.WiFiPwd[Ho] = 0; } Temp = Server.Arg("APPW"); Len = Temp.Lunghezza(); Per ( Ho = 0; Ho < Len;Ho++) { MyWiFiConfig.WiFiPwd[Ho] = Temp[Ho]; } MyWiFiConfig.WiFiPwd[Len+1] = '\0'; Temp = ""; Se (saveCredentials (informazioni in base alle credenziali del servizio()) Salva AP ConfigCongfig { Temp = "Daten des AP Modes erfolgreich gespeichert. Riavviare notwendig."; } Altro { Temp = "Daten des AP Modes fehlerhaft."; } } Altro Se (Server.Arg("APPW") != Server.Arg("APPWRipeti")) { Temp = ""; Temp = "WLAN Passwort nicht gleich. Abgebrochen ".; } Altro { Temp = ""; Temp = "WLAN Passwort oder AP Nome zu kurz. Abgebrochen ".; } Fine WifiAP } Intestazione HTML Server.sendHeader (Intestazione)("Cache-Control", "no-cache, no-store, must-revalidate"); Server.sendHeader (Intestazione)("Pragma", "no-cache"); Server.sendHeader (Intestazione)("Scadenza", "-1"); Server.setContentLength (lunghezza in cui è impostato)(CONTENT_LENGTH_UNKNOWN); Contenuto HTML Temp += "<! HTML DOCTYPE><html lang>'de'><head><meta charset''UTF-8'><meta name'viewport content''width'device-width, initial-scale'1.0,'>"; Server.Invia ( 200, "testo/html", Temp ); Temp = ""; Temp += "<tipo di stile>'testo/css'><!-- DIV.container : min-height: 10em; display:cella di tabella; vertical-align: middle .button : altezza:35px; width:90px; font-size:16px; Temp += "corpo: colore di sfondo: powderblue; </style><head><title>Smartes Tuerschild - Impostazioni WiFi</title></head>"; Server.sendContent(Temp); Temp = ""; Temp += "<h2>Impostazioni WiFi</h2><corpo><sinistra>"; Temp += "<bordo tabella>2 bgcolor , larghezza bianca , 500 ><td><h4>Impostazioni WiFi correnti: </h4>"; Se (Server.Client().localIP (informazioni in locale)() == apIP) { Temp += "Modalità : Punto di accesso soft (AP)<br>"; Temp += "SSID : " + Stringa (MyWiFiConfig.Nome APSTA) + "<br><br>"; } Altro { Temp += "Modalità: Stazione (STA) <br>"; Temp += "SSID : "+ Stringa (MyWiFiConfig.Nome APSTA) + "<br>"; Temp += "BSSID : " + Wifi.BSSIDstr()+ "<br><br>"; } Temp += "</td></tabella><br>"; Server.sendContent(Temp); Temp = ""; Temp += "<azione di forma''/wifi' metodo''post'>"; Temp += "<bordo tabella>2 bgcolor , larghezza del bianco , 500><tr><th><br>"; Se (MyWiFiConfig.APSTA == 1) { Temp += "<tipo di ingresso'valore 'radio' '1' nome''WiFiMode' > Modalità stazione WiFi<br>"; } Altro { Temp += "<tipo di ingresso'valore 'radio' '1' nome''WiFiMode' checked > Modalità stazione WiFi<br>"; } Temp += "Reti WiFi disponibili:<bordo tabella>2 bgcolor ></tr></th><td>Numero </td><< td>SSID </td><td>Crittografia </td><td>Forza WiFi </td>"; Server.sendContent(Temp); Temp = ""; Wifi.scanDelete(); Int N = Wifi.scanNetworks(False, False); WiFi.scanNetworks(async, show_hidden) Se (N > 0) { Per (Int Ho = 0; Ho < N; Ho++) { Temp += "</tr></th>"; Stringa Nrb = Stringa(Ho); Temp += "<td>" + Nrb + "</td>"; Temp += "<td>" + Wifi.Ssid(Ho) +"</td>"; Nrb = Tipo di crittografia GetEncryptionType(Wifi.encryptionType (tipo di crittografia)(Ho)); Temp += "<td>"+ Nrb + "</td>"; Temp += "<td>" + Stringa(Wifi.Rssi(Ho)) + "</td>"; } } Altro { Temp += "</tr></th>"; Temp += "<td>1 </td>"; Temp += "<td>Nessuna WLAN trovata</td>"; Temp += "<td> --- </td>"; Temp += "<td> --- </td>"; } Temp += "</tabella><table border>2 bgcolor </tr></th><td>Connetti a SSID WiFi: </td><td><selezionare nome<'WiFi_Network''>"; Se (N > 0) { Per (Int Ho = 0; Ho < N; Ho++) { Temp += "<valore opzione'' + Wifi.Ssid(Ho) +"'>" + Wifi.Ssid(Ho) +"</opzione>"; } } Altro { Temp += "<valore opzione:'No_WiFi_Network'>Nessuna rete WiFi (nessuna rete WiFi)!/opzione>"; } Server.sendContent(Temp); Temp = ""; Temp += "</select></td></tr></th></tr></th><td>Password WiFi: </td><td>"; Temp += "<tipo di input''testo' nome''STAWLanPW' maxlength''40' dimensione ''40'>"; Temp += "</td></tr></th><br></th></tr></table></table><table border<2 bgcolor - 500 ><tr><th><<table border<<table border<2 bgcolor; Server.sendContent(Temp); Temp = ""; Se (MyWiFiConfig.APSTA == Vero) { Temp += "<tipo di ingresso:'radio' nome''WiFiMode' valore''2' checked> Modalità punto di accesso WiFi <br>"; } Altro { Temp += "<tipo di ingresso>'radio' nome'''WiFiMode' value''2' > Modalità punto di accesso WiFi <br>"; } Temp += "<bordo tabella>2 bgcolor <</tr></th> <td>Nome punto di accesso WiFi: </td><td>"; Server.sendContent(Temp); Temp = ""; Se (MyWiFiConfig.APSTA == Vero) { Temp += "<tipo di input''testo' nome''NomeAPPoint' maxlength''"+Stringa(NomeAPSTALen-1)+"' dimensione''30' valore'' + Stringa(MyWiFiConfig.Nome APSTA) + "'></td>"; } Altro { Temp += "<tipo di input''testo' nome''NomeAPPoint' maxlength''"+Stringa(NomeAPSTALen-1)+"' dimensione:'30' ></td>"; } Server.sendContent(Temp); Temp = ""; Se (MyWiFiConfig.APSTA == Vero) { Temp += "</tr></th><td>Password WiFi: </td><td>"; Temp += "<tipo di input''password' nome''APPW' maxlength''"+Stringa(WiFiPwdLen-1)+"' dimensione''30' valore'' + Stringa(MyWiFiConfig.WiFiPwd) + "'> </td>"; Temp += "</tr></th><td>Ripeti password WiFi: </td>"; Temp += "<td><tipo di input''password' nome''APPWRepeat' maxlength''"+Stringa(WiFiPwdLen-1)+"' dimensione''30' valore'' + Stringa(MyWiFiConfig.WiFiPwd) + "'> </td>"; } Altro { Temp += "</tr></th><td>Password WiFi: </td><td>"; Temp += "<tipo di input''password' nome''APPW' maxlength''"+Stringa(WiFiPwdLen-1)+"'dimensione:'30'> </td>"; Temp += "</tr></th><td>Ripeti password WiFi: </td>"; Temp += "<td><tipo di input''password' nome''APPWRepeat' maxlength''"+Stringa(WiFiPwdLen-1)+"'dimensione:'30'> </td>"; } Temp += "</tabella>"; Server.sendContent(Temp); Temp = ""; Se (MyWiFiConfig.PwDReq) { Temp += "<tipo di input:'casella di controllo' nome''PasswordReq' checked> Password per l'accesso richiesto. "; } Altro { Temp += "<tipo di input:'checkbox' name'''PasswordReq' > Password per l'accesso richiesta. "; } Server.sendContent(Temp); Temp = ""; Se (MyWiFiConfig.CapPortal) { Temp += "<tipo di input:'checkbox' name'''CaptivePortal' checked> Attiva Captive Portal'; } Altro { Temp += "<tipo di input:'checkbox' name''''CaptivePortal' > Attiva captive Portal"; } Server.sendContent(Temp); Temp = ""; Temp += "<br></tr></th></table><br> <button type''submit' name'''Settings' value''1' style''height: 50px; larghezza: autofocus di 140px>Imposta impostazioni WiFi</pulsante>"; Temp += "<tipo di pulsante''submit' name'''Reboot' value''1' style''height: 50px; larghezza: 200px' > Sistema di riavvio</pulsante>"; Server.sendContent(Temp); Temp = ""; Temp += "<tipo di pulsante''reset' name'''action' value''1' style''height: 50px; larghezza: 100px' >Reimposta</pulsante></form>"; Temp += "<bordo tabella>2 bgcolor , larghezza bianca , 500 cellum, 5 ><didascalia><p><h3>Systemlinks:</h2></p></caption><tr><th><br>& lt;/br>"; Server.sendContent(Temp); Temp = ""; Temp += "<a href>Pagina principale</a><br><br></th></tr></tabella><br><br>"; Temp += "<piè di pagina><p>Programmato e progettato da: Tobias Kuch</p><p>Informazioni di contatto: <a href>'mailto:tobias kuch@googlemail.com'>tobias.kuch@googlemail.com</a>.</p></footer>"; Temp += "</body></html>"; Server.sendContent(Temp); Server.Client().Fermare(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto Temp = ""; } Vuoto handleUploadSalva() { Stringa Filedata ; Temp = ""; Per (byte Ho = 0; Ho < Server.Args(); Ho++) { Temp += "Arg" + (Stringa)Ho + " –> "; Includere il valore di iterazione corrente Temp += Server.argName (nome arg)(Ho) + ": "; Ottenere il nome del parametro Temp += Server.Arg(Ho) + "N"; Ottenere il valore del parametro } server.invio(200, "testo/semplice", temp); Risposta alla richiesta HTTP Filedata = Server.Arg("datei"); Server.sendHeader (Intestazione)("Posizione", "filesystem", Vero); Server.sendHeader (Intestazione)("Cache-Control", "no-cache, no-store, must-revalidate"); Server.sendHeader (Intestazione)("Pragma", "no-cache"); Server.sendHeader (Intestazione)("Scadenza", "-1"); Server.Invia ( 302, "testo/semplice", ""); Il contenuto vuoto inibisce l'intestazione Content-length, quindi dobbiamo chiudere il socket da soli. Server.Client().Fermare(); L'arresto è necessario perché non abbiamo inviato alcuna lunghezza del contenuto } Si tratta di un indirizzo IP? */ Boolean isIp (isIp)(Stringa Str) { Per (Int Ho = 0; Ho < Str.Lunghezza(); Ho++) { Int C = Str.charAt(Ho); Se (C != '.' && (C < '0' || C > '9')) { Ritorno False; } } Ritorno Vero; } Stringa Tipo di crittografia GetEncryptionType(byte ThisType (tipo)) { Stringa Output = ""; leggere il tipo di crittografia e stampare il nome: Interruttore (ThisType (tipo)) { Caso 5: Output = "WEP"; Ritorno Output; Pausa; Caso 2: Output = "WPA"; Ritorno Output; Pausa; Caso 4: Output = "WPA2"; Ritorno Output; Pausa; Caso 7: Output = "Nessuno"; Ritorno Output; Pausa; Caso 8: Output = "Auto"; Ritorno Output; Pausa; } } da IP a stringa? */ Stringa toStringIp (Informazioni in base a toStringIp(Ipaddress Ip) { Stringa Res = ""; Per (Int Ho = 0; Ho < 3; Ho++) { Res += Stringa((Ip >> (8 * Ho)) & 0xff) + "."; } Res += Stringa(((Ip >> 8 * 3)) & 0xff); Ritorno Res; } Stringa formatBytes (Byte di formato)(Size_t Byte) { lesbare Anzeige der Speichergràen Se (Byte < 1024) { Ritorno Stringa(Byte) + " Byte"; } Altro Se (Byte < (1024 * 1024)) { Ritorno Stringa(Byte / 1024.0) + " KB"; } Altro Se (Byte < (1024 * 1024 * 1024)) { Ritorno Stringa(Byte / 1024.0 / 1024.0) + " MB "; } } Stringa getContentType (tipo getContentType)(Stringa Filename) { convertire l'estensione del file nel tipo MIME Se (Filename.endsWith(".htm")) Ritorno "testo/html"; Altro Se (Filename.endsWith(".css")) Ritorno "testo/css"; Altro Se (Filename.Finisce con(".js" (informazioni in questo conto in questo sin)) Ritorno "applicazione/javascript"; Altro Se (Filename.Finisce con(".ico")) Ritorno "immagine/icona x"; Altro Se (Filename.Finisce con(".gz")) Ritorno "applicazione/x-gzip"; Altro Se (Filename.Finisce con(".bmp")) Ritorno "immagine/bmp"; Altro Se (Filename.Finisce con(".tif")) Ritorno "immagine/tiff"; Altro Se (Filename.Finisce con(".pbm")) Ritorno "immagine/x-bitmap"; Altro Se (Filename.Finisce con(".jpg")) Ritorno "immagine/parola-------------; Altro Se (Filename.Finisce con(".gif")) Ritorno "immagine/gif"; Altro Se (Filename.Finisce con(".png")) Ritorno "immagine/png"; Altro Se (Filename.Finisce con(".svg")) Ritorno "immagine/svg-xml"; Altro Se (Filename.Finisce con(".html")) Ritorno "testo/html"; Altro Se (Filename.Finisce con(".wav")) Ritorno "audio/x-wav"; Altro Se (Filename.Finisce con(".zip")) Ritorno "applicazione/zip"; Altro Se (Filename.Finisce con(".rgb")) Ritorno "immagine/x-rg"; Completa elenco su https://wiki.selfhtml.org/wiki/MIME-Type/Panoramica Ritorno "testo/semplice"; } Bool handleFileRead(Stringa Percorso) { inviare il file corretto al client (se esiste) Se (Percorso.Finisce con("/")) Percorso += "index.html"; Se viene richiesta una cartella, inviare il file di indice Stringa Contenttype = getContentType (tipo getContentType)(Percorso); Ottenere il tipo MIMEGet the MIME type Stringa percorsoWithGz = Percorso + ".gz"; Se (SPIFFS.Esiste(percorsoWithGz) || SPIFFS.Esiste(Percorso)) { Se il file esiste, come archivio compresso o normale Se (SPIFFS.Esiste(percorsoWithGz)) Se è disponibile una versione compressa Percorso += ".gz"; Utilizzare la verion compressa file file = SPIFFS.Aperto(Percorso, "r"); Aprire il file Size_t Inviato = Server.streamFile(file, Contenttype); Inviarlo al client file.Vicino(); Chiudere di nuovo il file Ritorno Vero; } Ritorno False; } Vuoto Ciclo() { Se (SoftAccOK) { server dns.processNextRequest (richiesta di processosuccessivo)(); Dns } HTTP (informazioni in due Server.handleClient(); }
Ho creato alcuni 8x8 grafica BMP in diversa profondità di colore per voi per testare:
Nella parte successiva ci occuperemo di una risoluzione più alta del nostro display a LED. Fino ad allora, si augura un sacco di divertimento con la visualizzazione dei propri file BMP sul display LED.
3 commenti
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.