Controlling House Alarm From HA

Overview of the setup

Home Assistant is running perfectly on a Raspberry Pi version 2B - $35

[attachment=2]IMG_20151211_103127.jpg[/attachment]

It is connected to the Alarm system using the GPIO ports. Also notice it is connected to a USB modem that sends command over the phone line to the alarm system.

[attachment=1]IMG_20151211_103101.jpg[/attachment]

The GPIO inputs are connected to the PIR Sensors on the alarm. There are resistors in between, I can give more info if someone is interested.

[attachment=0]IMG_20151211_103144.jpg[/attachment]

Overview of the setup (Continued)

Relay switches powered by the output from the alarm are connected to GPIO on RPI2 to give status of alarm (on or off)

[attachment=1]IMG_20151211_103200.jpg[/attachment]

The RPI2 is inside a Server Rack. I use to have a $2000 server which ran an number of virtual machines. I have replaced it with 2 RPI2. One for HA and another for Media.

[attachment=0]IMG_20151211_103044.jpg[/attachment]

Overview of the setup (Cont)

To turn on and off the Alarm I use a RFID Reader connected to a ESP8266 .
For those that don’t know the ESP8266 is a micro controller (mini computer) that has a built in Wifi adapter and can be used to do all sorts of interesting things like send information back to HA.

Note that my existing alarm’s RFID reader still works and I have not touched that. This gives me the option to add more control panels and more tokens. Here is a picture of the setup:

Overview of the setup (Cont)

I put the whole setup in a plastic Garfield doll. I drilled a couple holes for the LED in the front and one hole in the back for USB power.
When I present the token to Garfield it either turns on or off the alarm depending on it’s current state.
I have a few “Garfield’s” around the house so that I can see the status of the alarm and set it if necessary.

I can easily move them around the house as they are connected using wifi.

The RFid sensor is tapped on the inside of Garfield’s belly. Garfield’s head screws off.

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

Setting up an RFID reader to interface with HA

The following python code is run on the HA server (or any other server). It listens for MQTT messages from the RFID Reader.
To add token serial numbers you will need to read MQTT messages as they are being published from the ESP8266 and add it to the python script.

Couple of things: Note the section bellow, which allows the maid to only unlock the alarm in the morning on weekdays when she comes to work.
If you are concerned about someone brute forcing your RFID token serial number then you can add a few seconds or minute wait after wrong token to make that attack ineffective.

import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
import time
import datetime
import homeassistant.remote as remote
import os

"""
Script to check rfid token to allow access to turn on and off alarm system
"""

# mqtt server and home assistant server
host = '192.168.0.59'

#  Make sure to change the serial number to match your tokens
allowed_tokens = [
'xxxxxxxxx;james',
'xxxxxxxxx;annie',
'xxxxxxxxx:maid'
]


# home assistant api
api = remote.API(host, '')
day_of_week = datetime.date.today().weekday() # 0 is Monday, 6 is Sunday


# Get current alarm state
def get_alarm_state():
	alarm = remote.get_state(api, 'sensor.alarm')
	alarm_state = alarm.state.lower()
	print ("Alarm state is: ", alarm_state)
	return alarm_state

alarm_state = get_alarm_state()

# check if user is authorized to turn off alarm
def authorized_off(token):
	if token.split(';')[1] == 'henry' or token.split(';')[1] == 'annie':
		return True
	# To let the maid unlock the alarm between 7:30 AM and 10AM weekdays only
	if day_of_week < 6 and (now > datetime.time(7,50) and now < datetime.time(10,00)) and token.split(';')[1] == 'maid':
		return True
	else:
		return False


# Send message using pushover service
def pushover(message):
	m = {"title":"RFID Access", "message":message}
	#remote.call_service(api, 'notify', 'pushover', m)


# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
	print("Connected with result code "+str(rc))
	client.subscribe([("/rfid/user", 1), ("/alarm/state", 1)])


# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
	global alarm_state

	if msg.topic == "/alarm/state":
		print ("Message Topic:", msg.topic)
		print ("Message payload:", msg.payload)
		print(msg.topic+" "+str(msg.payload))
		alarm_state = str(msg.payload) 
		print ("Alarm state is:", alarm_state)
		return

	elif msg.topic == "/rfid/user":
		print ("user rfid token presented:", str(msg.payload))
		# check for valid tokens
		for token in allowed_tokens:
			if token.split(';')[0] in str(msg.payload):
				print (token.split(';')[0], 'presented access token')

				# if alarm is on, turn it off (if authorized)
				if 'on' in str(alarm_state) and authorized_off(token):
					print ("Turning off alarm")
					#remote.call_service(api, 'switch', 'turn_off', {'entity_id': '{}'.format('switch.alarm')})
					os.system('python3 alarm.py -s off')
					message = "%s has turned off the alarm" %token.split(';')
					#time.sleep(2)
					#pushover(message)
					#time.sleep(30)

				# if alarm is off turn in on
				elif 'off' in str(alarm_state):
					print ("Turning on alarm")
					#remote.call_service(api, 'switch', 'turn_on', {'entity_id': '{}'.format('switch.alarm')})
					os.system('python3 alarm.py -s on')
					message = "%s has turned on the alarm" %token.split(';')
					#time.sleep(2)
					#pushover(message)
					#time.sleep(90)

				# in case the alarm is being controlled somewhere else	
				else:
					print ("Alarm state is: ", alarm_state)
					publish.single("/alarm/state", "error", hostname=host)
					time.sleep(5)
					alarm_state = get_alarm_state()
					publish.single("/alarm/state", alarm_state, hostname=host)


	else:
		pass


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(host, 1883, 60)
client.loop_forever()

The above script could probably be done entirely inside the HA configuration, however I was lazy and just did what would be quickest.

1 Like

Controlling the Alarm

My alarm system can be controlled by calling in by telephone and pressing buttons on the phone to enter passwords, set the alarm etc.
To control the alarm, I wanted to automate the pressing of the phone keys by using a USB modem. The script automatically dials the phone and sends dial tones at the right time interval.

This was the hardest part as I spend a day or two trying to find modem software that would still work and work on Raspberry Pi Arm CPU.
Almost nobody uses dial tone modem software anymore so most of the code is no longer working.

The only software that I found that still works on RPI is wvdial.

The following python code can be called from HA as a command switch or from the RFID python script.
It sends commands to the USB modem, which calls the alarm system on the phone line (local house call) and automatically sends key presses at the right time.

It also does other things like publish alarm status to MQTT server and sets the alarm status in HA.

import os
import sys
import time
import subprocess
from optparse import OptionParser
import RPi.GPIO as GPIO
import homeassistant.remote as remote
from homeassistant.const import STATE_ON, STATE_OFF


"""
Script to turn on and off my Bosche EZ Series Alarm using modem to call into alarm system
"""

alarm_set_time = 20
alarm_arm_time = 60


# command line options
parser = OptionParser()
parser.add_option("-s", "--state", dest="state",
				  help="on or off")
(switch, args) = parser.parse_args()


#::: Publish state of the alarm to mqtt server :::
def publish_mqtt(alarm_state):
	command = "mosquitto_pub -r -h '192.168.0.59' -t '/alarm/state' -m '%s' " % alarm_state
	os.system(command)


#::: Make sure this program is not still running :::
def file_exist(_file):
	try:
		with open(_file) as f: pass
	except IOError:
		return False
	return True
	f.close

if file_exist("wvdial.conf"):
	print ("Script to set alarm already running will now exit")
	sys.exit()


# GET ALARM STATE
GPIO.setmode(GPIO.BOARD)
pin = 8
GPIO.setup(pin, GPIO.IN)

if GPIO.input(pin):
	alarm = 'on'
else:
	alarm = 'off'


if switch.state == 'on' and alarm == 'off':
	publish_mqtt('arming')
	print("Turning on the alarm")
	config = '''
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Modem Type = USB Modem
Phone = ,,,###,,,1111,,,1,,,1,,,#,
ISDN = 0
Password = ''
New PPPD = yes
Username = ''
Modem = /dev/ttyACM0
Baud = 460800
	'''

elif switch.state == 'off' and alarm == 'on':
	publish_mqtt('disarming')
	print("Turning off the alarm")
	config = '''
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Modem Type = USB Modem
Phone = ,,,###,,,1111,,,1,,,#,
ISDN = 0
Password = ''
New PPPD = yes
Username = ''
Modem = /dev/ttyACM0
Baud = 460800
		'''

