fix(aiot): 修复告警汇总应用名更新不同步问题

问题:应用名修改后,告警列表显示正确,但告警汇总仍显示旧名称
原因:device_id字段混用app/stream和camera_code格式,汇总直接显示device_id
影响:用户无法看到摄像头当前的实际应用名

修复内容:
- 告警汇总API实时查询WVP获取当前摄像头信息
- 支持camera_code格式查询(通过cameraCode参数)
- 支持app/stream格式查询(通过列表筛选)
- 查询失败时回退显示device_id

修复效果:
 应用名修改后告警汇总立即同步
 兼容两种device_id格式
 降级策略保证稳定性
This commit is contained in:
2026-02-13 15:25:10 +08:00
parent 683791d1c9
commit 8838905305
2 changed files with 80 additions and 3 deletions

7
.gitignore vendored
View File

@@ -59,3 +59,10 @@ Thumbs.db
# PyInstaller
*.manifest
*.spec
# Diagnostic documents and scripts - DO NOT COMMIT
*诊断*.md
*分析*.md
*报告*.md
*修复*.py
*patch*.py

View File

@@ -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):