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:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -59,3 +59,10 @@ Thumbs.db
|
|||||||
# PyInstaller
|
# PyInstaller
|
||||||
*.manifest
|
*.manifest
|
||||||
*.spec
|
*.spec
|
||||||
|
|
||||||
|
# Diagnostic documents and scripts - DO NOT COMMIT
|
||||||
|
*诊断*.md
|
||||||
|
*分析*.md
|
||||||
|
*报告*.md
|
||||||
|
*修复*.py
|
||||||
|
*patch*.py
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from typing import Optional
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import httpx
|
import httpx
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import os
|
||||||
|
|
||||||
from app.yudao_compat import YudaoResponse, get_current_user
|
from app.yudao_compat import YudaoResponse, get_current_user
|
||||||
from app.services.alarm_event_service import get_alarm_event_service, AlarmEventService
|
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)
|
result = service.get_device_summary(page=pageNo, page_size=pageSize)
|
||||||
|
|
||||||
# 添加前端兼容字段别名
|
# 添加前端兼容字段别名,并查询摄像头名称
|
||||||
compat_list = []
|
compat_list = []
|
||||||
for item in result.get("list", []):
|
for item in result.get("list", []):
|
||||||
item["cameraId"] = item.get("deviceId")
|
device_id = item.get("deviceId")
|
||||||
item["cameraName"] = item.get("deviceName")
|
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["pendingCount"] = item.get("unhandledCount")
|
||||||
item["lastAlertTime"] = item.get("lastEventTime")
|
item["lastAlertTime"] = item.get("lastEventTime")
|
||||||
item["lastAlertType"] = item.get("lastAlarmType")
|
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"
|
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):
|
async def _notify_ops_platform(data: dict):
|
||||||
|
|||||||
Reference in New Issue
Block a user