else:
	print ("Alarm is already:", switch.state, " no action taken ...")
	publish_mqtt(switch.state)
	sys.exit()


# write wvdial config file
f = open('wvdial.conf','w')
f.write(config)
f.close()


# run wvdial
command = 'wvdial -C wvdial.conf'
print ('running wvdial: ', command)
p = subprocess.Popen(command, shell=True)


# Wait 30 seconds for dial command to finish
print ('waiting %s seconds to set alarm' % alarm_set_time)
time.sleep(alarm_set_time)


# Kill wvdial
p.kill()
os.system('killall wvdial')

# Set Alarm state
api = remote.API('localhost', '')
if switch.state == 'on':
	# Wait for system to be set
	time.sleep(alarm_arm_time)
	remote.set_state(api, 'switch.alarm', new_state=STATE_ON)
	remote.set_state(api, 'sensor.alarm', new_state=STATE_ON)
	publish_mqtt('on')
else:
	remote.set_state(api, 'switch.alarm', new_state=STATE_OFF)
	remote.set_state(api, 'sensor.alarm', new_state=STATE_OFF)
	publish_mqtt('off')

os.remove("wvdial.conf")
print ('Finished setting the alarm', switch.state)


Controlling the Alarm

Finally here are some entries in the HA configuration file:

GPIO sensor component (I have added only 2 PIR sensors):

sensor:
  platform: rpi_gpio
  ports:
    4: Office
    14: Alarm
    18: Dining Room
  pull_mode: "UP"
  value_high: "on"
  value_low: "off"

Command switch to turn on and off the alarm (python script in previous post):

switch:
  platform: command_switch
  switches:
    Alarm:
      oncmd: "python3 /root/scripts/alarm.py -s on"
      offcmd: "python3 /root/scripts/alarm.py -s off"

Some automation rules to turn on and off the alarm:


automation 6:
  alias: "Make sure alarm is turned on at night after 9:15 PM"
  trigger:
    platform: time
    after: '21:15:00'
  action:
    service: switch.turn_on 
    entity_id: switch.alarm

automation 7:
  alias: "Turn on Alarm after work"
  trigger:
    platform: time
    after: '17:15:00'
  condition:
    platform: time
    after: '17:00:00'
    before: '23:00:00'
    weekday:
      - tue
      - thu
  action:
    service: switch.turn_on
    entity_id: switch.alarm

automation 8:
  alias: "Turn off Alarm in morning"
  trigger:
    platform: time
    after: '06:30:00'
  action:
    service: switch.turn_off 
    entity_id: switch.alarm  

I will post a screen shot of HA to show the alarm switch and the PIR sensors and alarm state when I get back home.

Wow that is a very impressive job!

Impressive indeed!

[quote=“thaijames”]Overview of the setup (Continued)
The RPI2 is inside a Server Rack. I use to have a $2000 server which ran an number of virtual machines. I have replaced it with 2 RPI2. One for HA and another for Media.
[/quote]

Am I reading this correctly that what once required a $2000 server rack can now be accomplished with two RPi2’s? Or are they two totally unrelated things? Just curious…

RE: RFID- One of my next automation projects on my list is to install a smartlock using a lockitron assembly with custom electronics. RFID/NFC is an obvious candidate for this project along with BLE, wifi etc… I was initially going to use my one Adafruit Huzzah that I’ve been reserving for this project (which is why my other ESP projects need to be limited to two pins each as they must use the ESP v01)… However, looking at your own RFID reader connection it looks like it eats up a lot of pins on its own and I’m wondering if adding an RFID/NFC reader would crowd out any other peripherals on my Huzzah.

