背景:
最近琢磨怎么才能尽快的熟悉树莓派各方面的功能,所以想找个合适的切入点。之前配套Arduino的许多套间里面可以挑出来一个USB摄像头,参考了网上一些朋友的思路发现可以实现一个基本的网络监控功能。所以决定使用raspbian+motion+python来实现。
功能:
- 动态配置,motion配置项比较灵活;
- ”云“存储,实现发送到笔者邮箱作为存储位置,这一点是根本上区别于常规监控将监控内容存储行为的;
- 随意放置,在家庭局域网内,树莓派与路由器采用无线连接,可以任意挪动整套系统其位置;
- 间断查询特定目录下(本例检测的目录是/var/lib/motion)的文件变化,若有新文件存在则打包发送至特定邮箱
准备:
motion是一个提供视频监控解决方案的开源软件,支持Linux/FreeBSD/Mac平台,功能主要有以下几个:
- 支持USB摄像头和webcam(可通过HTTP查看实时视频直播的摄像头)
- 支持多摄像头(不过需要额外的多项配置,不建议一开始就搞)
- 提供web访问实时视频功能(暂时还没实现)
- 重点是运动检测,可以在画面中像素变化时拍摄、记录、触发事件
- 可以配置web远程管理(用处不大,建议关闭)
- 可以配置使用数据库(支持MySQL和PostgreSQL)
看到我raspbian的系统是默认安装motion也是很简单,sudo apt-get install motion就好了。
实现:
网上对motion的配置有比较全面介绍,我这里不再叙述。只需要在配置项中配置好发送邮件的脚本绝对路径即可。例如:on_motion_detected /home/pi/Desktop/mail_me/sendmail.py。下面直接贴上代码供参考。
#!/usr/bin/bash python
import os
import sys
import datetime
import time
import logging
import threading
import smtplib
import subprocess
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
class SendMaNMOnce(object):
"""
sending a mail when new file(s) was/were added to the path:jpg_avi_path as a attachment.
in case of saving space, ".tar.gz" file is a good choice for the attachment.
Args:
is_debug, in debug model, stdout is to console, otherwise,file handler.
frequece, int, the frequece of sending a mail. example:frequece=60 means every 60 seconds
jpg_avi_path, (str), motion result abs path.
Exception:
All exceptions will be catched and printed.
"""
def __init__(self, is_debug=True, frequece=60, jpg_avi_path='/var/lib/motion'):
self.is_debug = is_debug
self.frequece = frequece
self.jpg_avi_path = jpg_avi_path
self.alreadystfiles = []
try:
for root, dirs, files in os.walk(self.jpg_avi_path, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
except Exception as e:
self.print_log(e)
self.TBsendfls = threading.Thread(target=self.sendmail)
self.TBsendfls.start()
def __del__(self):
self.print_log('del total file:%s' % len(self.alreadystfiles))
del self.alreadystfiles
def print_log(self, astring):
timestamp = datetime.datetime.now().strftime('[%Y-%m-%d %H:%M:%S] ')
if not self.is_debug:
log_file = open("sendmail.log", "a")
console = sys.stdout
sys.stdout = log_file
print timestamp +str(astring)
log_file.close()
sys.stdout = console
else:
print timestamp +str(astring)
def sendmail(self):
while 1:
filesTBsent = []
time.sleep(self.frequece)
timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
targz = timestamp +'.tar.gz'
[filesTBsent.append(f) for f in os.listdir(self.jpg_avi_path) if f not in self.alreadystfiles and (f.endswith('jpg') or f.endswith('avi'))]
def send():
self.print_log('start to send a mail...')
os.chdir(self.jpg_avi_path)
try:
self.print_log('file:[%s]' % ' '.join(filesTBsent))
os.system("tar -Pzcf %s %s" % (targz, ' '.join(filesTBsent)))
except Exception as e:
self.print_log(e)
sender = 'sender@126.com'
receiver = '1048015805@qq.com'
smtpserver = 'smtp.126.com'
username = 'username'
password = 'password'
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = '%s' % timestamp
msgRoot['from'] = 'raspberry@raspberry.com'
msgRoot['to'] = '1048015805@qq.com'
if targz in os.listdir(self.jpg_avi_path):
self.print_log('file [%s] exists, it`s very good.' % targz)
attachment = MIMEText(open(targz, 'rb').read(),'base64', 'utf-8')
attachment["Content-Type"] = 'application/octet-stream'
attachment["Content-Disposition"] = 'attachment; filename="%s"' % targz
else:
self.print_log('file [%s] not exists, it`s unexpected.' % targz)
attachment = MIMEText('file not found', 'plain', 'utf-8')
msgRoot.attach(attachment)
smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.login(username,password)
smtp.sendmail(sender, receiver, msgRoot.as_string())
smtp.quit()
self.print_log('mail is sending...')
self.alreadystfiles += filesTBsent
try:
os.remove(targz)
except Exception as e:
self.print_log('Exception when remove %s'%targz + str(e))
self.print_log('end to send a mail...\n')
if len(filesTBsent)!=0:
self.print_log('%s new pictures found, will mail.'%len(filesTBsent))
send()
self.print_log('no pictures found.')
return
if __name__ == "__main__":
s = SendMaNMOnce()
可改进的地方:
1.网络实时访问监控画面,这需要对局域网做DDNS,出于安全考虑,建议网友谨慎实现;
2.利用移动电源提供电力,可以将本系统置于任何有wifi网络的地方;
3.必要时,将移动电源换成“蓄电池+太阳能电池板”就可以实现全天候全方位监控了;