feat(aiot): 告警结束接口 + 持续时长更新 + first_frame_time存储
新增告警结束接口: - 新增EdgeAlarmResolve请求模型 - 新增POST /edge/resolve端点(无需认证,Edge设备调用) - 新增resolve_alarm服务方法:更新duration_ms、last_frame_time - 人员回岗/非工作时间自动设置alarm_status=CLOSED、handle_status=DONE 告警创建修复: - create_from_edge_report现在从ext_data读取first_frame_time写入数据库 - create_from_edge_report现在从ext_data读取duration_ms写入数据库 - 统一edge_node_id从ext_data提取
This commit is contained in:
@@ -171,12 +171,21 @@ class AlarmEventService:
|
||||
|
||||
alarm_type = data.get("alarm_type", "unknown")
|
||||
alarm_level = data.get("alarm_level")
|
||||
ext_data = data.get("ext_data") or {}
|
||||
if alarm_level is None:
|
||||
# 从 ext_data 取 duration_ms
|
||||
ext_data = data.get("ext_data") or {}
|
||||
duration_ms = ext_data.get("duration_ms")
|
||||
alarm_level = _determine_alarm_level(alarm_type, confidence or 0, duration_ms)
|
||||
|
||||
# 解析 first_frame_time(离岗开始时间,由 Edge 在 ext_data 中传递)
|
||||
first_frame_time = None
|
||||
first_frame_time_str = ext_data.get("first_frame_time")
|
||||
if first_frame_time_str:
|
||||
try:
|
||||
first_frame_time = datetime.fromisoformat(first_frame_time_str.replace("Z", "+00:00"))
|
||||
except ValueError:
|
||||
first_frame_time = None
|
||||
|
||||
alarm = AlarmEvent(
|
||||
alarm_id=alarm_id,
|
||||
alarm_type=alarm_type,
|
||||
@@ -184,12 +193,14 @@ class AlarmEventService:
|
||||
device_id=data.get("device_id", "unknown"),
|
||||
scene_id=data.get("scene_id"),
|
||||
event_time=event_time,
|
||||
first_frame_time=first_frame_time,
|
||||
duration_ms=ext_data.get("duration_ms"),
|
||||
alarm_level=alarm_level,
|
||||
confidence_score=confidence,
|
||||
alarm_status="NEW",
|
||||
handle_status="UNHANDLED",
|
||||
snapshot_url=data.get("snapshot_url"), # COS object_key
|
||||
edge_node_id=data.get("ext_data", {}).get("edge_node_id") if data.get("ext_data") else None,
|
||||
snapshot_url=data.get("snapshot_url"),
|
||||
edge_node_id=ext_data.get("edge_node_id"),
|
||||
)
|
||||
|
||||
db.add(alarm)
|
||||
@@ -520,6 +531,46 @@ class AlarmEventService:
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def resolve_alarm(self, alarm_id: str, duration_ms: int, last_frame_time: str, resolve_type: str) -> bool:
|
||||
"""更新告警的持续时长和结束时间"""
|
||||
db = get_session()
|
||||
try:
|
||||
alarm = db.query(AlarmEvent).filter(AlarmEvent.alarm_id == alarm_id).first()
|
||||
if not alarm:
|
||||
return False
|
||||
|
||||
alarm.duration_ms = duration_ms
|
||||
|
||||
# 解析 last_frame_time
|
||||
try:
|
||||
alarm.last_frame_time = datetime.fromisoformat(last_frame_time.replace("Z", "+00:00"))
|
||||
except Exception:
|
||||
alarm.last_frame_time = datetime.now(timezone.utc)
|
||||
|
||||
# 如果是人员回岗,标记为自动关闭
|
||||
if resolve_type == "person_returned":
|
||||
alarm.alarm_status = "CLOSED"
|
||||
alarm.handle_status = "DONE"
|
||||
alarm.handle_remark = "人员回岗自动关闭"
|
||||
alarm.handled_at = datetime.now(timezone.utc)
|
||||
elif resolve_type == "non_work_time":
|
||||
alarm.alarm_status = "CLOSED"
|
||||
alarm.handle_status = "DONE"
|
||||
alarm.handle_remark = "非工作时间自动关闭"
|
||||
alarm.handled_at = datetime.now(timezone.utc)
|
||||
|
||||
alarm.updated_at = datetime.now(timezone.utc)
|
||||
db.commit()
|
||||
|
||||
logger.info(f"告警已更新结束信息: {alarm_id}, duration={duration_ms}ms, type={resolve_type}")
|
||||
return True
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f"更新告警结束信息失败: {e}")
|
||||
return False
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def save_llm_analysis(
|
||||
self,
|
||||
alarm_id: str,
|
||||
|
||||
Reference in New Issue
Block a user