PolyScrubRyan TanAloysius Chng
Published

IOTca2

A home security application, providing surveillance of the front door and the kitchen.

BeginnerWork in progress2,963
IOTca2

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×3
Arduino UNO
Arduino UNO
×1
Grove - Gas Sensor(MQ2)
Seeed Studio Grove - Gas Sensor(MQ2)
×1
Flame sensor
Ensure flame sensor senses via IR waves.
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
×2
RGB LED
As the colour red and green are used, ensure that whatever multi-colored LED is used can support those 2 colours.
×1
Buzzer
Buzzer
×3
MFRC522 RFID reader/writer module
×1
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
×1
LED (generic)
LED (generic)
×3
Resistor 220 ohm
Resistor 220 ohm
×6
Resistor 10k ohm
Resistor 10k ohm
×1
Gravity:Digital Push Button (Yellow)
DFRobot Gravity:Digital Push Button (Yellow)
×1

Software apps and online services

AWS DynamoDB
Amazon Web Services AWS DynamoDB
Telegram Bot
SMS Messaging API
Twilio SMS Messaging API
Arduino IDE
Arduino IDE
Boto3
AWS IoT
Amazon Web Services AWS IoT
MQTT
MQTT

Story

Read more

Schematics

RPi 1: Kitchen

RPi 3: Front door part 2

RPi 2: Front door part 1

Code

ReadNFC.py

Python
#!/usr/bin/env python
# -*- coding: utf8 -*-
 
import sys
import Adafruit_DHT
import mysql.connector
import RPi.GPIO as GPIO
import MFRC522
import signal
import time

from gpiozero import LED
from gpiozero import Buzzer
from signal import pause

from rpi_lcd import LCD
from time import sleep
 
continue_reading = True
 
# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    continue_reading = False
    GPIO.cleanup()

led = LED(18)
led2 = LED(20)
bz = Buzzer(5)

def ledOn():
    led.on()
    led2.off()

def ledOn2():
	led2.on()
	led.off()
    
lcd = LCD()
def Open():
    lcd.text('Door Opened',1)
    sleep(5)
    lcd.clear()

def Close():
    lcd.text('Access Denied',1)
    lcd.text('Wrong Key',2)
    sleep(5)
    lcd.clear()
 
# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)
 
# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# Welcome message
 
# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:    
    # Scan for cards    
    (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
 
    # If a card is found
    if status == MIFAREReader.MI_OK:
	time.sleep(2)    

    # Get the UID of the card
    (status,uid) = MIFAREReader.MFRC522_Anticoll()
 
    # If we have the UID, continue
    if status == MIFAREReader.MI_OK:

        
        # Select the scanned tag
        MIFAREReader.MFRC522_SelectTag(uid)
        
        #ENTER Your Card UID here
        my_uid = [136,4,20,190,38]

        uid1 = ''.join(str(e) for e in uid)
        uid1.replace("'","")
        cnx = mysql.connector.connect(user='iotuser',password='dmitiot',host='localhost',database='assignmentdatabase') 
        cursor = cnx.cursor()
        cursor.execute("Select rfid_values FROM rfid WHERE rfid_values =('%s')" %uid1)
        result = cursor.fetchone()

        
        #Check to see if card UID read matches your card UID
        if cursor.rowcount == 1:                
            print("Access Granted - {}".format(uid1))
            ledOn()
	    Open()
            bz.off()
		
        else:                            #Don't open if UIDs don't match
            print("Access Denied - {}".format(uid1))
	    ledOn2()
	    Close()
	    bz.on()
	    sleep(1)
	    bz.on()
	    sleep(1)
	    bz.off()

telegrambot.py

Python
import telepot
from gpiozero import LED
from time import sleep
#Import all libraries needed


my_bot_token = '943409193:AAHG7RMbNR1C31Y6PGACVsPvfkAx1KiHeyU'
#Enter the bot token 
led = LED(18)
led2 = LED(20)

def UnlockDoor():
   led.on()
   led2.off()
   return "Door is now unlocked..."

def LockDoor():
   led2.on()
   led.off()
   return "Door is now locked"

def respondToMsg(msg):
    chat_id = msg['chat']['id']
    command = msg['text']
	
    print('Got command: {}'.format(command))

    if command == 'Unlock':
       bot.sendMessage(chat_id, UnlockDoor())
    elif command =='Lock':
       bot.sendMessage(chat_id, LockDoor())

bot = telepot.Bot(my_bot_token)
bot.message_loop(respondToMsg)
print('Listening for RPi commands...')


while True:
	 LockDoor()
     sleep(15)
	 

Doorbelltb.py

Python
import pyimgur
import time
import os
import sys
import re
import threading
import picamera
import telepot
import schedule
import requests
from gpiozero import Button, Buzzer
from time import sleep

my_bot_token = '943409193:AAHG7RMbNR1C31Y6PGACVsPvfkAx1KiHeyU'

def DetectAndNotify(bot_message):
    
    bot_token = '943409193:AAHG7RMbNR1C31Y6PGACVsPvfkAx1KiHeyU'
    bot_chatID = '-375074177'
    send_text = 'https://api.telegram.org/bot' + bot_token + '/sendMessage?chat_id=' + bot_chatID + '&parse_mode=Markdown&text=' + bot_message

    response = requests.get(send_text)

    return response.json()

#for twilio
from twilio.rest import Client
account_sid = "ACbc81590032ee12b7e205394aae9130ec"
auth_twilio = "331dbfab7b747f16036c39d3545fb353"
client = Client(account_sid, auth_twilio)
my_hp = "+6591440914"
twilio_hp = "+19088544663"

# For Imgur
CLIENT_ID = "84017be6449ab0b"
im = pyimgur.Imgur(CLIENT_ID)

# Minimum time between each pictures
DELAY = 10

# Text messages
TXT_MSG = "Someone is at the door."

# Picture definition
IMG_WIDTH = 800
IMG_HEIGHT = 600

button = Button(13, pull_up=False)
bz = Buzzer(5)

def TakePictureAndSend():
  timestring = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
  filename = '/home/pi/photo_'+timestring+'.jpg'
  with picamera.PiCamera() as camera:
    camera.resolution = (IMG_WIDTH, IMG_HEIGHT)
    camera.capture(filename)
  uploaded_image = im.upload_image(filename, title=TXT_MSG)
  print "Sending message"
  client.messages.create(to=my_hp,
                      from_=twilio_hp,
                      body=TXT_MSG,
                      media_url=uploaded_image.link)

  # 20 Seconds between each picture
  time.sleep(DELAY)

def buzzOn():
	bz.on()
	sleep(2)
	bz.off()
	TakePictureAndSend()
	test = DetectAndNotify("Someone is at the door. You can control the door using the bot by typing 'Lock' or 'Unlock'.")
	print(test)
	sleep(2)
    
while True:
	button.when_pressed = buzzOn

styles.css

CSS
/* Colours used: #3AAFA9, #17252A, #2B7A7B, #DEF2F1, #FEFFFF */

html {
    color: #17252A;
}

body {
    background-color: #3AAFA9;
    font-family: 'Merriweather', serif;
}

a {
    text-decoration: none;
}

.active, a:hover {
    color: #FEFFFF;
}

a:visited, a:link {
    color: #17252A;
}

.grid-container {
    display: grid;
    grid-template-areas:
        'header header header header'
        'main main main right';
    grid-gap: 10px;
    padding: 10px;
    background-color: #2B7A78;
}

.grid-container > div {
    padding: 20px 0;
    background-color: #3AAFA9;
}

.itemHeader { 
    text-align: center;
    grid-area: header;
}

.itemMain {
    grid-area: main;
}

.entryLog {
    padding: 10px;
}

.gasGraph {
    padding: 10px;
    width: 75%;
}

.dataTable {
    padding: 10px;
    width: 75%;
}

.btn {
    margin: 10px;
    background-color: #FEFFFF;
}

.itemRight {
    grid-area: right;
    text-align: center;
}

.welcome {
    font-family: 'Saira Extra Condensed', sans-serif;
    font-size: 2.5vw;
    color: #FEFFFF;
}

.FireLvL {
    font-weight: bold;
}

footer {
    position: relative;
    left: 0;
    bottom: 0;
    width: 100%;
    text-align: center;
    font-size: 1vw;
}

index.html

HTML
<!DOCTYPE html>
<html lang=en>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Home Security - Front Door</title>
    <link href="https://fonts.googleapis.com/css?family=Merriweather|Saira+Extra+Condensed:900&display=swap" rel="stylesheet">
    <link type="text/css" rel="stylesheet" href="{{ url_for('static',filename='styles.css') }}">
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.js"></script>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    
    <!-- JScript for Clock -->
    <script>
        function startTime() {
            var today = new Date();
            var h = today.getHours();
            var m = today.getMinutes();
            var s = today.getSeconds();
            m = checkTime(m);
            s = checkTime(s);
            document.getElementById('clock').innerHTML = h + ":" + m + ":" + s;
            var t = setTimeout(startTime, 500);
        }
        function checkTime(i) {
            if (i < 10) {
                i = "0" + i;
            }
            return i;
        }
    </script>

    <!-- JScript for DataTable -->
    <script type="text/javascript">
        google.charts.load('current', {'packages': ['corechart', 'table']});
        google.charts.setOnLoadCallback(googlecharts_is_ready);

        var graphdata;

        function reset_status_messages() {
            $("#status").html("");
        }

        function googlecharts_is_ready() {
            $("#buttonloadchart").show();
            loadChart();
            $("#status").html("Google charts is ready");
        }

        function loadChart() {
            getData_and_drawChart();
        }

        function getData_and_drawChart() {
            getNewData();
        }

        function getNewData() {
            $("#status").html("Fetching data to plot graph...");

            jQuery.ajax({
                url: "/api/getdata",
                type: 'POST',
                success: function (ndata, textStatus, xhr) {
                    $("#status").html("Data fetched! Now plotting graph!");
                    console.log(ndata.chart_data.data);
                    chartdata = ndata.chart_data.data;
                    graphdata = createDataTable(chartdata);
                    drawLineChart(graphdata);
                    drawDataTable(graphdata);
                    $("#status").html("Graph plotted");
                }//end success
            });//end ajax
        } //end getNewData

        function createDataTable(newdata) {
            graphdata = new google.visualization.DataTable();
            graphdata.addColumn('string', 'Date');
            graphdata.addColumn('number', 'Gas Level');
            run_once = true;
            for (i in newdata) {
                datetime = newdata[i].Date;
                raw_value = String(newdata[i].RawValue);
                var splitvalue = raw_value.split("+"),
                a = splitvalue[0], b = splitvalue[1];
                var level = parseInt(b);
                var firelvl = a.bold();
                if (run_once == true){
                    if (a == "NO FIRE") {
                        document.getElementById("FireLvL").style.color = '#FEFFFF';
                        document.getElementById("FireLvL").innerHTML = firelvl;
                    }

                    else if (a == "LOW") {
                        document.getElementById("FireLvL").style.color = '#FFAE42';
                        document.getElementById("FireLvL").innerHTML = firelvl;
                    }

                    else if (a == "HIGH") {
                        document.getElementById("FireLvL").style.color = '#FF2323';
                        document.getElementById("FireLvL").innerHTML = firelvl;
                    }
                    run_once = false;
                }
                graphdata.addRows([[datetime, level]]);
            }//end for
            return graphdata
        }

        function drawDataTable(graphdata) {
            var table = new google.visualization.Table(document.getElementById('table'));
            table.draw(graphdata, { showRowNumber: true, width: '100%', height: '100%' });
        }//end drawTable

        function drawLineChart(graphdata) {
            var chart = new google.visualization.LineChart(document.getElementById('chart'));
            chart.draw(graphdata, {legend: 'none', vAxis: { baseline: 0 }, colors: ['#3AAFA9']});
        } //end drawChart

        $(document).ready(function() {
            reset_status_messages()
            setInterval(function() {loadChart()}, 1000);
        }); //end of Ready and setInterval
    </script>
</head>

<body onload="startTime()">
    <!-- Start of grid -->
    <div class="grid-container">

        <!-- Header -->
        <div class="itemHeader">
            <div class="welcome">
                <h2>Welcome to HomeSecurity</h2>
            </div>
        </div>

        <!-- Kitchen -->
        <div class="itemMain">
            <!-- LineGraph -->
            <div class="gasGraph">
                <h3>Gas Sensor Reading</h3>
                <div id="chart"></div>
            </div>

            <!-- Load Button -->
            <input class="btn" id="buttonloadchart" type="button" onclick="loadChart()" value="Update graph">

            <!-- DataTable -->
            <div class="dataTable">
                <h3>Gas Sensor History Log</h3>
                <div id="table"></div>
            </div>
        </div>

        <!-- Clock and Light indicator -->
        <div class="itemRight">
            <!-- Clock for user -->
            <div class="Clock">
                <h3 id="clock"></h3>
                <div class="Fire">
                    <h3>Fire Level:</h3>
                    <div id="FireLvL"></div>
                </div>
            </div>
        </div>
    </div>
    <!-- End of grid -->
</body>

<footer>
    <p>created by Ryan Tan, Tan Jia Liang and Aloysius Chng.</p>
</footer>
</html>

kitchen_db.py

Python
# Import SDK packages
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from time import sleep
import serial
import re
import sys
from gpiozero import LED

#for twilio
from twilio.rest import Client

account_sid = "ACbc81590032ee12b7e205394aae9130ec"
auth_twilio = "331dbfab7b747f16036c39d3545fb353"
client = Client(account_sid, auth_twilio)
my_hp = "+6591440914"
twilio_hp = "+19088544663"

sprinkler = LED(18)

#establish connection to arduino IDE
device = "/dev/ttyUSB0"
baud = 9600

# Custom MQTT message callback
def customCallback(client, userdata, message):
	print("Received a new message: ")
	print(message.payload)
	print("from topic: ")
	print(message.topic)
	print("--------------\n\n")
	
host = "a1xbz9pmhe6x41-ats.iot.ap-northeast-1.amazonaws.com"
rootCAPath = "rootca.pem"
certificatePath = "certificate.pem.crt"
privateKeyPath = "private.pem.key"

my_rpi = AWSIoTMQTTClient("basicPubSub")
my_rpi.configureEndpoint(host, 8883)
my_rpi.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

my_rpi.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
my_rpi.configureDrainingFrequency(2)  # Draining: 2 Hz
my_rpi.configureConnectDisconnectTimeout(10)  # 10 sec
my_rpi.configureMQTTOperationTimeout(5)  # 5 sec

# Connect and subscribe to AWS IoT
my_rpi.connect()
my_rpi.subscribe("iot/kitchen", 1, customCallback)
sleep(2)

# Test connection to Arduino
try:
    update = True
    print ("Connecting to {}".format(device)) 
    arduino = serial.Serial(device, baud) 
except: 
    print ("Failed to connect to {}".format(device)) 
    update = False   

sprinkler_counter = 0

# Publish to the same topic in a loop forever
while update:

    try:
        data=arduino.readline() # smoke detector sample data "FLAME_LEVEL+GAS_SENSOR_RAW_VALUE"

        if data.find("+") != -1: #returning -1 means .find cant find the specified string
            data = data.translate(None, "\n")
            ino_output = data.split('+')
            print(ino_output[0], ino_output[1]) #to display collection of data

            if(ino_output[0] == 'HIGH' and int(ino_output[1]) >= 300):
                TXT_MSG = 'FIRE DETECTED IN KITCHEN'
                client.messages.create(to=my_hp,
                from_=twilio_hp,
                body=TXT_MSG)
                sprinkler.on()
                print(ino_output[0], ino_output[1])
                sprinkler_counter = sprinkler_counter + 1
            
            elif(int(ino_output[1]) >= 300):
                TXT_MSG = 'GAS LEAK DETECTED IN KITCHEN'
                client.messages.create(to=my_hp,
                from_=twilio_hp,
                body=TXT_MSG)
                print('hello')
            
            if (sprinkler_counter >= 1 and sprinkler_counter <= 4):
                sprinkler_counter = sprinkler_counter + 1
            
            if(sprinkler_counter >= 4):
                sprinkler.off()

            msg_output = data
            message = {}
            message["deviceid"] = "deviceid_1836860_JL"
            import datetime as datetime
            now = datetime.datetime.now()
            dt = now.strftime("%d/%m/%Y %H:%M:%S")
            message["datetimeid"] = dt
            message["value"] = msg_output
            import json
            my_rpi.publish("iot/kitchen", json.dumps(message), 1)
            sleep(1)   

    except KeyboardInterrupt: # ctrl+c to stop program
        update = False
    
    except:
        print("Error while inserting data...")
        print(sys.exc_info()[0])
        print(sys.exc_info()[1])

kitchensensor.ino

C/C++
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int MQ_PIN=A1;
int FLAME_PIN=A0;
const int sensorMin = 0;     // sensor minimum
const int sensorMax = 1024;  // sensor maximum
String flameLevel = ".";
const int maxGas = 300;
int redPin= 4;
int greenPin = 5;
int bluePin = 6;
int buzzPin = 10;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // sets the serial port to 9600
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  Serial.println("Gas sensor warming up!");
  lcd.clear();
  lcd.begin(16,2);
  lcd.print("Calibrating..."); 
  delay(20000); // allow the MQ-2 to warm up
  lcd.setCursor(0,1);
  lcd.print("Done");
  setColor(0, 255, 0); // Green Color
  delay(3000);
}


