A simple way to manually control alarm system with RFID reader

This is a very simple alternative way to manually control alarm system by RFID reader using a badge or a tag.
Usually I arm and disarm it using device_tracker with both wifi and bt but sometimes it do not recognize my smartphone in time before it triggers the alarm, so I decided to try an alternative way to control AlarmSystem and disarm it.
I tested it successfully and I share it to anyone is interested to improve it in a better system.

Hardware needed:

  • RFID reader MFRC-522 with a badge and a tag (6 eur)
  • D1 Mini NodeMCU ESP8266 (5 eur)
  • Logic Level Converter Bi Directional 3.3V 5V Step Up Down (8 eur 5 pcs)
  • Samsung ETA-U90EWEGSTD usb charger for smartphones (6 eur)
  • USB-MicroUSB 10cm cable (9 eur 2 pcs)

Follow this wiring scheme: http://lazyzero.de/elektronik/esp8266/rfid_mqtt/start
in this project MFRC-522 is linked to 3v of D1 Mini… but I suggest to use a Logic Level Converter Bi Directional 3.3V 5V Step Up Down to link 5v of D1 Mini to a real 3v for MFRC-522

I put all these components in a electric box wall mounted… the result is very fine.

Flash the D1 Mini with this firmware…

// SIMPLIFIED FIRMWARE FOR ESP8266 WITH MFRC522 WITHOUT LEDS  

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <MFRC522.h>
/* wiring the MFRC522 to ESP8266 (ESP-12)
RST     = GPIO4
SDA(SS) = GPIO2 
MOSI    = GPIO13
MISO    = GPIO12
SCK     = GPIO14
GND     = GND
3.3V    = 3.3V
*/

/* wiring the MFRC522 to D1 Mini ESP8266 (ESP - 12)
RST     = D3
SDA(SS) = D8
MOSI    = D7
MISO    = D6
SCK     = D5
GND     = GND
3.3V    = 3.3V
 */
 
#define RST_PIN  D3 // RST-PIN GPIO4 
#define SS_PIN  D8  // SDA-PIN GPIO2 
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

// Wifi Connection details
const char* ssid = "TIM-90987215";
const char* password = "V7Dlk4I9RWSsPNAKfOxUlGwO";

const char* mqtt_server = "192.168.1.1";  // mqtt IP
const char* mqtt_user = "userxxx";  // mqtt user
const char* mqtt_password = "12345";  // mqtt password
const char* clientID = "RFID";  // rfid name
const char* rfid_topic = "home/rfid";  // rfid path

WiFiClient espClient;
PubSubClient client(espClient);

long lastMsg = 0;
char msg[50];
void setup() {
  Serial.begin(115200);
  SPI.begin();           // Init SPI bus
  mfrc522.PCD_Init();    // Init MFRC522
  delay(2);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}
// Connect to Wifi
void setup_wifi() {
  //Turn off Access Point
  WiFi.mode(WIFI_STA);
  delay(10);
  
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
// Check for incoming messages
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("");
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  char s[20];
  
  sprintf(s, "%s", payload);

    if ( (strcmp(topic,"home/alarm")==0))
  {
    payload[length] = '\0';
    String sp = String((char*)payload);

  // Alarm is off
    if (sp == "disarmed")
    {
    Serial.println();
    Serial.print("Alarm is set to Disarmed");
    Serial.println();   
  }   
  // Alarm is Armed Home    
    else if (sp == "armed_home")
    {
    Serial.println();
    Serial.print("Alarm is set to Armed Home");
    Serial.println(); 
  } 
  // Alarm is arming
      else if (sp == "pending")
    {
    Serial.println();
    Serial.print("Alarm set to Pending");
    Serial.println();  
  }   
  // Alarm is Armed Away
    else if (sp == "armed_away")
    {
    Serial.println();
    Serial.print("Alarm set to Armed Away");
    Serial.println();  
  } 
  // Alarm is Triggered
    else if (sp == "triggered")
    {
    Serial.println();
    Serial.print("Alarm is triggered!!");
    Serial.println(); 
  }
}}
/* interpret the ascii digits in[0] and in[1] as hex
* notation and convert to an integer 0..255.
*/
int hex8(byte *in)
{
   char c, h;

   c = (char)in[0];

   if (c <= '9' && c >= '0') {  c -= '0'; }
   else if (c <= 'f' && c >= 'a') { c -= ('a' - 0x0a); }
   else if (c <= 'F' && c >= 'A') { c -= ('A' - 0x0a); }
   else return(-1);

   h = c;

   c = (char)in[1];

   if (c <= '9' && c >= '0') {  c -= '0'; }
   else if (c <= 'f' && c >= 'a') { c -= ('a' - 0x0a); }
   else if (c <= 'F' && c >= 'A') { c -= ('A' - 0x0a); }
   else return(-1);

   return ( h<<4 | c);
}
// Reconnect to wifi if connection lost
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientID, mqtt_user, mqtt_password)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("home/rfid", "connected");
      // ... and resubscribe
      client.subscribe("home/alarm");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
