From cf41db2983bd600a0f2599967ddd60a29a485c93 Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Wed, 11 Feb 2026 14:00:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(aiot):=20=E5=91=8A=E8=AD=A6=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=97=B6=E5=BC=82=E6=AD=A5=E4=B8=8A=E6=8A=A5=E8=BF=90?= =?UTF-8?q?=E7=BB=B4=E5=B9=B3=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 边缘告警入库后异步 POST 到运维平台 /admin-api/ops/alarm/receive - 提前提取 ORM 字段避免异步执行时 session 关闭导致属性为空 - event_time 转为 ISO 字符串格式,修复时间显示为 1970 的问题 - 请求参数含 alarmId、alarmType、deviceId、eventTime、alarmLevel、notifyUserIds、tenantId Co-Authored-By: Claude Opus 4.6 --- app/routers/yudao_aiot_alarm.py | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/app/routers/yudao_aiot_alarm.py b/app/routers/yudao_aiot_alarm.py index e73ed55..eb1d60b 100644 --- a/app/routers/yudao_aiot_alarm.py +++ b/app/routers/yudao_aiot_alarm.py @@ -15,12 +15,15 @@ API 路径规范: from fastapi import APIRouter, Query, Depends, HTTPException from typing import Optional from datetime import datetime +import httpx +import asyncio from app.yudao_compat import YudaoResponse, get_current_user from app.services.alarm_event_service import get_alarm_event_service, AlarmEventService from app.services.notification_service import get_notification_service from app.services.oss_storage import get_oss_storage from app.schemas import EdgeAlarmReport +from app.utils.logger import logger router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"]) @@ -285,6 +288,16 @@ async def edge_alarm_report( except Exception: pass # WebSocket 通知失败不影响主流程 + # 异步上报运维平台(提前提取字段,避免 ORM session 关闭后无法访问) + ops_data = { + "alarm_id": alarm.alarm_id, + "alarm_type": alarm.alarm_type, + "device_id": alarm.device_id, + "event_time": alarm.event_time.strftime("%Y-%m-%dT%H:%M:%S") if isinstance(alarm.event_time, datetime) else str(alarm.event_time or ""), + "alarm_level": alarm.alarm_level or 2, + } + asyncio.create_task(_notify_ops_platform(ops_data)) + return YudaoResponse.success({ "alarmId": alarm.alarm_id, "created": True, @@ -293,6 +306,31 @@ async def edge_alarm_report( # ==================== 辅助函数 ==================== +OPS_ALARM_URL = "http://192.168.0.104:48080/admin-api/ops/alarm/receive" + + +async def _notify_ops_platform(data: dict): + """异步上报告警到运维平台(失败不影响主流程)""" + payload = { + "alarmId": data["alarm_id"], + "alarmType": data["alarm_type"], + "deviceId": data["device_id"], + "eventTime": data["event_time"], + "alarmLevel": data["alarm_level"], + "notifyUserIds": [1], + "tenantId": 1, + } + try: + async with httpx.AsyncClient(timeout=10) as client: + resp = await client.post(OPS_ALARM_URL, json=payload) + if resp.status_code == 200: + logger.info(f"运维平台上报成功: {data['alarm_id']}, resp={resp.text[:200]}") + else: + logger.warning(f"运维平台上报失败: status={resp.status_code}, body={resp.text[:200]}") + except Exception as e: + logger.warning(f"运维平台上报异常: {e}") + + def _get_alarm_type_name(alarm_type: Optional[str]) -> str: """获取告警类型名称""" type_names = {