RE:ESP8266
On a related note, i’m wondering if your network might be a good use-case for where an OpenWRT/Arduino Yun style controller might have a niche? (Please note that my intention here is not to actually suggest you make any changes to an already well-functioning system. On the contrary it is precisely because it is such a mature network that it makes a great starting point for exploring hypothetical alternatives…) I’ve always approached the RPi as a great server, or network hub but not so much as a hardwired sensor/actuator in of itself. Likewise, in the ESP8266 I see something which was originally meant to function as a wireless peripheral (e.g XBee, nrf24 RF Modules etc…) but has nonetheless been embraced for its potential as a low-cost standalone microcontroller. In other words, I wonder if you have deployed the two devices in a manner that plays to their weakest points rather than where they can perform to their potential? As you mentioned the difficulty in configuring the RPi to communicate with the modem, OpenWRT as a home router platform, is often used for this purpose and supports various utilities that can be deployed more efficiently than the RPi. While its price point has made it far less popular than both the ESP and/or RPi, the Arduino Yun offers a full OpenWRT stack embedded on top of a full Arduino “Leonardo” style microcontroller. Perhaps most importantly, Arduino ships with a default “Bridge Library” which facilitates communication between the Linux and Arduino functions. Such a platform might give you access to more IO pins while handling the USB modem connections more efficiently. Which in turn could free the RPi and ESP for other uses that they may be better suited…

Again, I’m just exploring the possibilities. For all useful purposes you clearly have a fully functioning, mature system that probably doesnt need much improvement as is:)
Great Job!

Thank you.

In my case the 2 RPIs replaced the 2000 dollar server because I wanted to reduce power consumption. However I do not mean to imply that the RPIs have the power, speed or storage capacity of a $2000 server. They obviously don’t. Having said that I have absolutely no problems running HA on a PI2 and use the other PI2 for Media downloading and server. My power usage seems to have gone down by 50 dollars a month.

Regarding using OpenWrt you make a good point. It is a amazing platform for networking and can be used for all kinds of good things considering it is linux. The only problem is getting the drivers for the modem. (There are plenty of drivers for 3G modems, but we are talking about Telephone dial up modems used 20 years ago) I am not sure if OpenWrt would have drivers for it.

I am trying to keep some functions separated. I have a large house and two RFID sensors, so it is easier to just have ESP8266 sending info to the the HA server (RPI).

The lines are blurring rapidly with hardware. By the same token if I was not limited by the modem drivers I could have used a cheap old android tablet or phone to run HA (linux deploy) connected to an arduino by USB. Then you have the possibility of having an interface on the screen and communications by telephone, Internet and Mobile Data. Depending on the hardware you might have access to the built in GPS, barometers, temperature sensors, finger print sensors etc.

EDIT:
Actually since phones use ARM processors there should be no problem installing the modem drivers. Also the phone or tablet batteries act as a built in UPS!

thaijames,

I’m interested in what you have accomplished, but would like to take it one step further without the RFID and replace my current alarm system with a rpi gpio and HA based alarm system.

I would like to replace my keypad with cheap android tablet which will also be hooked up to a front door camera. PIR sensors would trigger the alarm when active and a relay would set off the siren and strobe and pushbullet a message or maybe an sms gateway

I’m interested in how you setup the PIR sensors on the rpi but your attachments don’t seem to load. Can you please repost the photos.

Thanks,

Mark

Thanks for this @thaijames I’ve just set this up and it work brilliantly! I’m very please. Not installed it yet but in testing it’s been working well!

Just wondering, what LED did you use and how did you wire it to the NodeMCU? This is the only part I dont have working yet. Not critical but would be nice to have!

Many thanks!

Hi Guys

