2026-08-30 22:22:11 +08:00
|
|
|
|
import json
|
|
|
|
|
|
from app.views.ViewsBase import *
|
|
|
|
|
|
from app.models import *
|
|
|
|
|
|
from django.shortcuts import render, redirect
|
|
|
|
|
|
from app.utils.Utils import buildPageLabels, group_by_field, GB28181CodeUtils
|
|
|
|
|
|
from app.utils.UploadUtils import UploadUtils
|
|
|
|
|
|
from app.utils.LogUtils import LogUtils
|
|
|
|
|
|
from app.utils.Credentials import encrypt_credential
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _hide_stream_credentials(stream):
|
|
|
|
|
|
if not isinstance(stream, dict):
|
|
|
|
|
|
return stream
|
|
|
|
|
|
stream["has_pull_stream_username"] = bool(stream.get("pull_stream_username"))
|
|
|
|
|
|
stream["has_pull_stream_password"] = bool(stream.get("pull_stream_password"))
|
|
|
|
|
|
stream["pull_stream_username"] = ""
|
|
|
|
|
|
stream["pull_stream_password"] = ""
|
|
|
|
|
|
return stream
|
|
|
|
|
|
|
|
|
|
|
|
def online(request):
|
|
|
|
|
|
context = {}
|
|
|
|
|
|
# data = Camera.objects.all().order_by("-sort")
|
|
|
|
|
|
return render(request, 'app/stream/online.html', context)
|
|
|
|
|
|
def index(request):
|
|
|
|
|
|
context = {}
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
stream_code = params.get("code","").strip()
|
|
|
|
|
|
context["search_text"] = stream_code # v4.716新增
|
|
|
|
|
|
return render(request, 'app/stream/index.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openAddContext(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
request_ip = f_parseRequestIp(request) # (v4.725新增) 获取实时请求ip
|
|
|
|
|
|
stream_info = {}
|
|
|
|
|
|
|
|
|
|
|
|
if "GET" == request.method:
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openAddContext() request_ip:%s,params:%s" % (request_ip,str(params)))
|
|
|
|
|
|
|
|
|
|
|
|
code = GB28181CodeUtils().generate_by_time()
|
|
|
|
|
|
app = g_zlm.default_stream_app
|
|
|
|
|
|
name = code
|
|
|
|
|
|
camera_device_id = "default"
|
|
|
|
|
|
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"code": code,
|
|
|
|
|
|
"app": app,
|
|
|
|
|
|
"name": name,
|
|
|
|
|
|
"camera_device_id": camera_device_id,
|
|
|
|
|
|
"is_audio": 0,
|
|
|
|
|
|
"pull_stream_username": "",
|
|
|
|
|
|
"pull_stream_password": "",
|
|
|
|
|
|
"rtspUrl": g_zlm.get_rtspUrl(app=app,name=name,request_ip=request_ip),
|
|
|
|
|
|
"hlsUrl": g_zlm.get_hlsUrl(app=app,name=name,request_ip=request_ip),
|
|
|
|
|
|
"httpMp4Url": g_zlm.get_httpMp4Url(app=app,name=name,request_ip=request_ip),
|
|
|
|
|
|
"wsMp4Url": g_zlm.get_wsMp4Url(app=app,name=name,request_ip=request_ip),
|
|
|
|
|
|
"record_enable": 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"stream": stream_info,
|
|
|
|
|
|
"pull_stream_types": g_pull_stream_types,
|
|
|
|
|
|
"audio_types": get_audio_types(f_parseRequestLang(request))
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openAddContext() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openAdd(request):
|
|
|
|
|
|
__ret = False
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
|
|
|
|
|
|
if "POST" == request.method:
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
try:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
g_logger.info("StreamView.openAdd() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
code = params.get("code", "").strip()
|
|
|
|
|
|
# app = params.get("app", "live").strip()
|
|
|
|
|
|
# name = params.get("name", "").strip()
|
|
|
|
|
|
nickname = params.get("nickname", "").strip()
|
|
|
|
|
|
pull_stream_type = int(params.get("pull_stream_type", 0))
|
|
|
|
|
|
pull_stream_url = params.get("pull_stream_url", "").strip()
|
|
|
|
|
|
pull_stream_ip = params.get("pull_stream_ip", "").strip()
|
|
|
|
|
|
pull_stream_port = int(params.get("pull_stream_port"))
|
|
|
|
|
|
|
|
|
|
|
|
camera_name = params.get("camera_name", "").strip()
|
|
|
|
|
|
camera_manufacturer = params.get("camera_manufacturer", "").strip()
|
|
|
|
|
|
camera_device_id = params.get("camera_device_id", "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
remark = params.get("remark", "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
onvif_username = params.get("onvif_username", "").strip()
|
|
|
|
|
|
onvif_password = params.get("onvif_password", "").strip()
|
|
|
|
|
|
is_audio = int(params.get("is_audio", 0))
|
|
|
|
|
|
record_enable = int(params.get("record_enable", 0))
|
|
|
|
|
|
|
|
|
|
|
|
if code == "":
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_code_invalid"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stream = StreamModel.objects.filter(code=code).filter()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "msg_code_already_exists"))
|
|
|
|
|
|
# if app == "":
|
|
|
|
|
|
# raise Exception(LANG_VIEWS_T(request, "stream_app_invalid"))
|
|
|
|
|
|
# if name == "":
|
|
|
|
|
|
# raise Exception(LANG_VIEWS_T(request, "stream_name_invalid"))
|
|
|
|
|
|
if nickname == "":
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_name_incorrect"))
|
|
|
|
|
|
else:
|
|
|
|
|
|
nickname_len = len(nickname)
|
|
|
|
|
|
if len(nickname) > 50:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_name_max_length") % nickname_len)
|
|
|
|
|
|
|
|
|
|
|
|
if pull_stream_type == 21:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_gb28181_hint"))
|
|
|
|
|
|
else:
|
|
|
|
|
|
if pull_stream_type == 1 or pull_stream_type == 2 or pull_stream_type == 3 or pull_stream_type == 4:
|
|
|
|
|
|
pass
|
|
|
|
|
|
else:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_protocol_not_supported"))
|
|
|
|
|
|
|
|
|
|
|
|
if pull_stream_url == "":
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_url_incorrect"))
|
|
|
|
|
|
|
|
|
|
|
|
if camera_device_id == "":
|
|
|
|
|
|
camera_device_id = code
|
|
|
|
|
|
|
|
|
|
|
|
user_id = f_sessionReadUserId(request)
|
|
|
|
|
|
now_date = datetime.now()
|
|
|
|
|
|
|
|
|
|
|
|
stream = StreamModel()
|
|
|
|
|
|
stream.user_id = user_id
|
|
|
|
|
|
stream.sort = 0
|
|
|
|
|
|
stream.code = code
|
|
|
|
|
|
stream.app = APP_NAME_LIVE
|
|
|
|
|
|
stream.name = code
|
|
|
|
|
|
stream.pull_stream_url = pull_stream_url
|
|
|
|
|
|
stream.pull_stream_type = pull_stream_type # v4.405新增
|
|
|
|
|
|
stream.pull_stream_transfer_mode = 0 # v4.405新增
|
|
|
|
|
|
stream.pull_stream_ip = pull_stream_ip # v4.405新增
|
|
|
|
|
|
stream.pull_stream_port = pull_stream_port # v4.405新增
|
|
|
|
|
|
stream.pull_stream_username = encrypt_credential(onvif_username)
|
|
|
|
|
|
stream.pull_stream_password = encrypt_credential(onvif_password)
|
|
|
|
|
|
|
|
|
|
|
|
stream.nickname = nickname
|
|
|
|
|
|
stream.remark = remark
|
|
|
|
|
|
stream.forward_state = 0 # 默认未开启转发
|
|
|
|
|
|
stream.is_audio = is_audio # v4.405新增
|
|
|
|
|
|
|
|
|
|
|
|
stream.camera_name = camera_name
|
|
|
|
|
|
stream.camera_manufacturer = camera_manufacturer
|
|
|
|
|
|
stream.camera_device_id = camera_device_id
|
|
|
|
|
|
|
|
|
|
|
|
stream.record_enable = record_enable
|
|
|
|
|
|
|
|
|
|
|
|
stream.create_time = now_date
|
|
|
|
|
|
stream.last_update_time = now_date
|
|
|
|
|
|
stream.add_type = 0
|
|
|
|
|
|
stream.state = 0
|
|
|
|
|
|
|
|
|
|
|
|
stream.save()
|
|
|
|
|
|
|
|
|
|
|
|
# 添加日志
|
|
|
|
|
|
user_id = f_sessionReadUserId(request)
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
LogUtils.add_stream_log(user_id=user_id, stream_code=code,
|
|
|
|
|
|
log_type=LogUtils.LOG_TYPE_ADD, lang=lang)
|
|
|
|
|
|
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_add_success")
|
|
|
|
|
|
__ret = True
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
__msg = str(e)
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if __ret else 0,
|
|
|
|
|
|
"msg": __msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openAdd() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openEditContext(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
request_ip = f_parseRequestIp(request) # (v4.725新增) 获取实时请求ip
|
|
|
|
|
|
stream_info = {}
|
|
|
|
|
|
|
|
|
|
|
|
if "GET" == request.method:
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openEditContext() request_ip:%s,params:%s" % (request_ip,str(params)))
|
|
|
|
|
|
|
|
|
|
|
|
stream_code = params.get("code", "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
stream = g_database.select("select * from av_stream where code=%s limit 1", [stream_code])
|
|
|
|
|
|
if len(stream) > 0:
|
|
|
|
|
|
stream_info = _hide_stream_credentials(stream[0])
|
|
|
|
|
|
camera_device_id = stream_info["camera_device_id"]
|
|
|
|
|
|
if camera_device_id is None or camera_device_id == "":
|
|
|
|
|
|
stream_info["camera_device_id"] = stream_code
|
|
|
|
|
|
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_not_found")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"stream": stream_info,
|
|
|
|
|
|
"pull_stream_types": g_pull_stream_types,
|
|
|
|
|
|
"audio_types": get_audio_types(f_parseRequestLang(request))
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openEditContext() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openStreamByAppAndName(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
data = {}
|
|
|
|
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openStreamByAppAndName() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
app = params.get("app", "").strip()
|
|
|
|
|
|
name = params.get("name", "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
if app and name:
|
|
|
|
|
|
streams = g_database.select(
|
|
|
|
|
|
"select * from av_stream where app=%s and name=%s limit 1", [app, name])
|
|
|
|
|
|
if len(streams) > 0:
|
|
|
|
|
|
data = _hide_stream_credentials(streams[0])
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_not_found")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_app_name_required")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"data": data
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openStreamByAppAndName() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openEdit(request):
|
|
|
|
|
|
__ret = False
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
|
|
|
|
|
|
if "POST" == request.method:
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
try:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openEdit() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
|
|
|
|
|
|
code = params.get("code", "").strip()
|
|
|
|
|
|
nickname = params.get("nickname", "").strip()
|
|
|
|
|
|
pull_stream_url = params.get("pull_stream_url", "").strip()
|
|
|
|
|
|
pull_stream_ip = params.get("pull_stream_ip", "").strip()
|
|
|
|
|
|
pull_stream_port = int(params.get("pull_stream_port", 0))
|
|
|
|
|
|
|
|
|
|
|
|
camera_name = params.get("camera_name", "").strip()
|
|
|
|
|
|
camera_manufacturer = params.get("camera_manufacturer", "").strip()
|
|
|
|
|
|
camera_device_id = params.get("camera_device_id", "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
remark = params.get("remark", "").strip()
|
|
|
|
|
|
is_audio = int(params.get("is_audio", 0))
|
|
|
|
|
|
record_enable = int(params.get("record_enable", 0))
|
|
|
|
|
|
|
|
|
|
|
|
if code == "":
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_code_invalid"))
|
|
|
|
|
|
|
|
|
|
|
|
if nickname == "":
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_name_incorrect"))
|
|
|
|
|
|
else:
|
|
|
|
|
|
nickname_len = len(nickname)
|
|
|
|
|
|
if len(nickname) > 50:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_name_max_length") % nickname_len)
|
|
|
|
|
|
|
|
|
|
|
|
stream = StreamModel.objects.filter(code=code).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
if (stream.pull_stream_type == 1 or stream.pull_stream_type == 2 or
|
|
|
|
|
|
stream.pull_stream_type == 3 or stream.pull_stream_type == 4):
|
|
|
|
|
|
if pull_stream_url == "":
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_url_required"))
|
|
|
|
|
|
|
|
|
|
|
|
# 检测是否修改摄像头视频地址 start
|
|
|
|
|
|
if stream.pull_stream_url != pull_stream_url:
|
|
|
|
|
|
# 拉流地址不一致,则首先需要停止拉流代理
|
|
|
|
|
|
__del_ret, __del_msg = GlobalUtils.delStreamProxy(stream, lang=lang)
|
|
|
|
|
|
stream.forward_state = 0
|
|
|
|
|
|
stream.pull_stream_url = pull_stream_url
|
|
|
|
|
|
# 检测是否修改摄像头视频地址 end
|
|
|
|
|
|
|
|
|
|
|
|
if stream.pull_stream_type != 21:
|
|
|
|
|
|
# 非gb28181接入,需要设置分组编号
|
|
|
|
|
|
stream.camera_device_id = camera_device_id
|
|
|
|
|
|
|
|
|
|
|
|
stream.pull_stream_ip = pull_stream_ip # v4.405新增
|
|
|
|
|
|
stream.pull_stream_port = pull_stream_port # v4.405新增
|
|
|
|
|
|
stream.is_audio = is_audio
|
|
|
|
|
|
stream.nickname = nickname
|
|
|
|
|
|
stream.remark = remark
|
|
|
|
|
|
stream.camera_name = camera_name
|
|
|
|
|
|
stream.camera_manufacturer = camera_manufacturer
|
|
|
|
|
|
|
|
|
|
|
|
old_record = stream.record_enable
|
|
|
|
|
|
stream.record_enable = record_enable
|
|
|
|
|
|
|
|
|
|
|
|
stream.last_update_time = datetime.now()
|
|
|
|
|
|
stream.save()
|
|
|
|
|
|
|
|
|
|
|
|
from app.views.NvrView import _sync_stream_recording
|
|
|
|
|
|
_sync_stream_recording(stream)
|
|
|
|
|
|
|
|
|
|
|
|
# 添加日志
|
|
|
|
|
|
user_id = f_sessionReadUserId(request)
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
LogUtils.add_stream_log(user_id=user_id, stream_code=code,
|
|
|
|
|
|
log_type=LogUtils.LOG_TYPE_EDIT, lang=lang)
|
|
|
|
|
|
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_edit_success")
|
|
|
|
|
|
__ret = True
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "stream_not_found")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
__msg = str(e)
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if __ret else 0,
|
|
|
|
|
|
"msg": __msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openEdit() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
def api_openPlayer(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
info = {}
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openPlayer() params:%s" % str(params))
|
|
|
|
|
|
request_ip = f_parseRequestIp(request) # (v4.725新增) 获取实时请求ip
|
|
|
|
|
|
|
|
|
|
|
|
app = params.get("app","").strip()
|
|
|
|
|
|
name = params.get("name","").strip()
|
|
|
|
|
|
try:
|
|
|
|
|
|
if app and name:
|
|
|
|
|
|
media_info = g_zlm.getMediaInfo(app=app, name=name)
|
|
|
|
|
|
media_is_online = 1 if media_info else 0
|
|
|
|
|
|
# v4.706确认,返回结构需要保持当前现状
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"is_online": media_is_online,
|
|
|
|
|
|
"app": app,
|
|
|
|
|
|
# "produce_speed": produce_speed,
|
|
|
|
|
|
# "video": video_str,
|
|
|
|
|
|
"aliveSecond": media_info.get("aliveSecond", 0),
|
|
|
|
|
|
"totalReaderCount": media_info.get("totalReaderCount", 0),
|
|
|
|
|
|
"video_codec_name": media_info.get("video_codec_name", ""),
|
|
|
|
|
|
"video_width": media_info.get("video_width", 0),
|
|
|
|
|
|
"video_height": media_info.get("video_height", 0),
|
|
|
|
|
|
# "audio": audio_str,
|
|
|
|
|
|
# "originUrl": d.get("originUrl"), # 推流地址
|
|
|
|
|
|
# "originType": d.get("originType"), # 推流地址采用的推流协议类型
|
|
|
|
|
|
# "originTypeStr": d.get("originTypeStr"), # 推流地址采用的推流协议类型(字符串)
|
|
|
|
|
|
# "clients": d.get("totalReaderCount"), # 客户端总数量
|
|
|
|
|
|
# "schemas_clients": schemas_clients,
|
|
|
|
|
|
"videoUrl": g_zlm.get_wsMp4Url(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"wsHost": g_zlm.get_wsHost(request_ip=request_ip),
|
|
|
|
|
|
"wsMp4Url": g_zlm.get_wsMp4Url(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"wsFlvUrl": g_zlm.get_wsFlvUrl(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"httpMp4Url": g_zlm.get_httpMp4Url(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"httpFlvUrl": g_zlm.get_httpFlvUrl(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"rtspUrl": g_zlm.get_rtspUrl(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"rtmpUrl": g_zlm.get_rtmpUrl(app=app, name=name, request_ip=request_ip)
|
|
|
|
|
|
}
|
|
|
|
|
|
stream = StreamModel.objects.filter(app=app, name=name).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
stream_info["code"] = stream.code
|
|
|
|
|
|
stream_info["pull_stream_type"] = stream.pull_stream_type
|
|
|
|
|
|
else:
|
|
|
|
|
|
stream_info["code"] = name
|
|
|
|
|
|
stream_info["pull_stream_type"] = 0
|
|
|
|
|
|
else:
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"pull_stream_type": 0,
|
|
|
|
|
|
"is_online": 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
g_logger.error("StreamView.openPlayer() e:%s" % str(e))
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"pull_stream_type": 0,
|
|
|
|
|
|
"is_online": 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
info["stream"] = stream_info
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"info": info
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openPlayer() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def player(request):
|
|
|
|
|
|
context = {}
|
|
|
|
|
|
request_ip = f_parseRequestIp(request) # (v4.725新增) 获取实时请求ip
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.player() request_ip:%s,params:%s" % (request_ip,str(params)))
|
|
|
|
|
|
|
|
|
|
|
|
app = params.get("app","").strip()
|
|
|
|
|
|
name = params.get("name","").strip()
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
if app and name:
|
|
|
|
|
|
media_info = g_zlm.getMediaInfo(app=app, name=name)
|
|
|
|
|
|
media_is_online = 1 if media_info else 0
|
|
|
|
|
|
# v4.706确认,返回结构需要保持当前现状
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"is_online": media_is_online,
|
|
|
|
|
|
"app": app,
|
|
|
|
|
|
"name": name,
|
|
|
|
|
|
"aliveSecond": media_info.get("aliveSecond", 0),
|
|
|
|
|
|
"totalReaderCount": media_info.get("totalReaderCount", 0),
|
|
|
|
|
|
"video_codec_name": media_info.get("video_codec_name", ""),
|
|
|
|
|
|
"video_width": media_info.get("video_width", 0),
|
|
|
|
|
|
"video_height": media_info.get("video_height", 0),
|
|
|
|
|
|
"videoUrl": g_zlm.get_wsMp4Url(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"wsHost": g_zlm.get_wsHost(request_ip=request_ip),
|
|
|
|
|
|
"wsMp4Url": g_zlm.get_wsMp4Url(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"wsFlvUrl": g_zlm.get_wsFlvUrl(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"httpMp4Url": g_zlm.get_httpMp4Url(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"httpFlvUrl": g_zlm.get_httpFlvUrl(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"rtspUrl": g_zlm.get_rtspUrl(app=app, name=name, request_ip=request_ip),
|
|
|
|
|
|
"rtmpUrl": g_zlm.get_rtmpUrl(app=app, name=name, request_ip=request_ip)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 优先:直接按 app+name 查找(live 原始流、rtp 等内部流)
|
|
|
|
|
|
stream = StreamModel.objects.filter(app=app, name=name).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
stream_info["code"] = stream.code
|
|
|
|
|
|
stream_info["pull_stream_type"] = stream.pull_stream_type
|
|
|
|
|
|
else:
|
|
|
|
|
|
stream_info["code"] = name
|
|
|
|
|
|
stream_info["pull_stream_type"] = 0
|
|
|
|
|
|
else:
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"pull_stream_type": 0,
|
|
|
|
|
|
"is_online": 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
g_logger.error("StreamView.player() e:%s" % str(e))
|
|
|
|
|
|
stream_info = {
|
|
|
|
|
|
"pull_stream_type": 0,
|
|
|
|
|
|
"is_online": 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 用 json.dumps 序列化为合法 JSON 字符串(True/False -> true/false),
|
|
|
|
|
|
# 避免 Django 模板 {{ stream|safe }} 把 Python bool 渲染成 JS 标识符导致 "True/False is not defined"
|
|
|
|
|
|
context["stream_json"] = json.dumps(stream_info, ensure_ascii=False)
|
|
|
|
|
|
g_logger.info("StreamView.player() stream_info:%s" % str(stream_info))
|
|
|
|
|
|
return render(request, 'app/stream/player.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openIndex(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
data = []
|
|
|
|
|
|
pageData = {}
|
|
|
|
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
# g_logger.info("StreamView.openIndex() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
# 同步数据库和在线流状态 start
|
|
|
|
|
|
medias = g_zlm.getMediaList()
|
|
|
|
|
|
if len(medias) == 0:
|
|
|
|
|
|
# 流媒体服务不在线,全部更新下线状态
|
|
|
|
|
|
g_database.execute("update av_stream set forward_state=0")
|
|
|
|
|
|
else:
|
|
|
|
|
|
media_dict = {}
|
|
|
|
|
|
for m in medias:
|
|
|
|
|
|
media_dict[m["an"]] = m
|
|
|
|
|
|
|
|
|
|
|
|
db_streams = f_dbReadStreamData()
|
|
|
|
|
|
for d in db_streams:
|
|
|
|
|
|
d_id = int(d.get("id", 0))
|
|
|
|
|
|
d_forward_state = d.get("forward_state", 0)
|
|
|
|
|
|
app_name = "{app}_{name}".format(app=d["app"], name=d["name"])
|
|
|
|
|
|
|
|
|
|
|
|
if media_dict.get(app_name):
|
|
|
|
|
|
if d_forward_state != 1:
|
|
|
|
|
|
g_database.execute("update av_stream set forward_state=1 where id=%s", [d_id])
|
|
|
|
|
|
else:
|
|
|
|
|
|
if d_forward_state != 0:
|
|
|
|
|
|
g_database.execute("update av_stream set forward_state=0 where id=%s", [d_id])
|
|
|
|
|
|
# 同步数据库和在线流状态 end
|
|
|
|
|
|
|
|
|
|
|
|
page = params.get('p', 1)
|
|
|
|
|
|
page_size = params.get('ps', 10)
|
|
|
|
|
|
search_text = str(params.get('search_text', "")).strip() # v4.638新增
|
|
|
|
|
|
search_status = int(params.get('search_status', -1)) # v4.716新增 转发状态筛选:-1全部 0未转发 1转发中
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
page = int(page)
|
|
|
|
|
|
except:
|
|
|
|
|
|
page = 1
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
page_size = int(page_size)
|
|
|
|
|
|
if page_size < 1:
|
|
|
|
|
|
page_size = 1
|
|
|
|
|
|
except:
|
|
|
|
|
|
page_size = 10
|
|
|
|
|
|
|
|
|
|
|
|
# 构建查询条件
|
|
|
|
|
|
conditions = []
|
|
|
|
|
|
query_params = []
|
|
|
|
|
|
if search_text:
|
|
|
|
|
|
conditions.append("(nickname like %s or code = %s)")
|
|
|
|
|
|
query_params.extend(["%%%s%%" % search_text, search_text])
|
|
|
|
|
|
|
|
|
|
|
|
if search_status != -1:
|
|
|
|
|
|
conditions.append("forward_state = %s")
|
|
|
|
|
|
query_params.append(search_status)
|
|
|
|
|
|
|
|
|
|
|
|
if search_text and search_status != -1:
|
|
|
|
|
|
sql = ("select * from av_stream where (nickname like %s or code = %s) "
|
|
|
|
|
|
"and forward_state = %s order by id desc")
|
|
|
|
|
|
elif search_text:
|
|
|
|
|
|
sql = "select * from av_stream where (nickname like %s or code = %s) order by id desc"
|
|
|
|
|
|
elif search_status != -1:
|
|
|
|
|
|
sql = "select * from av_stream where forward_state = %s order by id desc"
|
|
|
|
|
|
else:
|
|
|
|
|
|
sql = "select * from av_stream order by id desc"
|
|
|
|
|
|
|
|
|
|
|
|
skip = (page - 1) * page_size
|
|
|
|
|
|
|
|
|
|
|
|
data = g_database.select(sql, query_params)
|
|
|
|
|
|
rec_ids = set()
|
|
|
|
|
|
try:
|
|
|
|
|
|
from app.recording.manager import get_recording_manager
|
|
|
|
|
|
rec_ids = set(get_recording_manager().list_recording())
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
pass
|
|
|
|
|
|
for d in data:
|
|
|
|
|
|
_hide_stream_credentials(d)
|
|
|
|
|
|
camera_device_id = d.get("camera_device_id")
|
|
|
|
|
|
if camera_device_id is None or camera_device_id == "":
|
|
|
|
|
|
camera_device_id = d["code"]
|
|
|
|
|
|
d["camera_device_id"] = camera_device_id
|
|
|
|
|
|
sid = int(d.get("id", 0) or 0)
|
|
|
|
|
|
d["record_enable"] = int(d.get("record_enable", 0) or 0)
|
|
|
|
|
|
d["is_recording"] = 1 if sid in rec_ids else 0
|
|
|
|
|
|
|
|
|
|
|
|
grouped_data = group_by_field(data, field="camera_device_id")
|
|
|
|
|
|
count = len(grouped_data)
|
|
|
|
|
|
if count > 0:
|
|
|
|
|
|
grouped_data = grouped_data[skip:skip + page_size]
|
|
|
|
|
|
for i, group in enumerate(grouped_data):
|
|
|
|
|
|
# print(f"组 {i + 1}: {group}")
|
|
|
|
|
|
|
|
|
|
|
|
for d in group:
|
|
|
|
|
|
camera_name = d.get("camera_name","unknown name")
|
|
|
|
|
|
d["camera_name"] = camera_name
|
|
|
|
|
|
camera_manufacturer = d.get("camera_manufacturer","unknown manufacturer")
|
|
|
|
|
|
d["camera_manufacturer"] = camera_manufacturer
|
|
|
|
|
|
d["last_update_time"] = d.get("last_update_time").strftime("%Y/%m/%d %H:%M")
|
|
|
|
|
|
|
|
|
|
|
|
data = grouped_data
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
data = []
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_empty")
|
|
|
|
|
|
|
|
|
|
|
|
page_num = int(count / page_size) # 总页数
|
|
|
|
|
|
if count % page_size > 0:
|
|
|
|
|
|
page_num += 1
|
|
|
|
|
|
|
|
|
|
|
|
pageData = {
|
|
|
|
|
|
"page": page,
|
|
|
|
|
|
"page_size": page_size,
|
|
|
|
|
|
"page_num": page_num,
|
|
|
|
|
|
"count": count,
|
|
|
|
|
|
"pageLabels": buildPageLabels(page=page, page_num=page_num, lang=f_parseRequestLang(request))
|
|
|
|
|
|
}
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"data": data,
|
|
|
|
|
|
"pageData": pageData,
|
|
|
|
|
|
"extra": {
|
|
|
|
|
|
"audioTypes": get_audio_types(f_parseRequestLang(request)),
|
|
|
|
|
|
"pullStreamTypes": g_pull_stream_types
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openExportFile(request):
|
|
|
|
|
|
"""导出所有摄像头数据为Excel文件(与导入模板格式一致)"""
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
g_logger.info("StreamView.openExportFile()")
|
|
|
|
|
|
|
|
|
|
|
|
import io
|
|
|
|
|
|
from openpyxl import Workbook
|
|
|
|
|
|
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
|
|
|
|
|
|
# lang = f_parseRequestLang(request)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 查询所有摄像头数据
|
|
|
|
|
|
streams = StreamModel.objects.all().order_by("id")
|
|
|
|
|
|
|
|
|
|
|
|
# 创建工作簿
|
|
|
|
|
|
wb = Workbook()
|
|
|
|
|
|
ws = wb.active
|
|
|
|
|
|
ws.title = "摄像头数据"
|
|
|
|
|
|
|
|
|
|
|
|
# 定义表头(与导入模板完全一致)
|
|
|
|
|
|
headers = [
|
|
|
|
|
|
"摄像头编号", "摄像头昵称", "拉流地址", "IP地址", "端口",
|
|
|
|
|
|
"用户名", "密码", "备注", "是否音频", "分组编号"
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# 表头样式
|
|
|
|
|
|
header_font = Font(name='微软雅黑', size=11, bold=True, color='FFFFFF')
|
|
|
|
|
|
header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
|
|
|
|
|
|
header_align = Alignment(horizontal='center', vertical='center', wrap_text=True)
|
|
|
|
|
|
thin_border = Border(
|
|
|
|
|
|
left=Side(style='thin'),
|
|
|
|
|
|
right=Side(style='thin'),
|
|
|
|
|
|
top=Side(style='thin'),
|
|
|
|
|
|
bottom=Side(style='thin')
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 写入表头
|
|
|
|
|
|
for col_idx, header in enumerate(headers, 1):
|
|
|
|
|
|
cell = ws.cell(row=1, column=col_idx, value=header)
|
|
|
|
|
|
cell.font = header_font
|
|
|
|
|
|
cell.fill = header_fill
|
|
|
|
|
|
cell.alignment = header_align
|
|
|
|
|
|
cell.border = thin_border
|
|
|
|
|
|
|
|
|
|
|
|
# 数据样式
|
|
|
|
|
|
data_font = Font(name='微软雅黑', size=10)
|
|
|
|
|
|
data_align = Alignment(horizontal='left', vertical='center', wrap_text=True)
|
|
|
|
|
|
|
|
|
|
|
|
# 写入数据行
|
|
|
|
|
|
for row_idx, stream in enumerate(streams, 2):
|
|
|
|
|
|
# 设备ID处理:如果为空则使用code
|
|
|
|
|
|
camera_device_id = stream.camera_device_id if stream.camera_device_id else stream.code
|
|
|
|
|
|
|
|
|
|
|
|
row_data = [
|
|
|
|
|
|
stream.code or "",
|
|
|
|
|
|
stream.nickname or "",
|
|
|
|
|
|
stream.pull_stream_url or "",
|
|
|
|
|
|
stream.pull_stream_ip or "",
|
|
|
|
|
|
stream.pull_stream_port or 554,
|
|
|
|
|
|
"[REDACTED]" if stream.pull_stream_username else "",
|
|
|
|
|
|
"[REDACTED]" if stream.pull_stream_password else "",
|
|
|
|
|
|
stream.remark or "",
|
|
|
|
|
|
stream.is_audio or 0,
|
|
|
|
|
|
camera_device_id
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
for col_idx, value in enumerate(row_data, 1):
|
|
|
|
|
|
cell = ws.cell(row=row_idx, column=col_idx, value=value)
|
|
|
|
|
|
cell.font = data_font
|
|
|
|
|
|
cell.alignment = data_align
|
|
|
|
|
|
cell.border = thin_border
|
|
|
|
|
|
|
|
|
|
|
|
# 设置列宽
|
|
|
|
|
|
col_widths = [20, 20, 40, 18, 10, 18, 18, 30, 10, 20]
|
|
|
|
|
|
for col_idx, width in enumerate(col_widths, 1):
|
|
|
|
|
|
ws.column_dimensions[ws.cell(row=1, column=col_idx).column_letter].width = width
|
|
|
|
|
|
|
|
|
|
|
|
# 设置行高(表头)
|
|
|
|
|
|
ws.row_dimensions[1].height = 25
|
|
|
|
|
|
|
|
|
|
|
|
# 生成响应
|
|
|
|
|
|
buffer = io.BytesIO()
|
|
|
|
|
|
wb.save(buffer)
|
|
|
|
|
|
buffer.seek(0)
|
|
|
|
|
|
|
|
|
|
|
|
response = HttpResponse(buffer.getvalue(),
|
|
|
|
|
|
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
|
|
|
|
|
filename = "cameras_export_%s.xlsx" % datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
|
|
|
|
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
|
|
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
msg = str(e)
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openExportFile() res:%s" % str(res))
|
|
|
|
|
|
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openImportFile(request):
|
|
|
|
|
|
__ret = False
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
g_logger.info("StreamView.openImportFile() params:%s" % str(params))
|
|
|
|
|
|
try:
|
|
|
|
|
|
file = request.FILES.get("file")
|
|
|
|
|
|
importRemark = str(params.get("importRemark", "")).strip()
|
|
|
|
|
|
|
|
|
|
|
|
upload_utils = UploadUtils()
|
|
|
|
|
|
__upload_ret, __upload_msg, __upload_data = upload_utils.upload_camera_xlsx(file=file,
|
|
|
|
|
|
upload_dir=g_config.storageTempDir,
|
|
|
|
|
|
lang=lang)
|
|
|
|
|
|
|
|
|
|
|
|
if __upload_ret:
|
|
|
|
|
|
user_id = f_sessionReadUserId(request)
|
|
|
|
|
|
success_count = 0
|
|
|
|
|
|
error_count = 0
|
|
|
|
|
|
for d in __upload_data:
|
|
|
|
|
|
try:
|
|
|
|
|
|
stream_code = d["code"]
|
|
|
|
|
|
if not stream_code: # 未填写编号,则自动生成编号
|
|
|
|
|
|
stream_code = GB28181CodeUtils().generate_by_time()
|
|
|
|
|
|
|
|
|
|
|
|
nickname = d["nickname"]
|
|
|
|
|
|
pull_stream_url = d["pull_stream_url"]
|
|
|
|
|
|
pull_stream_ip = d["pull_stream_ip"]
|
|
|
|
|
|
pull_stream_port = d["pull_stream_port"]
|
|
|
|
|
|
username = d["username"]
|
|
|
|
|
|
password = d["password"]
|
|
|
|
|
|
camera_device_id = str(d.get("camera_device_id", "")).strip()
|
|
|
|
|
|
is_audio = int(d.get("is_audio", 0))
|
|
|
|
|
|
remark = str(d.get("remark", "")).strip()
|
|
|
|
|
|
|
|
|
|
|
|
remark = "remark=%s,importRemark=%s" % (remark, importRemark)
|
|
|
|
|
|
|
|
|
|
|
|
if camera_device_id is None or camera_device_id == "":
|
|
|
|
|
|
camera_device_id = stream_code
|
|
|
|
|
|
|
|
|
|
|
|
if pull_stream_url.startswith("rtsp://") or pull_stream_url.startswith("rtsps://"):
|
|
|
|
|
|
pull_stream_type = 1
|
|
|
|
|
|
elif pull_stream_url.startswith("rtmp://") or pull_stream_url.startswith("rtmps://"):
|
|
|
|
|
|
pull_stream_type = 2
|
|
|
|
|
|
elif pull_stream_url.startswith("http://") or pull_stream_url.startswith("https://"):
|
|
|
|
|
|
pull_stream_type = 3
|
|
|
|
|
|
else:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_url_format_error"))
|
|
|
|
|
|
|
|
|
|
|
|
stream = StreamModel.objects.filter(code=stream_code).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
raise Exception(LANG_VIEWS_T(request, "stream_code_exists"))
|
|
|
|
|
|
else:
|
|
|
|
|
|
stream = StreamModel()
|
|
|
|
|
|
stream.user_id = user_id
|
|
|
|
|
|
stream.sort = 0
|
|
|
|
|
|
stream.code = stream_code
|
|
|
|
|
|
stream.app = g_zlm.default_stream_app
|
|
|
|
|
|
stream.name = stream_code
|
|
|
|
|
|
stream.pull_stream_url = pull_stream_url
|
|
|
|
|
|
stream.pull_stream_type = pull_stream_type # v4.405新增
|
|
|
|
|
|
stream.pull_stream_transfer_mode = 0 # v4.405新增
|
|
|
|
|
|
stream.pull_stream_ip = pull_stream_ip # v4.405新增
|
|
|
|
|
|
stream.pull_stream_port = pull_stream_port # v4.405新增
|
|
|
|
|
|
stream.pull_stream_username = encrypt_credential(username)
|
|
|
|
|
|
stream.pull_stream_password = encrypt_credential(password)
|
|
|
|
|
|
stream.nickname = nickname
|
|
|
|
|
|
stream.remark = remark
|
|
|
|
|
|
stream.forward_state = 0 # 默认未开启转发
|
|
|
|
|
|
stream.camera_device_id = camera_device_id # v4.638新增
|
|
|
|
|
|
|
|
|
|
|
|
stream.create_time = datetime.now()
|
|
|
|
|
|
stream.last_update_time = datetime.now()
|
|
|
|
|
|
stream.add_type = 1
|
|
|
|
|
|
stream.state = 0
|
|
|
|
|
|
stream.is_audio = is_audio # v4.405新增
|
|
|
|
|
|
|
|
|
|
|
|
stream.save()
|
|
|
|
|
|
|
|
|
|
|
|
success_count += 1
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
g_logger.error("StreamView.openImportFile() error: %s, d=%s" % (str(e),str(d)))
|
|
|
|
|
|
error_count += 1
|
|
|
|
|
|
|
|
|
|
|
|
__ret = True
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_batch_result") % (success_count, error_count)
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = __upload_msg
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
__msg = str(e)
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
__msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if __ret else 0,
|
|
|
|
|
|
"msg": __msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openImportFile() res:%s" % str(res))
|
|
|
|
|
|
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openDel(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openDel() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
handle = params.get("handle") # one:删除一个视频流,all:删除全部视频流
|
|
|
|
|
|
stream_code = params.get("code")
|
|
|
|
|
|
|
|
|
|
|
|
if handle == "one":
|
|
|
|
|
|
stream = StreamModel.objects.filter(code=stream_code).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
__ret, __msg = GlobalUtils.delStreamProxy(stream, lang=lang)
|
|
|
|
|
|
if stream.delete():
|
2026-09-04 18:16:14 +08:00
|
|
|
|
# 同步清理内存里的该通道,避免 Catalog 刷新后自动恢复
|
|
|
|
|
|
g_gb28181SipServer.remove_channel(
|
|
|
|
|
|
stream_code,
|
|
|
|
|
|
device_id=stream.camera_device_id or None,
|
|
|
|
|
|
)
|
2026-08-30 22:22:11 +08:00
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_delete_failed")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_not_found")
|
|
|
|
|
|
elif handle == "all":
|
|
|
|
|
|
success_count = 0
|
|
|
|
|
|
error_count = 0
|
|
|
|
|
|
streams = StreamModel.objects.all()
|
|
|
|
|
|
for stream in streams:
|
|
|
|
|
|
__ret, __msg = GlobalUtils.delStreamProxy(stream, lang=lang)
|
|
|
|
|
|
if stream.delete():
|
2026-09-04 18:16:14 +08:00
|
|
|
|
g_gb28181SipServer.remove_channel(stream.code, device_id=stream.camera_device_id or None)
|
2026-08-30 22:22:11 +08:00
|
|
|
|
success_count += 1
|
|
|
|
|
|
else:
|
|
|
|
|
|
error_count += 1
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_batch_result") % (success_count, error_count)
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_invalid_parameter")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openDel() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
def api_openHandleAllStreamProxy(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openHandleAllStreamProxy() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
handle = params.get("handle") # add,del (add 开启流,del 关闭流)
|
|
|
|
|
|
|
|
|
|
|
|
if handle == "add": # 全部开启转发
|
|
|
|
|
|
ret,msg = GlobalUtils.addAllStreamProxy(lang=lang)
|
|
|
|
|
|
elif handle == "del": # 全部关闭转发
|
|
|
|
|
|
GlobalUtils.delAllStreamProxy(lang=lang)
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_invalid_parameter")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openHandleAllStreamProxy() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def api_openAddStreamProxy(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openAddStreamProxy() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
stream_code = params.get("code", "").strip()
|
|
|
|
|
|
stream = StreamModel.objects.filter(code=stream_code).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
if stream.forward_state == 1:
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_forward_already_enabled")
|
|
|
|
|
|
else:
|
|
|
|
|
|
ret, msg = GlobalUtils.addStreamProxy(stream, lang=lang)
|
|
|
|
|
|
if ret:
|
|
|
|
|
|
stream.forward_state = 1
|
|
|
|
|
|
stream.save()
|
|
|
|
|
|
from app.views.NvrView import _sync_stream_recording
|
|
|
|
|
|
_sync_stream_recording(stream)
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_forward_enabled_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_not_found")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openAddStreamProxy() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
def api_openDelStreamProxy(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openDelStreamProxy() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
stream_code = params.get("code", "").strip()
|
|
|
|
|
|
stream = StreamModel.objects.filter(code=stream_code).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
__ret, __msg = GlobalUtils.delStreamProxy(stream, lang=lang)
|
|
|
|
|
|
stream.forward_state = 0
|
|
|
|
|
|
stream.save()
|
|
|
|
|
|
from app.views.NvrView import _sync_stream_recording
|
|
|
|
|
|
_sync_stream_recording(stream)
|
|
|
|
|
|
|
|
|
|
|
|
ret = __ret
|
|
|
|
|
|
msg = __msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_not_found")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openDelStreamProxy() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
def api_openPtz(request):
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
lang = f_parseRequestLang(request)
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parsePostParams(request)
|
|
|
|
|
|
g_logger.info("StreamView.openPtz() params:%s" % str(params))
|
|
|
|
|
|
|
|
|
|
|
|
code = params.get("code", "").strip()
|
2026-09-04 18:16:14 +08:00
|
|
|
|
try:
|
|
|
|
|
|
ptzType = int(params.get("ptzType", 0))
|
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
|
ptzType = -1
|
|
|
|
|
|
# 优先读取前端实际参数名 ptzSpeed,兼容旧字段 val
|
|
|
|
|
|
try:
|
|
|
|
|
|
val = int(params.get("ptzSpeed", params.get("val", 0)) or 0)
|
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
|
val = 0
|
2026-08-30 22:22:11 +08:00
|
|
|
|
|
2026-09-04 18:16:14 +08:00
|
|
|
|
if ptzType < 0 or ptzType > 14:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "ptz_type_range_error")
|
|
|
|
|
|
else:
|
|
|
|
|
|
# 除停止外均需非零速度才会动作;越界值钳制到0-255
|
|
|
|
|
|
if ptzType != 0 and val < 1:
|
|
|
|
|
|
val = 32
|
|
|
|
|
|
val = min(max(val, 0), 255)
|
2026-08-30 22:22:11 +08:00
|
|
|
|
|
2026-09-04 18:16:14 +08:00
|
|
|
|
stream = StreamModel.objects.filter(code=code).first()
|
|
|
|
|
|
if stream:
|
|
|
|
|
|
if stream.pull_stream_type == 21:
|
|
|
|
|
|
ret, msg = g_gb28181SipServer.request_ptz(
|
|
|
|
|
|
client_id=stream.camera_device_id,
|
|
|
|
|
|
channel_id=stream.code,
|
|
|
|
|
|
ptz_type=ptzType,
|
|
|
|
|
|
val=val,
|
|
|
|
|
|
# 分进程模式:web进程无实时SIP注册表,从库中取设备地址外发
|
|
|
|
|
|
device_ip=stream.pull_stream_ip or None,
|
|
|
|
|
|
device_port=stream.pull_stream_port or 0)
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_pull_type_not_supported")
|
2026-08-30 22:22:11 +08:00
|
|
|
|
else:
|
2026-09-04 18:16:14 +08:00
|
|
|
|
msg = LANG_VIEWS_T(request, "stream_not_found")
|
2026-08-30 22:22:11 +08:00
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openPtz() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def api_openGetAllStreamData(request):
|
|
|
|
|
|
"""在线预览页面获取所有在线流数据(原 OpenView 中的同名接口迁移至此)"""
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
data = []
|
|
|
|
|
|
request_ip = f_parseRequestIp(request)
|
|
|
|
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
handle = params.get("handle", "").strip()
|
|
|
|
|
|
g_logger.info("StreamView.openGetAllStreamData() request_ip:%s,params:%s" % (request_ip, str(params)))
|
|
|
|
|
|
|
|
|
|
|
|
# 获取所有 ZLM 在线流
|
|
|
|
|
|
medias = g_zlm.getMediaList(request_ip=request_ip)
|
|
|
|
|
|
|
|
|
|
|
|
# 构建 app_name -> 摄像头信息 映射(从数据库)
|
|
|
|
|
|
db_streams = g_database.select("select id,app,name,code,nickname from av_stream")
|
|
|
|
|
|
db_dict = {}
|
|
|
|
|
|
for s in db_streams:
|
|
|
|
|
|
key = "{app}_{name}".format(app=s["app"], name=s["name"])
|
|
|
|
|
|
db_dict[key] = s
|
|
|
|
|
|
|
|
|
|
|
|
for m in medias:
|
|
|
|
|
|
app = m.get("app", "")
|
|
|
|
|
|
name = m.get("name", "")
|
|
|
|
|
|
app_name = m.get("app_name", "{0}_{1}".format(app, name))
|
|
|
|
|
|
|
|
|
|
|
|
nickname = name
|
|
|
|
|
|
code = app_name
|
|
|
|
|
|
|
|
|
|
|
|
db_info = db_dict.get(app_name)
|
|
|
|
|
|
if db_info:
|
|
|
|
|
|
code = db_info.get("code") or app_name
|
|
|
|
|
|
nickname = db_info.get("nickname") or name
|
|
|
|
|
|
m["id"] = db_info.get("id")
|
|
|
|
|
|
|
|
|
|
|
|
m["code"] = code
|
|
|
|
|
|
m["nickname"] = nickname
|
|
|
|
|
|
data.append(m)
|
|
|
|
|
|
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"data": data
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openGetAllStreamData() res.data length:%d" % len(data))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def api_openGetStatisticsStream(request):
|
|
|
|
|
|
"""首页流媒体统计(原 OpenView 接口迁移至此)"""
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
info = {"groupCount": 0, "count": 0, "forwardCount": 0}
|
|
|
|
|
|
request_ip = f_parseRequestIp(request)
|
|
|
|
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
g_logger.info("StreamView.openGetStatisticsStream() request_ip:%s" % request_ip)
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 接入数量 = 数据库中摄像头总数
|
|
|
|
|
|
db_rows = g_database.select("select app,name from av_stream")
|
|
|
|
|
|
info["count"] = len(db_rows)
|
|
|
|
|
|
|
|
|
|
|
|
# 在线数量 = ZLM 中实际存在的流数量
|
|
|
|
|
|
medias = g_zlm.getMediaList(request_ip=request_ip)
|
|
|
|
|
|
info["forwardCount"] = len(medias)
|
|
|
|
|
|
|
|
|
|
|
|
# 分组数量 = 不同 app 的数量
|
|
|
|
|
|
apps = set()
|
|
|
|
|
|
for r in db_rows:
|
|
|
|
|
|
if r.get("app"):
|
|
|
|
|
|
apps.add(r["app"])
|
|
|
|
|
|
info["groupCount"] = len(apps)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
g_logger.error("StreamView.openGetStatisticsStream() e:%s" % str(e))
|
|
|
|
|
|
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
|
|
|
|
|
|
res = {
|
|
|
|
|
|
"code": 1000 if ret else 0,
|
|
|
|
|
|
"msg": msg,
|
|
|
|
|
|
"info": info
|
|
|
|
|
|
}
|
|
|
|
|
|
g_logger.info("StreamView.openGetStatisticsStream() res:%s" % str(res))
|
|
|
|
|
|
return f_responseJson(res)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def api_openOnvifDiscover(request):
|
|
|
|
|
|
"""WS-Discovery 发现局域网 ONVIF 设备"""
|
|
|
|
|
|
ret = False
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|
|
|
|
|
data = []
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|
|
|
|
|
if __check_ret:
|
|
|
|
|
|
try:
|
|
|
|
|
|
from app.services.onvif_discovery import discover_onvif, get_rtsp_url_from_onvif
|
|
|
|
|
|
params = f_parseGetParams(request)
|
|
|
|
|
|
timeout = float(params.get("timeout", 3))
|
|
|
|
|
|
username = (params.get("username") or "").strip()
|
|
|
|
|
|
password = (params.get("password") or "").strip()
|
|
|
|
|
|
resolve = str(params.get("resolve_rtsp", "0")).strip() in ("1", "true", "yes")
|
|
|
|
|
|
devices = discover_onvif(timeout=timeout)
|
|
|
|
|
|
for d in devices:
|
|
|
|
|
|
item = dict(d)
|
|
|
|
|
|
if resolve and d.get("xaddr"):
|
|
|
|
|
|
rtsp = get_rtsp_url_from_onvif(d["xaddr"], username, password)
|
|
|
|
|
|
if rtsp:
|
|
|
|
|
|
item["rtsp_url"] = rtsp
|
|
|
|
|
|
data.append(item)
|
|
|
|
|
|
ret = True
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
msg = str(e)
|
|
|
|
|
|
g_logger.exception("openOnvifDiscover: %s", e)
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = __check_msg
|
|
|
|
|
|
else:
|
|
|
|
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|
|
|
|
|
return f_responseJson({"code": 1000 if ret else 0, "msg": msg, "data": data})
|