summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2023-06-11 05:03:43 +0300
committerEvgeny Zinoviev <me@ch1p.io>2023-06-11 05:03:43 +0300
commit62ee71fdb0eb07adbf0071103617aa96c993fe22 (patch)
tree07a5d7ec63c66efcf3162a388f22f371367000f7 /include
parentba321657e0e724082df206857f80ca08c4d999dc (diff)
ipcam: start porting to new config and multiserver scheme
Diffstat (limited to 'include')
-rw-r--r--include/py/homekit/camera/config.py82
-rw-r--r--include/py/homekit/camera/types.py12
-rw-r--r--include/py/homekit/config/config.py3
-rw-r--r--include/py/homekit/database/sqlite.py11
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))