feat(aiot): 离岗检测重写 - 单次告警 + 回岗确认 + 持续时长追踪
算法逻辑修改: - OFF_DUTY状态只告警一次,不再每600秒重复告警 - 人员回岗后需经CONFIRMING(10秒)重新确认才恢复ON_DUTY - 确认在岗后清除冷却记录,允许新一轮离岗检测 - 非工作时间进入时清除冷却记录 持续时长追踪(新增resolve机制): - 离岗告警记录alarm_id和leave_start_time - 人员回岗确认后生成resolve事件(duration_ms + last_frame_time) - 进入非工作时间时也生成resolve事件 - ResultReporter新增report_alarm_resolve()写入Redis队列 - AlarmUploadWorker新增_process_resolve() HTTP POST到云端 - main.py区分普通告警和resolve事件,回填alarm_id到算法实例 - 告警ext_data附加first_frame_time(离岗开始时间)
This commit is contained in:
31
main.py
31
main.py
@@ -514,6 +514,23 @@ class EdgeInferenceService:
|
||||
for alert in alerts:
|
||||
alert_type = alert.get("alert_type", "detection")
|
||||
|
||||
# resolve 事件:更新已有告警,不创建新告警
|
||||
if alert_type == "alarm_resolve":
|
||||
resolve_data = {
|
||||
"alarm_id": alert.get("resolve_alarm_id"),
|
||||
"duration_ms": alert.get("duration_ms"),
|
||||
"last_frame_time": alert.get("last_frame_time"),
|
||||
"resolve_type": alert.get("resolve_type"),
|
||||
}
|
||||
if self._reporter:
|
||||
self._reporter.report_alarm_resolve(resolve_data)
|
||||
self._logger.info(
|
||||
f"离岗告警结束: alarm_id={resolve_data['alarm_id']}, "
|
||||
f"duration_ms={resolve_data['duration_ms']}, "
|
||||
f"reason={resolve_data['resolve_type']}"
|
||||
)
|
||||
continue
|
||||
|
||||
# 摄像头级别去重:同一摄像头+告警类型在冷却期内只上报一次
|
||||
dedup_key = f"{camera_id}_{alert_type}"
|
||||
now = frame.timestamp
|
||||
@@ -530,6 +547,13 @@ class EdgeInferenceService:
|
||||
self._camera_alert_cooldown[dedup_key] = now
|
||||
self._performance_stats["total_alerts_generated"] += 1
|
||||
|
||||
# 获取算法的离岗开始时间
|
||||
leave_start_time = None
|
||||
if alert_type == "leave_post":
|
||||
algo = self._algorithm_manager.algorithms.get(roi_id, {}).get(f"{roi_id}_{bind.bind_id}", {}).get("leave_post")
|
||||
if algo and hasattr(algo, '_leave_start_time') and algo._leave_start_time:
|
||||
leave_start_time = algo._leave_start_time.isoformat()
|
||||
|
||||
from core.result_reporter import AlarmInfo, generate_alarm_id
|
||||
alarm_info = AlarmInfo(
|
||||
alarm_id=generate_alarm_id(self._settings.mqtt.device_id),
|
||||
@@ -548,10 +572,17 @@ class EdgeInferenceService:
|
||||
"bind_id": bind.bind_id,
|
||||
"message": alert.get("message", ""),
|
||||
"edge_node_id": self._settings.mqtt.device_id,
|
||||
"first_frame_time": leave_start_time,
|
||||
},
|
||||
)
|
||||
self._reporter.report_alarm(alarm_info, screenshot=frame.image)
|
||||
|
||||
# 回填 alarm_id 到算法实例(用于后续 resolve 追踪)
|
||||
if alert_type == "leave_post":
|
||||
algo = self._algorithm_manager.algorithms.get(roi_id, {}).get(f"{roi_id}_{bind.bind_id}", {}).get("leave_post")
|
||||
if algo and hasattr(algo, 'set_last_alarm_id'):
|
||||
algo.set_last_alarm_id(alarm_info.alarm_id)
|
||||
|
||||
self._logger.info(
|
||||
f"告警已生成: type={alert_type}, "
|
||||
f"camera={camera_id}, roi={roi_id}, "
|
||||
|
||||
Reference in New Issue
Block a user