Salve e benvenuti a un nuovo post sul blog per MiFare Card Reader.
Nel post di oggi e nel prossimo post di blog della serie, ci concentriamo sulla sicurezza e la flessibilità.
Vogliamo fare un po' di luce sulla sicurezza e la flessibilità del nostro lettore di schede, nonché garantire una maggiore trasparenza nelle azioni dei lettori di schede. Un grave difetto delle parti precedenti di questa serie era che, anche se la password di accesso dell'amministratore sull'interfaccia web differiva da lettore di schede a lettore di schede, questa password non poteva essere modificata singolarmente.
Oggi vogliamo cambiarlo. D'ora in e' possibile utilizzare il
Interfaccia eb in Sistema -> Sicurezza per immettere una password di accesso separata per l'utente "admin".
Questa password può avere una lunghezza compresa tra 3 e 16 caratteri.
Questo intervallo di disegno definito può essere impostato con le definizioni PwMinLength e PwMaxLength nel codice. Se si desiderano limiti di password più brevi o più lunghi, i valori possono essere regolati singolarmente.
La procedura per modificare la password dell'utente "admin" è:
- Primo login all'interfaccia web con il nome utente "admin" e la password costituita dall'ESP ChipId. (Come descritto nelle parti precedenti della serie)
Navigazione sotto Sistema -> Sicurezza quindi inserire la stessa (nuova) password 2x e pulsante ... passeggiata.
- Logout in Sistema -> Annulla iscrizione. La nuova password è immediatamente valida.
Quindi abbiamo aumentato un po 'la sicurezza in modo che qualcuno che conosce il nostro progetto e ha accesso all'interfaccia seriale e sulla rete non può trovare subito la password di accesso valida.
Passiamo a un altro punto della sicurezza di Rubrick: dal punto di vista della sicurezza, sarebbe auspicabile sapere chi ha usato il nostro lettore di carte con successo o non con successo con quale carta. Ora stiamo creando l'opportunità di farlo. Sotto la nuova voce di menu "Registro eventi" ora vediamo diverse voci per determinate azioni o eventi intorno al nostro lettore.
Ad esempio, vediamo ora nel registro eventi tutti i tentativi con schede valide e non valide per ottenere il lettore di eseguire un'azione.
La schermata seguente mostra questo come esempio:The following screenshot shows this as an example:
Come si può vedere nella schermata precedente, l'elenco dell'ora e della data è ancora genericamente impostato su un valore fisso, perché manca ancora un'origine ora valida. Aggiungeremo questa fonte a una delle parti successive.
La corretta inizializzazione e l'utilizzo del file system Interno ESP SPIFFS sono essenziali per il registro eventi. A tale scopo, abbiamo impostato le opzioni di compilazione in modo che 2 MB dei nostri 4 MB di memoria disponibile di memoria del programma sia formattato come un file system SPIFFS. Come fare questo, ho già descritto in un altro post di blog "ESP8266 – Tutto SPIFFS o cosa?" da me sotto il programma di installazione.
Importante: senza l'impostazione SPIFFS corretta, il codice viene compilato e caricato in ESP, ma quando si avvia l'ESP con il messaggio "ATFS:NOK" sull'interfaccia seriale, "hang" e l'avvio non riesce ulteriormente. Dobbiamo mantenere questa impostazione SPIFFS per tutte le altre parti successive di questa serie.
Il codice per il nostro blog oggi è:
#include <Spi.H> #include <Numero di unità DI CRITTOGRAFIA.H> #include <ESP8266WiFi.H> #include <Server Web ESP8266.H> #include <ESP8266mDNS (dns).H> #include <Eeprom.H> #include <Fs.H> Includere la libreria SPIFFS # define RST_PIN 5 SPI Reset Pin (uscita D1) # define RELAIS_PIN 16 Relè (uscita D0) [LOW Active] - Anche LED interno vicino alla porta USB # define SS_PIN 15 SPI Slave Seleziona Pin # define RGBLED_R 2 Rosso (uscita D4) # define RGBLED_G 0 Verde (uscita D3) - Anche LED interno sul modulo ESP # define RGBLED_B 4 Blu (uscita D2) # define WiFiPwdLen 25 Lunghezza massima della password WiFi # define STANameLen 20 Lunghezza SSID WiFi massima # define ESPHostNameLen 20 Numero massimo di caratteri ESPHostName # define Keya Vero Definizione flag PICC # define Tasto False Definizione flag PICC # define LED_BUILTIN 16 # define PIN_WIRE_SDA 4 # define PIN_WIRE_SCL 5 # define PwMinLunghezza 3 Lunghezza minima password di accesso # define PwMaxLength (Lunghezza massima) 16 Lunghezza massima della password di accesso # define LoginNameMaxLength 16 Lunghezza massima del nome di accesso # define USED_Sector 1 Settore scheda utilizzato per i dati di autenticazione e configurazione (valido: 1- 15) ADC_MODE(ADC_TOUT); Configurare l'ingresso analogico A0 all'esterno. ADC_TOUT (per tensione esterna), ADC_VCC (per la tensione del sistema). Numero di unità DI CRITTOGRAFIA mfrc522(SS_PIN, RST_PIN); Crea istanza di MFRC522 Numero di unità DI CRITTOGRAFIA::MIFARE_Key Chiave; Server Web ESP8266 Server(80); Crea istanza server Web file Documento; creare una variabile di gestione SPIFFSCreate a SPIFFS Handling Variable Informazioni su FSInfo fs_info; Struct WiFiEEPromData 68 byte Oggetto Lenght { Char Nomehost ESPHost[ESPHostNameLen]; // 20 Char Nome APSTA[STANameLen]; STATION /AP Nome punto da collegare, se detrovato 20 Char WiFiPwd[WiFiPwdLen]; WiFiPAssword, se detrovato 25 Char ConfigValid (Valido)[3]; Se Config è Vaild, è richiesto il tag "TK" 3 }; Struct MiFareClassicKeyTable { Byte Key_A[6] = {0x22 (in questo 0x22), 0x44 (in questo 0x44), 0xFA, 0xAB (in formato 0xAB), 0x90 (in questo 0x90), 0x11 (in questo formato 0x11)}; Tasto per la carta PICC si prega di cambiare. Byte Key_B[6] = {0xFE (in modo 0xFE), 0xE1 (in modo 0xE1), 0xAA, 0x3D (in modo 0x3D), 0xDF (informazioni in due), 0x37 (in questo stato del sistema)}; Tasto per la carta PICC si prega di cambiare. Char ConfigValid (Valido)[3]; Se Config è Vaild, è necessario il tag "TK"" }; Struct SysConf (informazioni in stato di // { Char Loginname[LoginNameMaxLength]; // 16 Char LoginPassword (Password di accesso)[PwMaxLength (Lunghezza massima)]; // 16 Bool PCD_Disabled; // 1 Byte USED_PICC_Sector; // 1 Char ConfigValid (Valido)[3]; Se Config è Vaild, è richiesto il tag "TK", - 3 }; MiFareClassicKeyTable MiFareClassicKey; WiFiEEPromData MyWiFiConfig; SysConf (informazioni in stato di Configurazionedisistema; Variabili utilizzate a livello globale Bool Risultato = False; Bool LearnNewCard = False; Bool Cancellascheda = False; Bool ScadenzaDataAttivo = False; Bool PCD_Disabled = False; Stringa Cognome; Stringa Givenname; Stringa Data scadenza; Stringa Temp; Unsigned Lungo Sessionid; Unsigned Lungo PCD_ServiceCall_Handler = 0; Unsigned Lungo PCD_WatchDog_Handler = 0; uint8_t DataBuffer (DataBuffer)[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; Vuoto Installazione() { PinMode (Modalità pin)(RST_PIN, Output); digitalWrite (Scrittura digitale)(RST_PIN, alto); PinMode (Modalità pin)(RELAIS_PIN, Output); PinMode (Modalità pin)(RGBLED_R, Output); PinMode (Modalità pin)(RGBLED_G, Output); PinMode (Modalità pin)(RGBLED_B, Output); digitalWrite (Scrittura digitale)(RELAIS_PIN, alto); Relè inattivo SetRGBLed(255, 0, 255, False); Led Colore Viola Initalization Inizio Seriale.Iniziare(115200); Inizializzare la comunicazione seriale con il PC con 115200 Baud Seriale.println(D(" ")); Temp = "ATSN:" + Stringa(Spagnolo.getChipId()); Seriale.println(Temp); Serial.print("Valore ADC:"); Serial.println(analogRead(A0)); Spi.Iniziare(); Inizializzare la comunicazione SPI PCDHardReset (Ripristino PCDHard)(); Sessionid = millis(); Risultato = loadSysConfig (informazioni in base alla proprietà loadSys(); Risultato = InitalizeFileSystem (Filesystem)(); Risultato = startWiFiClient (avviOWiFiClient)(); InitalizeHTTPServer(); Temp = "Avvio del sistema: "; Temp += Stringa(Spagnolo.getResetReason()); WriteToLog(Temp, 0); Temp = ""; Spagnolo.WDtEnable (abilitazione di wdtEnable)(4000); Avvia Watchdog SetRGBLed(0, 0, 255, False); Inialization a led blu completato } Per l'Helper di supporto all'avvio/ funzioni di ottimizzazione , o o o oos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O , , , , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vuoto SetRGBLed(Byte Valore rosso, Byte Valore verde, Byte Valore blu, Boolean SlowFade) Funkion per il controllo del Led RGB { digitalWrite (Scrittura digitale)(RGBLED_R, Basso); digitalWrite (Scrittura digitale)(RGBLED_G, Basso); digitalWrite (Scrittura digitale)(RGBLED_B, Basso); Se (Valore rosso == 255) { digitalWrite (Scrittura digitale)(RGBLED_R, alto); } Se (Valore verde == 255) { digitalWrite (Scrittura digitale)(RGBLED_G, alto); } Se (Valore blu == 255) { digitalWrite (Scrittura digitale)(RGBLED_B, alto); } } Interrompere l'assistente per l'assistente di supporto/le funzioni di ottimizzazione , s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O , , , , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Per le funzioni di avvio, il server Web delle funzioni di avvio, o ome di posta o me , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O , , , , , , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le routine di base dei cookie si basano su un estratto di GIT: //https://github.com/esp8266/ESPWebServer/blob/master/examples/SimpleAuthentification/SimpleAuthentification.ino Bool is_authentified() { Se (Server.Hasheader("Cookie")) { Cookie trovato Temp = Server.Intestazione("Cookie"); Serial.println(temp); Stringa SessionStr (Str) = Stringa(Spagnolo.getChipId()) + "=" + Stringa(Sessionid); Rendimento(); Se (Temp.Indice di(SessionStr (Str)) != -1) { Autenticazione Web riuscita Temp = ""; Ritorno Vero; } } Autenticazione Web non riuscita Temp = ""; Sessionid = millis(); Ritorno False; } Vuoto handleLogin() { Stringa Msg; Cookie stringa: server.header("Cookie"); Serial.println(cookie); Se (Server.hasArg("DISCONNECT" (DISCONNECT))) { Disconnettere gli utenti; Sessionid = millis(); Temp = Stringa(Spagnolo.getChipId()) + N. NA ; HttpOnly ; SameSite - Strict"; Server.sendHeader (Intestazione)("Imposta cookie", Temp); Temp = "Annullamento della sottoscrizione dall'interfaccia Web."; WriteToLog(Temp, 0); Temp = ""; PCD_Disabled = False; Attivare PCD dopo la disconnessione ; SetRGBLed(0, 0, 255, False); Colore a Led Blu StandardModre Server.sendHeader (Intestazione)("Posizione", "/login"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Server.Invia(301); Server.Invia(301); rendimento(); } Se (Server.hasArg("NOMEUTENTE") && Server.hasArg("PASSWORD")) { Temp = Stringa(Spagnolo.getChipId()); Se (Server.Male("NOMEUTENTE") == Configurazionedisistema.Loginname && Server.Male("PASSWORD") == Configurazionedisistema.LoginPassword (Password di accesso) ) { Server.sendHeader (Intestazione)("Posizione", "/"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Sessionid = millis(); Temp = Stringa(Spagnolo.getChipId()) + "=" + Stringa(Sessionid) + "; HttpOnly ; SameSite - Strict"; Server.sendHeader (Intestazione)("Imposta cookie", Temp); Temp = "Registrazione di" + Server.Male("NOMEUTENTE") + " all'interfaccia web."; WriteToLog(Temp, 0); Temp = ""; Server.Invia(301); PCD_Disabled = Vero; Disattivare PCD finché ogni web funziona; SetRGBLed(255, 0, 255, False); Colore a Led Viola nella moda del servizio Ritorno; } Msg = "<script>alert('Nome utente errato o password !'); </script>"; Temp = "Tentativo di accesso non riuscito di" + Server.Male("NOMEUTENTE") + " all'interfaccia web. Password: " + Server.Male("PASSWORD") ; WriteToLog(Temp, 1); Temp = ""; } CSS_Header_Template(); Temp = "<head><titolo>Login</title></head><body><DIV ALIGN>"; Server.sendContent(Temp); Temp = "<h2>Registrazione al lettore di schede RC522</h2><body><br><br><br><br>table border>0 bgcolor<black><tr><th><DIV ALIGN>"; Server.sendContent(Temp); Temp = "<azione modulo''/login' metodo''post'>Nome utente: <tipo di input, nome testo, 'USERNAME' Dimensione ><br>"; Server.sendContent(Temp); Temp = "Password: <tipo di input>Nome password>Password' Dimensione ><br><br><br><br><br><tipo di pulsante>invio'"; Server.sendContent(Temp); Temp = "nome: 'Login_Button' valore'''1' stile''altezza: 30px; width: 100px' >Accesso</pulsante><br></th></tr></form></DIV></tabella>"; Server.sendContent(Temp); Temp = "<br><SMALL>Per il funzionamento dell'accesso, i cookie per questo sito Web devono essere consentiti.</SMALL>"; Server.sendContent(Temp); Temp = Msg + "</DIV></body></HTML>"; Server.sendContent(Temp); Temp = ""; } Vuoto handleNotFound() { Sessionid = millis(); Temp = "Pagina non trovata.; Temp += "URI: "; Temp += Server.Uri(); Temp += "AnMethod: "; Temp += (Server.Metodo() == HTTP_GET) ? "OTTIENI" : "Post" (Posta); Temp += "AnArguments: "; Temp += Server.Args(); Temp += "An"; Per (uint8_t Ho. = 0; Ho. < Server.Args(); Ho.++) { Temp += " " + Server.argName (nome arg)(Ho.) + ": " + Server.Male(Ho.) + "An"; } Rendimento(); Server.Invia(404, "testo/semplice", Temp); Temp = "Chiamare l'URL non valido: " + Server.Uri() + " Parametri: " + Stringa(Server.Args()) ; WriteToLog(Temp, 2); Temp = ""; } Vuoto handleErasePICC() { Se (!is_authentified()) { Server.sendHeader (Intestazione)("Posizione", "/login"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Server.Invia(301); Rendimento(); Ritorno; } CSS_Header_Template(); Rendimento(); Temp = "<head><title>Lettore di schede RC522</title></head><body>"; Server.sendContent(Temp); Struttura HtmlNavStructure(); Temp = "<script>alert('Si prega di mantenere la scheda da eliminare davanti al lettore ORA!'); </script>"; Server.sendContent(Temp); Rendimento(); Cancellascheda = Vero; PCD_Disabled = False; SetRGBLed(0, 255, 255, False); Modalità di programmazione ciano a led Temp = "</body></html>"; Server.sendContent(Temp); Server.Client().Fermare(); Temp = ""; } Vuoto handleImpostazioni() { Se (!is_authentified()) { Server.sendHeader (Intestazione)("Posizione", "/login"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Server.Invia(301); Ritorno; } CSS_Header_Template(); Temp = "<head><title>Lettore di schede RC522</title></head><body>"; Server.sendContent(Temp); Struttura HtmlNavStructure(); Temp = "<br><br><div align><metodo di forma'''post'azione''/settings' method'''post'>"; Server.sendContent(Temp); Temp = "<p><etichetta>Nuova password di accesso</label><br> <tipo di input>'password'nome'''newPassword'>"; Server.sendContent(Temp); Temp = "</p><p><etichetta>ripeti password di accesso</label><br> <input type>'password' name>'confirmNewPassword'><br><br><br>br>"; Server.sendContent(Temp); Temp = "<tipo di pulsante:'submit' name''''Salva' valore''1' stile''altezza: 30px; larghezza: 200px' >Salva</pulsante></p></form></div>"; Server.sendContent(Temp); temp - "</p><p><button type<'submit' name</button>"; Se (Server.hasArg("Salva")) { Se (Server.Male("confirmNewPassword") == Server.Male("nuovaPassword")) { Temp = Server.Male("nuovaPassword"); Se ((Temp.Lunghezza() < PwMinLunghezza ) | (Temp.Lunghezza() > PwMaxLength (Lunghezza massima) )) { Temp = "<br><div align-center><br>La password deve essere compresa almeno "; Server.sendContent(Temp); Temp = Stringa(PwMinLunghezza) + " e massimo " + Stringa(PwMaxLength (Lunghezza massima)) + " Essere un carattere lungo.</div>"; Server.sendContent(Temp); } Altro { Temp = Server.Male("nuovaPassword"); Temp.Tochararray(Configurazionedisistema.LoginPassword (Password di accesso) , PwMaxLength (Lunghezza massima)); saveSysConfig (informazioni in base al ruolo di save(); Temp = "La password di accesso dell'utente" + Stringa(Configurazionedisistema.Loginname) + "è stato cambiato."; WriteToLog(Temp, 0); Temp = "<script>alert('La password di accesso è stata modificata correttamente.'); </script>"; Server.sendContent(Temp); } } Altro { Temp = "<br><div align-center><br>Le password immesse non corrispondono. Reinserire.</div>"; Server.sendContent(Temp); } } Temp = "</body></html>"; Server.sendContent(Temp); Server.Client().Fermare(); Temp = ""; } Vuoto handleNewPICC() { Se (!is_authentified()) { Server.sendHeader (Intestazione)("Posizione", "/login"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Server.Invia(301); Ritorno; } Se (Server.hasArg("Cognome") && Server.hasArg("Nome")) { Cognome = Server.Male("Cognome"); Givenname = Server.Male("Nome"); Data scadenza = Server.Male("ExpDate" (ExpDate)); Se (Server.hasArg("ExpDateOption")) { ScadenzaDataAttivo = Vero; } Altro { ScadenzaDataAttivo = False; } Temp = "Creazione di una nuova mappa per: " + Server.Male("Nome") + ", " + Server.Male("Cognome"); WriteToLog(Temp, 0); PCD_Disabled = False; LearnNewCard = Vero; CSS_Header_Template(); Temp = "<head><title>Lettore di schede RC522</title></head><body>"; Server.sendContent(Temp); Struttura HtmlNavStructure(); Temp = "<script>alert('Si prega di tenere la nuova carta davanti al lettore ORA!'); </script>"; Server.sendContent(Temp); Temp = "</body></html>"; Server.sendContent(Temp); Server.Client().Fermare(); SetRGBLed(255, 255, 0, False); Modalità di programmazione giallo colore a Led Rendimento(); Ritorno; } CSS_Header_Template(); Temp = "<head><title>Lettore di schede RC522</title></head><body>"; Server.sendContent(Temp); Struttura HtmlNavStructure(); Temp = ""; Temp = "<br><br><br<br><br><bordo tabella<0 ALIGN><th>"; Server.sendContent(Temp); Temp = "<bordo tabella>1 bgcolor >nero><forma azione''/newPICC' method'''post'>"; Server.sendContent(Temp); Temp = "<tr><th>Cardholder:<br><div ALIGN>"; Server.sendContent(Temp); Temp = "Nome: <tipo di input:testo>'Cognome' Dimensione'17 segnaposto maxlenght'16''Max' obbligatorio><br>"; Server.sendContent(Temp); Temp = "Cognome: <tipo di input:testo>'NomeGiven' Dimensione'17 maxlenght'16 segnaposto''Mustermann' obbligatorio><br>"; Server.sendContent(Temp); Temp = "</div></th><th>Mappa metadati:<br><DIV ALIGN>"; Server.sendContent(Temp); Temp = "<input Name''ExpDateOption' TYPE''checkbox VALUE'1 >Data di scadenza:<tipo di input'nome'''ExpDate' Size ' 17 >"; Server.sendContent(Temp); Temp = "<br><th><tr><th></table><br>"; Server.sendContent(Temp); Temp = "<tipo di pulsante''submit' name''''NuovoBiglietto della Carta''1' style''height: 30px; larghezza: 200px' >Crea smart card</button>"; Server.sendContent(Temp); Temp = "<br></form></tr></th></tabella>"; Server.sendContent(Temp); Temp = "</body></html>"; Server.sendContent(Temp); Server.Client().Fermare(); Temp = ""; } Vuoto handleLog() { Int Dimensione = 0; Se (!is_authentified()) { Server.sendHeader (Intestazione)("Posizione", "/login"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Server.Invia(301); Ritorno; } Se (Server.hasArg("ClearLog")) { Se (SPIFFS.Esiste ("/usage_log.csv") ) Controllare se il file usage_log.csv essia. { SPIFFS.Rimuovere("/usage_log.csv"); Elimina file Seriale.println(D("ATFS:LogDelete")); Temp = "File di registrazione eventi eliminato."; WriteToLog(Temp, 0); Temp = ""; } Altro { Seriale.println(D("ATFS:LogDelete_ERR")); } Rendimento(); } CSS_Header_Template(); Rendimento(); Temp = "<head><title>Lettore di schede RC522</title></head><body>"; Server.sendContent(Temp); Struttura HtmlNavStructure(); Temp = "<br><br><br<br><br><bordo tabella >4 ALIGN><th>"; Server.sendContent(Temp); Temp = "<righe dell'area di testo,'20' cols''110' warp-soft readonly>"; Server.sendContent(Temp); Se (SPIFFS.Esiste ("/usage_log.csv")) Controllare se il file usage_log.csv essia. { Documento = SPIFFS.Aperto("/usage_log.csv", "r"); Aprire il file usage_log.csv nella directory radice per la lettura Se (!Documento) { Temp = "Impossibile aprire l'errore interno: Impossibile aprire il file di registro usage_log.csv!"; Server.sendContent(Temp); } Altro { Dimensione = Documento.Dimensione(); Mentre (Documento .Posizione() < Documento.Dimensione()) { Temp = Documento.ReadStringUntil (finestra in lettura)('n'); Temp.Tagliare(); Temp += "N"; Aggiungi avanzamento riga carattere Server.sendContent(Temp); } Documento.Vicino(); } } Altro { Temp = "Interner Fehler: Logdatei usage_log.csv nicht gefunden !"; Server.sendContent(Temp); } Temp = "</textarea></th></table><bordo tabella; Server.sendContent(Temp); SPIFFS.Informazioni(fs_info); Temp = "<br><div ALIGN> Loggroesse" + Stringa(Dimensione) + " Byte.<br>"; Server.sendContent(Temp); Temp = Stringa(fs_info.usedBytes (Byte usati)) + " Byte von " + Stringa(fs_info.totalBytes) + " Byte belegt.</div>"; Server.sendContent(Temp); Temp = "<th><azione modulo''/log' method'''post'><br><br>"; Server.sendContent(Temp); Temp = "<tipo di pulsante''submit' name'''RefreshLog' value''1' style''height: 30px; larghezza: 100px' >Aggiorna</pulsante>"; Server.sendContent(Temp); Temp = "<tipo di pulsante:'submit' name''''ClearLog' value''1' style''height: 30px; larghezza: 100px' >Cancella registro</pulsante>"; Server.sendContent(Temp); Temp = "</form></th></table></HTML>"; Server.sendContent(Temp); Server.Client().Fermare(); Temp = ""; } Vuoto handleRoot() { Se (!is_authentified()) { Server.sendHeader (Intestazione)("Posizione", "/login"); Server.sendHeader (Intestazione)("Cache-Control", "no-cache"); Server.Invia(301); Ritorno; } Contenuto HTML CSS_Header_Template(); Rendimento(); Temp = "<head><title>Kartenleser RC522</title></head><body>"; Server.sendContent(Temp); Struttura HtmlNavStructure(); Temp = "<div ALIGN><br><br><br><br><BIG>Willkommen auf der Smartkartenleser RC522 Webseite.</BIG><br>"; Server.sendContent(Temp); Temp = "Resetgrund: " + Stringa(Spagnolo.getResetReason()) + "<br>"; Server.sendContent(Temp); Temp = "Freier Heapspeicher: " + Stringa(Spagnolo.getFreeHeap()) + " Byte<br>"; Server.sendContent(Temp); Temp = "Int. Flash: " + Stringa(Spagnolo.getFlashChipRealSize()) + " Byte<br>"; Server.sendContent(Temp); Risultato = mfrc522.PCD_PerformSelfTest(); mfrc522.PCD_Init(); Initialisiere MFRC522 Lesemodul mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Setzt Antenne auf max. Empfang mfrc522.PCD_AntennaOn(); Rendimento(); Se (Risultato) { Temp = "RC522 PCD-Status: OK<br>"; } Altro { Temp = "RC522 PCD-Status: Fehler!<br>"; } Server.sendContent(Temp); Temp = "ID CPU: " + Stringa(Spagnolo.getChipId()) + " @ " + Stringa(Spagnolo.getCpuFreqMHz()) + " MHz<br>"; Server.sendContent(Temp); Temp = "<br>Sie sind erfolgreich angemeldet !<br>"; Server.sendContent(Temp); Temp = "<br>Programmiert von <a href>'mailto:tobias.kuch@googlemail.com'>Tobias Kuch</a><br></div></body></html>"; Server.sendContent(Temp); Se (Server.hasArg("Riavvia") ) Riavvia il sistema { Temp = "<script>alert('Das System startet JET-T neu.'); </script>"; Server.sendContent(Temp); Server.Client().Fermare(); Rendimento(); Temp = ""; Spagnolo.Reimpostare(); Ritardo(4000); } Server.Client().Fermare(); Temp = ""; } Vuoto CSS_Header_Template() Formatvorlage fàr alle internen ESP Webseiten. https://wiki.selfhtml.org/wiki/CSS { Server.setContentLength (lunghezza in cui è impostato)(CONTENT_LENGTH_UNKNOWN); Temp = ""; Server.Invia (200, "testo/html", Temp); Temp = "<! DOCTYPE HTML PUBLIC '---//W3C//DTD HTML 4.01 Transitional//EN'><html lang''de'><meta charset''UTF-8'>"; Server.sendContent(Temp); Temp = "<tipo di stile''testo/css'>'margin: 0;padding: 0; corpo:background:black;colore:darkorchid;font-size: 16px;"; "span color""#000000" style"color: #000000;">server span color" #434f54" "color: #434f54;"- &span color""#000000" style""color: #000000;"'sendContent'"span color""#000000" style""color: #000000;">('span color"style""#000000 color: #000000 "color: ""temp stile "#000000 #000000 #000000 #000000" color"#000000" style"color: #000000;">>temp color""#434f54" style""color:"color #434f54: " "span color"""#005c5f" style "color: #005c5f;">"font-family: sans-serif,arial;'. nav-width: 1300px;altezza: 30px;margin: 0 auto;border-radius: 5px;""; Server.sendContent(Temp); Temp = "ul li-list-style: nessuno;larghezza: 200px;line-height: 60px;position: relative;background: darkorchid;" ; "span color""#000000" style"color: #000000;">server span color" #434f54" "color: #434f54;"- &span color""#000000" style""color: #000000;"'sendContent'"span color""#000000" style""color: #000000;">('span color"style""#000000 color: #000000 "color: ""temp stile "#000000 #000000 #000000 #000000" &span color"#000000" style "color: #000000;">>temp span color'"#434f54" style""color: #434f54;"", "span color""style""#005c5f color: #005c5f;">"box-shadow: 0px 2px 0px 0px grey;text-: center;float: left;background-color: #010000; ul ul; Server.sendContent(Temp); Temp = "Posizione: assoluto; nav > ul > li:nth-of-type(1) - border-radius: 5px 0px 0px 5px; nav > ul > li:nth-of-type(5)"; Server.sendContent(Temp); Temp = "-border-radius: 0px 5px 0px; ul li a-color: rgb(182, 18, 18);width: 200px;height: 58px;display: inline-block;" ; "span color""#000000" style"color: #000000;">server span color" #434f54" "color: #434f54;"- &span color""#000000" style""color: #000000;"'sendContent'"span color""#000000" style""color: #000000;">('span color"style""#000000 color: #000000 "color: ""temp stile "#000000 #000000 #000000 #000000" "span color"#000000" style"color: #000000;">>temp "#434f54" style "color #434f54: "color: "" "span color"""#005c5f color""color: #005c5f;">"text-decoration: none;' ul li a:hover-font-weight: grassetto;bordo-inferiore: 2px solido #fff; ul li ul-display: nessuno;; Server.sendContent(Temp); Temp = ".nav ul li:hover ul-display: block; fa-margin-right: 5px; contenitore- larghezza: 1000px;altezza: 200px;" ; "span color""#000000" style"color: #000000;">server span color" #434f54" "color: #434f54;"- &span color""#000000" style""color: #000000;"'sendContent'"span color""#000000" style""color: #000000;">('span color"style""#000000 color: #000000 "color: ""temp stile "#000000 #000000 #000000 #000000" &span color"#000000" style"color: #000000;">>temp "#434f54" style "color: #434f54 "color: " "#005c5f" style "color: #005c5f;">"margin: 0 auto;padding:20px 20px; @media schermo e (larghezza massima: 480px) - intestazione - larghezza: 100%;."; Server.sendContent(Temp); Temp = ".nav-display: nessuno;larghezza: 100%;altezza: auto; ul li-larghezza: 100%;float: nessuno; ul li a-larghezza: 100%;" ; "span color""#000000" style"color: #000000;">server span color" #434f54" "color: #434f54;"- &span color""#000000" style""color: #000000;"'sendContent'"span color""#000000" style""color: #000000;">('span color"style""#000000 color: #000000 "color: ""temp stile "#000000 #000000 #000000 #000000" "span color"#000000" style"color: #000000;">>temp "span color""#434f54" style "color: #434f54 "color: "" """#005c5f "stile" "#005c5f" "color: #005c5f;">"display: block; ul li ul posizione: statica; ul ul ul li a - sfondo: #222; fa-list.modify-display: blocco;; Server.sendContent(Temp); Temp = ".contenitore-larghezza: 100%;altezza: auto; body, overflow-x:nascosto; </style>"; Server.sendContent(Temp); Temp = ""; } Vuoto Struttura HtmlNavStructure() { Temp = "<classe div''menu'><nav class''nav'><ul>"; Server.sendContent(Temp); Temp = "<li><a href''>Sistema</a>"; Server.sendContent(Temp); Temp = "<ul><li><a href'/'>Informazioni</a></li>"; Server.sendContent(Temp); Temp = "<li><a href'/settings'>Sicherheit</a></li>"; Server.sendContent(Temp); Temp = "<li><a href'/login? DISCONNECT-1'>Abmelden</a></li>"; Server.sendContent(Temp); Temp = "<li><a href''/? Riavviare il sistema >Neustart</a></li>"; Server.sendContent(Temp); Temp = "</ul>"; Server.sendContent(Temp); Temp = "</li><li><a href''>PICC</a>"; Server.sendContent(Temp); Temp = "<ul><li><a href>Neue Karte erstellen</a></li>"; Server.sendContent(Temp); Temp = "<li><a href>/erasePICC'>Karte l'schen</a></li></ul>"; Server.sendContent(Temp); Temp = "</li>"; Temp = "</li><li><a href>'/log'>Ereignisprotokoll</a></li>"; Server.sendContent(Temp); Temp = "</ul></nav></div>"; Server.sendContent(Temp); Temp = ""; } Vuoto InitalizeHTTPServer() { Bool initok = False; Const Char * headerkeys (chiave dell'intestazione[] = {"Agente utente", "Cookie"} ; Intestazione zum Tracken Size_t headerkeyssize = Sizeof(headerkeys (chiave dell'intestazione) / Sizeof(Char*); Intestazione zum Tracken Server.su("/", handleRoot); Server.su("/login", handleLogin); Server.su("/newPICC", handleNewPICC); Server.su("/cancellaPICC", handleErasePICC); Server.su("/impostazioni", handleImpostazioni); Server.su("/log", handleLog); Server.onNotFound (innotiere) ( handleNotFound ); Server.collectHeaders(headerkeys (chiave dell'intestazione, headerkeyssize );Anweisen server, morire zu Tracken Server.Iniziare(); Avvio del server Web } "" , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , "" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Boolean InitalizeFileSystem (Filesystem)() { Bool initok = False; initok = SPIFFS.Iniziare(); Ritardo(200); Senza indugio ho visto l'indirizzo IP vuoto Se (!(initok)) Formato SPIFS, di non formattato. - Prova 1 { Seriale.println(F("ATFS:FRM")); SPIFFS.Formato(); initok = SPIFFS.Iniziare(); } Se (!(initok)) Formato SPIFS, di non formattato. - Prova 2 { SPIFFS.Formato(); initok = SPIFFS.Iniziare(); } Se (initok) { Seriale.println(F("ATFS:OK")); } Altro { Seriale.println(F("ATFS:NOK")); } Ritorno initok; } Boolean WriteToLog(Stringa LogEntry (Ingresso log), byte Tipo di log) { Bool writeok = False; SPIFFS.Informazioni(fs_info); Se (fs_info.totalBytes - fs_info.usedBytes (Byte usati) - 2000 > 1) Speicherplatz { Documento = SPIFFS.Aperto("/usage_log.csv", "a"); Dio Datei usage_log.csv im Root Verzeichnis zum schreiben Se (!Documento) { Documento.Vicino(); Seriale.println(F("ATFS:InitLog_ERR")); Ritorno writeok; } Temp = ""; Temp += "01.01.1980 12:00:00 "; noch EchtDatum hinzuf-gen Interruttore (Tipo di log) { Caso 0: Temp += "Info: "; Pausa; Caso 1: Temp += "Warnung: "; Pausa; Caso 2: Temp += "Fehler: "; Pausa; Predefinito: Temp += "Info: "; Pausa; } Temp += LogEntry (Ingresso log); writeok = Documento.println(Temp); Se (!(writeok)) { Seriale.println(F("ATFS:WriteLog_ERR")); } Documento.Vicino(); Temp = ""; } Ritorno writeok; } " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "" , o oos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktion von https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/wps-mit-dem-esp8266?ls=de Bool startWPS (avviWPS)() { Bool wpsSuccess (con i m: incui in = Wifi.beginWPSConfig (informazioni in base a un'impostazione in(); Se (wpsSuccess (con i m: incui in) { Muss nicht immer erfolgreich hei-en! Nach einem Timeout ist die SSID leer Stringa newSSID (informazioni in cui si crea il din) = Wifi.Ssid(); Se (newSSID (informazioni in cui si crea il din).Lunghezza() > 0) { Nur wenn eine SSID gefunden wurde waren wir erfolgreich Rendimento(); Seriale.println(F("ATWPS:OK")); saveCredentials (informazioni in base alle credenziali del servizio(); Salvare le credenziali in EEPROM } Altro { Seriale.println(F("ATWPS:NOK")); } } Ritorno wpsSuccess (con i m: incui in; } Bool startWiFiClient (avviOWiFiClient)() { Bool WiFiClientStarted = False; Size_t A0_ADCValue = 0; byte Ho = 0; byte connRes = 0; Seriale.setDebugOutput(False); Aktivieren Debugzwecken. Wifi.Hostname("CrdRdr41667"); Wifi.softAPdisconnect (softAPdisconnect)(Vero); Wifi.Scollegare(); Wifi.Modalità(WIFI_STA); Se (loadCredentials()) { Wifi.Iniziare(MyWiFiConfig.Nome APSTA, MyWiFiConfig.WiFiPwd); Mentre (( connRes != 3 ) E ( connRes != 4 ) E (Ho != 30)) se connRes : 0 "IDLE_STATUS - modificare Statius" { Ho++; Serial.print(F(".")); Collegare vorgang auf der seriellen Schnittstelle beobachten ESP.wdtFeed(); Ritardo(500); Rendimento(); connRes = Wifi.waitForConnectResult(); } Se (connRes == 4 ) { se la password non è corretta Seriale.println(F("ATWIFI:PWDERR")); Wifi.Scollegare(); } Se (connRes == 6 ) { modulo non è configurato in modalità stazione Seriale.println(F("ATWIFI:STAERR")); Wifi.Scollegare(); } } Se (Wifi.Stato() == WL_CONNECTED) { ESP.wdtFeed(); Seriale.Stampare(F("ATIP:")); Seriale.println(Wifi.localIP (informazioni in locale)()); Wifi.setAutoReconnect(Vero); Impostare se il modulo tenterà di riconnettersi a un punto di accesso nel caso in cui sia disconnesso. Configurare il risponditore MDNS Se (!Mdns.Iniziare("CrdRdr41667")) { Seriale.println(F("ATMDNS:NOK")); } Altro { Mdns.addService (servizio aggiuntivo)("http" (http), "tcp", 80); } WiFiClientStarted = Vero; } Altro { A0_ADCValue = analogicOLettura(A0); Wir waren nicht erfolgreich, daher starten wir WPS, wenn WPS Taster un A0 w'hrend des Resets gedr-ckt ist Se (A0_ADCValue > 499) { Se (startWPS (avviWPS)()) { ESP.wdtFeed(); Ritardo(500); Wifi.Scollegare(); Wifi.Modalità(WIFI_STA); Wifi.Iniziare(Wifi.Ssid().c_str(), Wifi.Psk().c_str()); ESP.wdtFeed(); WiFiClientStarted = Vero; } Altro { WiFiClientStarted = False; Wifi.Scollegare(); } } Altro { Wifi.Scollegare(); } } WiFi.printDiag(Serial); Aktivieren Debugzwecken. Ritorno WiFiClientStarted; } "" , o oos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le funzioni di avvio per l'eSEProM s., o, con il valore di e- , o le funzioni di avvio , ovvero le funzioni di avvio per l'EEPROM. Bool loadCredentials() { Bool RetValue (RetValue); Eeprom.Iniziare(512); Eeprom.Ottieni(0, MyWiFiConfig); Eeprom.Fine(); Se (Stringa(MyWiFiConfig.ConfigValid (Valido)) == "TK") { RetValue (RetValue) = Vero; } Altro { RetValue (RetValue) = False; Impostazioni WLAN nicht gefunden. } ESP.wdtFeed(); Ritorno RetValue (RetValue); } Vuoto saveCredentials (informazioni in base alle credenziali del servizio() Credenziali Speichere WLAN auf EEPROM { Size_t Ho; Per (Ho = 0 ; Ho < Sizeof(MyWiFiConfig) ; Ho++) Loeschen der alten Konfiguration { Eeprom.Scrivere(Ho, 0); } Per (Ho = 0 ; Ho < STANameLen ; Ho++) Loeschen der alten Konfiguration { MyWiFiConfig.WiFiPwd[Ho] = 0; } Per (Ho = 0 ; Ho < WiFiPwdLen ; Ho++) Loeschen der alten Konfiguration { MyWiFiConfig.Nome APSTA[Ho] = 0; } Temp = Wifi.Ssid().c_str(); Ho = Temp.Lunghezza(); Temp.toCharArray (matrice)(MyWiFiConfig.Nome APSTA, Ho + 1); Temp = Wifi.Psk().c_str(); Ho = Temp.Lunghezza(); Temp.toCharArray (matrice)(MyWiFiConfig.WiFiPwd, Ho + 1); Temp = ""; Strncpy(MyWiFiConfig.ConfigValid (Valido) , "TK", Sizeof(MyWiFiConfig.ConfigValid (Valido)) ); Eeprom.Iniziare(512); Eeprom.Mettere(0, MyWiFiConfig); Eeprom.Commettere(); Eeprom.Fine(); ESP.wdtFeed(); } Vuoto saveSysConfig (informazioni in base al ruolo di save() { byte Ho; Strncpy(Configurazionedisistema.ConfigValid (Valido) , "TK", Sizeof(Configurazionedisistema.ConfigValid (Valido)) ); Eeprom.Iniziare(512); Eeprom.Mettere(80, Configurazionedisistema); Eeprom.Commettere(); Eeprom.Fine(); ESP.wdtFeed(); } Bool loadSysConfig (informazioni in base alla proprietà loadSys() { Bool RetValue (RetValue); Eeprom.Iniziare(512); Eeprom.Ottieni(80, Configurazionedisistema); Eeprom.Fine(); Se (Stringa(Configurazionedisistema.ConfigValid (Valido)) == "TK") { RetValue (RetValue) = Vero; } Altro { Temp = Stringa(Spagnolo.getChipId()); Temp.toCharArray (matrice)(Configurazionedisistema.LoginPassword (Password di accesso) , PwMaxLength (Lunghezza massima)); Temp = ""; Strncpy(Configurazionedisistema.Loginname , "amministratore", Sizeof(Configurazionedisistema.Loginname) ); Configurazionedisistema.PCD_Disabled = False; Configurazionedisistema.USED_PICC_Sector = 1; saveSysConfig (informazioni in base al ruolo di save(); RetValue (RetValue) = False; Impostazioni di configurazione nicht g'ltig //Standardinitalisierung ausf-hre } ESP.wdtFeed(); Ritorno RetValue (RetValue); } Le funzioni di FINE Di s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "" , o , o , o , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Vuoto PCDHardReset (Ripristino PCDHard)() { digitalWrite (Scrittura digitale)(RST_PIN, Basso); Ritardo(200); digitalWrite (Scrittura digitale)(RST_PIN, alto); mfrc522.PCD_Reset(); mfrc522.PCD_Init(); Initialisiere MFRC522 Lesemodul mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Setzt Antenne auf max. Empfang mfrc522.PCD_AntennaOn(); } Boolean CardAuthenticate (Autenticard)(Boolean Tasto AB, byte Settore, byte Ikey[6]) { Const byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63}; byte statusA; statusA = 0; Per (Int Un = 0; Un < 6; Un++) { Chiave.keyByte (byte)[Un] = Ikey[Un]; } Tasto A Se (Tasto AB) { statusA = mfrc522.PCD_Authenticate(Numero di unità DI CRITTOGRAFIA::PICC_CMD_MF_AUTH_KEY_A, sectorkeytable[Settore], &Chiave, &(mfrc522.Uid)); Se (statusA != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { Seriale.println(F("ATAUTH:ERR_A")); Ritorno False; } } Tasto B Altro Se (Non Tasto AB) { statusA = mfrc522.PCD_Authenticate(Numero di unità DI CRITTOGRAFIA::PICC_CMD_MF_AUTH_KEY_B, sectorkeytable[Settore], &Chiave, &(mfrc522.Uid)); Se (statusA != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { Seriale.println(F("ATAUTH:ERR_B")); Ritorno False; } } Ritorno Vero; } WriteData . utilizza la variabile globale DataBuffer per la restituzione dei dati Boolean Dati di cardScrittura(byte Settore, byte Blocco, byte Valore[16]) { byte Stato; byte writevector; byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63}; writevector = Settore * 4 + Blocco - 1 ; Per (byte Un = 0; Un < 16; Un++) { Se (writevector == sectorkeytable[Un]) { Serial.println("NAK"); Ritorno False; } } Stato = mfrc522.MIFARE_Write(writevector, Valore, 16); Se (Stato != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { Seriale.println(F("ATPCD:W_ERR")); Serial.println(mfrc522. GetStatusCodeName(status)); Ritorno False; } Altro { Serial.print(F("ATPCD:Write_Card_OK")); Ritorno Vero; } } Lettura dati: utilizza dataBuffer variabile globale per la restituzione dei datiRead Data - uses Global Variable DataBuffer for Data Return Boolean CardDataLettura(byte Settore, byte Blocco) { byte statusi; byte readvector; Const byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63}; byte Dimensioni = 18; readvector = Settore * 4 + Blocco - 1 ; Per (byte Un = 0; Un < 16; Un++) { Se (readvector == sectorkeytable[Un]) { Seriale.println(F("ATPCD:R_ERR")); Ritorno False; } } statusi = mfrc522.MIFARE_Read(readvector, DataBuffer (DataBuffer), &Dimensioni); Se (statusi != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { Seriale.println(F("ATPCD:R_ERR")); Ritorno False; } Altro { Ritorno Vero; } } Boolean ImpostaCardToDefault() { byte Ikey[16]; byte Stato, Ho; byte writevector; Const byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63}; writevector = sectorkeytable[USED_Sector]; Se (CardAuthenticate (Autenticard)(CHIAVEB, USED_Sector, MiFareClassicKey.Key_B)) Servizio Dissolvito per l'accesso WRITE { Per (Ho = 0; Ho <= 16; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; } Se (!(Dati di cardScrittura(USED_Sector, 1, DataBuffer (DataBuffer)))) { Ritorno False; } Per (Ho = 0; Ho <= 16; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; } Se (!(Dati di cardScrittura(USED_Sector, 2, DataBuffer (DataBuffer)))) { Ritorno False; } Per (Ho = 0; Ho <= 16; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; } Se (!(Dati di cardScrittura(USED_Sector, 3, DataBuffer (DataBuffer)))) { Ritorno False; } } Per (byte Ho = 0; Ho <= 16; Ho++) { Ikey[Ho] = 255; Carica chiave predefinita per tutti i settori } Ikey[6] = 0xff; Impostazione predefinita per i bit di accesso Ikey[7] = 0x07 (in tissuta in stato di; // Ikey[8] = 0x80 (in questo 0x80); // Ikey[9] = 0x69 (in inglese); Stato = mfrc522.MIFARE_Write(writevector, Ikey, 16); Se (Stato != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { Ritorno False; } Ritorno Vero; } Boolean SetSectorAccessControl (controllo di comando) (byte Settore, byte Achiave[6], byte Bkey[6]) { byte Ikey[16]; byte Stato; byte writevector; Const byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63}; writevector = sectorkeytable[Settore]; Ikey[0] = Achiave[0]; Ikey[1] = Achiave[1]; Ikey[2] = Achiave[2]; Ikey[3] = Achiave[3]; Ikey[4] = Achiave[4]; Ikey[5] = Achiave[5]; Ikey[6] = 0x78 (in tissuta); Condizioni di accesso del blocco dati 0-3: chiave B scrittura / chiave a lettura Ikey[7] = 0x77 (in via di sinfamin2; KEY A & KEY B & Acces Bits Write:Key B / Key A Read Access Bits Ikey[8] = 0x88 (informazioni in due); Calcolatrice: http://calc.gmss.ru/Mifare1k/ Ikey[9] = 0x69 (in inglese); Fissaggio Wert - > esadecimale predefinito 69 Ikey[10] = Bkey[0]; Ikey[11] = Bkey[1]; Ikey[12] = Bkey[2]; Ikey[13] = Bkey[3]; Ikey[14] = Bkey[4]; Ikey[15] = Bkey[5]; Stato = mfrc522.MIFARE_Write(writevector, Ikey, 16); Se (Stato != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { Seriale.println(F("ATPCD:W_KEY_ERR")); Ritorno False; } Altro { Ritorno Vero; } } Boolean Controllo T:System.Windows.Web.com/default< () { byte Tkey[6]; Boolean CardRisultato; byte readvector; byte statusi; Const byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63}; byte Dimensioni = 18; Per (byte Ho = 0; Ho <= 6; Ho++) { Tkey[Ho] = 255; Carica chiave predefinita per tutti i settori } CardRisultato = Vero; Se (!CardAuthenticate (Autenticard)(Keya, USED_Sector, Tkey)) { CardRisultato = False; }; readvector = sectorkeytable[USED_Sector]; statusi = mfrc522.MIFARE_Read(readvector, DataBuffer (DataBuffer), &Dimensioni); Se (statusi != Numero di unità DI CRITTOGRAFIA::STATUS_OK) { CardRisultato = False; } if (!( (DataBuffer[7] - 0x07) & (DataBuffer[7] - 0x80)) . Ritorno CardRisultato; } Boolean ScritturaNewMiFareClassicPIC () { byte Tkey[6]; byte Ho, Un; Boolean CardRisultato; Se (ControlloT:System.Windows.Web.com/default< ()) { Per (Ho = 0; Ho <= 6; Ho++) { Tkey[Ho] = 255; Carica chiave predefinita per tutti i settori } Per (Ho = 0; Ho <= 16; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; Cancella buffer variabile } CardRisultato = Vero; Se (CardAuthenticate (Autenticard)(Keya, USED_Sector, Tkey)) Settore Autosiate { Serial.println("Auth Sec 0 OK"); Se (Cognome.Lunghezza() > 15) { Un = 15; } Altro { Un = Cognome.Lunghezza(); } Se (Cognome.Lunghezza() > 0) { Per (Ho = 0; Ho <= 16; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; } Per (Ho = 0; Ho <= Un; Ho++) { DataBuffer (DataBuffer)[Ho] = Cognome[Ho]; } Se (!(Dati di cardScrittura(USED_Sector, 2, DataBuffer (DataBuffer)))) { CardRisultato = False; Settore 0 Blocco 2 Vorname mit Chiave A schreiben } } Se (Givenname.Lunghezza() > 15) { Un = 15; } Altro { Un = Givenname.Lunghezza(); } Se (Givenname.Lunghezza() > 0) { Per (Ho = 0; Ho <= 16; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; } Per (Ho = 0; Ho <= Un; Ho++) { DataBuffer (DataBuffer)[Ho] = Givenname[Ho]; } Se (!(Dati di cardScrittura(USED_Sector, 3, DataBuffer (DataBuffer)))) { CardRisultato = False; Settore 0 Blocco 3 Nachname mit Chiave A schreiben } } Se (!(SetSectorAccessControl (controllo di comando) (USED_Sector, MiFareClassicKey.Key_A, MiFareClassicKey.Key_B))) { CardRisultato = False; (byte Settore,byte Akey[6],byte Bkey[6]) } } Altro { CardRisultato = False; Ritorno CardRisultato; } } Altro { CardRisultato = False; Ritorno CardRisultato; } Se (CardRisultato) { Serial.println("PICC scritto"); CardRisultato = Vero; } Altro { Serial.println("PICC non vuoto"); CardRisultato = False; } Rendimento(); Ritorno CardRisultato; } Boolean LetturaMiFareClassicPICC () { Boolean CardRisultato; byte Ho ; CardRisultato = Vero; Se (CardAuthenticate (Autenticard)(Keya, USED_Sector, MiFareClassicKey.Key_A)) Settore Autosiate con LEGGI Chiave A { Givenname = " "; Segnaposto Cognome = " "; Segnaposto Per (Ho = 0; Ho < 18; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; Cancella buffer variabile } Se (CardDataLettura(USED_Sector, 2)) Feld Vorname auslesen { Per (Ho = 0; Ho < 16; Ho++) { Cognome[Ho] = Char(DataBuffer (DataBuffer)[Ho]); } } Altro { Ritorno False; } Per (Ho = 0; Ho < 18; Ho++) { DataBuffer (DataBuffer)[Ho] = 0; Cancella buffer variabile } Se (CardDataLettura(USED_Sector, 3)) Feld Nachname auslesen { Per (Ho = 0; Ho < 16; Ho++) { Givenname[Ho] = Char(DataBuffer (DataBuffer)[Ho]); } } Altro { Ritorno False; } } Altro { Ritorno False; } Ritorno Vero; } Vuoto Server di scheda() { byte Ho ; # define PCD_Poll_Interval 400 # define PCD_Watchdog_Interval 60000 Se (millis() - PCD_ServiceCall_Handler >= PCD_Poll_Interval) { PCD_ServiceCall_Handler = millis(); Se (mfrc522.PICC_IsNewCardPresent()) PICC - scheda di circuito integrato di prossimità - kontaktlose Chipkarte { mfrc522.PICC_ReadCardSerial(); Rendimento(); Unterscheidung nach Kartentyp 0x08 f'r MIFARE Classico 1K 0x18 f'r MIFARE Classic 4K 0x11 miFARE PLUS Se (mfrc522.Uid.Sak == 0x08 (in tissuta 0x0 || mfrc522.Uid.Sak == 0x18 (in tissuda (in due)) { MiFare_Classic_Processor START (mfrc522.uid.sak); Nur ausf'hren wenn Eine Mifare Classic Karte vor den Leser gehalten wurde. byte Tkey[6]; Per (byte Ho = 0; Ho <= 6; Ho++) { Tkey[Ho] = 255; Carica chiave predefinita per tutti i settori } Se (LearnNewCard) neue Karte soll angelernt werden. { Se (ScritturaNewMiFareClassicPIC()) { SetRGBLed(0, 255, 0, False); LearnNewCard = False; } Altro { SetRGBLed(255, 0, 0, False); LearnNewCard = False; } } Altro Se (Cancellascheda) KartenDaten sollen gel-scht werden. { Se (ImpostaCardToDefault()) { SetRGBLed(0, 255, 0, False); Cancellascheda = False; } Altro { SetRGBLed(255, 0, 0, False); Cancellascheda = False; } } Altro { Se (LetturaMiFareClassicPICC()) { Karte gàltig ! Seriale.Stampare (F("ATAUTH_S:")); Seriale.println (Cognome); Seriale.Stampare (F("ATAUTH_G:")); Seriale.println (Givenname); Temp = "Gàltige Karte. Benutzer: "; Per (Ho = 0; Ho < 16; Ho++) { Se (Givenname[Ho] == 0) { Pausa; } Temp += Char(Givenname[Ho]); } Temp += ", "; Per (Ho = 0; Ho < 16; Ho++) { Se (Cognome[Ho] == 0) { Pausa; } Temp += Char(Cognome[Ho]); } Temp += " - UUID der Karte: "; Per (byte Ho = 0; Ho < 4; Ho++) { Temp += Stringa(mfrc522.Uid.bytedByte[Ho], Hex) + " "; } WriteToLog(Temp, 0); Temp = " "; Eseguire azioni se viene rilevata la scheda corretta Bool PinState = digitalRead (Lettura digitale)(RELAIS_PIN); PinState = !PinState; digitalWrite (Scrittura digitale)(RELAIS_PIN, PinState); SetRGBLed(0, 255, 0, False); Led Gràn Temp = ""; } Altro { SetRGBLed(255, 0, 0, False); Temp = ""; Per (byte Ho = 0; Ho < 4; Ho++) { Temp += Stringa(mfrc522.Uid.bytedByte[Ho], Hex) + " "; } Temp = "Unbekannte MiFare Classic Karte. UUID der Karte: " + Temp ; WriteToLog(Temp, 1); Temp = ""; } } LearnNewCard = False; MiFare_Classic_Processor STOP (mfrc522.uid.sak); } Altro Se (mfrc522.Uid.Sak == 0x00 (in questo 0x00)) Mifare Ultraleggero { SetRGBLed(255, 0, 0, False); Temp = ""; Per (byte Ho = 0; Ho < 7; Ho++) { Temp += Stringa(mfrc522.Uid.bytedByte[Ho], Hex) + " "; } Temp = "Mifare UltraLight Karte nicht unterst-tzt. UUID der Karte: " + Temp; WriteToLog(Temp, 1); Temp = ""; } Altro { SetRGBLed(255, 0, 0, False); Temp = ""; Per (byte Ho = 0; Ho < mfrc522.Uid.Dimensione; Ho++) { Temp += Stringa(mfrc522.Uid.bytedByte[Ho], Hex) + " "; } Temp = "Unbekannte Karte und Kartentyp. Typnummer: " + Stringa(mfrc522.Uid.Sak) + " UUID der Karte: " + Temp ; WriteToLog(Temp, 1); Temp = ""; } mfrc522.PCD_StopCrypto1(); mfrc522.PICC_HaltA(); Ritardo(2000); SetRGBLed(0, 0, 255, False); Led Farbe Blau Leser ist a Grundzustand } } Se (millis() - PCD_WatchDog_Handler >= PCD_Watchdog_Interval) { PCD_WatchDog_Handler = millis(); Risultato = mfrc522.PCD_PerformSelfTest(); Rendimento(); mfrc522.PCD_Init(); Inizializzare nuovamente il modulo di lettura MFRC522 mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Imposta l'antenna su max. ricezione mfrc522.PCD_AntennaOn(); Rendimento(); Se (!(Risultato)) { PCDHardReset (Ripristino PCDHard)(); Seriale.println(D("ATPCD:ERR_H")); } } } Stop Functions CardServices ************************************************************************************************************************* Vuoto Ciclo() Ciclo principale { Server.handleClient(); Modificare le richieste del server Web Se (!(PCD_Disabled) | !(Configurazionedisistema.PCD_Disabled)) { Server di scheda(); Lettore di mappe per gestire richieste specifiche } Spagnolo.wdtFeed (informazioni in due)(); Watchdog. Disabilita con "wdt_disable();" }
Vi auguro un sacco di divertimento e molto successo nella costruzione del progetto e fino alla prossima volta.
3 commenti
Markus
Hallo,
vielen Dank für das wunderbare Projekt.
Ich habe es mir einmal durchgelesen und bin gespannt wie es funktionieren wird.
Freundliche Grüße!
Martin Kurth
Leider hat Tobias dieses Projekt nicht weiter verfolgt oder veröffentlicht. Ich würde es wirklich gerne einsetzen. Aber leider hat er wohl keine Zeit mehr dafür.
Martin Kurth
Ich bekomme die Fehler nicht weg. IDE 1.8.10.
G:\BOX.heidelberg.projekt\MiFare_CardReader-master\CardReader_ESP8266_-Teil_5\CardReader_ESP8266_-Teil_5.ino:27:0: warning: "PINWIRESDA" redefined [enabled by default]
#define PIN_WIRE_SDA 4 ^In file included from C:\Users\Martin\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\cores\esp8266/Arduino.h:302:0,
from sketch\CardReader_ESP8266_-_Teil_5.ino.cpp:1:C:\Users\Martin\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\variants\nodemcu/pins_arduino.h:29:0: note: this is the location of the previous definition
#define PIN_WIRE_SDA (4) ^G:\BOX.heidelberg.projekt\MiFare_CardReader-master\CardReader_ESP8266_-Teil_5\CardReader_ESP8266_-Teil_5.ino:28:0: warning: "PINWIRESCL" redefined [enabled by default]
#define PIN_WIRE_SCL 5 ^In file included from C:\Users\Martin\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\cores\esp8266/Arduino.h:302:0,
from sketch\CardReader_ESP8266_-_Teil_5.ino.cpp:1:C:\Users\Martin\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2\variants\nodemcu/pins_arduino.h:30:0: note: this is the location of the previous definition
#define PIN_WIRE_SCL (5) ^G:\BOX.heidelberg.projekt\MiFare_CardReader-master\CardReader_ESP8266_-Teil_5\CardReader_ESP8266_-_Teil5.ino: In function ‘void saveCredentials()’:
G:\BOX.heidelberg.projekt\MiFare_CardReader-master\CardReader_ESP8266_-Teil_5\CardReader_ESP8266_-_Teil5.ino:806:34: warning: iteration 20u invokes undefined behavior [-Waggressive-loop-optimizations]
MyWiFiConfig.APSTAName[i] = 0; ^G:\BOX.heidelberg.projekt\MiFare_CardReader-master\CardReader_ESP8266_-Teil_5\CardReader_ESP8266_-_Teil5.ino:804:3: note: containing loop
for (i = 0 ; i < WiFiPwdLen ; i++) // Loeschen der alten Konfiguration ^In file included from C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522Extended.cpp:8:0:
C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522Extended.h: In constructor ‘MFRC522Extended::MFRC522Extended(uint8_t)’:
C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522Extended.h:81:44: warning: ‘MFRC522::MFRC522’ is deprecated (declared at C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.h:339): use MFRC522 [-Wdeprecated-declarations]
MFRC522Extended(uint8_t rst) : MFRC522 {}; ^C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.cpp: In member function ‘bool MFRC522::MIFARE_SetUid(byte*, byte, bool)’:
C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.cpp:1853:39: warning: ‘bool MFRC522::MIFARE_OpenUidBackdoor(bool)’ is deprecated (declared at C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.cpp:1709): will move to extra class in next version [-Wdeprecated-declarations]
if (!MIFARE_OpenUidBackdoor(logErrors)) { ^C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.cpp: In member function ‘bool MFRC522::MIFARE_UnbrickUidSector(bool)’:
C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.cpp:1882:34: warning: ‘bool MFRC522::MIFARE_OpenUidBackdoor(bool)’ is deprecated (declared at C:\Users\Martin\Documents\Arduino\libraries\MFRC522\src\MFRC522.cpp:1709): will move to extra class in next version [-Wdeprecated-declarations]
MIFARE_OpenUidBackdoor(logErrors); ^