Last active
October 10, 2018 00:58
-
-
Save brysonreece/e97f38ec1e7f36dfb26a6d6781d2314c to your computer and use it in GitHub Desktop.
Sends a MQTT packet to a subscribed topic after authenticating with a known NFC tag using the MFRC522 Reader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <ESP8266WiFi.h> | |
| #include <SPI.h> | |
| #include <MFRC522.h> | |
| #include <PubSubClient.h> | |
| /** | |
| * LED = GPIO16 | |
| * RST = GPIO5 | |
| * SDA(SS) = GPIO4 | |
| * MOSI = GPIO13 | |
| * MISO = GPIO12 | |
| * SCK = GPIO14 | |
| * GND = GND | |
| * 3.3V = 3.3V | |
| */ | |
| /** Whether to toggle Serial output */ | |
| const bool DEBUG_MODE = true; | |
| /** WiFi Details */ | |
| const char* WIFI_SSID = "YOUR_WIFI_SSID_HERE"; | |
| const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD_HERE"; | |
| /** MQTT Details */ | |
| const char* MQTT_SERVER_HOST = "YOUR_MQTT_BROKER_HERE"; | |
| const uint16_t MQTT_SERVER_PORT = 1883; | |
| const char* MQTT_SERVER_USER = "YOUR_MQTT_USER_HERE"; | |
| const char* MQTT_SERVER_PASSWORD = "YOUR_MQTT_PASSWORD_HERE"; | |
| const char* MQTT_CLIENT_ID = "YOUR_MQTT_CLIENT_ID_HERE"; | |
| const char* MQTT_OUT_TOPIC = "YOUR_MQTT_TOPIC_HERE"; | |
| const char* MQTT_TOPIC_ON_STATE = "ON"; | |
| /** Pin Mappings (see diagram above) */ | |
| const int SS_PIN = 4; | |
| const int RST_PIN = 5; | |
| const int LED_PIN = 16; | |
| /** Reader config values */ | |
| const int SCAN_TIMEOUT_SEC = 5; | |
| const int NUM_KEYS = 2; | |
| const int UID_LENGTH = 7; | |
| /** Keycard Struct */ | |
| struct Keycard { | |
| byte uid[UID_LENGTH]; | |
| byte password[4]; | |
| }; | |
| /** Known Keycards */ | |
| const Keycard known_keys[2] = { | |
| { | |
| { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // UID #1 | |
| { 0xFF, 0xFF, 0xFF, 0xFF } // Password #1 | |
| }, | |
| { | |
| { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // UID #2 | |
| { 0xFF, 0xFF, 0xFF, 0xFF } // Password #2 | |
| } | |
| }; | |
| /** Various Clients */ | |
| WiFiClient espClient; | |
| PubSubClient client(espClient); | |
| MFRC522 mfrc522(SS_PIN, RST_PIN); | |
| /** Timestamp of when we last scanned a known keycard */ | |
| unsigned long last_scanned = 0; | |
| void setup() { | |
| // Check if we're in debug mode | |
| if (DEBUG_MODE) { | |
| // If so, enable serial output | |
| Serial.begin(115200); | |
| } | |
| // Wait a bit before printing to console | |
| delay(50); | |
| // Alert that we're booting | |
| Serial.println("Booting..."); | |
| // Attempt WiFi connection | |
| Serial.print("Connecting to Wifi..."); | |
| WiFi.begin(WIFI_SSID, WIFI_PASSWORD); | |
| // Keep trying until we're connected to WiFi | |
| while (WiFi.status() != WL_CONNECTED) { | |
| Serial.print("."); | |
| delay(500); | |
| } | |
| // Print out WiFi details | |
| Serial.println(""); | |
| Serial.print("WiFi connected => IP Address: "); | |
| Serial.println(WiFi.localIP()); | |
| // Set up our MQTT connection | |
| client.setServer(MQTT_SERVER_HOST, MQTT_SERVER_PORT); | |
| // Enable our RFID/NFC Reader | |
| SPI.begin(); | |
| mfrc522.PCD_Init(); | |
| // Set up our indicator LED | |
| pinMode(LED_PIN, OUTPUT); | |
| } | |
| void loop() { | |
| // If we're not connected to MQTT, attempt to | |
| if (!client.connected()) { | |
| mqtt_reconnect(); | |
| } | |
| // Tell our MQTT callback to loop here | |
| client.loop(); | |
| // Check if a card is held to the reader | |
| if (!mfrc522.PICC_IsNewCardPresent()) { | |
| // If not, don't do anything | |
| delay(50); | |
| return; | |
| } | |
| // Check if we can read from the card | |
| if (!mfrc522.PICC_ReadCardSerial()) { | |
| // If not, don't do anything | |
| delay(50); | |
| return; | |
| } | |
| // Check if the scanned card is known and authenticated | |
| if (check_uid(mfrc522.uid)) { | |
| // Ignore publishing to MQTT if it's been less than 5s since the last scan | |
| if (millis() > (last_scanned + (SCAN_TIMEOUT_SEC * 1000))) { | |
| // Print out MQTT intent | |
| Serial.print("Publishing MQTT Data \""); | |
| Serial.print(MQTT_TOPIC_ON_STATE); | |
| Serial.print("\" to topic \""); | |
| Serial.print(MQTT_OUT_TOPIC); | |
| Serial.print("\" at "); | |
| Serial.print(MQTT_SERVER_HOST); | |
| Serial.print(':'); | |
| Serial.println(MQTT_SERVER_PORT); | |
| // Turn our indicator LED on | |
| digitalWrite(LED_PIN, LOW); | |
| // Publish an MQTT packet | |
| client.publish(MQTT_OUT_TOPIC, MQTT_TOPIC_ON_STATE); | |
| // Update the timestamp of when we last read a card | |
| last_scanned = millis(); | |
| // Wait a bit to allow the LED to stay on for indication | |
| delay(250); | |
| // Turn the LED off | |
| digitalWrite(LED_PIN, HIGH); | |
| } | |
| } | |
| } | |
| /** | |
| * Check if the scanned UID is known and can authenticate with the | |
| * provided password | |
| */ | |
| bool check_uid(MFRC522::Uid uid) { | |
| // Get an instance of the UID buffer | |
| byte *buffer = uid.uidByte; | |
| // Iterate over the known keys | |
| for (int i = 0; i < NUM_KEYS; i++) { | |
| // Get an instance of a known keycard | |
| Keycard keycard = known_keys[i]; | |
| // Check that it's the correct size | |
| if (uid.size != UID_LENGTH) { | |
| continue; | |
| } | |
| // Check UID bytes | |
| bool uidMismatch = false; | |
| for (byte j = 0; j < UID_LENGTH; j++) { | |
| // Skip remaining bytes | |
| if (uidMismatch) { | |
| continue; | |
| } | |
| // Check byte comparison | |
| if (buffer[j] != keycard.uid[j]) { | |
| uidMismatch = true; | |
| } | |
| } | |
| // Skip keycard | |
| if (uidMismatch) { | |
| continue; | |
| } | |
| // Attempt authentication | |
| byte pACK[] = {0, 0}; | |
| MFRC522::StatusCode status = mfrc522.PCD_NTAG216_AUTH(keycard.password, pACK); | |
| // Check if authentication worked. If so, return | |
| if (status == MFRC522::STATUS_OK) { | |
| return true; | |
| } | |
| } | |
| // UID provided failed. Return false | |
| return false; | |
| } | |
| /** | |
| * Attempts to connect to the provided MQTT broker | |
| */ | |
| void mqtt_reconnect() { | |
| // Loop until we're reconnected | |
| while (!client.connected()) { | |
| // Alert intent | |
| Serial.print("Attempting MQTT connection... "); | |
| // Attempt to connect | |
| if (client.connect(MQTT_CLIENT_ID, MQTT_SERVER_USER, MQTT_SERVER_PASSWORD)) { | |
| // Yay, we're connected | |
| Serial.println("CONNECTED"); | |
| // Subscribe to the provided topic | |
| client.subscribe(MQTT_OUT_TOPIC); | |
| } | |
| else { | |
| // Print out error details | |
| Serial.print("FAILED, rc = ("); | |
| Serial.print(client.state()); | |
| Serial.println(") | Trying again in 5 seconds"); | |
| // Wait 5 seconds before retrying | |
| delay(5000); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment