Access restriction to devices via contactless card with the NodeMCU and the RC522 module part 5 - security.

Hello and welcome to a new blog post for the MiFare Card Reader.

In today's and the next blog post in the series, we focus on security and flexibility.

We want to shed some light on the security and flexibility of our card reader, as well as to ensure greater transparency in card reader actions. A major shortcoming of the preceding parts of this series was that although the administrator's login password on the web interface differed from card reader to card reader, this password could not be changed individually.
We want to change that today. From now on, it is possible to use the W

eb interface under System -> Security to enter a separate login password for the user "admin".

Menu: Password change

This own password can be between 3 and 16 characters long.
This defined drawing span can be set with the definitions PwMinLength and PwMaxLength in the code. If shorter or longer password limits are desired, the values can be adjusted individually.

 

The procedure for changing the user's password "admin" is:

• First login to the web interface with the username "admin" and the password consisting of the ESP ChipId. (As described in the previous parts of the series)
• Navigation under System -> Security then enter the same (new) password 2x and button ... Press.
• Logout under System -> Unsubscribe. The new password is immediately valid.

So we've increased the security a bit so that someone who knows our project and has access to the serial interface and over the network can't find out the valid login password right away.
Let's move on to another point of Rubrick security: from a security point of view, it would be desirable to know who used our card reader successfully or not successfully with which card. We are now creating the opportunity to do so. Under the new menu item "Event Log" we now see different entries for certain actions or events around our reader.
For example, we now see in the event log all attempts with valid and invalid cards to get our reader to take an action.

The following screenshot shows this as an example:

Event

 

As can be seen in the above screenshot, the list of the time and date is still generically set to a fixed value, because we still lack a valid time source. We will add this source to one of the next parts.
The correct initialization and use of the internal ESP SPIFFS file system is essential for the event log. To do this, we set the compilation options so that 2 MB of our available 4 MB of program memory is formatted as a SPIFFS file system. How to do this, I have already described in another blog post "ESP8266 – Everything SPIFFS or what?" by me under Setup.

Important: Without the correct SPIFFS setting, the code is compiled and uploaded to the ESP, but when booting the ESP with the message "ATFS:NOK" on the serial interface, "hang" and further initiation fails. We must keep this SPIFFS setting for all other following parts of this series.

 

The code for our blog today is:

 

#include <Spi.H>
#include <MFRC522.H>
#include <ESP8266WiFi.H>
#include <ESP8266WebServer.H>
#include <ESP8266mDNS.H>
#include <Eeprom.H>
#include <Fs.H>           Include the SPIFFS library

#define RST_PIN     5     SPI Reset Pin (D1 output)
#define RELAIS_PIN  16    Relay (D0 output) [LOW Active] - Also internal LED near USB port
#define SS_PIN      15    SPI Slave Select Pin

#define RGBLED_R    2     Red (D4 output) 
#define RGBLED_G    0     Green (D3 output) - Also internal LED on the ESP module
#define RGBLED_B    4     Blue (D2 output)

#define WiFiPwdLen 25     Maximum WiFi password length
#define STANameLen 20     Maximum WiFi SSID length
#define ESPHostNameLen 20 Maximum number of characters ESPHostName

#define Keya True         PICC Flag Definition
#define Keyb False        PICC Flag Definition

#define LED_BUILTIN 16
#define PIN_WIRE_SDA 4
#define PIN_WIRE_SCL 5

#define PwMinLength 3  Minimum login password length
#define PwMaxLength 16  Maximum login password length
#define LoginNameMaxLength 16  Maximum Login Name Length

#define USED_Sector 1  Card sector used for authentication and configuration data (valid: 1- 15)

ADC_MODE(ADC_TOUT);   Configure analog input A0 to external. ADC_TOUT (for external voltage), ADC_VCC (for system voltage).
MFRC522 mfrc522(SS_PIN, RST_PIN);   Create instance of MFRC522
MFRC522::MIFARE_Key Key;
ESP8266WebServer Server(80);        Web Server Create Instance
File Myfile;               create a SPIFFS Handling Variable
FSInfo fs_info;

Struct WiFiEEPromData 68 Bytes Object Lenght
{   Char ESPHostName[ESPHostNameLen]; // 20   Char APSTAName[STANameLen]; STATION /AP Point Name TO Connect, if definded 20   Char WiFiPwd[WiFiPwdLen]; WiFiPAssword, if definded 25   Char ConfigValid[3]; If Config is Vaild, tag "TK" is required" 3
};

Struct MiFareClassicKeyTable
{   Byte Key_A[6] = {0x22, 0x44, 0xFA, 0xAB, 0x90, 0x11}; Key for PICC card please change.   Byte Key_B[6] = {0xFE, 0xE1, 0xAA, 0x3D, 0xDF, 0x37}; Key for PICC card please change.   Char ConfigValid[3]; If Config is Vaild, tag "TK" is required"
};

Struct SysConf //
{   Char Loginname[LoginNameMaxLength]; // 16   Char LoginPassword[PwMaxLength];  // 16   Bool PCD_Disabled; // 1   Byte USED_PICC_Sector; // 1   Char ConfigValid[3]; If Config is Vaild, tag "TK" is required" - 3
};




MiFareClassicKeyTable MiFareClassicKey;
WiFiEEPromData MyWiFiConfig;
SysConf SystemConfiguration;


