From 62ee71fdb0eb07adbf0071103617aa96c993fe22 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Sun, 11 Jun 2023 05:03:43 +0300 Subject: ipcam: start porting to new config and multiserver scheme --- include/py/homekit/camera/config.py | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 include/py/homekit/camera/config.py (limited to 'include/py/homekit/camera/config.py') diff --git a/include/py/homekit/camera/config.py b/include/py/homekit/camera/config.py new file mode 100644 index 0000000..e0891a6 --- /dev/null +++ b/include/py/homekit/camera/config.py @@ -0,0 +1,82 @@ +from ..config import ConfigUnit, LinuxBoardsConfig +from typing import Optional +from .types import CameraType, VideoContainerType, VideoCodecType + + +_lbc = LinuxBoardsConfig() + + +def _validate_roi_line(field, value, error) -> bool: + p = value.split(' ') + if len(p) != 4: + error(field, f'{field}: must contain four coordinates separated by space') + for n in p: + if not n.isnumeric(): + error(field, f'{field}: invalid coordinates (not a number)') + return True + + +class IpcamConfig(ConfigUnit): + NAME = 'ipcam' + + @classmethod + def schema(cls) -> Optional[dict]: + lbc = LinuxBoardsConfig() + return { + 'cams': { + 'type': 'dict', + 'keysrules': {'type': ['string', 'integer']}, + 'valuesrules': { + 'type': 'dict', + 'schema': { + 'type': {'type': 'string', 'allowed': [t.value for t in CameraType], 'required': True}, + 'codec': {'type': 'string', 'allowed': [t.value for t in VideoCodecType], 'required': True}, + 'container': {'type': 'string', 'allowed': [t.value for t in VideoContainerType], 'required': True}, + 'server': {'type': 'string', 'allowed': list(lbc.get().keys()), 'required': True}, + 'disk': {'type': 'integer', 'required': True}, + 'motion': { + 'type': 'dict', + 'schema': { + 'threshold': {'type': ['float', 'integer']}, + 'roi': { + 'type': 'list', + 'schema': {'type': 'string', 'check_with': _validate_roi_line} + } + } + } + } + } + }, + 'motion_padding': {'type': 'integer', 'required': True}, + 'motion_telegram': {'type': 'boolean', 'required': True}, + 'fix_interval': {'type': 'integer', 'required': True}, + 'fix_enabled': {'type': 'boolean', 'required': True}, + 'cleanup_min_gb': {'type': 'integer', 'required': True}, + 'cleanup_interval': {'type': 'integer', 'required': True}, + + # TODO FIXME + 'fragment_url_templates': cls._url_templates_schema(), + 'original_file_url_templates': cls._url_templates_schema() + } + + @staticmethod + def custom_validator(data): + for n, cam in data['cams'].items(): + linux_box = _lbc[cam['server']] + if 'ext_hdd' not in linux_box: + raise ValueError(f'cam-{n}: linux box {cam["server"]} must have ext_hdd defined') + disk = cam['disk']-1 + if disk < 0 or disk >= len(linux_box['ext_hdd']): + raise ValueError(f'cam-{n}: invalid disk index for linux box {cam["server"]}') + + @classmethod + def _url_templates_schema(cls) -> dict: + return { + 'type': 'list', + 'empty': False, + 'schema': { + 'type': 'list', + 'empty': False, + 'schema': {'type': 'string'} + } + } \ No newline at end of file -- cgit v1.2.3 From 26bd30dff41f5f0e3857283155362a96c47ab9bb Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Sun, 11 Jun 2023 05:04:41 +0300 Subject: minor fix --- include/py/homekit/camera/config.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/py/homekit/camera/config.py') diff --git a/include/py/homekit/camera/config.py b/include/py/homekit/camera/config.py index e0891a6..331e595 100644 --- a/include/py/homekit/camera/config.py +++ b/include/py/homekit/camera/config.py @@ -21,7 +21,6 @@ class IpcamConfig(ConfigUnit): @classmethod def schema(cls) -> Optional[dict]: - lbc = LinuxBoardsConfig() return { 'cams': { 'type': 'dict', @@ -32,7 +31,7 @@ class IpcamConfig(ConfigUnit): 'type': {'type': 'string', 'allowed': [t.value for t in CameraType], 'required': True}, 'codec': {'type': 'string', 'allowed': [t.value for t in VideoCodecType], 'required': True}, 'container': {'type': 'string', 'allowed': [t.value for t in VideoContainerType], 'required': True}, - 'server': {'type': 'string', 'allowed': list(lbc.get().keys()), 'required': True}, + 'server': {'type': 'string', 'allowed': list(_lbc.get().keys()), 'required': True}, 'disk': {'type': 'integer', 'required': True}, 'motion': { 'type': 'dict', -- cgit v1.2.3 From 3da04de6fd83bca19447a865bf84b3403a14e0c1 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Sun, 11 Jun 2023 05:06:28 +0300 Subject: ipcam/config: fix schema validation --- include/py/homekit/camera/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/py/homekit/camera/config.py') diff --git a/include/py/homekit/camera/config.py b/include/py/homekit/camera/config.py index 331e595..0d4c747 100644 --- a/include/py/homekit/camera/config.py +++ b/include/py/homekit/camera/config.py @@ -65,7 +65,7 @@ class IpcamConfig(ConfigUnit): if 'ext_hdd' not in linux_box: raise ValueError(f'cam-{n}: linux box {cam["server"]} must have ext_hdd defined') disk = cam['disk']-1 - if disk < 0 or disk >= len(linux_box['ext_hdd']): + if disk < 1 or disk >= len(linux_box['ext_hdd']): raise ValueError(f'cam-{n}: invalid disk index for linux box {cam["server"]}') @classmethod -- cgit v1.2.3 From 08e736c48990bec0423f72cf52dd1a457e9f9590 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Sun, 11 Jun 2023 05:06:47 +0300 Subject: Revert "ipcam/config: fix schema validation" This reverts commit 3da04de6fd83bca19447a865bf84b3403a14e0c1. --- include/py/homekit/camera/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/py/homekit/camera/config.py') diff --git a/include/py/homekit/camera/config.py b/include/py/homekit/camera/config.py index 0d4c747..331e595 100644 --- a/include/py/homekit/camera/config.py +++ b/include/py/homekit/camera/config.py @@ -65,7 +65,7 @@ class IpcamConfig(ConfigUnit): if 'ext_hdd' not in linux_box: raise ValueError(f'cam-{n}: linux box {cam["server"]} must have ext_hdd defined') disk = cam['disk']-1 - if disk < 1 or disk >= len(linux_box['ext_hdd']): + if disk < 0 or disk >= len(linux_box['ext_hdd']): raise ValueError(f'cam-{n}: invalid disk index for linux box {cam["server"]}') @classmethod -- cgit v1.2.3 From e97f98e5e27a6df3827564cce594f27f18c89267 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Wed, 14 Jun 2023 14:06:26 +0300 Subject: wip --- include/py/homekit/camera/config.py | 57 ++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'include/py/homekit/camera/config.py') diff --git a/include/py/homekit/camera/config.py b/include/py/homekit/camera/config.py index 331e595..c7dbc38 100644 --- a/include/py/homekit/camera/config.py +++ b/include/py/homekit/camera/config.py @@ -1,8 +1,9 @@ +import socket + from ..config import ConfigUnit, LinuxBoardsConfig from typing import Optional from .types import CameraType, VideoContainerType, VideoCodecType - _lbc = LinuxBoardsConfig() @@ -42,7 +43,8 @@ class IpcamConfig(ConfigUnit): 'schema': {'type': 'string', 'check_with': _validate_roi_line} } } - } + }, + 'rtsp_tcp': {'type': 'boolean'} } } }, @@ -55,7 +57,19 @@ class IpcamConfig(ConfigUnit): # TODO FIXME 'fragment_url_templates': cls._url_templates_schema(), - 'original_file_url_templates': cls._url_templates_schema() + 'original_file_url_templates': cls._url_templates_schema(), + + 'hls_path': {'type': 'string', 'required': True}, + 'motion_processing_tmpfs_path': {'type': 'string', 'required': True}, + + 'rtsp_creds': { + 'required': True, + 'type': 'dict', + 'schema': { + 'login': {'type': 'string', 'required': True}, + 'password': {'type': 'string', 'required': True}, + } + } } @staticmethod @@ -78,4 +92,39 @@ class IpcamConfig(ConfigUnit): 'empty': False, 'schema': {'type': 'string'} } - } \ No newline at end of file + } + + def get_all_cam_names(self, + filter_by_server: Optional[str] = None, + filter_by_disk: Optional[int] = None) -> list[int]: + cams = [] + if filter_by_server is not None and filter_by_server not in _lbc: + raise ValueError(f'invalid filter_by_server: {filter_by_server} not found in {_lbc.__class__.__name__}') + for cam, params in self['cams'].items(): + if filter_by_server is None or params['server'] == filter_by_server: + if filter_by_disk is None or params['disk'] == filter_by_disk: + cams.append(int(cam)) + return cams + + def get_all_cam_names_for_this_server(self, + filter_by_disk: Optional[int] = None): + return self.get_all_cam_names(filter_by_server=socket.gethostname(), + filter_by_disk=filter_by_disk) + + def get_cam_server_and_disk(self, cam: int) -> tuple[str, int]: + return self['cams'][cam]['server'], self['cams'][cam]['disk'] + + def get_camera_container(self, cam: int) -> VideoContainerType: + return VideoContainerType(self['cams'][cam]['container']) + + def get_camera_type(self, cam: int) -> CameraType: + return CameraType(self['cams'][cam]['type']) + + def get_rtsp_creds(self) -> tuple[str, str]: + return self['rtsp_creds']['login'], self['rtsp_creds']['password'] + + def should_use_tcp_for_rtsp(self, cam: int) -> bool: + return 'rtsp_tcp' in self['cams'][cam] and self['cams'][cam]['rtsp_tcp'] + + def get_camera_ip(self, camera: int) -> str: + return f'192.168.5.{camera}' -- cgit v1.2.3