summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2023-02-05 01:38:27 +0300
committerEvgeny Zinoviev <me@ch1p.io>2023-02-05 02:37:52 +0300
commit378c912dd52072ed0dc86f00c4b4483bda615096 (patch)
tree73cb1482ed7838f3f827028d30daabb9edde8c27 /src
parent110f1619acbeb50ed86fb5eecde364ac99e45dff (diff)
ipcam_server: centralized config, universal workers
Diffstat (limited to 'src')
-rw-r--r--src/home/http/http.py6
-rwxr-xr-xsrc/ipcam_server.py94
2 files changed, 74 insertions, 26 deletions
diff --git a/src/home/http/http.py b/src/home/http/http.py
index 76197d2..3e70751 100644
--- a/src/home/http/http.py
+++ b/src/home/http/http.py
@@ -2,6 +2,7 @@ import logging
import asyncio
from aiohttp import web
+from aiohttp.web import Response
from aiohttp.web_exceptions import HTTPNotFound
from ..util import stringify, format_tb, Addr
@@ -99,4 +100,7 @@ class HTTPServer:
event_loop.run_forever()
def ok(self, data=None):
- return ok(data) \ No newline at end of file
+ return ok(data)
+
+ def plain(self, text: str):
+ return Response(text=text, content_type='text/plain')
diff --git a/src/ipcam_server.py b/src/ipcam_server.py
index 3fdf888..0159b77 100755
--- a/src/ipcam_server.py
+++ b/src/ipcam_server.py
@@ -39,6 +39,10 @@ def filename_to_datetime(filename: str) -> datetime:
return datetime.strptime(filename, datetime_format)
+def get_all_cams() -> list:
+ return [cam for cam in config['camera'].keys()]
+
+
# ipcam database
# --------------
@@ -125,6 +129,7 @@ class IPCamWebServer(http.HTTPServer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.get('/api/recordings', self.get_motion_queue)
self.get('/api/recordings/{name}', self.get_camera_recordings)
self.get('/api/recordings/{name}/download/{file}', self.download_recording)
self.get('/api/camera/list', self.camlist)
@@ -139,6 +144,9 @@ class IPCamWebServer(http.HTTPServer):
self.post('/api/motion/done/{name}', self.submit_motion)
self.post('/api/motion/fail/{name}', self.submit_motion_failure)
+ self.get('/api/motion/params/{name}', self.get_motion_params)
+ self.get('/api/motion/params/{name}/roi', self.get_motion_roi_params)
+
async def get_camera_recordings(self, req):
cam = int(req.match_info['name'])
try:
@@ -146,8 +154,21 @@ class IPCamWebServer(http.HTTPServer):
except KeyError:
filter = None
- files = get_recordings_files(cam, filter)
+ try:
+ limit = int(req.query['limit'])
+ except KeyError:
+ limit = 0
+
+ files = get_recordings_files(cam, filter, limit)
+ return self.ok({'files': files})
+
+ async def get_motion_queue(self, req):
+ try:
+ limit = int(req.query['limit'])
+ except KeyError:
+ limit = 0
+ files = get_recordings_files(None, TimeFilterType.MOTION, limit)
return self.ok({'files': files})
async def download_recording(self, req: http.Request):
@@ -234,6 +255,20 @@ class IPCamWebServer(http.HTTPServer):
async def get_all_timestamps(self, req: http.Request):
return self.ok(db.get_all_timestamps())
+ async def get_motion_params(self, req: http.Request):
+ data = config['motion_params'][int(req.match_info['name'])]
+ lines = [
+ f'threshold={data["threshold"]}',
+ f'min_event_length=3s',
+ f'frame_skip=2',
+ f'downscale_factor=3',
+ ]
+ return self.plain('\n'.join(lines)+'\n')
+
+ async def get_motion_roi_params(self, req: http.Request):
+ data = config['motion_params'][int(req.match_info['name'])]
+ return self.plain('\n'.join(data['roi'])+'\n')
+
@staticmethod
def _getset_timestamp_params(req: http.Request, need_time=False):
values = []
@@ -279,33 +314,42 @@ def get_motion_path(cam: int) -> str:
return config['camera'][cam]['motion_path']
-def get_recordings_files(cam: int,
- time_filter_type: Optional[TimeFilterType] = None) -> List[dict]:
+def get_recordings_files(cam: Optional[int] = None,
+ time_filter_type: Optional[TimeFilterType] = None,
+ limit=0) -> List[dict]:
from_time = 0
to_time = int(time.time())
- if time_filter_type:
- from_time = db.get_timestamp(cam, time_filter_type)
- if time_filter_type == TimeFilterType.MOTION:
- to_time = db.get_timestamp(cam, TimeFilterType.FIX)
-
- from_time = datetime.fromtimestamp(from_time)
- to_time = datetime.fromtimestamp(to_time)
-
- recdir = get_recordings_path(cam)
- files = [{
- 'name': file,
- 'size': os.path.getsize(os.path.join(recdir, file))}
- for file in os.listdir(recdir)
- if valid_recording_name(file) and from_time < filename_to_datetime(file) <= to_time]
- files.sort(key=lambda file: file['name'])
-
- if files:
- last = files[len(files)-1]
- fullpath = os.path.join(recdir, last['name'])
- if camutil.has_handle(fullpath):
- logger.debug(f'get_recordings_files: file {fullpath} has opened handle, ignoring it')
- files.pop()
+ cams = [cam] if cam is not None else get_all_cams()
+ files = []
+ for cam in cams:
+ if time_filter_type:
+ from_time = db.get_timestamp(cam, time_filter_type)
+ if time_filter_type == TimeFilterType.MOTION:
+ to_time = db.get_timestamp(cam, TimeFilterType.FIX)
+
+ from_time = datetime.fromtimestamp(from_time)
+ to_time = datetime.fromtimestamp(to_time)
+
+ recdir = get_recordings_path(cam)
+ cam_files = [{
+ 'cam': cam,
+ 'name': file,
+ 'size': os.path.getsize(os.path.join(recdir, file))}
+ for file in os.listdir(recdir)
+ if valid_recording_name(file) and from_time < filename_to_datetime(file) <= to_time]
+ cam_files.sort(key=lambda file: file['name'])
+
+ if cam_files:
+ last = cam_files[len(cam_files)-1]
+ fullpath = os.path.join(recdir, last['name'])
+ if camutil.has_handle(fullpath):
+ logger.debug(f'get_recordings_files: file {fullpath} has opened handle, ignoring it')
+ cam_files.pop()
+ files.extend(cam_files)
+
+ if limit > 0:
+ files = files[:limit]
return files