Globally used variables
Bool Result  = False;
Bool LearnNewCard = False;
Bool EraseCard = False;
Bool ExpirationDateActive = False;
Bool PCD_Disabled = False;
String Surname;
String Givenname;
String ExpirationDate;
String Temp;
Unsigned Long Sessionid;
Unsigned Long PCD_ServiceCall_Handler = 0;
Unsigned Long PCD_WatchDog_Handler = 0;
uint8_t DataBuffer[18]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };


Void Setup()
{   pinMode(RST_PIN, Output);   digitalWrite(RST_PIN, High);   pinMode(RELAIS_PIN, Output);   pinMode(RGBLED_R, Output);   pinMode(RGBLED_G, Output);   pinMode(RGBLED_B, Output);   digitalWrite(RELAIS_PIN, High);   Relay inactive   SetRGBLed(255, 0, 255, False);    Led Color Purple Initalization Begin   Serial.Begin(115200);               Initialize serial communication with the PC with 115200 Baud   Serial.println(Q(" "));   Temp = "ATSN:" + String(Esp.getChipId());   Serial.println(Temp);   Serial.print("ADC Value:"); Serial.println(analogRead(A0));   Spi.Begin();                      Initialize SPI communication   PCDHardReset();   Sessionid = millis();   Result = loadSysConfig();   Result = InitalizeFileSystem();   Result = startWiFiClient();   InitalizeHTTPServer();   Temp = "System startup: ";   Temp += String(Esp.getResetReason());   WriteToLog(Temp, 0);   Temp = "";   Esp.wdtEnable(4000);             Start Watchdog   SetRGBLed(0, 0, 255, False);    Led Color Blue Initalization Completed
}


Start Helper/ Optimization Functions **************************************************************************************************************

Void SetRGBLed(Byte RedValue, Byte GreenValue, Byte BlueValue, Boolean SlowFade) Funkion for controlling the RGB Led
{   digitalWrite(RGBLED_R, Low);   digitalWrite(RGBLED_G, Low);   digitalWrite(RGBLED_B, Low);   If (RedValue == 255)   {     digitalWrite(RGBLED_R, High);   }   If (GreenValue == 255) {     digitalWrite(RGBLED_G, High);   }   If (BlueValue == 255)  {     digitalWrite(RGBLED_B, High);   }
}

Stop Helper/ Optimization Functions *****************************************************************************************************************

Start Functions Web server *******************************************************************************************************************************************

Cookie base routines are based on GIT excerpt:
//https://github.com/esp8266/ESPWebServer/blob/master/examples/SimpleAuthentification/SimpleAuthentification.ino
Bool is_authentified()
{   If (Server.Hasheader("Cookie")) {     Cookie found     Temp = Server.Header("Cookie");     Serial.println(temp);     String SessionStr = String(Esp.getChipId()) + "=" + String(Sessionid);     Yield();     If (Temp.Indexof(SessionStr) != -1) {       Web authentication successful       Temp = "";       Return True;     }   }   Web Authentication Failed   Temp = "";   Sessionid = millis();   Return False;
}

Void handleLogin() {   String Msg;   String cookie = server.header("Cookie");   Serial.println(cookie);   If (Server.hasArg("DISCONNECT")) {     Disconnect users;     Sessionid = millis();     Temp = String(Esp.getChipId()) + "= NA ; HttpOnly ; SameSite=Strict";     Server.sendHeader("Set cookie", Temp);     Temp = "Unsubscribing from web interface.";     WriteToLog(Temp, 0);     Temp = "";     PCD_Disabled = False; Activate PCD after logout ;     SetRGBLed(0, 0, 255, False);    Led Color Blue StandardModre     Server.sendHeader("Location", "/login");     Server.sendHeader("Cache-Control", "no-cache");     Server.send(301);     Server.send(301);     yield();   }   If (Server.hasArg("USERNAME") && Server.hasArg("PASSWORD")) {     Temp = String(Esp.getChipId());     If (Server.Bad("USERNAME") == SystemConfiguration.Loginname &&  Server.Bad("PASSWORD") == SystemConfiguration.LoginPassword ) {       Server.sendHeader("Location", "/");       Server.sendHeader("Cache-Control", "no-cache");       Sessionid = millis();       Temp = String(Esp.getChipId()) + "=" + String(Sessionid) + "; HttpOnly ; SameSite=Strict";       Server.sendHeader("Set cookie", Temp);       Temp = "Registration of " + Server.Bad("USERNAME") + " to web interface.";       WriteToLog(Temp, 0);       Temp = "";       Server.send(301);       PCD_Disabled = True; Disable PCD as long as per web is working;       SetRGBLed(255, 0, 255, False);    Led Color Purple in Service Fashion       Return;     }     Msg = "<script>alert('Wrong username or password !'); </script>";     Temp = "Failed login attempt of " + Server.Bad("USERNAME") + " to web interface. Password: " + Server.Bad("PASSWORD") ;     WriteToLog(Temp, 1);     Temp = "";   }   CSS_Header_Template();   Temp = "<head><title>Login</title></head><body><DIV ALIGN=CENTER>";   Server.sendContent(Temp);   Temp = "<h2>Registration to card reader RC522</h2><body><br><br><br>table border=0 bgcolor=black><tr><th><DIV ALIGN=RIGHT>";   Server.sendContent(Temp);   Temp = "<form action='/login' method='post'>Username: <input type=text Name='USERNAME' Size=17 required><br>";   Server.sendContent(Temp);   Temp = "Password: <input type=password Name='PASSWORD' Size=17 required><br><br><br><br><button type=submit' ";   Server.sendContent(Temp);   Temp = "name='Login_Button' value='1' style='height: 30px; width: 100px' >Login</button><br></th></tr></form></DIV></table>";   Server.sendContent(Temp);   Temp = "<br><SMALL>For login to work, cookies for this website should be allowed.</SMALL>";   Server.sendContent(Temp);   Temp = Msg + "</DIV></body></HTML>";   Server.sendContent(Temp);   Temp = "";
}

Void handleNotFound()
{   Sessionid = millis();   Temp = "Page not found.;   Temp += "URI: ";   Temp += Server.Uri();   Temp += "AnMethod: ";   Temp += (Server.method() == HTTP_GET) ? "GET" : "POST";   Temp += "AnArguments: ";   Temp += Server.Args();   Temp += "An";   for (uint8_t  = 0;  < Server.Args(); ++) {     Temp += " " + Server.argName() + ": " + Server.Bad() + "An";   }   Yield();   Server.send(404, "text/plain", Temp);   Temp = "Calling the invalid URL: " + Server.Uri() + " Parameters: " + String(Server.Args()) ;   WriteToLog(Temp, 2);   Temp = "";
}



Void handleErasePICC()
{   If (!is_authentified())   {     Server.sendHeader("Location", "/login");     Server.sendHeader("Cache-Control", "no-cache");     Server.send(301);     Yield();     Return;   }   CSS_Header_Template();   Yield();   Temp = "<head><title>Card reader RC522</title></head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "<script>alert('Please keep the card to be deleted in front of the reader NOW!'); </script>";   Server.sendContent(Temp);   Yield();   EraseCard = True;   PCD_Disabled = False;   SetRGBLed(0, 255, 255, False);    Led color cyan programming mode   Temp = "</body></html>";   Server.sendContent(Temp);   Server.Client().Stop();   Temp = "";
}

Void handleSettings()
{   If (!is_authentified())   {     Server.sendHeader("Location", "/login");     Server.sendHeader("Cache-Control", "no-cache");     Server.send(301);     Return;   }   CSS_Header_Template();   Temp = "<head><title>Card reader RC522</title></head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "<br><br><div align=center><form method='post' action='/settings' method='post'>";   Server.sendContent(Temp);   Temp = "<p><label>New login password</label><br> <input type='password' name='newPassword'>";   Server.sendContent(Temp);   Temp = "</p><p><label>repeat login password</label><br> <input type='password' name='confirmNewPassword'><br><br><br>br>";   Server.sendContent(Temp);   Temp = "<button type='submit' name='Save' value='1' style='height: 30px; width: 200px' >Save</button></p></form></div>";   Server.sendContent(Temp);   temp = "</p><p><button type='submit' name='save'>Save</button></p></form></div></body></html>";   If (Server.hasArg("Save"))   {     If (Server.Bad("confirmNewPassword") == Server.Bad("newPassword"))     {       Temp = Server.Bad("newPassword");       If ((Temp.length() < PwMinLength ) |  (Temp.length() > PwMaxLength ))       {         Temp = "<br><div align=center><br>The password must be between at least ";         Server.sendContent(Temp);         Temp = String(PwMinLength) + " and maximum " + String(PwMaxLength) + " Be a character long.</div>";         Server.sendContent(Temp);       } else       {         Temp = Server.Bad("newPassword");         Temp.Tochararray(SystemConfiguration.LoginPassword , PwMaxLength);         saveSysConfig();         Temp = "The login password of user" + String(SystemConfiguration.Loginname) + "has been changed.";         WriteToLog(Temp, 0);         Temp = "<script>alert('The login password has been successfully changed.'); </script>";         Server.sendContent(Temp);       }     } else     {       Temp = "<br><div align=center><br>The passwords you entered do not match. Please re-enter.</div>";       Server.sendContent(Temp);     }   }   Temp = "</body></html>";   Server.sendContent(Temp);   Server.Client().Stop();   Temp = "";
}

Void handleNewPICC()
{   If (!is_authentified())   {     Server.sendHeader("Location", "/login");     Server.sendHeader("Cache-Control", "no-cache");     Server.send(301);     Return;   }   If (Server.hasArg("Surname") && Server.hasArg("Givenname"))   {     Surname = Server.Bad("Surname");     Givenname = Server.Bad("Givenname");     ExpirationDate = Server.Bad("ExpDate");     If (Server.hasArg("ExpDateOption")) {       ExpirationDateActive = True;     } else {       ExpirationDateActive = False;     }     Temp = "Creating a new map for: " + Server.Bad("Givenname") + ", " + Server.Bad("Surname");     WriteToLog(Temp, 0);     PCD_Disabled = False;     LearnNewCard = True;     CSS_Header_Template();     Temp = "<head><title>Card reader RC522</title></head><body>";     Server.sendContent(Temp);     HtmlNavStructure();     Temp = "<script>alert('Please keep the new card in front of the reader NOW!'); </script>";     Server.sendContent(Temp);     Temp = "</body></html>";     Server.sendContent(Temp);     Server.Client().Stop();     SetRGBLed(255, 255, 0, False);    Led Color Yellow Programming Mode     Yield();     Return;   }   CSS_Header_Template();   Temp = "<head><title>Card reader RC522</title></head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "";   Temp = "<br><br><br<br><br><table border=0 ALIGN=CENTER><th>";   Server.sendContent(Temp);   Temp = "<table border=1 bgcolor = black><form action='/newPICC' method='post'>";   Server.sendContent(Temp);   Temp = "<tr><th>Cardholder:<br><div ALIGN=RIGHT>";   Server.sendContent(Temp);   Temp = "First name: <input type=text Name='Surname' Size=17 maxlenght=16 placeholder='Max' required><br>";   Server.sendContent(Temp);   Temp = "Last name: <input type=text Name='Givenname' Size=17 maxlenght=16 placeholder='Mustermann' required><br>";   Server.sendContent(Temp);   Temp = "</div></th><th>Map metadata:<br><DIV ALIGN=RIGHT>";   Server.sendContent(Temp);   Temp = "<input Name='ExpDateOption' TYPE=checkbox VALUE=1 >Expiration date:<input type=date Name='ExpDate' Size = 17 >";   Server.sendContent(Temp);   Temp = "<br><th><tr><th></table><br>";   Server.sendContent(Temp);   Temp = "<button type='submit' name='NewCard' value='1' style='height: 30px; width: 200px' >Create a smart card</button>";   Server.sendContent(Temp);   Temp = "<br></form></tr></th></table>";   Server.sendContent(Temp);   Temp = "</body></html>";   Server.sendContent(Temp);   Server.Client().Stop();   Temp = "";
}


