diff options
Diffstat (limited to 'include/py/homekit')
-rw-r--r-- | include/py/homekit/camera/config.py | 82 | ||||
-rw-r--r-- | include/py/homekit/camera/types.py | 12 | ||||
-rw-r--r-- | include/py/homekit/config/config.py | 3 | ||||
-rw-r--r-- | include/py/homekit/database/sqlite.py | 11 |
4 files changed, 104 insertions, 4 deletions
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 diff --git a/include/py/homekit/camera/types.py b/include/py/homekit/camera/types.py index de59022..0d3a384 100644 --- a/include/py/homekit/camera/types.py +++ b/include/py/homekit/camera/types.py @@ -3,3 +3,15 @@ from enum import Enum class CameraType(Enum): ESP32 = 'esp32' + ALIEXPRESS_NONAME = 'ali' + HIKVISION = 'hik' + + +class VideoContainerType(Enum): + MP4 = 'mp4' + MOV = 'mov' + + +class VideoCodecType(Enum): + H264 = 'h264' + H265 = 'h265' diff --git a/include/py/homekit/config/config.py b/include/py/homekit/config/config.py index 7344386..f2a3990 100644 --- a/include/py/homekit/config/config.py +++ b/include/py/homekit/config/config.py @@ -158,6 +158,9 @@ class ConfigUnit(BaseConfigUnit): else: normalized = v.validated(self._data, schema) + if not normalized: + raise cerberus.DocumentError(f'validation failed: {v.errors}') + self._data = normalized try: diff --git a/include/py/homekit/database/sqlite.py b/include/py/homekit/database/sqlite.py index 0af1f54..8b0c44c 100644 --- a/include/py/homekit/database/sqlite.py +++ b/include/py/homekit/database/sqlite.py @@ -15,10 +15,13 @@ def _get_database_path(name: str) -> str: class SQLiteBase: SCHEMA = 1 - def __init__(self, name=None, check_same_thread=False): - if name is None: - name = config.app_config['database_name'] - database_path = _get_database_path(name) + def __init__(self, name=None, path=None, check_same_thread=False): + if not path: + if not name: + name = config.app_config['database_name'] + database_path = _get_database_path(name) + else: + database_path = path if not os.path.exists(os.path.dirname(database_path)): os.makedirs(os.path.dirname(database_path)) |