feat(aiot): 告警冷却时间调整 + 截图本地保留 + 中文路径修复
- 离岗检测冷却时间: 300s → 600s(10分钟) - 入侵检测冷却时间: 120s → 300s(5分钟) - 入侵告警级别改为高(alarm_level=3) - COS 不可用时保留本地截图文件,不再上报后删除 - 修复 cv2.imwrite 中文路径失败,改用 imencode + write_bytes - 配置订阅在 LOCAL 模式下跳过 Redis 连接 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
122
main.py
122
main.py
@@ -14,6 +14,7 @@ from typing import Dict, Any, Optional, List, Tuple
|
||||
|
||||
from config.settings import get_settings, Settings
|
||||
from core.config_sync import get_config_sync_manager, ConfigSyncManager
|
||||
from core.debug_http_server import start_debug_http_server
|
||||
from core.video_stream import MultiStreamManager, VideoFrame
|
||||
from core.preprocessor import ImagePreprocessor
|
||||
from core.tensorrt_engine import TensorRTEngine, EngineManager
|
||||
@@ -48,6 +49,9 @@ class EdgeInferenceService:
|
||||
self._reporter: Optional[ResultReporter] = None
|
||||
self._alarm_worker: Optional[AlarmUploadWorker] = None
|
||||
self._algorithm_manager: Optional[AlgorithmManager] = None
|
||||
self._debug_reload_thread: Optional[threading.Thread] = None
|
||||
self._debug_http_server = None
|
||||
self._debug_http_thread: Optional[threading.Thread] = None
|
||||
|
||||
self._processing_threads: Dict[str, threading.Thread] = {}
|
||||
self._stop_event = threading.Event()
|
||||
@@ -90,6 +94,13 @@ class EdgeInferenceService:
|
||||
try:
|
||||
self._config_manager = get_config_sync_manager()
|
||||
self._config_manager.start_config_subscription()
|
||||
if self._settings.config_sync_mode == "LOCAL" and self._config_manager:
|
||||
def _on_config_update(topic, data):
|
||||
if self._algorithm_manager:
|
||||
self._algorithm_manager.reload_all_algorithms()
|
||||
# 配置更新后动态加载新摄像头流
|
||||
self._reload_cameras()
|
||||
self._config_manager.register_callback("config_update", _on_config_update)
|
||||
self._logger.info("配置管理器初始化成功")
|
||||
except Exception as e:
|
||||
self._logger.error(f"配置管理器初始化失败: {e}")
|
||||
@@ -127,6 +138,9 @@ class EdgeInferenceService:
|
||||
self._logger.info("后处理器初始化成功")
|
||||
|
||||
def _init_reporter(self):
|
||||
if self._settings.config_sync_mode == "LOCAL" and not self._settings.alarm_upload_enabled:
|
||||
self._logger.info("LOCAL 模式且 ALARM_UPLOAD_ENABLED=0:跳过告警上报组件初始化")
|
||||
return
|
||||
"""初始化结果上报器"""
|
||||
try:
|
||||
self._reporter = ResultReporter()
|
||||
@@ -157,6 +171,70 @@ class EdgeInferenceService:
|
||||
except Exception as e:
|
||||
self._logger.error(f"算法管理器初始化失败: {e}")
|
||||
|
||||
def _start_debug_reload_watcher(self):
|
||||
"""本地调试:监听文件触发同步"""
|
||||
if self._settings.config_sync_mode != "LOCAL":
|
||||
return
|
||||
if not getattr(self._settings, "debug", None) or not self._settings.debug.enabled:
|
||||
return
|
||||
if not self._config_manager:
|
||||
return
|
||||
|
||||
signal_file = self._settings.debug.reload_signal_file
|
||||
|
||||
def worker():
|
||||
last_mtime = None
|
||||
self._logger.info(f"[DEBUG] 本地同步模式已启用,监听: {signal_file}")
|
||||
while not self._stop_event.is_set():
|
||||
try:
|
||||
if os.path.exists(signal_file):
|
||||
mtime = os.path.getmtime(signal_file)
|
||||
if last_mtime is None:
|
||||
last_mtime = mtime
|
||||
elif mtime != last_mtime:
|
||||
last_mtime = mtime
|
||||
ok = self._config_manager.reload_local_config_from_file()
|
||||
if self._algorithm_manager:
|
||||
self._algorithm_manager.reload_all_algorithms()
|
||||
self._logger.info(f"[DEBUG] 本地配置已重新加载: {ok}")
|
||||
time.sleep(1.0)
|
||||
except Exception as e:
|
||||
self._logger.warning(f"[DEBUG] 监听本地配置失败: {e}")
|
||||
time.sleep(1.0)
|
||||
|
||||
self._debug_reload_thread = threading.Thread(
|
||||
target=worker,
|
||||
name="LocalConfigReloadWatcher",
|
||||
daemon=True,
|
||||
)
|
||||
self._debug_reload_thread.start()
|
||||
|
||||
def _start_debug_http_server(self):
|
||||
"""本地调试:启动 HTTP 同步接口"""
|
||||
if self._settings.config_sync_mode != "LOCAL":
|
||||
return
|
||||
if not getattr(self._settings, "debug", None) or not self._settings.debug.enabled:
|
||||
return
|
||||
if self._debug_http_server is not None:
|
||||
return
|
||||
|
||||
host = self._settings.debug.host
|
||||
port = self._settings.debug.port
|
||||
self._debug_http_server = start_debug_http_server(host, port)
|
||||
|
||||
def worker():
|
||||
try:
|
||||
self._debug_http_server.serve_forever()
|
||||
except Exception as e:
|
||||
self._logger.warning(f"[DEBUG] HTTP 服务器异常: {e}")
|
||||
|
||||
self._debug_http_thread = threading.Thread(
|
||||
target=worker,
|
||||
name="DebugHttpServer",
|
||||
daemon=True,
|
||||
)
|
||||
self._debug_http_thread.start()
|
||||
|
||||
def initialize(self):
|
||||
"""初始化所有组件"""
|
||||
self._logger.info("=" * 50)
|
||||
@@ -171,6 +249,8 @@ class EdgeInferenceService:
|
||||
self._init_postprocessor()
|
||||
self._init_reporter()
|
||||
self._init_algorithm_manager()
|
||||
self._start_debug_reload_watcher()
|
||||
self._start_debug_http_server()
|
||||
|
||||
self._performance_stats["start_time"] = datetime.now()
|
||||
|
||||
@@ -187,7 +267,7 @@ class EdgeInferenceService:
|
||||
def _load_cameras(self):
|
||||
"""加载摄像头配置"""
|
||||
cameras = self._config_manager.get_cameras()
|
||||
|
||||
|
||||
for camera in cameras:
|
||||
try:
|
||||
self._stream_manager.add_stream(
|
||||
@@ -199,6 +279,37 @@ class EdgeInferenceService:
|
||||
self._logger.info(f"已添加摄像头: {camera.camera_id}")
|
||||
except Exception as e:
|
||||
self._logger.error(f"添加摄像头失败 {camera.camera_id}: {e}")
|
||||
|
||||
def _reload_cameras(self):
|
||||
"""配置更新后动态加载新摄像头(不重复添加已有的)"""
|
||||
if not self._stream_manager or not self._config_manager:
|
||||
return
|
||||
try:
|
||||
cameras = self._config_manager.get_cameras(force_refresh=True)
|
||||
existing = set(self._stream_manager._streams.keys())
|
||||
added = 0
|
||||
for camera in cameras:
|
||||
if camera.camera_id in existing:
|
||||
continue
|
||||
if not camera.rtsp_url:
|
||||
self._logger.warning(f"摄像头 {camera.camera_id} 无 rtsp_url,跳过")
|
||||
continue
|
||||
try:
|
||||
self._stream_manager.add_stream(
|
||||
camera_id=camera.camera_id,
|
||||
rtsp_url=camera.rtsp_url,
|
||||
target_fps=self._settings.video_stream.default_fps,
|
||||
on_frame_callback=self._create_frame_callback(camera.camera_id)
|
||||
)
|
||||
self._stream_manager._streams[camera.camera_id].start()
|
||||
added += 1
|
||||
self._logger.info(f"动态添加并启动摄像头: {camera.camera_id}")
|
||||
except Exception as e:
|
||||
self._logger.error(f"动态添加摄像头失败 {camera.camera_id}: {e}")
|
||||
if added > 0:
|
||||
self._logger.info(f"配置更新后新增 {added} 个摄像头流")
|
||||
except Exception as e:
|
||||
self._logger.error(f"动态加载摄像头失败: {e}")
|
||||
|
||||
def _create_frame_callback(self, camera_id: str):
|
||||
"""创建帧处理回调"""
|
||||
@@ -358,6 +469,9 @@ class EdgeInferenceService:
|
||||
self._logger.warning("算法管理器不可用,跳过算法处理")
|
||||
return
|
||||
|
||||
if self._reporter is None:
|
||||
self._logger.debug("ResultReporter 未启用,跳过告警上报")
|
||||
return
|
||||
roi_id = roi.roi_id
|
||||
algo_code = bind.algo_code
|
||||
algo_params = bind.params or {}
|
||||
@@ -542,6 +656,12 @@ class EdgeInferenceService:
|
||||
|
||||
if self._reporter:
|
||||
self._reporter.close()
|
||||
|
||||
if self._debug_http_server:
|
||||
try:
|
||||
self._debug_http_server.shutdown()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self._performance_stats["uptime_seconds"] = (
|
||||
(datetime.now() - self._performance_stats["start_time"]).total_seconds()
|
||||
|
||||
Reference in New Issue
Block a user