树莓派监控服务器端

发现之前思路上有个严重的错误。AlarmSwitch状态我表示的时候思路如下

1
API修改SQL数据库的值 -> Camera.py在循环中读取SQL数据库中的值 -> 根据数据库中的进行判断

但这样两个进程需要同时修改数据库,实际操作中发现这样频频出错

改变思路后

1
API读取/修改SQL数据库值 -> Detect循环获取API中类返回的值(判断条件) -> 根据判断条件调用Camera类中的拍照函数

相关文章

基本API

HTTP方法 URL 动作
GET http://[hostname]/monitor/api/v1.0/piclist/ 获取图片信息列表
GET http://[hostname]/monitor/api/v1.0/piclist/[picid] 获取具体一张图片信息
PUT http://[hostname]/monitor/api/v1.0/piclist/[picid] 更新图片信息
DELETE http://[hostname]/monitor/api/v1.0/piclist/[picid] 删除一个图片
POST http://[hostname]/monitor/api/v1.0/userlogin/ 用户登录验证
GET http://[hostname]/monitor/api/v1.0/user/ 获取用户列表
GET http://[hostname]/monitor/api/v1.0/user/[userid] 获取具体用户信息
POST http://[hostname]/monitor/api/v1.0/user/ 增加用户
PUT http://[hostname]/monitor/api/v1.0/user/[userid] 更新已存在用户信息
DELETE http://[hostname]/monitor/api/v1.0/user/[userid] 删除一个用户
GET http://[hostname]/monitor/api/v1.0/setting/ 设置列表
PUT http://[hostname]/monitor/api/v1.0/setting/int:setid 修改具体设置
GET http://[hostname]/monitor/api/v1.0/week/ 获取数据统计
GET http://[hostname]/monitor/api/v1.0/shoot/ 手动拍照动作

完整代码

API.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
from flask import Flask,request
from flask.ext.restful import reqparse, abort, Api, Resource
from monitorDB import db,Piclist,User,Setting
from datetime import datetime, timedelta
from flask.ext.cors import CORS
import os
from camera import piCameraCapture
import datetime

app = Flask(__name__)

api = Api(app)
cors = CORS(app, resources={r"/monitor/api/v1.0/*": {"origins": "*"}})

#Deal with data form
parser = reqparse.RequestParser()
parser.add_argument('picid', type=int)
parser.add_argument('userid', type=int)
parser.add_argument('status', type=int)
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)
parser.add_argument('email', type=str)
parser.add_argument('setid', type=int)
parser.add_argument('setvalue', type=int)

def getTime():
return datetime.datetime.now()

def getCameraSwitch() :
cameraSwitch = Setting.query.filter_by(setname='cameraSwitch').first()
return cameraSwitch.setvalue

def getAlarmSwitch() :
alarmSwitch = Setting.query.filter_by(setname='alarmSwitch').first()
return alarmSwitch.setvalue

def getMailAddres() :
alarmMailto = Setting.query.filter_by(setname='alarmMailto').first()
mailID = alarmMailto.setvalue
mailAddress = User.query.filter_by(id=mailID).first()
return mailAddress.email

#get piclist
def getPiclist():
lim = request.args.get('limit', 10)
off = request.args.get('offset', 0)
results = Piclist.query.order_by(-Piclist.id).limit(lim).offset(off).all()

json_results = []
for result in results:
d = {'picid': result.id,
'picname': result.picname,
'time': result.time.strftime('%Y-%m-%d %H:%M:%S'),
'status':result.status
}
json_results.append(d)

return json_results

def deletePic(picid):
result = Piclist.query.filter_by(id=picid).first()
for i in range(1,5):
try:
os.remove('static/imgs/%s_%i.jpg' %(result.picname,i))
except:
print (' %s image file already deleted' %result.picname)
try:
os.remove('static/imgs/%s_%i_thumbnail.jpg' %(result.picname,i))
except:
print (' %s image file already deleted' %result.picname)
db.session.delete(result)
db.session.commit()
print('Removed image %s' %name)
conn.commit()
conn.close()

#get userlist
def getUserlist():
lim = request.args.get('limit', 10)
off = request.args.get('offset', 0)
results = User.query.limit(lim).offset(off).all()

