I want to know whenever the door is opened.
I want an email alert when the door open event is captured.
Capture an image from Panasonic IPCam BL-VP104W and attach it to the email so that I know who is entering the apartment.
I was thinking to buy a securifi door/window magnetic reed sensor. However I don’t have any zigbee hub yet. Some wired magnetic sensor also give better result but it need a long wired from the door to where the pi is located. I still prefer using HC-SR04 instead.
The panasonic IPCAM that I own also support motion detection. But it is not giving accurate alarm at all. Most were simply false alarm. A little bit change in lighting source can trigger a ‘movement’. It was not useable, at all.
I think the raspberry pi will actually do the same thing. And it is a success! The solution below doing a very good job.
This simple project took me a full day though.
- Setup a new pi
- Setup wifi on pi
- Setup firewall
- Looks for all the ingredient
- Integrate the circuit
- Write the scripts
- Trial and error
– script measuring distance with HC-SR04: /root/distance.py
– script looping the distance.py /root/monitor-door.py
– image downloaded from panasonic ipcam saved to /root/capture.jpg
– a temporary text file /tmp/distance.tmp used to prevent false alarm
Adjust the path for your own needed.
Add the distance.py script below to /root folder
There is some false alarm being generated, about one or twice a hour. The sensor just got some wrong reading like this.
The 41.9 is probably a false alarm. The door is hardly opened like 3 seconds then being closed.
Only a ninja or ghost can do that.
If people get in or out, more than one alarm should be detected.
A text file is used to solve this. The distance.py is modified to write an integer to a text file. When reading larger than 60cm, write a zero. If value smaller than 60cm, increment the value of the file by 1.
|sensor reading||value of text file|
So, alarm should be triggered only when the value of text file is larger than zero.
For the example above, two alarm were triggered when reading is 35.8 and 22.1. The first occurrence is always skipped to avoid a false alarm.
I’ve also read the current weather by calling forecast.io rest api. If it is raining, a recorded sound of my daughter will be play to remind the rain.
The byebye sound will also play to farewell.
A LED is also added to the circuit, flashing it when distance reading reached the threshold.
import RPi.GPIO as GPIO import time import os import os.path import base64 import smtplib import urllib, json from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart if os.path.isfile('/tmp/distance.tmp') : print "" else : os.system('echo 0 > /tmp/distance.tmp') infile = open('/tmp/distance.tmp','r') data=infile.read() infile.close() outfile = open('/tmp/distance.tmp','w') d=data.strip() d=d.replace("\n","") i=int(d)+1 url = "https://api.forecast.io/forecast/apikey/lat,long" image='/root/capture.jpg' email@example.com firstname.lastname@example.org' gmail_pwd='password' GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) TRIG = 23 ECHO = 24 LED = 16 GPIO.setup(TRIG,GPIO.OUT) GPIO.setup(ECHO, GPIO.IN) GPIO.setup(LED, GPIO.OUT) GPIO.output(TRIG, False) time.sleep(2) GPIO.output(TRIG,True) time.sleep(0.00001) GPIO.output(TRIG,False) while GPIO.input(ECHO) == 0: pulse_start = time.time() while GPIO.input(ECHO) == 1: pulse_end = time.time() pulse_duration = pulse_end - pulse_start distance = pulse_duration * 17150 distance = round(distance , 2) print "Distance:",distance, " cm" if distance < 60: if int(d) > 0: GPIO.output(LED,True) os.system("wget http://192.168.11.10:8080/cgi-bin/camera?resolution=qvga -O /root/capture.jpg") response = urllib.urlopen(url) data = json.loads(response.read()) if data['currently']['summary'] == "Rain": os.system("omxplayer /root/raining.mp3") os.system("omxplayer /root/byebye.mp3") msg = MIMEMultipart() msg['Subject']='Door trigger alarm ' + str(distance) msg['From'] = gmail_user msg['To']=to fp=open(image,'rb') img = MIMEImage(fp.read(), _subtype="jpg") fp.close() msg.attach(img) smtpserver=smtplib.SMTP('smtp.gmail.com',587) smtpserver.ehlo() smtpserver.starttls() smtpserver.ehlo smtpserver.login(gmail_user, gmail_pwd) smtpserver.sendmail(gmail_user, to, msg.as_string()) smtpserver.close() GPIO.output(LED,False) outfile.write(str(i)); else: outfile.write("0"); GPIO.cleanup() outfile.close()
Add the script monitor-door.py to /root folder.
import time import os time.sleep(10) while (0 < 1): time.sleep(3) os.system("sudo python /root/distance.py")
The script monitor-door.py will measure the distance per 3 seconds. Adjust the value for your own needed.
To start the monitor-door.py when pi power up, add the line below to /etc/rc.local
python /root/monitor-door.py &
The script will wait 10 seconds for server boot up.
After 12 hours of testing, I find it very accurate. I was notified who and when is leaving/entering my apartment while I am busying working at office. Finally got a clear picture about my home without the need of staring the video feed of those IPCAM. No longer need to make a phone call to confirm with logistic guy whether there are any person in home to pick up their delivery.
Very useful for me.
Version 2, Pending
Sending email with attachment is a bit slow. In version 2 I'll write a simple web page to display the screen capture instead. Then send a push notification to my mobile phone with URL of the screen capture web page. And I don't have to publish the screen capture to third party server (gmail) and have it stored in the pi for privacy.