void loop() {
  // put your main code here, to run repeatedly:
    // read the sensor on analog A0:
  int flameReading = analogRead(FLAME_PIN);
  int gasReading = analogRead(MQ_PIN);
  // map the sensor range (four options):
  // ex: 'long int map(long int, long int, long int, long int, long int)'
  int range = map(flameReading, sensorMin, sensorMax, 0, 3);

  switch (range) {
  case 0:    // A fire closer than 1.5 feet away.
    flameLevel = "HIGH";
    break;
  case 1:    // A fire between 1-3 feet away.
    flameLevel = "LOW";
    break;
  case 2:    // No fire detected.
    flameLevel = "NO FIRE";
    break;
  }
 
    
    Serial.print(flameLevel);
    Serial.print("+");
    Serial.print(gasReading);
    Serial.print("\n");

    if( gasReading >= maxGas && flameLevel.equals("HIGH") ){ //maxGas is a constant 300
      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print("DANGER!!!");
      lcd.setCursor(1,1);
      lcd.print("FIRE DETECTED");
      setColor(255, 0, 0); // Red Color
      tone(buzzPin,1000);
      delay(4000);  
      noTone(buzzPin);
    }
    else if(gasReading >= maxGas){
      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print("DANGER!!!");
      lcd.setCursor(0,1);
      lcd.print("GAS LEAK ACTIVE");
      int counter = 0;

      while(counter <= 4){
      tone(buzzPin,1000);
      setColor(255, 0, 0); // Red Color
      delay(750);
      noTone(buzzPin);
      setColor(0, 0, 0); // Red Color
      delay(250);
      counter++;        
      }

    }
    else{
    
    setColor(0, 255, 0); // Green Color
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("GAS LV  FLAME LV");
    lcd.setCursor(0,1);
    lcd.print(gasReading);
    lcd.setCursor(8,1);
    lcd.print(flameLevel);
    delay(1000);  // delay between reads
    }    
    


}
void setColor(int redValue, int greenValue, int blueValue) {
      analogWrite(redPin, redValue);
      analogWrite(greenPin, greenValue);
      analogWrite(bluePin, blueValue);
}

