Raspberry-Pi / SMS Alarm System

Description

Here are some information about a little Python Project I’ve made based on a Raspberry-Pi Platform. This is My first Python Project Ever, my code is not super clean, but it works great.

This system send me an SMS and/or Email if my door is open, or if the PIR (passive infrared movement detector) is triggered. This can be easily expanded to 8 or mores zones, or control something else.

In my case , I'm using a secret switch (zone3) to disable the PIR (zone2)

I'm not a super linux geek myself, every thing described here is do-able from a normal pc running windows 


Some features :

  -Send Email or SMS when alarm is trigered

  -Send Periodic report , 12-24 hours (configurable)

  -Send report when system boot, quit, is activated or desactivated

  -Get the system IP ant Time at boot-up and Present Time 

  -Can Send email or SMS via private SMTP server or ISP SMTP server , or via Gmail secure SMTP server

  -Flash a led when code is running

  -Has a saftety so it doesnt send more than x Email by every X sec time-laps.


 

Photos:


 

Hardware:

  •    RasberryPi model B

                            
                        http://www.raspberrypi.org/faqs

  •    Adafruit Prototyping Pi Plate Kit , or get another way to plug your stuff
                                               
                        http://www.adafruit.com/products/801

  • 2Gb SD Card Min.
  • Movement Detector(S)
  • Door switche(s)


Shematic:



Raspberry-Pi Pin-Out:



Software:


Get Raspbian “wheezy”
     
http://www.raspberrypi.org/downloads
     (do not use the GUI, it waste CPU power)


Flash the SD card using

     win32diskimager


Get remote acces with:

    Command Line Acces  Putty
    File transfer FileZilla


Instal Python

    http://www.raspberrypi-spy.co.uk/2012/07/install-rpi-gpio-library-in-raspbian/


Upload the script
   Upload the script, named main.py to the folder /home/pi/code


Verify / Adapt / Edit the script
    cd code
    sudo nano main.py


Make the script executable
    sudo chmod +x startup_mailer.py


Test
the script
    sudo python main.py


To start the script at startup:
    sudo nano /etc/rc.local


Edit the file so it look like this:


To Manually stop the script started at startup
Step #1
   Find the PID
    ---> ps -ef | grep python
    root      1876  1874  0 22:23 ?        00:00:00 sudo python /home/pi/code/main.py
    root      1877  1876 97 22:23 ?        00:04:53 python /home/pi/code/main.py
    pi        1986  1970  0 22:28 pts/1    00:00:00 grep --color=auto python

Step#2
   Kill the 2 first pids
   ---> sudo kill -9 1876
   ---> sudo kill -9 1877






Code:



# My first python project
#
# Sources and Ref.
#           http://elinux.org/RPi_Email_IP_On_Boot_Debian

#           http://elinux.org/RPi_BCM2835_GPIOs
#           http://docs.python.org/2/library/thread.html
#           http://elinux.org/RPi_Low-level_peripherals
#           http://pypi.python.org/pypi/RPi.GPIO

system_name='Alarm Name'
code_version='V022'
alarm_email1  = '5141234567@txt.bell.ca'
# see http://en.wikipedia.org/wiki/List_of_SMS_gateways

status_email1 = 'youre_destination_email@gmail.com'
my_ip_now='empty'
my_ip_boot='empty'

smtp_email_from = 'your_source_email@your_provider.com'
smtp_email_from_password='xxxx'#only used if secure smtp is used
smtp_email_server  = 'smtp.your_provider.com'
#smtp_email_server = 'smtp.teksavvy.com'
#smtp_email_server = 'relai.videotron.ca'
#smtp_email_server = 'smtp.gmail.com'

email_max_count=0
email_max_qte=20        #max of 20 emails
email_max_timelaps=60   #per 60secondes
email_max_skiped_qte=0

zone1_name='Front Door'
zone2_name='PIR'
zone3_name='Secret Switch'
zone4_name='Door4'
zone5_name='Door5'
zone6_name='Door6'
zone7_name='Door7'
zone8_name='Door8'

zone1_active=True
zone2_active=True
zone3_active=True
zone4_active=False
zone5_active=False
zone6_active=False
zone7_active=False
zone8_active=False

zone1_alarm_count=0
zone2_alarm_count=0
zone3_alarm_count=0
zone4_alarm_count=0
zone5_alarm_count=0
zone6_alarm_count=0
zone7_alarm_count=0
zone8_alarm_count=0

io_led1=18
io_led2=17
io_zone1=23
io_zone2=24
io_zone3=25
io_zone4=4
io_zone5=4
io_zone6=4
io_zone7=4
io_zone8=4

latch_zone1=1
latch_zone2=1
latch_zone3=1
latch_zone4=1
latch_zone5=1
latch_zone6=1
latch_zone7=1
latch_zone8=1

flashing_led=0

test=0

#########################
#      IMPORT           #   
#########################
import RPi.GPIO as GPIO #for gpio
import subprocess #for email
import smtplib #for email
import socket #for email
from email.mime.text import MIMEText #for email
import datetime #get date
import sys #to exit
import thread #for tread
import threading #for tread that send periodic status
import time #for delay


########################
#       DEFINE         #
########################
def periodic_report():
    while(1):
        print 'Send periodic report'
        send_status_email(status_email1,'Periodic Report')
        time.sleep(60*60*12) #12hours

def periodic_email_max_reset(): #Prevent email flooding
    global email_max_count
    global email_max_timelaps
    while(1):
        print 'Reset email max counter'
        email_max_count=0
        time.sleep(email_max_timelaps)

def periodic_test():
    global test
    while(1):
        time.sleep(2)
        print 'Test'
        test=1

def get_ip():
    arg='ip route list'
    p=subprocess.Popen(arg,shell=True,stdout=subprocess.PIPE)
    data = p.communicate()
    split_data = data[0].split()
    ipaddr = split_data[split_data.index('src')+1]
    my_ip= ' %s' %  ipaddr
    return my_ip


def sendemail_alarm(to,subject,message):
    global email_max_count
    global email_max_qte
    global email_max_skiped_qte

    email_max_count=email_max_count+1
    print'trying to send email'

    if(email_max_count < email_max_qte):
        print'go'
        sendemail(to,subject,message)
    else:   
        print 'Cant send email. %i Emails sent in the last %i sec. Max is:%i' % (email_max_count,email_max_timelaps,email_max_qte)
        email_max_skiped_qte=email_max_skiped_qte+1


def sendemail(to,subject,message):
    #chose you sending way
    thread.start_new_thread(send_through_smtp,(to,subject,message))
    #thread.start_new_thread(send_through_secure_smtp,(to,subject,message))

def send_through_secure_smtp(to,subject,message):
    GPIO.output(io_led1, GPIO.HIGH)
    gmail_user = smtp_email_from
    gmail_password = smtp_email_from_password
    server = smtplib.SMTP(smtp_email_server, 587)
    server.ehlo()
    server.starttls()
    server.ehlo
    server.login(gmail_user, gmail_password)
    today = datetime.date.today()
    arg='ip route list'
    p=subprocess.Popen(arg,shell=True,stdout=subprocess.PIPE)
    data = p.communicate()
    split_data = data[0].split()
    ipaddr = split_data[split_data.index('src')+1]
    my_ip =    'Alarm System Ip %s' %  ipaddr
    my_ip = my_ip + '\n' + message
    msg = MIMEText(my_ip)
    msg['Subject'] = subject
    msg['From'] = gmail_user
    msg['To'] = to
    server.sendmail(gmail_user, [to], msg.as_string())
    server.quit()
    GPIO.output(io_led1, GPIO.LOW)

def send_through_smtp(to,subject,message):
    GPIO.output(io_led1, GPIO.HIGH)
    user = smtp_email_from
    server = smtplib.SMTP(smtp_email_server, 25)
    message = system_name + '\n' + message
    msg = MIMEText(message)
    msg['Subject'] = subject
    msg['From'] = user
    msg['To'] = to
    server.sendmail(user, [to], msg.as_string())
    server.quit()
    GPIO.output(io_led1, GPIO.LOW)

def send_status_email(to,message):
    my_ip_now=get_ip()
    today = datetime.datetime.today()
    time_now = ' %s' % today.strftime('%Y %b %d  %H:%M:%S')

    io_text1='  Zone1: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone1) ,zone1_active, zone1_alarm_count ,zone1_name)
    io_text2='  Zone2: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone2) ,zone2_active, zone2_alarm_count ,zone2_name)
    io_text3='  Zone3: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone3) ,zone3_active, zone3_alarm_count ,zone3_name)
    io_text4='  Zone4: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone4) ,zone4_active, zone4_alarm_count ,zone4_name)
    io_text5='  Zone5: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone5) ,zone5_active, zone5_alarm_count ,zone5_name)
    io_text6='  Zone6: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone6) ,zone6_active, zone6_alarm_count ,zone6_name)
    io_text7='  Zone7: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone7) ,zone7_active, zone7_alarm_count ,zone7_name)
    io_text8='  Zone8: %i Active: %i Count: %i Name: %s \n' % (GPIO.input(io_zone8) ,zone8_active, zone8_alarm_count ,zone8_name)

    max_text1='  A Maximum of %i Alarm Email can be sended every %i Seconds \n' %(email_max_qte,email_max_timelaps)
    max_text2='  Alarm Emails recently sended: %i \n' % email_max_count
    max_text3='  Alarm Emails skipped: %i  \n' % email_max_skiped_qte

    io_text=io_text1 +io_text2 +io_text3 +io_text4 +io_text5 +io_text6 +io_text7 +io_text8 +max_text1 + max_text2 + max_text3

    sendemail(to,system_name+message, '\n Message: '+message+ '\n'+io_text+'\n Boot time:'+boot_time+ '\n Time Now:'+time_now+ '\n IP Boot :'+my_ip_boot+'\n IP Now  :'+my_ip_now+'\n Code Ver:'+code_version)

#########################
#        MAIN           #   
#########################
print'                                   '
print' J-F Payeur Alarm system                '
print' For Raspberry PI board v1.0'
print' BCMio Output 17,18 Input 23,24,25,4    '
print'                                   '
print'  To kill use ctrl-c'
print'  If in background, find the PID  -->ps -ef | grep python'
print'  and kill the pid  -->kill -9 PID '
print' '

GPIO.cleanup()
GPIO.setmode(GPIO.BCM) # to use Raspberry Pi bcm chip pin numbers
GPIO.setwarnings(False) #remove anoying warning   
GPIO.setup(io_led1, GPIO.OUT) #status led output
GPIO.setup(io_led2, GPIO.OUT) #
GPIO.setup(io_zone1, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 1
GPIO.setup(io_zone2, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 2
GPIO.setup(io_zone3, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 3
GPIO.setup(io_zone4, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 4
GPIO.setup(io_zone5, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 5
GPIO.setup(io_zone6, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 6
GPIO.setup(io_zone7, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 7
GPIO.setup(io_zone8, GPIO.IN, pull_up_down=GPIO.PUD_UP) #alarm zone 8
GPIO.setwarnings(True) #warning back just in case

#print 'Get boot time'
today = datetime.datetime.today()
boot_time = ' %s' % today.strftime('%Y %b %d  %H:%M:%S')
my_ip_boot=get_ip()

periodic_report_thread = threading.Thread(target=periodic_report)
periodic_report_thread.start()

periodic_test_thread = threading.Thread(target=periodic_test)
periodic_test_thread.start()

periodic_email_max_reset_thread = threading.Thread(target=periodic_email_max_reset)
periodic_email_max_reset_thread.start()

#Read input
if(GPIO.input(io_zone1)==False):
    print' Zone1:Secure'
else:
    print' Zone1:Alarm'
if(GPIO.input(io_zone2)==False):
    print' Zone2:Secure'
else:
    print' Zone2:Alarm'
if(GPIO.input(io_zone3)==False):
    print' Zone3:Secure'
else:
    print' Zone3:Alarm'
if(GPIO.input(io_zone4)==False):
    print' Zone4:Secure'
else:
    print' Zone4:Alarm'

print'Send Boot Emails'
send_status_email(status_email1,'Starting System ')

print'System armed'
while 1:
    try:
        today = datetime.datetime.today()
        now_time = ' %s' % today.strftime(' %d%b %H:%M:%S')

        flashing_led=flashing_led+1
        if (flashing_led==500):
            GPIO.output(io_led2, GPIO.LOW)
        if (flashing_led==1000):
            GPIO.output(io_led2, GPIO.HIGH)
            flashing_led=0

        if(zone1_active==True): #test
            if((GPIO.input(io_zone1) == False)&(latch_zone1==0)):
                time.sleep(0.2) #cheap debounce
                latch_zone1=1
                print 'Zone1 Secure '
                sendemail_alarm(alarm_email1,'Zone1 Secure'+now_time,'Zone1 Secure:'+zone1_name)
            if(((GPIO.input(io_zone1) == True)&(latch_zone1==1))|(test==1)):#test
                time.sleep(0.2) #cheap debounce
                test=0#test
                zone1_alarm_count=zone1_alarm_count+1
                latch_zone1=0
                print 'Zone1 Triger, Sending email'
                sendemail_alarm(alarm_email1,'Zone1 Alarm'+now_time,'Zone1 Alarm:'+zone1_name)

        if(zone2_active==True):
            if((GPIO.input(io_zone2) == False)&(latch_zone2==0)):
                time.sleep(0.2) #cheap debounce
                latch_zone2=1
                print 'Zone2 Secure  '
                sendemail_alarm(alarm_email1,'Zone2 Secure'+now_time,'Zone2 Secure:'+zone2_name)
            if((GPIO.input(io_zone2) == True)&(latch_zone2==1)):
                time.sleep(0.2) #cheap debounce
                zone2_alarm_count=zone2_alarm_count+1
                latch_zone2=0
                print 'Zone2 Triger, Sending email'
                sendemail_alarm(alarm_email1,'Zone2 Alarm'+now_time,'Zone2 Alarm:'+zone2_name)

        if(zone3_active==True):
            if((GPIO.input(io_zone3) == False)&(latch_zone3==0)):
                time.sleep(0.2) #cheap debounce
                latch_zone3=1
                print 'Zone2 Activated'
                zone2_active=True
                send_status_email(status_email1,'Zone2 Activated')
               
            if((GPIO.input(io_zone3) == True)&(latch_zone3==1)):
                time.sleep(0.2) #cheap debounce
                latch_zone3=0
                print 'Zone2 Unactivated'
                zone2_active=False
                send_status_email(status_email1,'Zone2 Unactivated')


    except:
        print'Exit'

        periodic_report_thread._Thread__stop()
        periodic_test_thread._Thread__stop()
        periodic_email_max_reset_thread._Thread__stop()

        GPIO.output(io_led1, GPIO.LOW)
        GPIO.output(io_led2, GPIO.LOW)
   
        send_status_email(status_email1,' Closing System')
        send_status_email(alarm_email1,' Closing System')
        print'Sending Closing Emails'
        time.sleep(2) #time so send last email

        sys.exit(0)
       



Install an internal SMTP server (optional)



   






References and Links:

List of SMS gateways
http://en.wikipedia.org/wiki/List_of_SMS_gateways

This project is mainly based on :
http://elinux.org/RPi_Email_IP_On_Boot_Debian

Help on the IO library:
http://pypi.python.org/pypi/RPi.GPIO

Help on the RPi hardware
http://elinux.org/RPi_Low-level_peripherals
http://elinux.org/RPi_BCM2835_GPIOs

Help on python
http://docs.python.org/2/library/thread.html

Other interesting Project
https://sites.google.com/site/raspilapse/home




Wanted features:

  -Log event to a file (and send file with report)

  -Have a web based menu to configure settings

  -Put a PIR ( movement detector) directly on the board 

  -Have a way to activate / desactivate stuff remotly with my cell-phone  (could be thrue the web based feature)
































Comments