json_results = []
for result in results:
d = {'id': result.id,
'username': result.username,
'password': result.password,
'email':result.email
}
json_results.append(d)

return json_results

def userLogin(username,password):
result = User.query.filter_by(username=username).first()
if (result == None):
return 401
else:
if(username == result.username and password == result.password):
return 201
else:
return 401

def getSettinglist():
results = Setting.query.all()

json_results = []
for result in results:
d = {'setid': result.id,
'setname': result.setname,
'setvalue': result.setvalue,
'setvalue2': result.setexplain
}
json_results.append(d)

return json_results

def getWeeklyCount():
NOW = datetime.now()
NOW = NOW.strftime('%Y-%m-%d')
NOW = datetime.strptime(NOW, '%Y-%m-%d')
last_10d_count = []
#range(start,stop,step)
for d in range(10,0,-1):
count = Piclist.query.filter(Piclist.time.between(NOW - timedelta(days=d-1), NOW - timedelta(days=d-2))).count()
# thisday = float((NOW - timedelta(days=d-1)).strftime('%m.%d'))
last_10d_count.append(count)
return last_10d_count

def abort_if_pic_doesnt_exist(picid):
if (Piclist.query.filter_by(id=picid).first() == None):
abort(404, message="Pic {} doesn't exist".format(picid))

def abort_if_user_id_doesnt_exist(userid):
if (User.query.filter_by(id=userid).first() == None):
abort(404, message="User {} doesn't exist".format(userid))

app.route('/')
def hello():
return "Hello! :)"

# Pic
# shows a single Pic item and lets you change or delete item
class pic(Resource):
def get(self, picid):
abort_if_pic_doesnt_exist(picid)
result = Piclist.query.filter_by(id=picid).first()
json_result = {'picid': result.id,
'picname': result.picname,
'time': result.time.strftime('%Y-%m-%d %H:%M:%S'),
'status':result.status
}

return json_result

def delete(self, picid):
abort_if_pic_doesnt_exist(picid)
deletePic(picid)
return 204

def put(self, picid):
args = parser.parse_args()
status = args['status']
pic = Piclist.query.filter_by(id=picid).first()
pic.status = status
db.session.commit()
return 201

# shows a list of all piclist
class piclists(Resource):
def get(self):
return getPiclist()

# show a user
class user(Resource):

def get(self, userid):
abort_if_user_id_doesnt_exist(userid)
result = User.query.filter_by(id=userid).first()
json_result = {'id': result.id,
'username': result.username,
'password': result.password,
'email':result.email
}
return json_result

def delete(self, userid):
abort_if_user_id_doesnt_exist(userid)
result = User.query.filter_by(id=userid).first()
count = User.query.count()
if (count == 1):
return 405
else:
db.session.delete(result)
db.session.commit()
return 204

def put(self, userid):
abort_if_user_id_doesnt_exist(userid)
args = parser.parse_args()
user = User.query.filter_by(id=userid).first()
user.userid = userid
user.username = args['username']
user.password = args['password']
user.email = args['email']
db.session.add(user)
db.session.commit()
return 201

# shows a list of all Users
class userlists(Resource):
def get(self):
return getUserlist()

def post(self):
args = parser.parse_args()
user = User(args['username'],args['password'],args['email'])
db.session.add(user)
db.session.commit()
return 201

class userlogin(Resource):
def post(self):
args = parser.parse_args()
username = args['username']
password = args['password']
return userLogin(username,password)

class setting(Resource):
def put(self, setid):
args = parser.parse_args()
setting = Setting.query.filter_by(id=setid).first()
setting.setvalue = args['setvalue']
db.session.commit()
return 201

# shows a list of all Users
class settinglists(Resource):
def get(self):
return getSettinglist()

class weeklycount(Resource):
def get(self):
return getWeeklyCount()

class shoot(Resource):
def get(self):
currentTime = getTime()
piCameraCapture(currentTime)
return 201

