Arduino MQTT publish RFID cards UID
Capturing the main points and the code that I finally got to work for me.
- Read RFID tags and publish just the UID to an MQTT server
- Future work will be for another system to subscribe to the Topic the UID is published on, if it matches an approved tag then it will publish a message to anther topic to perform an action such as through a Relay or Mosfet to open a door.
- Device: Freetronics EtherMega (Arduino Mega 256)
- RFID Reader: RC522
- SOA - 53
- SCK - 52
- MOSI - 51
- MISO - 50
- RST - 5
- Uses DHCP and reports into local MQTT (Mosquitto) on my Mac at 192.168.0.212
Sketch:
#include <SPI.h>
#include <MFRC522.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#define I2C_ADDRESS 0x50
#include <Wire.h>
#define LED 7
#define BUTTON 2
#define CLIENTID "ArduinoMega1"
#define SS_PIN 53//Arduino Uno
#define RST_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);// Create MFRC522 instance.
char message_buff[100];
// Update these with values suitable for your network.
byte mac[]= { 0xDE, 0xED, 0xAA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 0, 212 };
const int buttonPinOn = 2; // the number of the pushbutton pin
// variables will change:
int buttonOnState = 0; // variable for reading the pushbutton status
// Callback function header
void callback(char* topic, byte* payload, unsigned int length);
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
// Callback function
void callback(char* topic, byte* payload, unsigned int length) {
int i = 0;
Serial.println("Message arrived:topic: " + String(topic));
Serial.println("Length: " + String(length,DEC));
// create character buffer with ending null terminator (string)
for(i=0; i<length; i++) {
message_buff[i] = payload[i];
}
message_buff[i] = '\0';
String msgString = String(message_buff);
Serial.println("Payload: " + msgString);
if (msgString.equals("LED on")) {
digitalWrite(LED, HIGH);
}
else if (msgString.equals("LED off")){
digitalWrite(LED, LOW);
}
// In order to republish this payload, a copy must be made
// as the orignal payload buffer will be overwritten whilst
// constructing the PUBLISH packet.
// Allocate the correct amount of memory for the payload copy
byte* p = (byte*)malloc(length);
// Copy the payload to the new buffer
memcpy(p,payload,length);
client.publish("outTopic", p, length);
// Free the memory
free(p);
}
void setup()
{
Serial.begin(9600);// Initialize serial communications with the PC
SPI.begin();// Init SPI bus
mfrc522.PCD_Init();// Init MFRC522 card
Serial.println("Initialiased RFID reader");
Wire.begin();
mac[0] = readRegister(0xFA);
mac[1] = readRegister(0xFB);
mac[2] = readRegister(0xFC);
mac[3] = readRegister(0xFD);
mac[4] = readRegister(0xFE);
mac[5] = readRegister(0xFF);
//char tmpBuf[17];
//sprintf(tmpBuf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
// start the Ethernet connection and the server:
Ethernet.begin(mac);
Serial.print("EtherMega is at ");
Serial.println(Ethernet.localIP());
//Serial.println(tmpBuf);
pinMode(LED, OUTPUT);
if (client.connect("arduinoClient")) {
client.publish("outTopic","EtherMega reporting on net");
client.subscribe("inTopic");
}
}
void loop()
{
client.loop();
buttonOnState = digitalRead(buttonPinOn);
if (buttonOnState == HIGH) {
// turn LED on:
digitalWrite(LED, HIGH);
Serial.println("Turn LED on and send MQTT message.");
client.publish("outTopic","Button On");
delay(500);
digitalWrite(LED, LOW);
}
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())return;
Serial.print("Card UID:");//Dump UID
String rfidUid = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
rfidUid += String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
rfidUid += String(mfrc522.uid.uidByte[i], HEX);
}
Serial.println(rfidUid);
Serial.println("");
rfidUid.toCharArray(message_buff, rfidUid.length()+1);
client.publish("outTopic", message_buff);
mfrc522.PICC_HaltA(); // Halt PICC
mfrc522.PCD_StopCrypto1();// Stop encryption on PCD
}
byte readRegister(byte r)
{
unsigned char v;
Wire.beginTransmission(I2C_ADDRESS);
Wire.write(r);// Register to read
Wire.endTransmission();
Wire.requestFrom(I2C_ADDRESS, 1); // Read a byte
while(!Wire.available())
{
// Wait
}
v = Wire.read();
return v;
}