Void handleLog()
{   Int Filesize =  0;   If (!is_authentified())   {     Server.sendHeader("Location", "/login");     Server.sendHeader("Cache-Control", "no-cache");     Server.send(301);     Return;   }   If (Server.hasArg("ClearLog"))   {     If (SPIFFS.Exists ("/usage_log.csv") )  Check if file usage_log.csv exized.     {       SPIFFS.Remove("/usage_log.csv");  Delete File       Serial.println(Q("ATFS:LogDelete"));       Temp = "Event logging file deleted.";       WriteToLog(Temp, 0);       Temp = "";     } else {       Serial.println(Q("ATFS:LogDelete_ERR"));     }     Yield();   }   CSS_Header_Template();   Yield();   Temp = "<head><title>Card reader RC522</title></head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "<br><br><br<br><br><table border=4 ALIGN=CENTER><th>";   Server.sendContent(Temp);   Temp = "<textarea rows='20' cols='110' warp=soft readonly>";   Server.sendContent(Temp);   If (SPIFFS.Exists ("/usage_log.csv"))  Check if file usage_log.csv exized.   {     Myfile = SPIFFS.Open("/usage_log.csv", "r");  Open the file usage_log.csv in the root directory for reading     If (!Myfile)     {       Temp = "Internal error: Log file usage_log.csv could not be opened!";       Server.sendContent(Temp);     } else     {       Filesize = Myfile.Size();       while (Myfile .Position() < Myfile.Size())       {         Temp = Myfile.readStringUntil('n');         Temp.Trim();         temp += "\n"; // Add Character Line Feed         server.sendContent(temp);       }       myfile.close();     }   } else   {     temp = "Interner Fehler: Logdatei usage_log.csv nicht gefunden !";     server.sendContent(temp);   }   temp = "</textarea></th></table><table  border=0 ALIGN=CENTER>";   server.sendContent(temp);   SPIFFS.info(fs_info);   temp = "<br><div ALIGN=CENTER> Loggroesse " + String(FileSize) + " Bytes.<br>";   server.sendContent(temp);   temp = String(fs_info.usedBytes) + " Bytes von " + String(fs_info.totalBytes) + " Bytes belegt.</div>";   server.sendContent(temp);   temp = "<th><form action='/log' method='post'><br><br>";   server.sendContent(temp);   temp = "<button type='submit' name='RefreshLog' value='1' style='height: 30px; width: 100px' >Refresh</button>";   server.sendContent(temp);   temp = "<button type='submit' name='ClearLog' value='1' style='height: 30px; width: 100px' >Clear Log</button>";   server.sendContent(temp);   temp = "</form></th></table></HTML>";   server.sendContent(temp);   server.client().stop();   temp = "";
}

void handleRoot()
{   if (!is_authentified()) {     server.sendHeader("Location", "/login");     server.sendHeader("Cache-Control", "no-cache");     server.send(301);     return;   }   // HTML Content   CSS_Header_Template();   yield();   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);   Result = mfrc522.PCD_PerformSelfTest();   mfrc522.PCD_Init();                       // Initialisiere MFRC522 Lesemodul   mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); // Setzt Antenne auf max. Empfang   mfrc522.PCD_AntennaOn();   yield();   if (Result) {     temp = "RC522 PCD-Status: OK<br>";   } else {     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>";   server.sendContent(temp);   temp = "<br>Programmiert von <a href='mailto:tobias.kuch@googlemail.com'>Tobias Kuch</a><br></div></body></html>";   server.sendContent(temp);   if (server.hasArg("Reboot") )  // Reboot System   {     temp = "<script>alert('Das System startet JETZT neu.'); </script>";     server.sendContent(temp);     server.client().stop();     yield();     temp = "";     ESP.reset();     delay(4000);   }   server.client().stop();   temp = "";
}

void CSS_Header_Template() // Formatvorlage für alle internen ESP Webseiten. https://wiki.selfhtml.org/wiki/CSS
{   server.setContentLength(CONTENT_LENGTH_UNKNOWN);   temp = "";   server.send (200, "text/html", temp);   temp = "<! DOCTYPE HTML PUBLIC '-/-//W3C//DTD HTML 4.01 Transitional//EN'><html lang='de'><meta charset='UTF-8'>";   server.sendContent(temp);   temp = "<style type='text/css'>*{margin: 0;padding: 0;} body{background:black;color:darkorchid;font-size: 16px;" ;   server. sendContent(temp);   temp = "font-family: sans-serif,arial;}. nav{width: 1300px;height: 30px;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: 0px 2px 5px 0px grey;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-list.modify{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='#'>System</a>";   server.sendContent(temp);   temp = "<ul><li><a href='/'>Information</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='/? 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='/newPICC'>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 = "";
}