// Main functions
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    delay(50);
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    delay(50);
    return;
  }
  // Show some details of the PICC (that is: the tag/card)
  Serial.println("");
  Serial.print(F("Card UID:"));
  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
  Serial.println();
  //digitalWrite(idPin, HIGH);
  delay(500);
  //digitalWrite(idPin, LOW);
  delay(500);
  // Send data to MQTT
  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);
  }
  const char* id = rfidUid.c_str();
  client.publish("home/rfid", id);
  delay(3000);
}
// Helper routine to dump a byte array as hex values to Serial
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

In Home Assistant configuration.yaml add this…

sensor:
  - platform: mqtt
    state_topic: "home/rfid"
    name: RFID  c

and in automation.yaml add this…

  - alias: RFID 1 Alarm off
    trigger:
      platform: mqtt
      topic: "home/rfid"
      payload: 'abbccdd'   // the badge or tag code
    condition:
      condition: or
      conditions:
        - condition: state
          entity_id: alarm_control_panel.ha_alarm
          state: armed_home
        - condition: state
          entity_id: alarm_control_panel.ha_alarm
          state: armed_away
        - condition: state
          entity_id: alarm_control_panel.ha_alarm
          state: pending
    action:
      - service: notify.mail
        data:
          message: "RFID 1 -> Alarm off!"
      - service: logbook.log
        data_template:
          name: >-
           {{ MQTT }}
          message: RFID 1 -> Alarm off!
      - service: alarm_control_panel.alarm_disarm
        data: {"entity_id":"alarm_control_panel.ha_alarm","code":"12345"}

  - alias: RFID 1 Alarm on
    trigger:
      platform: mqtt
      topic: "home/rfid"
      payload: 'abbccdd'  // the badge or tag code
    condition:
      - condition: state
        entity_id: alarm_control_panel.ha_alarm
        state: disarmed
    action:
      - service: notify.hassio
        data:
          message: "RFID 1 -> Alarm on!"
      - service: logbook.log
        data_template:
          name: >-
           {{ MQTT }}
          message: RFID 1 -> Alarm on!
      - service: alarm_control_panel.alarm_arm_home
        data: {"entity_id":"alarm_control_panel.ha_alarm","code":"12345"}

Many thanks to thaijames for the original project and a special thanks to Rune for support to adapt this project to AlarmSystem

7 Likes

A minor suggestion would be to add conditions to both automations so that the state can’t “bounce” if the card is swiped in a manor that the card reader reads it twice.

It’s a minor tweak by adding a state condition

   condition:
      - condition: state
        entity_id: alarm_control_panel.ha_alarm
        state: disarmed
        for:
        seconds: 5
4 Likes

Thta’s a nicer way than disabling an automation in the actions and waiting 5 seconds before re-enabling it. Thanks!

If anyone else ever wants to use that state condition note there is a minor formatting error. seconds: should be indented like so:

   condition:
      - condition: state
        entity_id: alarm_control_panel.ha_alarm
        state: disarmed
        for:
          seconds: 5
2 Likes

I was looking for something like this.
Wouldn’t it be possible to use the RFID reader of a wall mounted Amazon Fire tablet?

As long as the fire tablet don’t have a RFID reader (as far as I know) nope. But nice scatch. Will try to install it
At the moment I use https://github.com/esprfid/esp-rfid but it’s losing the connection way to often to use.

Hi, i was searching for something similar and find this topic, my question is how to add multiple tags/badges? i have to do the automation 3 times for the different tags with different playload?

Thanks in advance

I have similar solution

For multiple tag IDs I have an automation starting with


- alias: 'NFC Reader'
  initial_state: true
  trigger:
    platform: mqtt
    topic: "alarm/nfcid"
  condition:
    - condition: template
      value_template: !secret nfc_alarm_values
      #in secrets we define nfc_alarm_values: "{{ trigger.payload in ['aaaaaaaa', 'bbbbbbbb', 'cccccccc', 'dddddddd'] }}"

2 Likes