I liked the idea of an RFID with the status lights attached and tested this code. The RFID ids are now sent to HA and this part is OK. The code I`am struggeling with is the part below. If the Alarm is armed (armed_home) the message is received and activates the “// Alarm is on” loop. The same for “// Alarm is off” loop. But nothing happens when “pending” is received. Has something changed in HA since this code were made? If anyone is kind enough, could someone please explain what this means: ((char)payload[2] == ‘m’)

[quote=“thaijames, post:7, topic:67”]
// 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();
[/quote]

I figured it out. Let me know if anyone else needs the code :slight_smile:

Yes. Please share. :slight_smile:

Hi

I choose to not use the flashing leds, since it stop any other actions from the Node MCU.
Works as intended on the following 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

RGB LED Setup
Red LED   = D1
Ground    = GND
Gr. LED   = D2
Blue LED  = D0
*/
#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 = "xxxxx";
const char* password = "xxxxxx";

const char* mqtt_server = "xxxxxxx";
const char* mqtt_user = "xxxxxxx";
const char* mqtt_password = "xxxxxxxx";
const char* clientID = "RFID";
const char* rfid_topic = "home/rfid";
const int redPin = D1;
const int greenPin = D2;
const int idPin = D0;

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
  pinMode(redPin, OUTPUT); // Red LED
  pinMode(redPin, HIGH); 
  pinMode(greenPin, OUTPUT); // Green :LED
  pinMode(greenPin, HIGH);
  pinMode(idPin, OUTPUT); // ID :LED
  pinMode(idPin, HIGH);
  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();
    off_both_led();    
  }   
  // Alarm is Armed Home    
    else if (sp == "armed_home")
    {
    Serial.println();
    Serial.print("Alarm is set to Armed Home");
    Serial.println();
    on_green_led();     
  } 
  // Alarm is arming
      else if (sp == "pending")
    {
    Serial.println();
    Serial.print("Alarm set to Pending");
    Serial.println();
    on_both_led();    
  }   
  // Alarm is Armed Away
    else if (sp == "armed_away")
    {
    Serial.println();
    Serial.print("Alarm set to Armed Away");
    Serial.println();
    on_green_led();    
  } 
  // Alarm is Triggered
    else if (sp == "triggered")
    {
    Serial.println();
    Serial.print("Alarm is triggered!!");
    Serial.println();
    on_red_led();    
  }
}}
/* 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);
}
// LED Loop
void off_both_led(){
  Serial.println("Turning off all led");
  digitalWrite(greenPin, LOW);
  digitalWrite(redPin, LOW);
}
void flash_green_led(){
  Serial.println("Flashing Green LED");
  digitalWrite(greenPin, LOW);
  // Flash 15 times:
  for(int i = 0; i < 14; i++)
  {
  digitalWrite(greenPin, HIGH);
  delay(1000);
  digitalWrite(greenPin, LOW);
  delay(500);
}}
void flash_red_led(){
  Serial.println("Flashing Red LED");
  digitalWrite(redPin, LOW);
  // Flash 20 times:
  for(int i = 0; i < 19; i++)
  {
  digitalWrite(redPin, HIGH);
  delay(1000);
  digitalWrite(redPin, LOW);
  delay(500);
}}
void on_green_led(){
  Serial.println("Turning on green led");
  digitalWrite(redPin, LOW);
  digitalWrite(greenPin, HIGH);
}
void on_red_led(){
  Serial.println("Turning on red led");
  digitalWrite(greenPin, LOW);
  digitalWrite(redPin, HIGH);
}
void on_both_led(){
  Serial.println("Turning on both led");
  digitalWrite(greenPin, HIGH);
  digitalWrite(redPin, 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);
  }
}
1 Like

Hi, this project is very interesting, actually I’m using this Alarm System (https://github.com/runningman84/home-assistant-apps) made by runningman84.
I wish to use a RFID card or tag only to arm or disarm alarm.
I need only the part of code to program ESP8266 to send to HA the authorized badge/tag to arm or disarm alarm.
Can you help me?

Hi. Do you mean the yaml part in HA?

Hi Rune, I use this Alarm System (https://github.com/runningman84/home-assistant-apps/blob/master/apps/alarm.py) that automatically arm and disarm alarm based on device_tracker recognition of my smartphone (when works fine). I wish an alternative way to arm and disarm it using RFID badge or tag.
I’ve a RC522, a Nodemcu V3 Lolin and I wish to use the firmware and scripts created by thaijames to integrate them in my Home Assistant.
I’m a newbie please help me…

There is a firmware to flash in Nodemcu to send RFID token to HA
(Controlling House Alarm From HA)

There is a code to interface RFID reader to HA …I suppose to put in a file like… rfid.py
(Controlling House Alarm From HA)
Where should this file be put?

Then there is some automation to put in configuration.yaml to arm or disarm alarm

My alarm code is based on appdaemon and is located in /config/appdaemon/apps/alarm.py
Usually I arm or disarm it using automations…

  action:
      - service: alarm_control_panel.alarm_arm_home
        data: {"entity_id":"alarm_control_panel.ha_alarm","code":"12345678"}

or

  action:
      - service: alarm_control_panel.alarm_disarm
        data: {"entity_id":"alarm_control_panel.ha_alarm","code":"12345678"}

To simplify operations at the moment I wish to exclude the management of the LEDs
Can you help me?