Controlling House Alarm From HA

Setting up an RFID reader to interface with HA

I flashed the ESP8266 (ESP-12) with the following code.

Here is what the code does:

  1. it waits for a token to be presented. it flashes one beep to acknowledge token and then sends the token serial number to MQTT server published as a topic
  2. I have a python script (in the next post) that subscribes to the topic, reads the serial number and if the token is authorized then either turns on or off the alarm and then publishes MQTT messages back to the ESP8266 as it is arming, disarming and setting the alarm.
  3. The ESP8266 reads the message and then flashes the appropriate led lights based on the message:
    Flashing Green: The alarm is in the process of being disarmed.
    Green: Alarm is off
    Flashing Red: Alarm is in the process of being armed
    Red: Alarm in on

Here is the code:

#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
*/

#define RST_PIN  4 // RST-PIN GPIO4 
#define SS_PIN  2  // SDA-PIN GPIO2 

MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

// Wifi Connection details
const char* ssid = "ENTER SSID";
const char* password = "PASSWORD HERE";

// MQTT Server address
const char* mqtt_server = "SERVER_IP_ADDRESS";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];



void setup() {
  Serial.begin(9600);

  SPI.begin();           // Init SPI bus
  mfrc522.PCD_Init();    // Init MFRC522
    
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}


// Connect to Wifi
void setup_wifi() {

  pinMode(5, OUTPUT); // Red LED
  pinMode(5, HIGH); 
  pinMode(0, OUTPUT); // Greem :LED
  pinMode(0, HIGH);

  delay(2);
  // 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.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }


  // Alarm is on
  if ((char)payload[1] == 'n') {
    Serial.println();
    Serial.print("Alarm is on");
    Serial.println();
    on_red_led();    
  } 
  
  // Alarm is off
  if ((char)payload[1] == 'f') {
    Serial.println();
    Serial.print("Alarm is off");
    Serial.println();
    on_green_led();    
  } 
  
  // Alarm is arming
  if ((char)payload[2] == 'm') {
    Serial.println();
    Serial.print("Alarm is arming");
    Serial.println();
    flash_red_led();    
  }   

  // Alarm is disarming
  if ((char)payload[2] == 's') {
    Serial.println();
    Serial.print("Alarm is disarming");
    Serial.println();
    flash_green_led();    
  } 

  // Error
  if ((char)payload[3] == 'o') {
    Serial.println();
    Serial.print("Error wrong token");
    Serial.println();
    blink_red_led();    
  }

}


// 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("ESP8266Client")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("/rfid/state", "connected");
      // ... and resubscribe
      client.subscribe("/alarm/state");
    } 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.print(F("Card UID:"));
  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
  Serial.println();

  // 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("/rfid/user", id);
  delay(3000);
}


// LED Loop
void blink_red_led(){
  Serial.println("Blinking Red");
  digitalWrite(0, LOW);
  // Flash 10 times:
  for(int i = 0; i < 9; i++)
  {
  digitalWrite(5, HIGH);
  delay(200);
}}

void flash_green_led(){
  Serial.println("Flashing Green LED");
  digitalWrite(5, LOW);
  // Flash 15 times:
  for(int i = 0; i < 14; i++)
  {
  digitalWrite(0, HIGH);
  delay(1000);
  digitalWrite(0, LOW);
  delay(500);
}}


void flash_red_led(){
  Serial.println("Flashing Red LED");
  digitalWrite(0, LOW);
  // Flash 20 times:
  for(int i = 0; i < 19; i++)
  {
  digitalWrite(5, HIGH);
  delay(1000);
  digitalWrite(5, LOW);
  delay(500);
}}


void on_green_led(){
  Serial.println("Turning on green led");
  digitalWrite(5, LOW);
  digitalWrite(0, HIGH);
}

void on_red_led(){
  Serial.println("Turning on red led");
  digitalWrite(0, LOW);
  digitalWrite(5, HIGH);
}


// 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);
  }
}

Please note that the setup of the pins on the ESP8266 will depend on the type of RFID card you have and also the version of the ESP8266
I am using the ESP8266 (ESP-12) which is a Node-cu development board.

2 Likes