Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- espRFIDRelaycontroller by Duncan McPherson
- Use a RFID-RC522 and ESP8266-12e to control a relay to activate
- a machine for authorised users. Pick up the list of authorised users from an MQTT server.
- */
- #include <EEPROM.h> // To read and write PICC's UIDs from/to EEPROM
- #include <SPI.h> // RC522 Module uses SPI protocol
- #include <MFRC522.h> // Library for Mifare RC522 Device
- #include <ESP8266WiFi.h> // To use WiFi to communicate with the mothership
- #include <IPStack.h>
- #include <Countdown.h>
- #include <MQTTClient.h> // Library for MQTT publishing and subscribing to get the authorised users from the mothership
- #include <ArduinoJson.h> // To parse the incoming messages
- const uint8_t relayPin = 16; // Nominate a pin to control the relay
- // ************* Stuff for reading cards with MFRC522 *******************
- boolean successfulRead = false; // Whether or not a card has been read
- byte presentedCard[4]; // The UID of the card just presented
- const uint8_t ss_pin = 4; // Nominate a pin to slave select the MFRC522
- const uint8_t rst_pin = 5; // Nominate a pin to reset the MFRC522
- MFRC522 mfrc522(ss_pin, rst_pin); // define the MFRC522
- // ************* Stuff for seting up WiFi ******************************
- const char* ssid = "mcphersons";
- const char* password = "ericthered";
- WiFiClient wiFiClient;
- // ************* Stuff for setting up MQTT client subscriptions ********
- char* mqttBroker = "192.168.0.2";
- int port = 1883;
- char* clientID = "GeorgeLathenby";
- char* user = "duncandoo_lathe";
- char* pw = ".........";
- char* topic = "confidential/somakeit/space/tags/#";
- int arrivedCount = 0;
- IPStack ipstack(wiFiClient);
- MQTT::Client<IPStack, Countdown, 50, 1> client = MQTT::Client<IPStack, Countdown, 50, 1>(ipstack);
- MQTT::Message message;
- char* topicTag = "confidential/somakeit/space/tags/ffffffff"; // example of MQTT topic we need
- // ************* Stuff for JSON parsing *****************************
- StaticJsonBuffer<128> jsonBuffer;
- char* json = "{\"member_id\": \"007\",\"member_name\":\"George Lathenby\",\"roles\":[1,3,9,11]}";
- void setup() {
- //pinMode(LED_BUILTIN, OUTPUT); // intialize the builtin led pin which
- // will be used to denote activation and Rx.
- pinMode(relayPin, OUTPUT); // Initialize the relayPin
- digitalWrite(relayPin, LOW); // Make sure the relay is off at the start
- Serial.begin(115200); // start a serial port
- SPI.begin(); // start SPI bus
- mfrc522.PCD_Init(); // start the MFRC522
- EEPROM.begin(512); // start the EEPROM and define it's size
- //run once to set the initial storedCard for testing then wipe it
- // // byte storedCard[4] = { 0x29, 0x80, 0xc, 0x3b };
- // EEPROM.write( 0, 1 );
- // for ( byte i = 0 ; i < 4 ; i++ ) {
- // EEPROM.write( i+1 , storedCard[i] );
- // }
- // EEPROM.commit();
- }
- void loop() {
- Serial.print("Present your card to be assessed.");
- do {
- successfulRead = getID(); // Check if a card has been read successfully
- }
- while (!successfulRead); // go no further until a card is read successfully
- if (checkID(presentedCard)) {
- digitalWrite(relayPin, HIGH); // Turn the relay on
- boolean relayState = digitalRead(relayPin);
- Serial.printf("You may use the lathe. The relay should be on and it is %u.\n", relayState);
- //Check for new users
- connectWiFi();
- connectMQTT();
- while (true) {
- //leave the relay on or some other stuff that might happen, like a time limit
- Serial.println("Waiting for message");
- client.yield(1000);
- addNewUsers( checkMessage( topicTag , json ) );
- //digitalWrite(relayPin, LOW);
- }
- }
- else {
- //keep the relay off
- digitalWrite(relayPin, LOW); // Just to make sure
- boolean relayState = digitalRead(relayPin);
- Serial.printf("You are not authorised. Extermination will now commence. The relay should be off and it is %u.\n", relayState);
- Serial.println("If you think you really should be able to use the lathe present your card again and I'll check with the mothership...");
- //Double check for new users
- connectWiFi();
- connectMQTT();
- char buf[100];
- strcpy(buf, "Hello World! QoS 0 message");
- message.qos = MQTT::QOS0;
- message.retained = false;
- message.dup = false;
- message.payload = (void*)buf;
- message.payloadlen = strlen(buf)+1;
- int rc = client.publish(topicTag, message);
- client.yield(5000);
- addNewUsers( checkMessage( topicTag , json ) );
- //It would be nice to put a bit here to allow a different card to interrupt the connecting to WiFi and MQTT, to run in parallel
- }
- }
- // Function to check for card being read //
- boolean getID() {
- if ( ! mfrc522.PICC_IsNewCardPresent()) {
- delay(500); // Look for a card being presented every 500ms until one is found
- return false;
- }
- if ( ! mfrc522.PICC_ReadCardSerial()) {
- // Check the card that has been found has been read
- return false;
- }
- Serial.print("Card UID: ");
- for (byte i = 0; i < 4; i++) {
- presentedCard[i] = mfrc522.uid.uidByte[i]; // Print the UID to serial as hex values
- Serial.print(presentedCard[i], HEX);
- }
- Serial.println();
- mfrc522.PICC_HaltA(); // Stop reading the card and tell it to switch off
- return true;
- }
- // function to check a card against list stored in EEPROM
- boolean checkID( byte testCard[] ) {
- byte users = EEPROM.read(0); //EEPROM[0] stores the number of authorised cards that need to be checked against
- byte storedCard[4]; // The UID of a card read from memory
- for ( byte user = 0 ; user < users ; user++) {
- for ( byte i = 0 ; i < 4 ; i++) {
- storedCard[i] = EEPROM.read( user * 4 + 1 + i ); //each UID is 4 bytes long and takes up 4 slots in EEPROM
- }
- boolean match = true; // assume there is a match
- for ( byte i = 0; i < 4; i++ ) {
- if ( testCard[i] != storedCard[i]) {
- match = false; // if any byte doesn't match fail
- }
- }
- if (match) {
- Serial.print("Welcome user number ");
- Serial.println(user, DEC);
- return true;
- }
- else {
- return false;
- }
- }
- }
- //function to connect to Wifi
- void connectWiFi() {
- delay(10);
- Serial.print("Connecting to ");
- Serial.println(ssid);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
- Serial.println("");
- Serial.print("WiFi connected to IP address ");
- Serial.println(WiFi.localIP());
- }
- //function to connect to MQTT server
- void connectMQTT() {
- Serial.print("Connecting to ");
- Serial.print(mqttBroker);
- Serial.print(":");
- Serial.println(port);
- int rc = ipstack.connect(mqttBroker, port);
- if (rc != 1)
- {
- Serial.print("rc from TCP connect is ");
- Serial.println(rc);
- }
- Serial.println("MQTT connecting");
- MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
- data.MQTTVersion = 3;
- data.clientID.cstring = clientID;
- data.username.cstring = user;
- data.password.cstring = pw;
- rc = client.connect(data);
- if (rc != 0)
- {
- Serial.print("rc from MQTT connect is ");
- Serial.println(rc);
- }
- Serial.println("MQTT connected");
- rc = client.subscribe(topic, MQTT::QOS1, messageArrived);
- if (rc != 0)
- {
- Serial.print("rc from MQTT subscribe is ");
- Serial.println(rc);
- }
- Serial.print("MQTT subscribed to topic: ");
- Serial.println(topic);
- }
- // function to handle callbacks from MQTT broker
- void messageArrived(MQTT::MessageData& md) {
- MQTT::Message &message = md.message;
- char* topic = md.topicName.cstring;
- Serial.print("Message ");
- Serial.print(++arrivedCount);
- Serial.print(" arrived: qos ");
- Serial.print(message.qos);
- Serial.print(", retained ");
- Serial.print(message.retained);
- Serial.print(", dup ");
- Serial.print(message.dup);
- Serial.print(", packetid ");
- Serial.println(message.id);
- Serial.print("Topic ");
- Serial.println(topic);
- Serial.print("Payload ");
- Serial.println((char*)message.payload);
- json = (char*)message.payload;
- topicTag = (char*)topic;
- }
- // function to check if message contains a new authorised user
- byte* checkMessage(char *topicTag , char *json ) {
- JsonObject &root = jsonBuffer.parseObject(json);
- byte len1 = sizeof(root["roles"]) / sizeof(root["roles"][0]);
- int roles[len1];
- for ( byte i = 0 ; i < len1 ; i++ ) {
- roles[i] = root["roles"][i];
- }
- byte len2 = sizeof(roles) / sizeof(roles[0]);
- byte newUser[4] = { 0xff, 0xff, 0xff, 0xff };
- for ( byte i ; i < len2 ; i++ ) {
- if ( roles[i] == 11 ) { // check if the list of roles includes 11, which is lathe user
- char *UID = &topicTag[strlen(topicTag)-8];
- for ( byte i = 0 ; i < 4 ; i++ ) {
- newUser[i] = UID[i];
- }
- }
- }
- return newUser;
- }
- // function to write new authorised cardNumber into EEPROM
- void addNewUsers(byte newUser[]) {
- byte users = EEPROM.read(0); //EEPROM[0] stores the number of authorised cards that need to be checked against
- byte storedCard[4]; // The UID of a card read from memory
- for ( byte user = 0 ; user < users ; user++) { // Check if the newUser is already in EEPROM by comparing against every user
- for ( byte i = 0 ; i < 4 ; i++) {
- storedCard[i] = EEPROM.read( user * 4 + 1 + i ); //each UID is 4 bytes long and takes up 4 slots in EEPROM
- }
- boolean match = true; // assume there is a match
- for ( byte i = 0; i < 4; i++ ) {
- if ( newUser[i] != storedCard[i]) {
- match = false; // if any byte doesn't match fail
- }
- }
- if (match) {
- Serial.print("User is already authorised and is number ");
- Serial.println(user, DEC);
- }
- else {
- users += users; // increment the number of users
- EEPROM.write(0, users);
- for ( byte i = 0 ; i < 4 ; i++ ) {
- EEPROM.write( users * 4 + 1 + i , newUser[i] );
- }
- EEPROM.commit();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement