It deals with the occasional hangs in the camera capture process by
rebooting when they happen. A line in /etc/rc.local runs the program again.
# Program for PiDoorCam
# Detects motion, and when it spots some, takes a high resolution
# picture, and sends the picture to PiScreen
import io
import os
import picamera
import ftplib
import time
from datetime import datetime
from PIL import Image
import requests
camera = picamera.PiCamera()
picamera.PiCamera.CAPTURE_TIMEOUT = 30
# If we detect 100 pixels that changed by 30, we have seen movement.
#difference = 30
#pixels = 100
# Desensitise!
#difference = 30
difference = 50
pixels = 150
# May as well use the maximum resolution of the camera.
# This is for V1. V2 is 3280 x 2464.
width = 2592
height = 1944
# I copied this voodoo motion detection from somewhere. Changed the timeout
# setting above to prevent the occasional failures to complete captures.
def compare():
camera.resolution = (100, 75)
stream = io.BytesIO()
format = ‘bmp’
# Handle occasional ‘Timed out waiting for capture to end’
try:
camera.capture(stream, format)
except:
print (“Camera timed out, reboot needed!”)
os.system(“sudo reboot now”)
stream.seek(0)
im = Image.open(stream)
buffer = im.load()
stream.close()
return im, buffer
# Function to take a new high resolution picture, send it to PiScreen
# send it to my phone, and then delete it.
def newimage(width, height):
when = datetime.now()
filename = “door-%04d%02d%02d-%02d%02d%02d.jpg” % (when.year, when.month, when.day, when.hour, when.minute, when.second)
camera.resolution = (width, height)
camera.capture(filename)
connected = True
ftp = ftplib.FTP()
ftp.connect(“PiScreen”)
try:
ftp.login(“pi”,”******************”)
except ftplib.all_errors:
connected = False
print (“Failed to connect to server %s” % e)
if connected:
ftp.storbinary(‘STOR ‘+filename, open(filename, “rb”))
print (“Sent “, filename)
ftp.quit()
# Code to send the Pushover message. Make picture smaller first.
im = Image.open(filename)
im.resize((324,243),Image.ANTIALIAS)
im.save(filename)
r = requests.post(“https://api.pushover.net/1/messages.json”, data = {
“token”: “***********************************”,
“user”: “*************************************”,
“device”: “***********”,
“sound”: “intermission”,
“message”: filename
},
files = {
“attachment”: (filename, open(filename, “rb”), “image/jpeg”)
})
# Check r for problems – maybe put a delay here?
if r.status_code != 200:
print(“Pushover message failed.”)
else:
print(“Pushover accepted the message.”)
# Now delete the file.
os.remove(filename)
# Delay to avoid being nasty to Pushover server.
time.sleep(5)
# Main program.
camera.rotation = 180
print(“Running door.py”)
image1, buffer1 = compare()
newimage(width, height)
while (True):
image2, buffer2 = compare()
changedpixels = 0
for x in range(0, 100):
for y in range(0, 75):
pixdiff = abs(buffer1[x,y][1] – buffer2[x,y][1])
if pixdiff > difference:
changedpixels += 1
if changedpixels > pixels:
newimage(width, height)
image1 = image2
buffer1 = buffer2
Code below is an older version, the “error handling” doesn’t actually work.
# Program for PiDoorCam
# Detects motion, and when it spots some, takes a high resolution
# picture, and sends the picture to PiScreen
import io
import os
import picamera
import ftplib
import time
from datetime import datetime
from PIL import Image
import requests
camera = picamera.PiCamera()
picamera.PiCamera.CAPTURE_TIMEOUT = 30
# If we detect 100 pixels that changed by 30, we have seen movement.
#difference = 30
#pixels = 100
# Desensitise!
difference = 30
pixels = 150
# May as well use the maximum resolution of the camera.
# This is for V1. V2 is 3280 x 2464.
width = 2592
height = 1944
# I copied this voodoo motion detection from somewhere. Changed the timeout
# setting above to prevent the occasional failures to complete captures.
def compare():
camera.resolution = (100, 75)
stream = io.BytesIO()
format = ‘bmp’
# Handle occasional ‘Timed out waiting for capture to end’
try:
camera.capture(stream, format)
except:
print (“Retrying camera.capture()”)
camera.capture(stream, format)
stream.seek(0)
im = Image.open(stream)
buffer = im.load()
stream.close()
return im, buffer
# Function to take a new high resolution picture, send it to PiScreen
# send it to my phone, and then delete it.
def newimage(width, height):
when = datetime.now()
filename = “door-%04d%02d%02d-%02d%02d%02d.jpg” % (when.year, when.month, when.day, when.hour, when.minute, when.second)
camera.resolution = (width, height)
camera.capture(filename)
connected = True
ftp = ftplib.FTP()
ftp.connect(“PiScreen”)
try:
ftp.login(“pi”,”**********************************”)
except ftplib.all_errors:
connected = False
print (“Failed to connect to server %s” % e)
if connected:
ftp.storbinary(‘STOR ‘+filename, open(filename, “rb”))
print (“Sent “, filename)
ftp.quit()
# Code to send the Pushover message. Make picture smaller first.
im = Image.open(filename)
# im.resize((648,486),Image.ANTIALIAS)
im.resize((324,243),Image.ANTIALIAS)
im.save(filename)
r = requests.post(“https://api.pushover.net/1/messages.json”, data = {
“token”: “**********************************”,
“user”: “********************************”,
“device”: “************”,
“sound”: “intermission”,
“message”: filename
},
files = {
# “attachment”: (“image.jpg”, open(filename, “rb”), “image/jpeg”)
“attachment”: (filename, open(filename, “rb”), “image/jpeg”)
})
# Check r for problems – maybe put a delay here?
if r.status_code != 200:
print(“Pushover message failed.”)
else:
print(“Pushover accepted the message.”)
# Now delete the file.
os.remove(filename)
# Delay to avoid being nasty to Pushover server.
time.sleep(5)
# Main program.
camera.rotation = 180
print(“Running door.py”)
image1, buffer1 = compare()
newimage(width, height)
while (True):
image2, buffer2 = compare()
changedpixels = 0
for x in range(0, 100):
for y in range(0, 75):
pixdiff = abs(buffer1[x,y][1] – buffer2[x,y][1])
if pixdiff > difference:
changedpixels += 1
if changedpixels > pixels:
newimage(width, height)
image1 = image2
buffer1 = buffer2