AddAccess.py

Python
import sys
import Adafruit_DHT
import mysql.connector
import RPi.GPIO as GPIO
import MFRC522
import signal
from rpi_lcd import LCD
from time import sleep

uid = None
prev_uid = None 
continue_reading = True
#GPIO.setwarnings(False)

# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    print "Ctrl+C captured, ending read."
    continue_reading = False
    GPIO.cleanup()

lcd = LCD()
def Add():
    lcd.text('User Added',1)
    sleep(5)
    lcd.clear()
    

# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
mfrc522 = MFRC522.MFRC522()


try:
    u='iotuser';pw='dmitiot';
    h='localhost';db='assignmentdatabase'

    cnx = mysql.connector.connect(user=u,password=pw,host=h,database=db) 
    cursor = cnx.cursor()
    print("Successfully connected to database!")
    # Scan for cards    
    (status,TagType) = mfrc522.MFRC522_Request(mfrc522.PICC_REQIDL)

    # If a card is found
    if status == mfrc522.MI_OK:
	
        # Get the UID of the card
        (status,uid) = mfrc522.MFRC522_Anticoll()
        if uid!=prev_uid:
           prev_uid = uid
	   uid1 = ''.join(str(e) for e in uid)
	   uid1.replace("'","")

	   print("Card is added! UID of card is {}".format(uid1))
	   Add()
      	   cursor.execute("INSERT INTO rfid (rfid_values) VALUES ('%s')" %(uid1))
	   cnx.commit()
		   
 
except:
    print(sys.exc_info()[0])
    print(sys.exc_info()[1])

DelAccess.py

Python
import sys
import Adafruit_DHT
import mysql.connector
import RPi.GPIO as GPIO
import MFRC522
import signal
from rpi_lcd import LCD
from time import sleep


uid = None
prev_uid = None 
continue_reading = True

# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    continue_reading = False
    GPIO.cleanup()

lcd = LCD()
def Del():
    lcd.text('User Deleted',1)
    sleep(5)
    lcd.clear()
# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
mfrc522 = MFRC522.MFRC522()


try:
    u='iotuser';pw='dmitiot';
    h='localhost';db='assignmentdatabase'

    cnx = mysql.connector.connect(user=u,password=pw,host=h,database=db) 
    cursor = cnx.cursor()
    # Scan for cards    
    (status,TagType) = mfrc522.MFRC522_Request(mfrc522.PICC_REQIDL)

    # If a card is found
    if status == mfrc522.MI_OK:
        # Get the UID of the card
        (status,uid) = mfrc522.MFRC522_Anticoll()
        if uid!=prev_uid:
           prev_uid = uid
	   uid1 = ''.join(str(e) for e in uid)
           uid1.replace("'","")
		   Del()
           cursor.execute("DELETE FROM rfid WHERE rfid_values = %s" %(uid1))
           print("Card is deleted! UID of card is {}".format(uid1))

           cnx.commit()
 
except:
    print(sys.exc_info()[0])
    print(sys.exc_info()[1])

MFRC522.py

Python
#!/usr/bin/env python
# -*- coding: utf8 -*-
#
#    Copyright 2014,2018 Mario Gomez <mario.gomez@teubi.co>
#
#    This file is part of MFRC522-Python
#    MFRC522-Python is a simple Python implementation for
#    the MFRC522 NFC Card Reader for the Raspberry Pi.
#
#    MFRC522-Python is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    MFRC522-Python is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public License
#    along with MFRC522-Python.  If not, see <http://www.gnu.org/licenses/>.
#
import RPi.GPIO as GPIO
import spidev
import signal
import time
import logging

class MFRC522:
    MAX_LEN = 16

    PCD_IDLE = 0x00
    PCD_AUTHENT = 0x0E
    PCD_RECEIVE = 0x08
    PCD_TRANSMIT = 0x04
    PCD_TRANSCEIVE = 0x0C
    PCD_RESETPHASE = 0x0F
    PCD_CALCCRC = 0x03

    PICC_REQIDL = 0x26
    PICC_REQALL = 0x52
    PICC_ANTICOLL = 0x93
    PICC_SElECTTAG = 0x93
    PICC_AUTHENT1A = 0x60
    PICC_AUTHENT1B = 0x61
    PICC_READ = 0x30
    PICC_WRITE = 0xA0
    PICC_DECREMENT = 0xC0
    PICC_INCREMENT = 0xC1
    PICC_RESTORE = 0xC2
    PICC_TRANSFER = 0xB0
    PICC_HALT = 0x50

    MI_OK = 0
    MI_NOTAGERR = 1
    MI_ERR = 2

    Reserved00 = 0x00
    CommandReg = 0x01
    CommIEnReg = 0x02
    DivlEnReg = 0x03
    CommIrqReg = 0x04
    DivIrqReg = 0x05
    ErrorReg = 0x06
    Status1Reg = 0x07
    Status2Reg = 0x08
    FIFODataReg = 0x09
    FIFOLevelReg = 0x0A
    WaterLevelReg = 0x0B
    ControlReg = 0x0C
    BitFramingReg = 0x0D
    CollReg = 0x0E
    Reserved01 = 0x0F

    Reserved10 = 0x10
    ModeReg = 0x11
    TxModeReg = 0x12
    RxModeReg = 0x13
    TxControlReg = 0x14
    TxAutoReg = 0x15
    TxSelReg = 0x16
    RxSelReg = 0x17
    RxThresholdReg = 0x18
    DemodReg = 0x19
    Reserved11 = 0x1A
    Reserved12 = 0x1B
    MifareReg = 0x1C
    Reserved13 = 0x1D
    Reserved14 = 0x1E
    SerialSpeedReg = 0x1F

    Reserved20 = 0x20
    CRCResultRegM = 0x21
    CRCResultRegL = 0x22
    Reserved21 = 0x23
    ModWidthReg = 0x24
    Reserved22 = 0x25
    RFCfgReg = 0x26
    GsNReg = 0x27
    CWGsPReg = 0x28
    ModGsPReg = 0x29
    TModeReg = 0x2A
    TPrescalerReg = 0x2B
    TReloadRegH = 0x2C
    TReloadRegL = 0x2D
    TCounterValueRegH = 0x2E
    TCounterValueRegL = 0x2F

    Reserved30 = 0x30
    TestSel1Reg = 0x31
    TestSel2Reg = 0x32
    TestPinEnReg = 0x33
    TestPinValueReg = 0x34
    TestBusReg = 0x35
    AutoTestReg = 0x36
    VersionReg = 0x37
    AnalogTestReg = 0x38
    TestDAC1Reg = 0x39
    TestDAC2Reg = 0x3A
    TestADCReg = 0x3B
    Reserved31 = 0x3C
    Reserved32 = 0x3D
    Reserved33 = 0x3E
    Reserved34 = 0x3F

    serNum = []

    def __init__(self, bus=0, device=0, spd=1000000, pin_mode=10, pin_rst=-1, debugLevel='WARNING'):
        self.spi = spidev.SpiDev()
        self.spi.open(bus, device)
        self.spi.max_speed_hz = spd

        self.logger = logging.getLogger('mfrc522Logger')
        self.logger.addHandler(logging.StreamHandler())
        level = logging.getLevelName(debugLevel)
        self.logger.setLevel(level)

        gpioMode = GPIO.getmode()
        
        if gpioMode is None:
            GPIO.setmode(pin_mode)
        else:
            pin_mode = gpioMode
            
        if pin_rst == -1:
            if pin_mode == 11:
                pin_rst = 15
            else:
                pin_rst = 22
            
        GPIO.setup(pin_rst, GPIO.OUT)
        GPIO.output(pin_rst, 1)
        self.MFRC522_Init()

    def MFRC522_Reset(self):
        self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE)

    def Write_MFRC522(self, addr, val):
        val = self.spi.xfer2([(addr << 1) & 0x7E, val])

    def Read_MFRC522(self, addr):
        val = self.spi.xfer2([((addr << 1) & 0x7E) | 0x80, 0])
        return val[1]

    def Close_MFRC522(self):
        self.spi.close()
        GPIO.cleanup()

    def SetBitMask(self, reg, mask):
        tmp = self.Read_MFRC522(reg)
        self.Write_MFRC522(reg, tmp | mask)

    def ClearBitMask(self, reg, mask):
        tmp = self.Read_MFRC522(reg)
        self.Write_MFRC522(reg, tmp & (~mask))

    def AntennaOn(self):
        temp = self.Read_MFRC522(self.TxControlReg)
        if (~(temp & 0x03)):
            self.SetBitMask(self.TxControlReg, 0x03)

    def AntennaOff(self):
        self.ClearBitMask(self.TxControlReg, 0x03)

    def MFRC522_ToCard(self, command, sendData):
        backData = []
        backLen = 0
        status = self.MI_ERR
        irqEn = 0x00
        waitIRq = 0x00
        lastBits = None
        n = 0

        if command == self.PCD_AUTHENT:
            irqEn = 0x12
            waitIRq = 0x10
        if command == self.PCD_TRANSCEIVE:
            irqEn = 0x77
            waitIRq = 0x30

        self.Write_MFRC522(self.CommIEnReg, irqEn | 0x80)
        self.ClearBitMask(self.CommIrqReg, 0x80)
        self.SetBitMask(self.FIFOLevelReg, 0x80)

        self.Write_MFRC522(self.CommandReg, self.PCD_IDLE)

        for i in range(len(sendData)):
            self.Write_MFRC522(self.FIFODataReg, sendData[i])

        self.Write_MFRC522(self.CommandReg, command)

        if command == self.PCD_TRANSCEIVE:
            self.SetBitMask(self.BitFramingReg, 0x80)

        i = 2000
        while True:
            n = self.Read_MFRC522(self.CommIrqReg)
            i -= 1
            if ~((i != 0) and ~(n & 0x01) and ~(n & waitIRq)):
                break

        self.ClearBitMask(self.BitFramingReg, 0x80)

        if i != 0:
            if (self.Read_MFRC522(self.ErrorReg) & 0x1B) == 0x00:
                status = self.MI_OK

                if n & irqEn & 0x01:
                    status = self.MI_NOTAGERR

                if command == self.PCD_TRANSCEIVE:
                    n = self.Read_MFRC522(self.FIFOLevelReg)
                    lastBits = self.Read_MFRC522(self.ControlReg) & 0x07
                    if lastBits != 0:
                        backLen = (n - 1) * 8 + lastBits
                    else:
                        backLen = n * 8

                    if n == 0:
                        n = 1
                    if n > self.MAX_LEN:
                        n = self.MAX_LEN

                    for i in range(n):
                        backData.append(self.Read_MFRC522(self.FIFODataReg))
            else:
                status = self.MI_ERR

        return (status, backData, backLen)

    def MFRC522_Request(self, reqMode):
        status = None
        backBits = None
        TagType = []

        self.Write_MFRC522(self.BitFramingReg, 0x07)

        TagType.append(reqMode)
        (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType)

        if ((status != self.MI_OK) | (backBits != 0x10)):
            status = self.MI_ERR

        return (status, backBits)

    def MFRC522_Anticoll(self):
        backData = []
        serNumCheck = 0

        serNum = []

        self.Write_MFRC522(self.BitFramingReg, 0x00)

        serNum.append(self.PICC_ANTICOLL)
        serNum.append(0x20)

        (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, serNum)

        if (status == self.MI_OK):
            i = 0
            if len(backData) == 5:
                for i in range(4):
                    serNumCheck = serNumCheck ^ backData[i]
                if serNumCheck != backData[4]:
                    status = self.MI_ERR
            else:
                status = self.MI_ERR

        return (status, backData)

    def CalulateCRC(self, pIndata):
        self.ClearBitMask(self.DivIrqReg, 0x04)
        self.SetBitMask(self.FIFOLevelReg, 0x80)

        for i in range(len(pIndata)):
            self.Write_MFRC522(self.FIFODataReg, pIndata[i])

        self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC)
        i = 0xFF
        while True:
            n = self.Read_MFRC522(self.DivIrqReg)
            i -= 1
            if not ((i != 0) and not (n & 0x04)):
                break
        pOutData = []
        pOutData.append(self.Read_MFRC522(self.CRCResultRegL))
        pOutData.append(self.Read_MFRC522(self.CRCResultRegM))
        return pOutData

    def MFRC522_SelectTag(self, serNum):
        backData = []
        buf = []
        buf.append(self.PICC_SElECTTAG)
        buf.append(0x70)
        
        for i in range(5):
            buf.append(serNum[i])

        pOut = self.CalulateCRC(buf)
        buf.append(pOut[0])
        buf.append(pOut[1])
        (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)

        if (status == self.MI_OK) and (backLen == 0x18):
            self.logger.debug("Size: " + str(backData[0]))
            return backData[0]
        else:
            return 0

    def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
        buff = []

        # First byte should be the authMode (A or B)
        buff.append(authMode)

        # Second byte is the trailerBlock (usually 7)
        buff.append(BlockAddr)

        # Now we need to append the authKey which usually is 6 bytes of 0xFF
        for i in range(len(Sectorkey)):
            buff.append(Sectorkey[i])

        # Next we append the first 4 bytes of the UID
        for i in range(4):
            buff.append(serNum[i])

        # Now we start the authentication itself
        (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT, buff)

        # Check if an error occurred
        if not (status == self.MI_OK):
            self.logger.error("AUTH ERROR!!")
        if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0:
            self.logger.error("AUTH ERROR(status2reg & 0x08) != 0")

        # Return the status
        return status

    def MFRC522_StopCrypto1(self):
        self.ClearBitMask(self.Status2Reg, 0x08)

    def MFRC522_Read(self, blockAddr):
        recvData = []
        recvData.append(self.PICC_READ)
        recvData.append(blockAddr)
        pOut = self.CalulateCRC(recvData)
        recvData.append(pOut[0])
        recvData.append(pOut[1])
        (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData)
        if not (status == self.MI_OK):
            self.logger.error("Error while reading!")

        if len(backData) == 16:
            self.logger.debug("Sector " + str(blockAddr) + " " + str(backData))
            return backData
        else:
            return None

    def MFRC522_Write(self, blockAddr, writeData):
        buff = []
        buff.append(self.PICC_WRITE)
        buff.append(blockAddr)
        crc = self.CalulateCRC(buff)
        buff.append(crc[0])
        buff.append(crc[1])
        (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff)
        if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A):
            status = self.MI_ERR

        self.logger.debug("%s backdata &0x0F == 0x0A %s" % (backLen, backData[0] & 0x0F))
        if status == self.MI_OK:
            buf = []
            for i in range(16):
                buf.append(writeData[i])

            crc = self.CalulateCRC(buf)
            buf.append(crc[0])
            buf.append(crc[1])
            (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
            if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A):
                self.logger.error("Error while writing")
            if status == self.MI_OK:
                self.logger.debug("Data written")


    def MFRC522_DumpClassic1K(self, key, uid):
        for i in range(64):
            status = self.MFRC522_Auth(self.PICC_AUTHENT1A, i, key, uid)
            # Check if authenticated
            if status == self.MI_OK:
                self.MFRC522_Read(i)
            else:
                self.logger.error("Authentication error")

    def MFRC522_Init(self):
        self.MFRC522_Reset()

        self.Write_MFRC522(self.TModeReg, 0x8D)
        self.Write_MFRC522(self.TPrescalerReg, 0x3E)
        self.Write_MFRC522(self.TReloadRegL, 30)
        self.Write_MFRC522(self.TReloadRegH, 0)

        self.Write_MFRC522(self.TxAutoReg, 0x40)
        self.Write_MFRC522(self.ModeReg, 0x3D)
        self.AntennaOn()

motionpicturetb.py

Python
import pyimgur
import time
import os
import sys
import re
import mysql.connector
import threading
import picamera
from gpiozero import LED, MCP3008, Button
from time import sleep
from gpiozero import Buzzer
from gpiozero import MotionSensor
import telepot
import schedule
import requests

my_bot_token = '943409193:AAHG7RMbNR1C31Y6PGACVsPvfkAx1KiHeyU'

# For Twilio
from twilio.rest import Client
account_sid = "ACbc81590032ee12b7e205394aae9130ec"
auth_twilio = "331dbfab7b747f16036c39d3545fb353"
client = Client(account_sid, auth_twilio)
my_hp = "+6591440914"
twilio_hp = "+19088544663"

# For Imgur
CLIENT_ID = "84017be6449ab0b"
im = pyimgur.Imgur(CLIENT_ID)

adc = MCP3008(channel=0)
btn = Button(13, pull_up=False)

# Minimum time between each pictures
DELAY = 20

# Text messages
TXT_MSG = "Someone is outside"

# Picture definition
IMG_WIDTH = 800
IMG_HEIGHT = 600

#Buzzer connected to GPIO5
pir = MotionSensor(26, sample_rate=5,queue_len=1)
bz = Buzzer(5)

#Minimum time between captures
DELAY = 5


