diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2023-02-05 01:38:27 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2023-02-05 02:37:52 +0300 |
commit | 378c912dd52072ed0dc86f00c4b4483bda615096 (patch) | |
tree | 73cb1482ed7838f3f827028d30daabb9edde8c27 /src | |
parent | 110f1619acbeb50ed86fb5eecde364ac99e45dff (diff) |
ipcam_server: centralized config, universal workers
Diffstat (limited to 'src')
-rw-r--r-- | src/home/http/http.py | 6 | ||||
-rwxr-xr-x | src/ipcam_server.py | 94 |
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 |