video_monitor/app/views/SystemView.py
2026-08-30 22:23:12 +08:00

325 lines
13 KiB
Python

import json
import shutil
import os
import threading
from app.views.ViewsBase import *
from django.shortcuts import render
from app.utils.OSSystem import OSSystem
from app.utils.GlobalUtils import g_filepath_settings_json, GlobalUtils
from framework.settings import PROJECT_VERSION, PROJECT_FLAG, PROJECT_UA, PROJECT_BUILT, PROJECT_ADMIN_START_TIMESTAMP
def f_readSettings(lang):
try:
for encoding in ["utf-8", "gbk"]:
try:
with open(g_filepath_settings_json, 'r', encoding=encoding) as f:
data = json.load(f)
# 从 languages 字典中直接获取对应语言的 oem 配置
languages = data.get("languages", {})
return languages.get(lang, {}).get("oem", {})
except Exception as e:
g_logger.error("f_readSettings() error: %s" % str(e))
return {}
except:
return {}
def f_writeSettings(lang, settings_data):
for encoding in ["utf-8", "gbk"]:
try:
with open(g_filepath_settings_json, 'r', encoding=encoding) as f:
data = json.load(f)
# 更新 languages 字典中对应语言的 oem 配置
languages = data.get("languages", {})
if lang in languages:
languages[lang]["oem"] = settings_data
with open(g_filepath_settings_json, 'w', encoding=encoding) as f:
json.dump(data, f, ensure_ascii=False, indent=2)
return True
except Exception as e:
g_logger.error("f_writeSettings() error: %s"%str(e))
continue
def config(request):
lang = f_parseRequestLang(request)
branding = f_readSettings(lang)
cfg = g_config.to_dict()
context = {
"config": cfg,
"branding": branding
}
return render(request, 'app/system/config.html', context)
def _config_api_payload():
data = g_config.to_dict()
# 前端习惯 0/1 开关
for k in (
"autoAddStreamProxy", "isEnableLoginCaptcha", "logDebug", "isEnableUpdatePopup",
"telemetryEnabled", "updateCheckEnabled",
"isEnableMediaProxyRtmp", "autoStartMedia", "analysisSharedInference",
"recordingEnabled",
):
if k in data:
data[k] = 1 if _bool_web(data.get(k)) else 0
sip = data.get("sipServer") or {}
if "autoInviteAfterRecCateLog" in sip:
sip["autoInviteAfterRecCateLog"] = 1 if _bool_web(sip.get("autoInviteAfterRecCateLog")) else 0
data["sipServer"] = sip
return data
def _bool_web(v):
return v is True or v == 1 or str(v).strip().lower() in ("1", "true", "yes")
def api_openConfig(request):
ret = False
msg = LANG_VIEWS_T(request, "msg_unknown_error")
if request.method == 'GET':
# 加载配置:同时返回基础配置 + OEM 品牌信息
__check_ret, __check_msg = f_checkRequestSafe(request)
if __check_ret:
try:
lang = f_parseRequestLang(request)
branding = f_readSettings(lang)
data = _config_api_payload()
ret = True
msg = LANG_VIEWS_T(request, "msg_success")
res = {
"code": 1000,
"msg": msg,
"data": data,
"config": data,
"branding": branding
}
g_logger.info("SystemView.openConfig(GET) ok")
return f_responseJson(res)
except Exception as e:
msg = str(e)
else:
msg = __check_msg
elif request.method == 'POST':
__check_ret, __check_msg = f_checkRequestSafe(request)
if __check_ret:
params = f_parsePostParams(request)
g_logger.info("SystemView.openConfig() requested")
try:
before = g_config.to_dict(include_secrets=True)
g_config.save_from_web(params)
notes = GlobalUtils.apply_runtime_config(before)
ret = True
msg = LANG_VIEWS_T(request, "syscfg_save_success")
hint_parts = []
if "adminPort" in notes:
hint_parts.append(LANG_VIEWS_T(request, "syscfg_hint_admin_port"))
if "logDebug" in notes:
hint_parts.append(LANG_VIEWS_T(request, "syscfg_hint_log_debug"))
if "zlm" in notes:
hint_parts.append(LANG_VIEWS_T(request, "syscfg_hint_zlm"))
if hint_parts:
msg = msg + " " + " ".join(hint_parts)
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("SystemView.openConfig() res: %s" % str(res))
return f_responseJson(res)
def api_openSaveSettings(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)
g_logger.info("SystemView.openSaveSettings() params: %s" % str(params))
try:
lang = f_parseRequestLang(request)
branding_name = str(params.get("name", "")).strip()
branding_welcome = str(params.get("welcome", "")).strip()
branding_logo_url = str(params.get("logo_url", "")).strip()
branding_bottom_name = str(params.get("bottom_name", "")).strip()
branding_author = str(params.get("author", "")).strip()
branding_author_link = str(params.get("author_link", "")).strip()
branding_check_version_download_url = str(params.get("check_version_download_url", "")).strip()
branding_is_show_author = params.get("is_show_author", False)
if isinstance(branding_is_show_author, str):
branding_is_show_author = branding_is_show_author.lower() in ['true', '1', 'yes']
settings_data = {
"name": branding_name,
"welcome": branding_welcome,
"logo_url": branding_logo_url,
"bottom_name": branding_bottom_name,
"is_show_author": branding_is_show_author,
"author": branding_author,
"author_link": branding_author_link,
"check_version_download_url": branding_check_version_download_url
}
f_writeSettings(lang, settings_data)
ret = True
msg = LANG_VIEWS_T(request, "syscfg_save_oem_success")
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("SystemView.openSaveSettings() res: %s" % str(res))
return f_responseJson(res)
def api_openExportLogs(request):
# 导出日志
ret = False
msg = LANG_VIEWS_T(request, "msg_unknown_error")
info = {
}
request_ip = f_parseRequestIp(request)
lang = f_parseRequestLang(request)
export_dir = None
if request.method == 'POST':
__check_ret, __check_msg = f_checkRequestSafe(request)
if __check_ret:
try:
params = f_parsePostParams(request)
g_logger.info("SystemView.openExportLogs() params:%s" % str(params))
g_gb28181SipServer.log_status()
run_errors = []
# 导出外层文件夹
export_dirname = "logs%s-%s-%s" % (PROJECT_VERSION, PROJECT_FLAG, datetime.now().strftime("%Y%m%d%H%M%S"))
export_dir = os.path.join(g_config.storageTempDir, export_dirname)
export_filename = "%s.xclogs" % export_dirname
export_filepath = os.path.join(g_config.storageTempDir, export_filename)
if not os.path.exists(export_dir):
os.makedirs(export_dir)
osSystem = OSSystem()
try:
# 压缩log文件夹->log.tar
log_dir = os.path.join(BASE_DIR, "log")
if os.path.exists(log_dir):
log_tar_filepath = os.path.join(export_dir, "log")
shutil.make_archive(log_tar_filepath, 'tar', log_dir)
except Exception as e:
run_errors.append("export log error:%s" % str(e))
# 写入config.json, settings.json
if os.path.exists(g_filepath_config_json):
dst = os.path.join(export_dir, "config.json")
shutil.copyfile(g_filepath_config_json, dst)
if os.path.exists(g_filepath_settings_json):
dst = os.path.join(export_dir, "settings.json")
shutil.copyfile(g_filepath_settings_json, dst)
if os.path.exists(g_config.mediaStartConfigPath):
dst = os.path.join(export_dir, "config.ini")
shutil.copyfile(g_config.mediaStartConfigPath, dst)
allowed_hosts_src = os.path.join(BASE_DIR, ".allowed_hosts")
if os.path.exists(allowed_hosts_src):
allowed_hosts_dst = os.path.join(export_dir, ".allowed_hosts")
shutil.copyfile(allowed_hosts_src, allowed_hosts_dst)
# 写入env.txt
export_filepath_env = os.path.join(export_dir, "env.txt")
env_f = open(export_filepath_env, 'w', encoding="utf-8")
env_f.write("name=%s\n" % PROJECT_UA)
env_f.write("built=%s\n" % PROJECT_BUILT)
env_f.write("version=%s\n" % PROJECT_VERSION)
env_f.write("flag=%s\n" % PROJECT_FLAG)
env_f.write("log_filename=%s\n" % export_filename)
env_f.write("app_start_date=%s\n" % datetime.fromtimestamp(PROJECT_ADMIN_START_TIMESTAMP).strftime('%Y-%m-%d %H:%M'))
env_f.write("current_date=%s\n" % datetime.now().strftime('%Y-%m-%d %H:%M'))
env_f.write("system=%s\n" % osSystem.getSystemName())
env_f.write("machine=%s\n" % osSystem.getMachineNode())
env_f.write("uname_a=%s\n" % osSystem.getMachineUnameA())
env_f.write("zlm.threadsLoad=%s\n" % str(g_zlm.getThreadsLoad()))
env_f.write("cpu=%s\n" % osSystem.getMachineCpu())
env_f.write("nvidia=%s\n" % osSystem.getMachineNvidia())
env_f.write("ascend=%s\n" % osSystem.getMachineAscend())
env_f.write("rknpu=%s\n" % osSystem.getMachineRknpu())
env_f.write("os=%s\n" % str(osSystem.getOSInfo()))
env_f.write("os_release=%s\n" % osSystem.getMachineOsRelease())
env_f.write("lscpu=%s\n" % osSystem.getMachineLsCpu())
env_f.close()
# 写入online.txt
export_filepath_online = os.path.join(export_dir, "online.txt")
online_f = open(export_filepath_online, 'w', encoding="utf-8")
run_info = {}
for k, v in run_info.items():
online_f.write("%s=%s\n" % (str(k), str(v)))
online_f.write("av_log=%s\n" % str(g_database.select("select * from av_log order by id desc limit 100")))
online_f.write("run_errors=%s\n" % str(run_errors))
online_f.close()
# 压缩导出文件夹
shutil.make_archive(export_filepath.replace(".xclogs", ""), 'tar', export_dir)
# 重命名为 .xclogs
tar_filepath = export_filepath.replace(".xclogs", ".tar")
if os.path.exists(tar_filepath):
shutil.move(tar_filepath, export_filepath)
from app.views.StorageView import issue_download_file_id
info["download_file_id"] = issue_download_file_id(export_filename)
info["download_filename"] = export_filename
ret = True
msg = LANG_VIEWS_T(request, "syscfg_export_log_success")
except Exception as e:
msg = str(e)
else:
msg = __check_msg
else:
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
g_logger.info("export_dir=%s" % str(export_dir))
if export_dir:
try:
if os.path.exists(export_dir):
shutil.rmtree(export_dir)
except Exception as e:
g_logger.error("e=%s" % str(e))
res = {
"code": 1000 if ret else 0,
"msg": msg,
"info": info
}
g_logger.info("SystemView.openExportLogs() res:%s" % str(res))
return f_responseJson(res)