-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
129 lines (100 loc) · 3.68 KB
/
app.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
import time
import uvicorn
from starlette.applications import Starlette
from starlette.exceptions import HTTPException
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse, StreamingResponse
from starlette.routing import Route, Mount
from starlette.staticfiles import StaticFiles
from camera import Camera
from config import cameras as camera_configs
from db import Face
cameras = []
async def get_faces(request):
res = Face.all_public()
return JSONResponse(res)
async def get_face(request):
fid = request.path_params['fid']
res = Face.find(fid)
return JSONResponse(res)
async def update_face(request):
fid = request.path_params['fid']
payload = await request.json()
name = payload['name']
room = payload['room']
note = payload['note']
res = Face.update(fid, name, room, note)
return JSONResponse(res)
# Renders current faces for a given camera
async def get_current_faces(request):
cid = request.path_params['cid']
camera = next(filter(lambda c: c.cid == cid, cameras), None)
current_faces = camera.current_faces
for current_face in current_faces:
if 'encoding' in current_face:
del current_face['encoding']
res = current_faces
return JSONResponse(res)
async def stop(request):
global cameras
print('Trying to stop all streams')
for c in cameras:
c.release()
async def stream(request):
cid = request.path_params['cid']
camera = next(filter(lambda c: c.cid == cid, cameras), None)
if not camera:
raise HTTPException(404)
only_faces = request.query_params and request.query_params['of']
async def generator(c):
print('Running Generator')
async for frame in c.frames(only_faces):
if await request.is_disconnected():
print('Stop Generator')
break
data = b"".join(
[
b"--frame\r\n",
b"Content-Type: image/jpeg\r\n\r\n",
frame,
b"\r\n",
]
)
yield data
return StreamingResponse(generator(camera),
media_type='multipart/x-mixed-replace; '
'boundary=frame')
def startup():
global cameras
Face.create_table()
for config in camera_configs:
camera = Camera(config['id'], config['type'], config['url'], config['lat'],
config['width'], config['height'], config['resize'])
cameras.append(camera.start())
print('Started Cameras:', list(map(lambda cam: cam.cid, cameras)))
def shutdown():
global cameras
print('Trying to stop all streams')
for c in cameras:
c.release()
time.sleep(1.0)
routes = [
Route("/faces/{fid:int}", endpoint=get_face, methods=["GET"]),
Route('/faces/{fid:int}', endpoint=update_face, methods=['PATCH']),
Route("/faces", endpoint=get_faces, methods=["GET"]),
Route("/current_faces/{cid:int}", endpoint=get_current_faces,
methods=["GET"]),
Route("/stream/{cid:int}", endpoint=stream, methods=["GET"]),
Route("/stop", endpoint=stop, methods=["GET"]),
Mount('/', app=StaticFiles(directory='client/dist', html=True),
name="client"),
]
app = Starlette(debug=True, routes=routes, on_startup=[startup],
on_shutdown=[shutdown])
# TODO it's dangerous to allow all origins. Restrict origins for prod.
app.add_middleware(CORSMiddleware,
allow_origins=['*'],
allow_methods=['*'],
allow_headers=['*'])
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)