ESP8266 mit RFID Reader
Der RC522 RFID Reader wird per SPI an den ESP8266 angeschlossen. Als Bibliothek wird die MFRC522 Library von Miguel Balboa verwendet. Die Bibliothek kann über den Library Manager in der Arduino IDE installieren. Leider habe ich keine alternative gefunden, die per I2C an den ESP8266 angebunden werden kann. Das kostet leider auch direkt 3 GPIO mehr als bei I2C.
Das Programm für den ESP verbindet sich per MQTT mit shiftr.io und sendet verschiedene Daten über MQTT, z.B. Batteriespannung (1/min) und die uid des eingescannt NFC Tags. Diese Daten lassen sich z.B. von andere Clients die an dem Broker subscriben und auswerten.
Im Sketch wird zusätzlich noch der HTTP Update Server den es in Arduino für ESP gibt verwendet. So lassen sich über ein den Browser updates einspielen. Dazu muss man auf die Seite http://rfid_reader.local/update
(der Hostname kann im Sketch definiert werden) gehen und den kompilierten Code hochladen. Nach dem Upload wird der neue Code installiert und der ESP neu gestartet. Den compilierten Code bekommt man in dem man in der Arduino IDE unter Sketch–>Export compiled Binary den Compilevorgang started. Die entstandene Datei ist im Ordner wo der Sketch gespeichert ist.
Als grosser Nachteil muss man die Sicherheitslücken von MIFARE classic ansehen. Mit der verwendeten Bibliothek kann man z.B. die uid der Karte neu setzen. Also nicht für den Türöffner verwenden!
Material & Links
Code
- ESP8266_rfid_mqtt.ino
/* ESP8266 RFID Reader - MQTT Sender Copyright 2016 Christian Moll <christian@chrmoll.de> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Dieses Programm ist Freie Software: Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation, Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren veröffentlichten Version, weiterverbreiten und/oder modifizieren. Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. Siehe die GNU General Public License für weitere Details. Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>. */ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <ESP8266HTTPUpdateServer.h> #include <MQTTClient.h> #include <SPI.h> #include <MFRC522.h> #define SS_PIN D8 //Pin on WeMos D1 Mini #define RST_PIN D3 //Pin on WeMos D1 Mini const char* host = "rfid_reader"; // will also be used on shiftr.io const char* ssid = "ssid"; const char* password = "passphrase"; const char* brocker = "broker.shiftr.io"; const char* mqttUser = "mqttuser"; const char* mqttPass = "mqttpassword"; ESP8266WebServer httpServer(80); ESP8266HTTPUpdateServer httpUpdater; WiFiClient wifi; MQTTClient mqtt; MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class MFRC522::MIFARE_Key key; unsigned int batt; double battV; unsigned long oldMillis; void connect(); void setup(void){ SPI.begin(); rfid.PCD_Init(); Serial.begin(115200); Serial.println(); Serial.println("Booting Sketch..."); WiFi.mode(WIFI_AP_STA); WiFi.begin(ssid, password); mqtt.begin(brocker, wifi); mqtt.publish("/rfid_reader/resetReason", ESP.getResetReason()); connect(); MDNS.begin(host); //Attach handles for different pages. httpUpdater.setup(&httpServer); httpServer.on("/", handleRoot); httpServer.begin(); MDNS.addService("http", "tcp", 80); Serial.println("Up and running!"); } void loop(void){ if(!mqtt.connected()) { connect(); } httpServer.handleClient(); mqtt.loop(); delay(10); handleRFID(); //things that should only be transmitted all 60 sec if (millis()-oldMillis > 60000) { batt = analogRead(A0); battV = mapDouble(batt, 0, 1023, 0.0, 6.6); mqtt.publish("/rfid_reader/batt", String(battV)); mqtt.publish("/rfid_reader/battRaw", String(batt)); oldMillis = millis(); } } void connect() { while(WiFi.waitForConnectResult() != WL_CONNECTED){ WiFi.begin(ssid, password); Serial.println("WiFi failed, retrying."); } Serial.print("IP address: "); Serial.println(WiFi.localIP()); while (!mqtt.connect(host, mqttUser, mqttPass)) { Serial.print("."); } Serial.println("\nconnected!"); } void handleRoot() { httpServer.send(200, "text/plain", "It works!!!"); } void messageReceived(String topic, String payload, char * bytes, unsigned int length) { Serial.print("incoming: "); Serial.print(topic); Serial.print(" - "); Serial.print(payload); Serial.println(); } void handleRFID() { if (!rfid.PICC_IsNewCardPresent()) return; if (!rfid.PICC_ReadCardSerial()) return; mqtt.publish("/rfid_reader/uid", printHex(rfid.uid.uidByte, rfid.uid.size)); rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); } double mapDouble(double x, double in_min, double in_max, double out_min, double out_max) { double temp = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; temp = (int) (4*temp + .5); return (double) temp/4; } String printHex(byte *buffer, byte bufferSize) { String id = ""; for (byte i = 0; i < bufferSize; i++) { id += buffer[i] < 0x10 ? "0" : ""; id += String(buffer[i], HEX); } return id; }