def TakePictureAndSend():
  timestring = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
  filename = '/home/pi/photo_'+timestring+'.jpg'
  with picamera.PiCamera() as camera:
    camera.resolution = (IMG_WIDTH, IMG_HEIGHT)
    camera.capture(filename)
  uploaded_image = im.upload_image(filename, title=TXT_MSG)
  print "Sending message"
  client.messages.create(to=my_hp,
                      from_=twilio_hp,
                      body=TXT_MSG,
                      media_url=uploaded_image.link)

  # 20 Seconds between each picture
  time.sleep(DELAY)


def DetectAndNotify(bot_message):
    
    bot_token = '943409193:AAHG7RMbNR1C31Y6PGACVsPvfkAx1KiHeyU'
    bot_chatID = '-375074177'
    send_text = 'https://api.telegram.org/bot' + bot_token + '/sendMessage?chat_id=' + bot_chatID + '&parse_mode=Markdown&text=' + bot_message

    response = requests.get(send_text)

    return response.json()

#motion sensor waits for motion --> detects motion --> takes a picture --> buzzer on --> delay --> buzzer off
while True:
	bz.off()
	pir.wait_for_motion()
	if pir.motion_detected:
		TakePictureAndSend()
		test = DetectAndNotify("Someone is outside")
		print(test)
		bz.on()
		time.sleep(DELAY)
		bz.off()

Credits

PolyScrub

PolyScrub

1 project • 0 followers
Ryan Tan

Ryan Tan

1 project • 0 followers
Aloysius Chng

Aloysius Chng

1 project • 0 followers

Comments

Add projectSign up / Login