void InitalizeHTTPServer()
{   bool initok = false;   const char * headerkeys[] = {"User-Agent", "Cookie"} ; //Header zum Tracken   size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); //Header zum Tracken   server.on("/", handleRoot);   server.on("/login", handleLogin);   server.on("/newPICC", handleNewPICC);   server.on("/erasePICC", handleErasePICC);   server.on("/settings", handleSettings);   server.on("/log", handleLog);   server.onNotFound ( handleNotFound );   server.collectHeaders(headerkeys, headerkeyssize );// Server anweisen, diese zu Tracken   server.begin(); // Web server start
}

// ******************* End Functions Webserver *********************************************

// ******************* Start Functions Filesystem ******************************************
boolean InitalizeFileSystem()
{   bool initok = false;   initok = SPIFFS.begin();   delay(200); // Without delay I've seen the IP address blank   if (!(initok)) // Format SPIFS, of not formatted. - Try 1   {     Serial.println(F("ATFS:FRM"));     SPIFFS.format();     initok = SPIFFS.begin();   }   if (!(initok)) // Format SPIFS, of not formatted. - Try 2   {     SPIFFS.format();     initok = SPIFFS.begin();   }   if (initok) {     Serial.println(F("ATFS:OK"));   } else {     Serial.println(F("ATFS:NOK"));   }   return initok;
}

boolean WriteToLog(String LogEntry, byte Logtype)
{   bool writeok = false;   SPIFFS.info(fs_info);   if (fs_info.totalBytes - fs_info.usedBytes - 2000 > 1) // Speicherplatz überprüfen   {     myfile = SPIFFS.open("/usage_log.csv", "a");  //Öffne die Datei usage_log.csv im Root Verzeichnis zum schreiben     if (!myfile)     {       myfile.close();       Serial.println(F("ATFS:InitLog_ERR"));       return writeok;     }     temp = "";     temp += "01.01.1980 12:00:00 "; // noch EchtDatum hinzufügen     switch (Logtype)     {       case 0:         temp += "Info: ";         break;       case 1:         temp += "Warnung: ";         break;       case 2:         temp += "Fehler: ";         break;       default:         temp += "Info: ";         break;     }     temp += LogEntry;     writeok = myfile.println(temp);     if (!(writeok)) {       Serial.println(F("ATFS:WriteLog_ERR"));     }     myfile.close();     temp = "";   }   return writeok;
}


// ******************* End Functions Filesystem ********************************************

// ******************* Start Functions 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();   if (wpsSuccess) {     // Muss nicht immer erfolgreich heißen! Nach einem Timeout ist die SSID leer     String newSSID = WiFi.SSID();     if (newSSID.length() > 0) {       // Nur wenn eine SSID gefunden wurde waren wir erfolgreich       yield();       Serial.println(F("ATWPS:OK"));       saveCredentials(); // Save Credentials to EEPROM     } else {       Serial.println(F("ATWPS:NOK"));     }   }   return wpsSuccess;
}

bool startWiFiClient()
{   bool WiFiClientStarted = false;   size_t A0_ADCValue = 0;   byte i = 0;   byte connRes = 0;   Serial.setDebugOutput(false);  // Zu Debugzwecken aktivieren.   WiFi.hostname("CrdRdr41667");   WiFi.softAPdisconnect(true);   WiFi.disconnect();   WiFi.mode(WIFI_STA);   if (loadCredentials())   {     WiFi.begin(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd);     while (( connRes != 3 ) and ( connRes != 4 ) and (i != 30)) //if connRes == 0  "IDLE_STATUS - change Statius"     {       i++;       // Serial.print(F(".")); // Connect vorgang auf der seriellen Schnittstelle beobachten       //ESP.wdtFeed();       delay(500);       yield();       connRes  = WiFi.waitForConnectResult();     }     if (connRes == 4 ) { // if password is incorrect       Serial.println(F("ATWIFI:PWDERR"));       WiFi.disconnect();     }     if (connRes == 6 ) { //  module is not configured in station mode       Serial.println(F("ATWIFI:STAERR"));       WiFi.disconnect();     }   }   if (WiFi.status() == WL_CONNECTED)   {     //ESP.wdtFeed();     Serial.print(F("ATIP:"));     Serial.println(WiFi.localIP());     WiFi.setAutoReconnect(true); // Set whether module will attempt to reconnect to an access point in case it is disconnected.     // Setup MDNS responder     if (!MDNS.begin("CrdRdr41667"))     {       Serial.println(F("ATMDNS:NOK"));     } else {       MDNS.addService("http", "tcp", 80);     }     WiFiClientStarted = true;   } else   {     A0_ADCValue = analogRead(A0);     //Wir waren nicht erfolgreich, daher starten wir WPS, wenn WPS Taster an A0 während des Resets gedrückt ist     if (A0_ADCValue > 499)     {       if (startWPS())       {         //ESP.wdtFeed();         delay(500);         WiFi.disconnect();         WiFi.mode(WIFI_STA);         WiFi.begin(WiFi.SSID().c_str(), WiFi.psk().c_str());         //ESP.wdtFeed();         WiFiClientStarted = true;       } else       {         WiFiClientStarted = false;         WiFi.disconnect();       }     } else     {       WiFi.disconnect();     }   }   //WiFi.printDiag(Serial);       // Zu Debugzwecken aktivieren.   return WiFiClientStarted;
}
// ******************* END Functions WiFi Management *************************************

