beperkingen op de toegang tot apparaten via een Contactloze Kaart met de NodeMCU en de RC522 module het derde deel van de WPA ,een web-interface met wachtwoord beveiliging, informatie over de status, en een uitvouwbaar menu bar.
Nadat we in het eerste deel van de Hardware is gedefinieerd, en een kaart voor het schakelen van de Relais kunnen gebruiken, kopen we onze ESP in het derde deel van deze serie met een WPS-drukknop, worden de WLAN-configuratie automatisch over te nemen in staat zijn om, evenals een pagina aanmelden voor onze ESP, de configuratie tegen niet-geautoriseerde Wijziging te beschermen.
WPA-registratie:
in de toekomst, de Wi-Fi-gegevens met behulp van de WPA-methode met drukknop in onze ESP opslaan, moeten we ons het eerste deel gepresenteerd van de basic-circuit een beetje.
We hebben 3 precisie Weerstanden met een 6.8 KOhm en een druk op de knop. Deze knop sluit het midden van de weerstand van het spannugn tussenschot kort om voor ons ESP kan voorafgaand nitreren een druk op de knop Regis. De bovenstaande grafiek toont de noodzakelijke verbindingen, en ons circuit dient te worden TOEGEVOEGD van het eerste artikel.
Hier is de Code:
#include <SPI.h> #include <MFRC522.h> #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <EEPROM.h> #define RST_PIN 5 / SPI/ Reset Pin (D1-uitgang) #define RELAIS_PIN 16 // Relais (D0-uitgang) [LAAG Actief] - Ook interne LED sluiten op de USB-Poort #define SS_PIN 15 // SPI Slave Select Pin #define RGBLED_R 2 // Rood (D4, output) #define RGBLED_G 0 // Groen (D3, output) - Ook interne LED op de ESP-module #define RGBLED_B 4 // Blue (D2 uitgang) #define WiFiPwdLen 25 // Maximale WiFi-wachtwoord lengte #define STANameLen 20 // Maximum WiFi SSIDlänge #define ESPHostNameLen 20 // Maximum aantal tekens ESPHostName #define LED_BUILTIN 16 #define PIN_WIRE_SDA 4 #define PIN_WIRE_SCL 5 ADC_MODE(ADC_TOUT); // analoge ingang A0 om extern te configureren. ADC_TOUT (voor externe spanning), ADC_VCC (voor systeem spanning). MFRC522 mfrc522(SS_PIN, RST_PIN); // instantie van de MFRC522 kan genereren MFRC522::MIFARE_Key toets; ESP8266WebServer server(80); / Web Server maken van een exemplaar struct de wifi-EEPROM de gegevens { char ESPHostName[ESPHostNameLen]; char APSTAName[STANameLen]; // STATION /AP Point name-Naam toegangspunt om Verbinding TE maken, indien gedefinieerd char WiFiPwd[WiFiPwdLen]; // wifi pass word, indien gedefinieerd char config geldig[3]; //Als Config is Vaild, Dag "TK" vereist" }; struct Piccard EEPROM de gegevens { char CardVaildUID[4]; char Voorbehouden[4]; }; wifi EEPROM de gegevens MyWiFiConfig; Piccard EEPROM de gegevens MyEEPROMValidCardUID; // Globale Variabele Gebruikt bool Resultaat = false; bool LearnNewCard = false,; String temp =""; unsigned long SessionID; void setup() { pinMode(RST_PIN,OUTPUT); digitalWrite(RST_PIN,, HOGE); pinMode(RELAIS_PIN,OUTPUT); pinMode(RGBLED_R,OUTPUT); pinMode(RGBLED_G,OUTPUT); pinMode(RGBLED_B,OUTPUT); digitalWrite(RELAIS_PIN,HIGH); // Relais inactief SetRGBLed(0,0,0,false); //Led UIT Seriële.beginnen(115200); // Seriële communicatie met een PC met 115200 Baud initialiseren van de opbrengst(); Seriële.println(""); temp = "ATSN:"+ String(ESP.getChipId()); Seriële.println(temp); // Serial.print("ADC-Waarde:");Serie.println(analogRead(A0)); SPI.beginnen(); // initialiseren van de SPI communicatie, ESP.wdtEnable(WDTO_4S); // Start Waakhond ESP.wdtFeed(); digitalWrite(RST_PIN,- LAGE); SessionID = millis(); ESP.wdtFeed(); Resultaat = start WiFi-client(); ESP.wdtFeed(); opbrengst(); EEPROM.beginnen(512); EEPROM.krijgen(100,MyEEPROMValidCardUID); // Beginnen op adres 100, de geldige kaart, opgeslagen in een EEPROM.einde(); initalize HTTPServer(); digitalWrite(RST_PIN,, HOGE); mfrc522.PCD_Reset(); mfrc522.PCD_Init(); // Initialiseren MF rc522 reader module MF rc522.PCD_AntennaOn(); opbrengst(); ESP.wdtFeed(); SetRGBLed(255,0,255,false,); //Led kleur Paars Initialisatie voltooid } // ******************* Start Helper/ Optimalisatie Functies ******************************** void SetRGBLed(byte RedValue,, byte waarde voor groen,- byte blue waarde,boolean SlowFade) //Funkion zur Steuerung der RGB Led { digitalWrite(RGBLED_R,LAGE); digitalWrite(RGBLED_G,LAGE); digitalWrite(RGBLED_B,LAAG); als (RedValue == 255) { digitalWrite(RGBLED_R,HOOG); } als (GreenValue == 255) { digitalWrite(RGBLED_G,HOOG); } als (BlueValue == 255) { digitalWrite(RGBLED_B,HOOG); } } // ******************* Stop Helper/ Optimalisatie Functies ********************************* // ******************* Start Functies Webserver ******************************************* //Cookie Basisroutinen basieren auf GIT Auszug: //https://github.com/esp8266/ESPWebServer/blob/master/examples/SimpleAuthentification/SimpleAuthentification.ino bool is_authentified() { als (server.hasHeader(de"Cookie" -)){ // Cookie gefunden temp = server.header("Cookie" -); //Serial.println(temp); String SessionStr = String(ESP.getChipId()) + "=" + String(SessionID); als (temp.indexOf(SessionStr) != -1) { // Web Authenticatie erfolgreich temp = ""; return true; } } // Web Authenticatie fehlgeschlagen temp = ""; SessionID = millis(); return false; } void handleLogin(){ String msg; //String cookie = server.header("Cookies"); //Serial.println(koekje); als (server.hasArg("LOS")){ //Scheiding Benutzers; server.sendHeader("Locatie","/login"); server.sendHeader("Cache-Control","no-cache"); SessionID = millis(); temp = String(ESP.getChipId()) + "= NA ; HttpOnly ; SameSite=Strenge"; server.sendHeader("Set-Cookie",temp); temp = ""; server.verzenden,(301); retourneren; } als (server.hasArg("GEBRUIKERSNAAM") && server.hasArg("WACHTWOORD")){ temp = String(ESP.getChipId()); als (server.arg("GEBRUIKERSNAAM") == , "admin" && server."arg("WACHTWOORD") == temp ){ server.sendHeader("Locatie","/"); server.sendHeader("Cache-Control","no-cache"); SessionID = millis(); temp = String(ESP.getChipId()) + "=" + String(SessionID) + "; HttpOnly ; SameSite=Strenge"; server.sendHeader("Set-Cookie",temp); temp = ""; server.verzenden(301); retourneren; } msg = "<script>alert('Falscher Benutzername oder falsches Wachtwoord !');</script>"; } CSS_Header_Template(); temp = "<head><title>Login</title></head><body><DIV ALIGN=CENTER>"; server.sendContent(temp); temp = "<h2>Anmeldung een Kartenleser RC522</h2><body><br><br><table border=0 bgcolor=black><tr><th><DIV ALIGN=RIGHT>"; server.sendContent(temp); temp = "<form action='/login' method='post'>Benutzername: <input type=text Name='GEBRUIKERSNAAM' Size=17 required><br>"; server.sendContent(temp); temp = "Wachtwoord: <input type=password Name='WACHTWOORD' Size=17 required><br><br><br><button type='submit' "; server.sendContent(temp); temp = "naam='Login_Button' value='1' style='hoogte: 30 met een afwijkende; width: 100px' >Inloggen</button><br></th></tr></form></DIV></table>"; server.sendContent(temp); temp = "<br><SMALL>Damit die Anmeldung funktioniert, sind Cookies für diese Webseite zu erlauben.</SMALL>"; server.sendContent(temp); temp = msg + "</DIV></body></HTML>"; server.sendContent(temp); temp = ""; } void handleNotFound() { SessionID = millis(); temp = "Seite nicht gefunden.\n\n"; temp += "URI: "; temp += server.uri(); temp += "\nMethod: "; temp += (server.methode() == HTTP_GET)?"KRIJGEN":"POST"; temp += "\nArguments: "; temp += server.args(); temp += "\n"; voor (uint8_t ik=0; ik<server.args(); ik++){ temp += " " + server.argName(ik) + ": " + server.arg(ik) + "\n""; } server.verzenden(404, "text/plain", temp); temp = ""; } void handleNewPICC() { als (!is_authentified()) { server.sendHeader("Locatie","/login"); server.sendHeader("Cache-Control","no-cache"); server.verzenden(301); retourneren; } CSS_Header_Template(); temp = "<head><title>Kartenleser RC522</title></head><body>"; server.sendContent(temp); HtmlNavStructure(); temp = "<script>alert('Bitte JETZT Karte vor den Leser halten!');</script>"; server.sendContent(temp); SetRGBLed(255,255,0,false); //Led Farbe Gelb Programmierungsmodus LearnNewCard = ware; temp = "</body></html>"; server.sendContent(temp); server.client().stop(); temp = ""; } void handleRoot(){ als (!is_authentified()){ server.sendHeader("Locatie","/login"); server.sendHeader("Cache-Control","no-cache"); server.verzenden(301); retourneren; } // HTML-Inhoud CSS_Header_Template(); temp = "<head><title>Kartenleser RC522</title></head><body>"; server.sendContent(temp); HtmlNavStructure(); temp = "<div ALIGN=CENTER><br><br><br><br><BIG>Willkommen auf der Smartkartenleser RC522 Webseite.</BIG><br>"; server.sendContent(temp); temp = "Resetgrund: " + String(ESP.getResetReason()) + "<br>"; server.sendContent(temp); temp = "Freier Heapspeicher: " + String(ESP.getFreeHeap()) + " Bytes<br>"; server.sendContent(temp); temp = "Int. Flash: " + String(ESP.getFlashChipRealSize()) + " Bytes<br>"; server.sendContent(temp); Resultaat = mfrc522.PCD_PerformSelfTest(); mfrc522.PCD_Init(); // Initialisiere MFRC522 Lesemodul mfrc522.PCD_AntennaOn(); als (Resultaat) {temp = "RC522 PCD-Status: OK<br>"; } anders {temp = "RC522 PCD-Status: Fehler!<br>"; } server.sendContent(temp); temp = "CPU ID: " + String(ESP.getChipId()) + " @ " + String(ESP.getCpuFreqMHz()) + " MHz<br>"; server.sendContent(temp); temp = "<br>Sie sind erfolgreich angemeldet !<br><br><form action='/login' method='get'>"; server.sendContent(temp); temp = "<button type='submit' name='verbinding VERBREKEN' value='JA' style='hoogte: 30 met een afwijkende; breedte: 200px' >Uitloggen</button>"; server.sendContent(temp); temp = "</form></div></body></html>"; server.sendContent(temp); als (server.hasArg("opnieuw opstarten") ) // Reboot het Systeem { ESP.wdtFeed(); ESP.wdtDisable(); temp = "<script>alert('Das Systeem startet JETZT neu.');</script>"; server.sendContent(temp); server.client().stop(); temp = ""; vertraging(1000); ESP.reset(); delay(4000); } server.client().stop(); temp = ""; } void CSS_Header_Template() // Formatvorlage für alle internen ESP Websites. https://wiki.selfhtml.org/wiki/CSS { server.setContentLength(CONTENT_LENGTH_UNKNOWN); temp = "<!DOCTYPE HTML PUBLIC '-/-//W3C//DTD HTML 4.01 Transitional//EN "><html lang= " de " ><meta charset='UTF-8'>"; server.verzenden (200, "text/html", temp); temp = "<style type='text/css'>*{margin: 0;padding: 0;}body{background:black;color:darkorchid;font-size: 16px;"; de server.sendContent(temp); temp = "font-family: sans-serif,arial;}.nav{width: 1300px;hoogte: 30 met een afwijkende;margin: 0 auto;border-radius: 5px;}"; server.sendContent(temp); temp = "ul li{list-style: none;width: 200px;line-height: 60px;position: relative;background: darkorchid;"; server.sendContent(temp); temp = "box-shadow: 2px 0px 5px 0px grijs;text-align: center;float: left;background-color: #010000;}ul li ul{"; server.sendContent(temp); temp = "position: absolute;}.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 5px 0px;}ul li a{color: rgb(182, 18, 18);width: 200px;height: 58px;display: inline-block;"; server.sendContent(temp); temp = "text-decoration: none;}ul li a:hover{font-weight: bold;border-bottom: 2px solid #fff;}ul li ul{display: none;}"; server.sendContent(temp); temp = ".nav ul li:hover ul{display: block;}.fa{margin-right: 5px;}.container{width: 1000px;height: 200px;"; server.sendContent(temp); temp = "margin: 0 auto;padding:20px 20px;}@media screen and (max-width: 480px){header{width: 100%;}"; server.sendContent(temp); temp = ".nav{display: none;width: 100%;height: auto;}ul li{width: 100%;float: none;}ul li a{width: 100%;"; server.sendContent(temp); temp = "display: block;}ul li ul{position: static;}ul li ul li a{background: #222;}.fa-lijst.wijzigen{display: block;}"; server.sendContent(temp); temp = ".container{width: 100%;height: auto;}body{overflow-x:hidden;}}</style>"; server.sendContent(temp); temp = ""; } void HtmlNavStructure() { temp = "<div class= "menu" ><nav class=nav><ul>"; server.sendContent(temp); temp = "<li><a href='#'>Systeem</a>"; server.sendContent(temp); temp = "<ul><li><a href="/nl">Informatie</a></li>"; server.sendContent(temp); temp = "<li><a href="/nl/?Reboot=YES">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="/nl/newPICC">Karte registrieren</a></li></ul>"; server.sendContent(temp); temp = "</li>"; server.sendContent(temp); temp = "</ul></nav></div>"; server.sendContent(temp); temp = ""; } void InitalizeHTTPServer() { bool initok = valse; const char * headerkeys[] = {"User-Agent",van"Cookie" -} ; //Header zum Tracken size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*); //Header zum Tracken server.op("/", handleRoot); server.op("/login", handleLogin); server.op("/newPICC", handleNewPICC); server.onNotFound ( handleNotFound ); server.collectHeaders(headerkeys, headerkeyssize );// Server anweisen, diese zu Tracken server.starten(); // Web-server start } // ******************* Eind Functies van de Webserver ********************************************* // ******************* Start Functies WiFi Management ************************************* // Funktion von https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/wps-mit-dem-esp8266?ls=de bool startWPS() { bool wpsSuccess = WiFi.beginWPSConfig(); als(wpsSuccess) { // Muss nicht immer erfolgreich heißen! Nach einem Time-out ist die SSID leer String newSSID = WiFi.SSID(); als(newSSID.lengte() > 0) { // Nur wenn eine SSID gefunden wurde waren wir erfolgreich opbrengst(); Seriële.println("ATWPS:OK"); saveCredentials(); // Opslaan van Referenties naar EEPROM } anders { Seriële.println("ATWPS:NOK"); } } terug wpsSuccess; } bool startWiFiClient() { bool WiFiClientStarted = valse; size_t A0_ADCValue = 0; byte ik = 0; byte connRes = 0; Seriële.setDebugOutput(false); // Zu Debugzwecken te activeren. WiFi.hostnaam("CrdRdr41667"); WiFi.softAPdisconnect(waar); WiFi.loskoppelen van(); WiFi.- modus(WIFI_STA); als(loadCredentials()) { WiFi.beginnen(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd); terwijl (( connRes != 3 ) en( connRes != 4 ) en (ik != 30)) //als connRes == 0 "IDLE_STATUS - wijzigen Statius" { i++; // Serial.print("."); // Connect vorgang auf der seriellen Schnittstelle beobachten ESP.wdtFeed(); vertraging(500); opleveren(); connRes = WiFi.waitForConnectResult(); } als (connRes == 4 ) { // als er een wachtwoord is onjuist Seriële.println("ATWIFI:PWDERR"); WiFi -.verbinding verbreken(); } als (connRes == 6 ) { // module is niet geconfigureerd in het station modus Seriële.println("ATWIFI:STAERR"); WiFi -.verbinding verbreken(); } } als(WiFi -.status() == WL_CONNECTED) { ESP.wdtFeed(); Serieel.afdrukken("ATIP:"); Seriële.println(WiFi.localIP()); WiFi.setAutoReconnect(true); // Set of module zal proberen opnieuw verbinding te maken met een toegangspunt in het geval dat de verbinding is verbroken. // Setup MDNS responder als (!MDNS.beginnen("CrdRdr41667")) { Seriële.println("ATMDNS:NOK"); } anders { MDNS.addService("http", "tcp", 80); } WiFiClientStarted = waar; } anders { A0_ADCValue = analogRead(A0); //Wir waren nicht erfolgreich, daher starten wir WPS wenn WPS Voorproefje van een A0 während des Zet gedrückt ist als (A0_ADCValue > 499) { als(startWPS()) { ESP.wdtFeed(); vertraging(500); WiFi.loskoppelen van(); WiFi.- modus(WIFI_STA); WiFi.beginnen(WiFi.SSID().c_str(), WiFi -.psk().c_str()); ESP.wdtFeed(); WiFiClientStarted = waar; } anders { WiFiClientStarted = valse; WiFi.verbinding verbreken(); } } anders { WiFi.koppel(); } } terug WiFiClientStarted; } // ******************* EIND Functies WiFi Management ************************************* // ******************* Start Functies Store WiFi Referenties naar EEPROM ****************** bool loadCredentials() { bool RetValue; EEPROM.beginnen(512); EEPROM.krijgen(0,MyWiFiConfig); EEPROM.einde(); als (String(MyWiFiConfig.ConfigValid) == "TK") { RetValue = waar; } anders { RetValue = false; // WLAN-Instellingen nicht gefunden. } ESP.wdtFeed(); terug RetValue; } void saveCredentials() // Speichere WLAN referenties auf EEPROM { size_t ik; voor (ik = 0 ; ik < sizeof(MyWiFiConfig) ; ik++) // Loeschen der alten Konfiguration { EEPROM.schrijf(ik, 0); } voor (ik = 0 ; ik < STANameLen ; ik++) // Loeschen der alten Konfiguration { MyWiFiConfig.WiFiPwd[ik] = 0; } voor (ik = 0 ; ik < WiFiPwdLen ; ik++) // Loeschen der alten Konfiguration { MyWiFiConfig.APSTAName[ik] = 0; } temp = WiFi.SSID().c_str(); ik = temp.lengte(); temp.toCharArray(MyWiFiConfig.APSTAName,ik+1); temp = WiFi -.psk().c_str(); ik = temp.lengte(); temp.toCharArray(MyWiFiConfig.WiFiPwd,ik+1); temp = ""; strncpy(MyWiFiConfig.ConfigValid , "TK", sizeof(MyWiFiConfig.ConfigValid) ); EEPROM.beginnen(512); EEPROM.zetten(0, MyWiFiConfig); EEPROM.plegen(); EEPROM.einde(); ESP.wdtFeed(); } // ******************* EIND Functies StoreCredentialsto EEPROM *************************** void loop() // Hauptschleife { // Nur wenn eine Karte gefunden wird und gelesen werden konnte, wird der Inhoud von ALS ausgeführt als (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() ) // PICC = nabijheid integrated circuit card = kontaktlose Chipkarte { Serieel.afdrukken("PICC UID:"); voor (byte ik = 0; ik < mfrc522.uid.grootte; i++) { // Abstand zwischen HEX-Zahlen und führende Null bei Byte < 16 Serieel.afdrukken(mfrc522.uid.uidByte[ik] < 0x10 ? " 0" : " "); Serieel.afdrukken(mfrc522.uid.uidByte[ik], HEX); } bool IsValid = ware; als (LearnNewCard) { voor (byte ik = 0; ik, < sizeof(MyEEPROMValidCardUID.CardVaildUID); ik++) { MyEEPROMValidCardUID.CardVaildUID[ik] = mfrc522.uid.uidByte[ik]; EEPROM.beginnen(512); EEPROM.zetten(100,MyEEPROMValidCardUID); EEPROM.plegen(); te EEPROM.einde(); LearnNewCard = false,; } IsValid = waar; } anders { voor (byte ik = 0; ik, < sizeof(MyEEPROMValidCardUID.CardVaildUID); ik++) { als (MF rc522.uid.uidByte[ik] != MyEEPROMValidCardUID.CardVaildUID[ik]) { IsValid = false; } } } als (IsValid) { bool PinState= digitalRead(RELAIS_PIN); PinState = !PinState; digitalWrite(RELAIS_PIN, PinState); SetRGBLed(0,255,0,false); //Groene Led Serieel.afdrukken(" geldig."); vertraging(2000); SetRGBLed(0,0,255,false,); //Led-kleur Blauw, de lezer is in de grond staat } anders { SetRGBLed(255,0,0,false,) ; //Led Rood - laatste-kaart is ongeldig Serieel.afdrukken('ongeldig'.); vertraging(2000); } Serial.. println(); mfrc522.PICC_HaltA(); // Zet de kaart lezen om een slaapstand om andere kaarten op zoek naar. vertraging(100); } server.afhandelen van de client(); / web server verzoeken opbrengst(); // interne ESP8266 call-functies, ESP.wdtFeed(); // Watchdog reset. vertraging(20); }
We de Code te compileren en uploaden naar onze ESP hoog. We beginnen de serial Monitor en zie het volgende output:
de eerste regel is het serienummer van de ESP ' s worden weergegeven. Dit maken we de opmerking van, aangezien we dit voor de eerste registratie op de website. De tweede rij is het IP-adres in, in ons LAN. Dit IP-we geven in de Browser, en krijgen het volgende beeld:
Als de aanmeldings-ID:#
gebruikersnaam: admin
wachtwoord: serienummer van het ESP-Chips. (ATSN nummer)
Als het aanmelden mislukt, zien we het volgende scherm:
Anders krijgen we naar het hoofdmenu:
PICC = Nabijheid Integrated Circuit Card
Om een nieuwe kaart te machtigen, klik dan wij nu, onder het menu "PICC" op de kaart om te registreren:
In het volgende artikel in de reeks luidt: Down the Rabbit Hole.. hebben we te maken met de functies van de Mifare Classic kaart schrijf ons voor de eerste keer gegevens op de chipkaart.
1 Reactie
Martin Kurth
Ich würde damit eine Wallbox Für ein E-Auto freischalten wollen. Es muss nur ein 12 V / 30mA Kontakt geschaltet werden. Da nehme ich dann ein Omron G3VM Halbleiterrelais.
Sinnvoll wäre auch eine feste IP. Dann muss man nicht im Terminal nach der Adresse schauen, wenn man später darauf zugreifen will. Helfen würde mir eine Routine, die die Freigabe nach einer definierten Zeit wieder entzieht, also den Ausgang wieder abschaltet. Der Ladevorgang dauert Max ca. 8h im ungünstigsten Fall.