feat: discover independent ONVIF lens sources and separate recorder archive links

This commit is contained in:
Codex
2026-10-03 16:16:23 +08:00
parent 9d7c20e4db
commit 528007ea43
5 changed files with 95 additions and 5 deletions
+18 -2
View File
@@ -23,6 +23,7 @@ import urllib.error
import urllib.parse as url
import urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import onvif
ROOT = Path(__file__).resolve().parent
os.umask(0o077)
@@ -163,8 +164,10 @@ def save_camera(body):
archiveSource=body.get('archiveSource', 'recorder' if recorder else 'local'))
if item['archiveSource'] not in ('local', 'recorder'):
raise Problem('录像存储来源不正确')
if item['archiveSource'] == 'recorder' and not recorder:
raise Problem('录像保存在录像机时,请先选择对应录像机')
archive_recorder = body.get('archiveRecorderId') or (recorder['id'] if recorder else '')
if archive_recorder and not get_object('recorders', archive_recorder):
raise Problem('关联的录像存储设备不存在')
item['archiveRecorderId'] = archive_recorder
item.update(id=key, siteId=site, host=host_address(recorder['host'] if recorder else body.get('host', '')),
port=integer(recorder['port'] if recorder else body.get('port', 554), 1, 65535))
for k, default in [('mainPath', '/stream1'), ('subPath', '/stream2')]:
@@ -513,6 +516,19 @@ class Handler(BaseHTTPRequestHandler):
self.answer(save_asset(data))
elif path == '/api/recorders':
self.answer(save_recorder(data))
elif path == '/api/onvif':
old = get_object('cameras', data.get('id')) or {}
host = host_address(data.get('host', ''))
port = integer(data.get('port', 80), 1, 65535)
username = clean_text(data.get('username', ''), 120, required=True)
password = data.get('password') or old.get('password', '')
if not isinstance(password, str) or len(password) > 256:
raise Problem('设备密码格式不正确')
try:
result = onvif.inspect(host, port, username, password)
except Exception:
raise Problem('ONVIF 读取未成功,请检查账号、设备时间、服务端口及 ONVIF 是否启用', 502)
self.answer(result)
elif path == '/api/storage':
policy = {'retentionDays': integer(data.get('retentionDays'), 1, 365),
'maxGB': integer(data.get('maxGB'), 5, 100000),