feat(aiot): 边缘告警HTTP上报 + 移除配置中转层
- 新增 edge/report 端点接收边缘端HTTP告警上报 - alarm_event_service 新增 create_from_edge_report 幂等创建 - schemas 新增 EdgeAlarmReport 模型 - 移除 config_service/redis_service/yudao_aiot_config 配置中转 - MQTT 服务标记废弃,告警上报改为HTTP+COS - config 新增 COS/Redis 配置项 - requirements 新增 redis 依赖 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -126,6 +126,97 @@ class AlarmEventService:
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def create_from_edge_report(self, data: Dict[str, Any]) -> Optional[AlarmEvent]:
|
||||
"""
|
||||
从边缘端 HTTP 上报创建告警事件
|
||||
|
||||
边缘端通过 POST /admin-api/aiot/alarm/edge/report 上报告警。
|
||||
使用边缘端生成的 alarm_id,支持幂等(重复 alarm_id 跳过)。
|
||||
|
||||
Args:
|
||||
data: 边缘端上报数据,字段与 alarm_event 表对齐
|
||||
|
||||
Returns:
|
||||
AlarmEvent 或 None
|
||||
"""
|
||||
db = get_session()
|
||||
try:
|
||||
alarm_id = data.get("alarm_id")
|
||||
if not alarm_id:
|
||||
logger.error("边缘上报缺少 alarm_id")
|
||||
return None
|
||||
|
||||
# 幂等校验:alarm_id 已存在则跳过
|
||||
existing = db.query(AlarmEvent).filter(AlarmEvent.alarm_id == alarm_id).first()
|
||||
if existing:
|
||||
logger.info(f"告警已存在,跳过: {alarm_id}")
|
||||
return existing
|
||||
|
||||
# 解析时间
|
||||
event_time_str = data.get("event_time")
|
||||
if event_time_str:
|
||||
try:
|
||||
event_time = datetime.fromisoformat(event_time_str.replace("Z", "+00:00"))
|
||||
except ValueError:
|
||||
event_time = datetime.now(timezone.utc)
|
||||
else:
|
||||
event_time = datetime.now(timezone.utc)
|
||||
|
||||
# 置信度
|
||||
confidence = data.get("confidence_score")
|
||||
if confidence is not None:
|
||||
confidence = float(confidence)
|
||||
if confidence > 1:
|
||||
confidence = confidence / 100.0
|
||||
|
||||
alarm_type = data.get("alarm_type", "unknown")
|
||||
alarm_level = data.get("alarm_level")
|
||||
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)
|
||||
|
||||
alarm = AlarmEvent(
|
||||
alarm_id=alarm_id,
|
||||
alarm_type=alarm_type,
|
||||
algorithm_code=data.get("algorithm_code"),
|
||||
device_id=data.get("device_id", "unknown"),
|
||||
scene_id=data.get("scene_id"),
|
||||
event_time=event_time,
|
||||
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,
|
||||
)
|
||||
|
||||
db.add(alarm)
|
||||
|
||||
# 写入扩展表
|
||||
ext_data = data.get("ext_data")
|
||||
if ext_data:
|
||||
ext = AlarmEventExt(
|
||||
alarm_id=alarm_id,
|
||||
ext_type="EDGE_HTTP",
|
||||
ext_data=ext_data,
|
||||
)
|
||||
db.add(ext)
|
||||
|
||||
db.commit()
|
||||
db.refresh(alarm)
|
||||
|
||||
logger.info(f"边缘端告警创建成功: {alarm_id}, type={alarm_type}, device={data.get('device_id')}")
|
||||
return alarm
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f"创建边缘端告警失败: {e}")
|
||||
return None
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def create_from_http(self, data: Dict[str, Any], snapshot_data: Optional[bytes] = None) -> Optional[AlarmEvent]:
|
||||
"""从 HTTP 请求创建告警事件"""
|
||||
db = get_session()
|
||||
|
||||
Reference in New Issue
Block a user