From 8838905305d55cca49974bdcb2cd230585005aaa Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Fri, 13 Feb 2026 15:25:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(aiot):=20=E4=BF=AE=E5=A4=8D=E5=91=8A?= =?UTF-8?q?=E8=AD=A6=E6=B1=87=E6=80=BB=E5=BA=94=E7=94=A8=E5=90=8D=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=B8=8D=E5=90=8C=E6=AD=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:应用名修改后,告警列表显示正确,但告警汇总仍显示旧名称 原因:device_id字段混用app/stream和camera_code格式,汇总直接显示device_id 影响:用户无法看到摄像头当前的实际应用名 修复内容: - 告警汇总API实时查询WVP获取当前摄像头信息 - 支持camera_code格式查询(通过cameraCode参数) - 支持app/stream格式查询(通过列表筛选) - 查询失败时回退显示device_id 修复效果: ✅ 应用名修改后告警汇总立即同步 ✅ 兼容两种device_id格式 ✅ 降级策略保证稳定性 --- .gitignore | 7 +++ app/routers/yudao_aiot_alarm.py | 76 +++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 9e959cd..64b3966 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,10 @@ Thumbs.db # PyInstaller *.manifest *.spec + +# Diagnostic documents and scripts - DO NOT COMMIT +*诊断*.md +*分析*.md +*报告*.md +*修复*.py +*patch*.py diff --git a/app/routers/yudao_aiot_alarm.py b/app/routers/yudao_aiot_alarm.py index f8a46b9..bc344df 100644 --- a/app/routers/yudao_aiot_alarm.py +++ b/app/routers/yudao_aiot_alarm.py @@ -17,6 +17,7 @@ from typing import Optional from datetime import datetime import httpx import asyncio +import os from app.yudao_compat import YudaoResponse, get_current_user from app.services.alarm_event_service import get_alarm_event_service, AlarmEventService @@ -243,11 +244,23 @@ async def get_device_summary_page( """获取设备告警汇总(分页)""" result = service.get_device_summary(page=pageNo, page_size=pageSize) - # 添加前端兼容字段别名 + # 添加前端兼容字段别名,并查询摄像头名称 compat_list = [] for item in result.get("list", []): - item["cameraId"] = item.get("deviceId") - item["cameraName"] = item.get("deviceName") + device_id = item.get("deviceId") + device_name = device_id # 默认使用 device_id + + # 尝试从 WVP 查询摄像头名称 + try: + camera_info = await _get_camera_info(device_id, current_user) + if camera_info: + device_name = camera_info.get("app") or camera_info.get("name") or device_id + except Exception as e: + logger.warning(f"查询摄像头信息失败: device_id={device_id}, error={e}") + + item["cameraId"] = device_id + item["cameraName"] = device_name + item["deviceName"] = device_name # 更新 deviceName 为实际名称 item["pendingCount"] = item.get("unhandledCount") item["lastAlertTime"] = item.get("lastEventTime") item["lastAlertType"] = item.get("lastAlarmType") @@ -329,6 +342,63 @@ async def edge_alarm_resolve( # ==================== 辅助函数 ==================== OPS_ALARM_URL = "http://192.168.0.104:48080/admin-api/ops/alarm/receive" +WVP_API_BASE = os.getenv("WVP_API_BASE", "http://localhost:18080") + + +async def _get_camera_info(device_id: str, current_user: dict) -> Optional[dict]: + """ + 从 WVP 查询摄像头信息 + 支持 camera_code 和 app/stream 两种格式 + """ + # 获取 token + token = current_user.get("access_token") or current_user.get("token") + if not token: + return None + + headers = {"Authorization": f"Bearer {token}"} + + # 如果是 camera_code 格式(cam_xxxxxxxxxxxx) + if device_id.startswith("cam_"): + try: + async with httpx.AsyncClient(timeout=5) as client: + # 调用 WVP 查询单个摄像头的 API + resp = await client.get( + f"{WVP_API_BASE}/admin-api/aiot/device/camera/get", + params={"cameraCode": device_id}, + headers=headers + ) + if resp.status_code == 200: + data = resp.json() + if data.get("code") == 0: + return data.get("data") + except Exception as e: + logger.warning(f"查询 camera_code 失败: {device_id}, error={e}") + + # 如果是 app/stream 格式 + elif "/" in device_id: + parts = device_id.split("/", 1) + if len(parts) == 2: + app, stream = parts + try: + async with httpx.AsyncClient(timeout=5) as client: + # 查询摄像头列表,筛选 app 和 stream + resp = await client.get( + f"{WVP_API_BASE}/admin-api/aiot/device/camera/list", + params={"page": 1, "count": 1, "query": stream}, + headers=headers + ) + if resp.status_code == 200: + data = resp.json() + if data.get("code") == 0: + camera_list = data.get("data", {}).get("list", []) + # 找到匹配的摄像头 + for camera in camera_list: + if camera.get("app") == app and camera.get("stream") == stream: + return camera + except Exception as e: + logger.warning(f"查询 app/stream 失败: {device_id}, error={e}") + + return None async def _notify_ops_platform(data: dict):