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:
2026-02-10 15:22:01 +08:00
parent 6cf1524013
commit 9f4cea0810
8 changed files with 207 additions and 307 deletions

View File

@@ -23,7 +23,6 @@ from app.schemas import (
from app.services.alert_service import alert_service, get_alert_service
from app.services.alarm_event_service import alarm_event_service, get_alarm_event_service
from app.services.ai_analyzer import trigger_async_analysis
from app.services.mqtt_service import get_mqtt_service
from app.services.notification_service import get_notification_service
from app.services.device_service import get_device_service
from app.utils.logger import logger
@@ -33,44 +32,10 @@ import json
# 全局服务实例
mqtt_service = get_mqtt_service()
notification_service = get_notification_service()
device_service = get_device_service()
def handle_mqtt_alert(payload: dict):
"""处理 MQTT 告警消息(双写:旧表 + 新表)"""
try:
# 1. 写旧表(保持兼容)
alert = alert_service.create_alert_from_mqtt(payload)
if alert:
logger.info(f"MQTT 告警写入旧表: {alert.alert_no}")
# 2. 写新表
alarm = alarm_event_service.create_from_mqtt(payload)
# 3. WebSocket 通知(优先使用新表数据)
if alarm:
notification_service.notify_sync("new_alert", alarm.to_dict())
logger.info(f"MQTT 告警已处理并推送: {alarm.alarm_id}")
elif alert:
notification_service.notify_sync("new_alert", alert.to_dict())
logger.info(f"MQTT 告警已处理并推送(旧表): {alert.alert_no}")
except Exception as e:
logger.error(f"处理 MQTT 告警失败: {e}")
def handle_mqtt_heartbeat(payload: dict):
"""处理 MQTT 心跳消息"""
try:
device = device_service.handle_heartbeat(payload)
if device:
# 通过 WebSocket 推送设备状态
notification_service.notify_sync("device_status", device.to_dict())
except Exception as e:
logger.error(f"处理 MQTT 心跳失败: {e}")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理"""
@@ -78,23 +43,15 @@ async def lifespan(app: FastAPI):
init_db()
logger.info("数据库初始化完成")
# 设置事件循环(用于从 MQTT 回调调用异步方法
# 设置事件循环(用于从同步代码调用异步方法,如 WebSocket 通知
loop = asyncio.get_event_loop()
notification_service.set_event_loop(loop)
# 注册 MQTT 处理器
mqtt_service.register_alert_handler(handle_mqtt_alert)
mqtt_service.register_heartbeat_handler(handle_mqtt_heartbeat)
# 启动 MQTT 服务
mqtt_service.start()
logger.info("AI 告警平台启动完成")
yield
# 关闭
mqtt_service.stop()
logger.info("AI 告警平台已关闭")
@@ -149,13 +106,9 @@ async def health_check():
except Exception as e:
db_status = f"unhealthy: {e}"
mqtt_stats = mqtt_service.get_statistics()
mqtt_status = "connected" if mqtt_stats["connected"] else "disconnected"
return HealthResponse(
status="healthy" if db_status == "healthy" and mqtt_stats["connected"] else "degraded",
status="healthy" if db_status == "healthy" else "degraded",
database=db_status,
mqtt=mqtt_status,
websocket_connections=notification_service.manager.connection_count,
)
@@ -333,14 +286,6 @@ async def get_device(
return DeviceResponse(**device.to_dict())
# ==================== MQTT 状态端点 ====================
@app.get("/api/v1/mqtt/statistics")
async def get_mqtt_statistics():
"""获取 MQTT 服务统计"""
return mqtt_service.get_statistics()
if __name__ == "__main__":
import uvicorn
uvicorn.run(