## Actually setup the Api resource routing here
api.add_resource(piclists, '/monitor/api/v1.0/piclist/')
api.add_resource(pic, '/monitor/api/v1.0/piclist/<int:picid>')
api.add_resource(userlists, '/monitor/api/v1.0/user/')
api.add_resource(userlogin, '/monitor/api/v1.0/userlogin/')
api.add_resource(user, '/monitor/api/v1.0/user/<int:userid>')
api.add_resource(settinglists, '/monitor/api/v1.0/setting/')
api.add_resource(setting, '/monitor/api/v1.0/setting/<int:setid>')
api.add_resource(weeklycount, '/monitor/api/v1.0/week/')
api.add_resource(shoot, '/monitor/api/v1.0/shoot/')

if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)

detect.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import picamera
import datetime
import camera
from monitorDB import db,User,Piclist,Setting
from mail import alarmMail
from api import getMailAddres, getAlarmSwitch, getCameraSwitch

sensorPin = 38
GPIO.setmode(GPIO.BOARD)
GPIO.setup(sensorPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

preState = 0
currState = 0

# Get current time
def getTime():
return datetime.datetime.now()

def sendAlarm():
mailAddress = getMailAddres()
alarmMail(mailAddress)

#Print when start running
print 'Camera running'
i = 0
while True:
time.sleep(0.1)
preState = currState
currState = GPIO.input(sensorPin)
if( preState != currState and preState != 0):
print 'Human detected'
cameraSwitch = getCameraSwitch()
print 'cameraSwitch setvalue is %i' %cameraSwitch
if (cameraSwitch == 1):
currentTime = getTime()
camera.piCameraCapture(currentTime)
alarmSwitch = getAlarmSwitch()
if (alarmSwitch == 1):
try:
sendAlarm()
except Exception, e:
print("Email sending Error")
raise e

camera.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import picamera
import time
import Image
from monitorDB import db,Piclist

#Save data to the database
def addToDB(currentTime):
name = currentTime.strftime('%Y-%m-%d_%H.%M.%S')
time = currentTime
picname = Piclist(str(name),time,1)
db.session.add(picname)
db.session.commit()

#Generate thumbnails
def generateThumbnails(currentTime):
print 'generating thumbnails'
currentTime = currentTime
for i in range(1, 5):
im = Image.open('static/imgs/%s_%i.jpg' %(currentTime.strftime('%Y-%m-%d_%H.%M.%S'),i))
im.thumbnail((300,255), Image.ANTIALIAS)
im.save('static/imgs/%s_%i_thumbnail.jpg' %(currentTime.strftime('%Y-%m-%d_%H.%M.%S'),i), "JPEG")
print 'generate thumbnails finished'

#Capture images
def piCameraCapture(gettime):
currentTime = gettime
with picamera.PiCamera() as camera:
camera.resolution = (1024, 768)
camera.start_preview()
print 'start shooting'
for i in range(1, 5):
camera.capture('static/imgs/%s_%i.jpg' %(currentTime.strftime('%Y-%m-%d_%H.%M.%S'),i),thumbnail = (320,240,80))
time.sleep(0.25)
print 'shoot ' + str(i)
camera.stop_preview()
print 'images saved'
addToDB(currentTime)
print 'data saved'
camera.close()
generateThumbnails(currentTime)

mail.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#coding=utf-8
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib, datetime
from monitorDB import db,Piclist

msg = MIMEMultipart()

def alarmMail(mailto):
#Mail server conf
mail_sender = '######'
mail_sender_password = '######'
SMTP_server = 'smtp.exmail.qq.com'
server = smtplib.SMTP(SMTP_server)
server.login(mail_sender,mail_sender_password)

#mail setting
msg['to'] = mailto
msg['from'] = mail_sender
msg['subject'] = Header('ALARM: Invader Detected (' + str(datetime.date.today()) + ')','gb2312')

#mail body
body_txt = MIMEText('Some one invaded the house, please cheak up the attachments')
msg.attach(body_txt)

#get picname
pic = Piclist.query.order_by('-id').first()
picname = pic.picname

#Add four attachment
for i in range(1,5):
att = MIMEText(open('static/imgs/%s_%i_thumbnail.jpg' %(picname,i) , 'rb').read(), 'base64', 'gb2312')
att["Content-Type"] = 'application/octet-stream'
att["Content-Disposition"] = 'attachment; filename="%s_%i.jpg"'%(picname,i)
msg.attach(att)

#Send mail
server.sendmail(msg['from'], msg['to'], msg.as_string())
server.close()
print('Successfully send mail to %s' %mailto)