// ******************* Start Functions Store WiFi Credentials to EEPROM ******************
bool loadCredentials()
{   bool RetValue;   EEPROM.begin(512);   EEPROM.get(0, MyWiFiConfig);   EEPROM.end();   if (String(MyWiFiConfig.ConfigValid) == "TK")   {     RetValue = true;   } else   {     RetValue = false; // WLAN Settings nicht gefunden.   }   //ESP.wdtFeed();   return RetValue;
}

void saveCredentials() // Speichere WLAN credentials auf EEPROM
{   size_t i;   for (i = 0 ; i < sizeof(MyWiFiConfig) ; i++) // Loeschen der alten Konfiguration   {     EEPROM.write(i, 0);   }   for (i = 0 ; i < STANameLen  ; i++) // Loeschen der alten Konfiguration   {     MyWiFiConfig.WiFiPwd[i] = 0;   }   for (i = 0 ; i < WiFiPwdLen ; i++) // Loeschen der alten Konfiguration   {     MyWiFiConfig.APSTAName[i] = 0;   }   temp = WiFi.SSID().c_str();   i = temp.length();   temp.toCharArray(MyWiFiConfig.APSTAName, i + 1);   temp = WiFi.psk().c_str();   i = temp.length();   temp.toCharArray(MyWiFiConfig.WiFiPwd, i + 1);   temp = "";   strncpy(MyWiFiConfig.ConfigValid , "TK", sizeof(MyWiFiConfig.ConfigValid) );   EEPROM.begin(512);   EEPROM.put(0, MyWiFiConfig);   EEPROM.commit();   EEPROM.end();   //ESP.wdtFeed();
}

void saveSysConfig()
{   byte i;   strncpy(SystemConfiguration.ConfigValid , "TK", sizeof(SystemConfiguration.ConfigValid) );   EEPROM.begin(512);   EEPROM.put(80, SystemConfiguration);   EEPROM.commit();   EEPROM.end();   //ESP.wdtFeed();

}

bool loadSysConfig()
{   bool RetValue;   EEPROM.begin(512);   EEPROM.get(80, SystemConfiguration);   EEPROM.end();   if (String(SystemConfiguration.ConfigValid) == "TK")   {     RetValue = true;   } else   {     temp = String(ESP.getChipId());     temp.toCharArray(SystemConfiguration.LoginPassword , PwMaxLength);     temp = "";     strncpy(SystemConfiguration.LoginName , "admin", sizeof(SystemConfiguration.LoginName) );     SystemConfiguration.PCD_Disabled = false;     SystemConfiguration.USED_PICC_Sector = 1;     saveSysConfig();     RetValue = false; // Config Settings nicht gültig //Standardinitalisierung ausführe   }   //ESP.wdtFeed();   return RetValue;
}

// ******************* END Functions StoreCredentialsto EEPROM ***************************

// ******************* Start Functions CardServices  *************************************

void PCDHardReset()
{   digitalWrite(RST_PIN, LOW);   delay(200);   digitalWrite(RST_PIN, HIGH);   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(boolean ABKey, byte Sector, 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;   for (int a = 0; a < 6; a++)   {     key.keyByte[a] = ikey[a];   }   // Key A   if (ABKey)   {     statusA = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, sectorkeytable[Sector], &key, &(mfrc522.uid));     if (statusA != MFRC522::STATUS_OK)     {       Serial.println(F("ATAUTH:ERR_A"));       return false;     }   }   // Key B   else if (not ABKey)   {     statusA = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, sectorkeytable[Sector], &key, &(mfrc522.uid));     if (statusA != MFRC522::STATUS_OK)     {       Serial.println(F("ATAUTH:ERR_B"));       return false;     }   }   return true;
}

// WriteData . uses Global Variable DataBuffer for Data Return
boolean CardDataWrite(byte Sector, byte block, byte value[16])
{   byte status;   byte writevector;   byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63};   writevector = Sector * 4 + block - 1 ;   for (byte a = 0; a < 16; a++)   {     if (writevector ==  sectorkeytable[a])     {       // Serial.println("NAK");       return false;     }   }   status = mfrc522.MIFARE_Write(writevector, value, 16);   if (status != MFRC522::STATUS_OK)   {     Serial.println(F("ATPCD:W_ERR"));     //Serial.println(mfrc522. GetStatusCodeName(status));     return false;   } else   {     // Serial.print(F("ATPCD:Write_Card_OK"));     return true;   }
}

// Read Data - uses Global Variable DataBuffer for Data Return
boolean CardDataRead(byte Sector, byte block)
{   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 sized = 18;   readvector = Sector * 4 + block - 1 ;   for (byte a = 0; a < 16; a++)   {     if (readvector ==  sectorkeytable[a])     {       Serial.println(F("ATPCD:R_ERR"));       return false;     }   }   statusi = mfrc522.MIFARE_Read(readvector, DataBuffer, &sized);   if (statusi != MFRC522::STATUS_OK)   {     Serial.println(F("ATPCD:R_ERR"));     return false;   } else   {     return true;   }
}

boolean ResetCardToDefault()
{   byte ikey[16];   byte status, i;   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];   if (CardAuthenticate(KEYB, USED_Sector, MiFareClassicKey.Key_B)) // Sector Autenticate for WRITE Access   {     for (i = 0; i <= 16; i++) {       DataBuffer[i] = 0;     }     if (!(CardDataWrite(USED_Sector, 1, DataBuffer))) {       return false;     }     for (i = 0; i <= 16; i++) {       DataBuffer[i] = 0;     }     if (!(CardDataWrite(USED_Sector, 2, DataBuffer))) {       return false;     }     for (i = 0; i <= 16; i++) {       DataBuffer[i] = 0;     }     if (!(CardDataWrite(USED_Sector, 3, DataBuffer))) {       return false;     }   }   for (byte i = 0; i <= 16; i++) {     ikey[i] = 255;  //Load Default Key for all Sectors   }   ikey[6] = 0xFF; // Default Setting for Access Bits   ikey[7] = 0x07; //   ikey[8] = 0x80; //   ikey[9] = 0x69;   status = mfrc522.MIFARE_Write(writevector, ikey, 16);   if (status != MFRC522::STATUS_OK)   {     return false;   }   return true;
}

boolean SetSectorAccessControl (byte Sector, byte Akey[6], byte Bkey[6])
{   byte ikey[16];   byte status;   byte writevector;   const byte sectorkeytable [16] = {3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63};   writevector = sectorkeytable[Sector];   ikey[0] = Akey[0];   ikey[1] = Akey[1];   ikey[2] = Akey[2];   ikey[3] = Akey[3];   ikey[4] = Akey[4];   ikey[5] = Akey[5];   ikey[6] = 0x78; // Data Block 0-3 Access Conditions: Key B write / Key A Read   ikey[7] = 0x77; // KEY A & KEY B & Acces Bits Write:Key B  / Key A Read Access Bits   ikey[8] = 0x88; // Calculator: http://calc.gmss.ru/Mifare1k/   ikey[9] = 0x69; // Fixer Wert - > default hex 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];   status = mfrc522.MIFARE_Write(writevector, ikey, 16);   if (status != MFRC522::STATUS_OK)   {     Serial.println(F("ATPCD:W_KEY_ERR"));     return false;   } else   {     return true;   }
}

boolean CheckforDefaultCardKey ()
{   byte tkey[6];   boolean CardResult;   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 sized = 18;   for (byte i = 0; i <= 6; i++) {     tkey[i] = 255;  //Load Default Key for all Sectors   }   CardResult = true;   if (!CardAuthenticate(KEYA, USED_Sector, tkey)) {     CardResult = false;   };   readvector = sectorkeytable[USED_Sector];   statusi = mfrc522.MIFARE_Read(readvector, DataBuffer, &sized);   if (statusi != MFRC522::STATUS_OK) {     CardResult = false;   }   //if (!( (DataBuffer[7] = 0x07) & (DataBuffer[7] = 0x80)))  { CardResult = false; };   return CardResult;
}

boolean WriteNewMiFareClassicPICC ()
{   byte tkey[6];   byte i, a;   boolean CardResult;   if (CheckforDefaultCardKey())   {     for (i = 0; i <= 6; i++) {       tkey[i] = 255;  //Load Default Key for all Sectors     }     for (i = 0; i <= 16; i++) {       DataBuffer[i] = 0;  // Clear Variable Buffer     }     CardResult = true;     if (CardAuthenticate(KEYA, USED_Sector, tkey)) // Sector  Autenticate     {       // Serial.println("Auth Sec 0 OK");       if (Surname.length() > 15) {         a = 15;       } else {         a = Surname.length();       }       if (Surname.length() > 0)       {         for (i = 0; i <= 16; i++) {           DataBuffer[i] = 0;         }         for (i = 0; i <= a; i++) {           DataBuffer[i] = Surname[i];         }         if (!(CardDataWrite(USED_Sector, 2, DataBuffer))) {           CardResult = false;  //Sector 0 Block 2 Vorname mit Key A schreiben         }       }       if (Givenname.length() > 15) {         a = 15;       } else {         a = Givenname.length();       }       if (Givenname.length() > 0)       {         for (i = 0; i <= 16; i++) {           DataBuffer[i] = 0;         }         for (i = 0; i <= a; i++) {           DataBuffer[i] = Givenname[i];         }         if (!(CardDataWrite(USED_Sector, 3, DataBuffer))) {           CardResult = false;  //Sector 0 Block 3 Nachname mit Key A schreiben         }       }       if (!(SetSectorAccessControl (USED_Sector, MiFareClassicKey.Key_A, MiFareClassicKey.Key_B))) {         CardResult = false;  // (byte Sector,byte Akey[6],byte Bkey[6])       }     } else {       CardResult = false;       return CardResult;     }   } else {     CardResult = false;     return CardResult;   }   if (CardResult)   {     //Serial.println("PICC written");     CardResult = true;   }   else   {     //Serial.println("PICC not empty");     CardResult = false;   }   yield();   return CardResult;
}


boolean ReadMiFareClassicPICC ()
{   boolean CardResult;   byte i ;   CardResult = true;   if (CardAuthenticate(KEYA, USED_Sector, MiFareClassicKey.Key_A)) // Sector  Autenticate with READ Key A   {     Givenname = "               "; //PlaceHolder     Surname   = "               "; //PlaceHolder     for (i = 0; i < 18; i++) {       DataBuffer[i] = 0;  // Clear Variable Buffer     }     if (CardDataRead(USED_Sector, 2)) // Feld Vorname auslesen     {       for (i = 0; i < 16; i++) {         Surname[i] = char(DataBuffer[i]);       }     } else {       return false;     }     for (i = 0; i < 18; i++) {       DataBuffer[i] = 0;  // Clear Variable Buffer     }     if (CardDataRead(USED_Sector, 3)) // Feld Nachname auslesen     {       for (i = 0; i < 16; i++) {         Givenname[i] = char(DataBuffer[i]);       }     } else {       return false;     }   } else   {     return false;   }   return true;
}

void CardServer()
{   byte i ;
#define PCD_Poll_Interval 400
#define PCD_Watchdog_Interval 60000   if (millis() - PCD_ServiceCall_Handler >= PCD_Poll_Interval)   {     PCD_ServiceCall_Handler = millis();     if (mfrc522.PICC_IsNewCardPresent())   // PICC = proximity integrated circuit card = kontaktlose Chipkarte     {       mfrc522.PICC_ReadCardSerial();       yield();       // Unterscheidung nach Kartentyp       // 0x08 für MIFARE Classic 1K       // 0x18 für MIFARE Classic 4K       // 0x11 für MIFARE PLUS       if (mfrc522.uid.sak == 0x08 || mfrc522.uid.sak == 0x18)       {         //  MiFare_Classic_Processor START (mfrc522.uid.sak);  // Nur ausführen wenn Eine Mifare Classic Karte vor den Leser gehalten wurde.         byte tkey[6];         for (byte i = 0; i <= 6; i++) {           tkey[i] = 255;  //Load Default Key for all Sectors         }         if (LearnNewCard) // neue Karte soll angelernt werden.         {           if (WriteNewMiFareClassicPICC()) {             SetRGBLed(0, 255, 0, false);             LearnNewCard = false;           } else           {             SetRGBLed(255, 0, 0, false);             LearnNewCard = false;           }         }         else if (EraseCard)  // KartenDaten sollen gelöscht werden.         {           if (ResetCardToDefault()) {             SetRGBLed(0, 255, 0, false);             EraseCard = false;           } else           {             SetRGBLed(255, 0, 0, false);             EraseCard = false;           }         }         else         {           if (ReadMiFareClassicPICC())           { // Karte gültig !             Serial.print (F("ATAUTH_S:"));             Serial.println (Surname);             Serial.print (F("ATAUTH_G:"));             Serial.println (Givenname);             temp = "Gültige Karte. Benutzer: ";             for (i = 0; i < 16; i++)             {               if  (Givenname[i] == 0)               {                 break;               }               temp += char(Givenname[i]);             }             temp += ", ";             for (i = 0; i < 16; i++)             {               if  (Surname[i] == 0)               {                 break;               }               temp += char(Surname[i]);             }             temp += " - UUID der Karte: ";             for (byte i = 0; i < 4; i++) {               temp += String(mfrc522.uid.uidByte[i], HEX) + " ";             }             WriteToLog(temp, 0);             temp = " ";             //Do actions if correct Card is detected             bool PinState = digitalRead(RELAIS_PIN);             PinState = !PinState;             digitalWrite(RELAIS_PIN, PinState);             SetRGBLed(0, 255, 0, false);     //Led Grün             temp = "";           } else {             SetRGBLed(255, 0, 0, false);             temp = "";             for (byte i = 0; i < 4; i++) {               temp += String(mfrc522.uid.uidByte[i], HEX) + " ";             }             temp = "Unbekannte MiFare Classic Karte. UUID der Karte: " + temp ;             WriteToLog(temp, 1);             temp = "";           }         }         LearnNewCard = false;         //  MiFare_Classic_Processor STOP (mfrc522.uid.sak);       } else if (mfrc522.uid.sak == 0x00) // Mifare Ultralight       {         SetRGBLed(255, 0, 0, false);         temp = "";         for (byte i = 0; i < 7; i++) {           temp += String(mfrc522.uid.uidByte[i], HEX) + " ";         }         temp = "Mifare UltraLight Karte nicht unterstützt. UUID der Karte: " + temp;         WriteToLog(temp, 1);         temp = "";       } else       {         SetRGBLed(255, 0, 0, false);         temp = "";         for (byte i = 0; i < mfrc522.uid.size; i++) {           temp += String(mfrc522.uid.uidByte[i], HEX) + " ";         }         temp = "Unbekannte Karte und Kartentyp. Typnummer: " + String(mfrc522.uid.sak) + " UUID der Karte: " + temp ;         WriteToLog(temp, 1);         temp = "";       }       mfrc522.PCD_StopCrypto1();       mfrc522.PICC_HaltA();       delay(2000);       SetRGBLed(0, 0, 255, false);     //Led Farbe Blau Leser ist in Grundzustand     }   }   if (millis() - PCD_WatchDog_Handler >= PCD_Watchdog_Interval)   {     PCD_WatchDog_Handler = millis();     Result = mfrc522.PCD_PerformSelfTest();     yield();     mfrc522.PCD_Init();                       Initialize MFRC522 Reading Module Again     mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Sets antenna to max. reception     mfrc522.PCD_AntennaOn();     Yield();     If (!(Result))     {       PCDHardReset();       Serial.println(Q("ATPCD:ERR_H"));     }   }
}

Stop Functions CardServices *************************************************************************************************************************

Void Loop()  Main loop
{   Server.handleClient();                    Edit Web server requests   If (!(PCD_Disabled) | !(SystemConfiguration.PCD_Disabled)) {     CardServer();  Map reader to handle specific requests   }   Esp.wdtFeed();                            Watchdog. Disable with "wdt_disable();"
}

 

I wish you a lot of fun and much success in the construction of the project and until the next time.

Projekte für fortgeschrittene

2 comments

Martin Kurth

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

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); ^

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN