文档:全面重写 README.md,反映当前项目架构

- 更新架构图:HTTP 上报替代 MQTT,新增 VLM/企微/工单/日报模块
- 补充完整 API 接口清单(边缘上报、告警管理、企微、工单等)
- 详述告警三表数据模型 + 工单/通知配置表
- 完善项目结构树(17 个 service + 11 个 router)
- 列出全部环境变量分组说明
- 描述告警处理全链路和企微交互流程
- 添加系统集成关系矩阵
This commit is contained in:
2026-03-25 09:12:04 +08:00
parent 2a36bd4ffc
commit b13d86f0a6

525
README.md
View File

@@ -1,61 +1,73 @@
# AI 告警平台后端服务
# AI 告警平台后端服务vsp-service
基于 FastAPI 的 AI 告警接收与管理平台,支持 MQTT 告警订阅、WebSocket 实时推送、设备心跳监控
基于 FastAPI 的 AI 安防告警平台后端。接收边缘 AI 设备 HTTP 上报的告警事件,通过 VLM 视觉模型复核,推送企微通知,管理安保工单,WebSocket 实时推送到前端
## 功能特性
- **MQTT 告警订阅**:自动订阅边缘设备告警消息(`edge/alert/#`
- **WebSocket 实时推送**:告警实时推送到前端
- **设备心跳监控**:监控边缘设备在线状态
- **REST API**:告警查询、处理、统计等完整接口
- **告警去重**:基于时间窗口的告警去重机制
- **边缘告警接收**HTTP 接口接收边缘端 AI 推理结果,幂等去重,自动分级
- **VLM 智能复核**Dashscope Qwen3-VL 对告警截图二次分析,识别误报,评估风险
- **企微通知推送**:企微应用消息卡片 + 群聊告警,支持 H5 详情页状态流转
- **每日告警日报**:定时生成前日告警汇总(类型分布、设备 Top5、环比变化推送到企微群聊
- **安保工单对接**:告警自动/手动创建工单,对接 AIoT 运维平台(开放接口)
- **交互式 Agent**:基于 Function Calling 的多轮对话,自然语言查询告警、创建工单
- **WebSocket 实时推送**:告警事件实时推送到前端
- **截图云存储**:腾讯云 COS 存储告警截图CVM 角色认证免密钥
- **芋道平台兼容**:双 API 层(原生 + 芋道格式),无缝对接 Vue 3 前端
## 系统架构
```
┌─────────────────────────────────────────────────────────────┐
AI 告警平台架构
├─────────────────────────────────────────────────────────────┤
┌──────────────┐ MQTT ┌──────────────────────┐ │
ai_edge │──────────────→│ EMQX Broker │ │
│ │ 边缘推理 │ edge/alert/# │ │ │
└──────────────┘ └──────────┬───────────┘
MQTT Subscribe
│ ┌──────────────────────────────────────────────────────┐
│ │ 本服务 (FastAPI)
───────────── ┌─────────────┐ ┌─────────────┐
│ MqttService │ │AlertService │ │DeviceService│ │
│ 消息订阅 │→告警处理 │ │ 心跳监控
│ └─────────────┘ └──────┬──────┘ └─────────────┘
▼ │
│ │ ┌─────────────┐ ┌─────────────┐
│ WebSocket │← │ Database │
实时推送 SQLite │
└──────┬──────┘ └─────────────┘ │
│ └─────────│────────────────────────────────────────────┘ │
│ │
│ ┌──────────────
│ │ 前端/AIOT │
│ │ 主平台 │
│ └──────────────┘
└─────────────────────────────────────────────────────────────┘
──────────────────────────────────────────┐
aiot-web-antd (9090)
│ Vue 3 前端 │
└────────────┬──────────────┬──────────────┘
│ REST API │ WebSocket
▼ ▼
┌──────────────┐ HTTP POST ┌─────────────────────────────────────────────────┐
ai-edge │─────────────→│ vsp-service (8000)
边缘 AI │ 告警上报 │
推理服务 │ ┌──────────────┐ ┌──────────────┐
└──────────────┘ │AlarmEventSvc │ │NotificationSvc│
│ │ 告警 CRUD │ │ WebSocket推送 │
┌──────────────────────│──│ 分级/去重 └──────────────┘
│ 截图上传 ─────────────
▼ │ │ 异步触发
┌──────────────┐ ├──→ VLMService (Qwen3-VL 复核)
腾讯云 COS │ │ ├──→ WeChatService (企微通知)
对象存储 ├──→ WorkOrderClient (工单创建)
└──────────────┘ └──→ DailyReportService (日报推送)
┌──────────────────────│ ┌──────────────┐ ┌──────────────┐
│ │AgentDispatcher│ │CameraNameSvc│
▼ │ │ 多轮对话 │ │ WVP名称解析 │
┌──────────────┐ │ │ Function Call │ └──────────────┘
腾讯云 MySQL └──────────────┘
数据库 │←─────────────│
────────────── └─────────────────────────────────────────────────┘
HTTP (开放接口)
┌──────────────────────┐
│ AIoT 运维平台 (48080) │
│ 安保工单系统 │
└──────────────────────┘
```
## 技术栈
| 组件 | 技术 |
|------|------|
| Web 框架 | FastAPI + Uvicorn |
| 消息队列 | MQTT (paho-mqtt) |
| Web 框架 | FastAPI 0.109 + Uvicorn |
| 数据库 | MySQL 8生产/ SQLite开发|
| ORM | SQLAlchemy 2.0 |
| 实时推送 | WebSocket |
| 数据库 | SQLite / MySQL |
| ORM | SQLAlchemy |
| 配置管理 | Pydantic Settings + YAML |
| 云存储 | 腾讯云 COScos-python-sdk-v5|
| AI 复核 | Dashscope Qwen3-VLOpenAI 兼容接口)|
| 企微集成 | 企业微信应用消息 + 群聊 + 回调 |
| Agent | Qwen3.5-Plus Function Calling |
| 加密 | pycryptodome企微消息加解密|
| HTTP 客户端 | httpx异步|
| 配置管理 | dataclass + dotenv 环境变量 |
## 快速开始
@@ -65,146 +77,383 @@
pip install -r requirements.txt
```
### 2. 配置服务
### 2. 配置环境变量
编辑 `config/config.yaml`
```yaml
app:
name: "AI Alert Platform"
debug: true
host: "0.0.0.0"
port: 8000
database:
url: "sqlite:///./data/alerts.db"
mqtt:
enabled: true
host: "127.0.0.1"
port: 1883
username: ""
password: ""
topic_alert: "edge/alert/#"
topic_heartbeat: "edge/alert/heartbeat/#"
```bash
cp .env.example .env
# 编辑 .env至少配置
# DATABASE_URL — 数据库连接
# COS_ENABLED + COS_BUCKET + COS_REGION — 截图存储
```
### 3. 启动服务
```bash
# 开发模式(自动重载)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# 开发模式(自动重载DEV_MODE=true 跳过认证
python -m app.main
# 生产模式
python -m app.main
uvicorn app.main:app --host 0.0.0.0 --port 8000
```
### 4. 访问 API 文档
### 4. 访问
启动后访问http://localhost:8000/docs
- API 文档http://localhost:8000/docs
- 健康检查http://localhost:8000/health
## Docker 部署
```bash
docker build -t vsp-service:latest .
docker run -d \
--name vsp-service \
-p 8000:8000 \
-e DATABASE_URL=mysql+pymysql://user:pass@host/dbname \
-e COS_ENABLED=true \
-e COS_BUCKET=your-bucket \
-e COS_REGION=ap-beijing \
-e WECHAT_ENABLED=true \
-e WECHAT_CORP_ID=your_corp_id \
-e WECHAT_AGENT_ID=your_agent_id \
-e WECHAT_SECRET=your_secret \
vsp-service:latest
```
## 项目结构
```
service/
iot-device-management-service/
├── app/
│ ├── main.py # FastAPI 入口 + 路由
│ ├── config.py # 配置管理YAML + 环境变量
│ ├── models.py # SQLAlchemy 数据模型
│ ├── schemas.py # Pydantic 请求/响应模型
── services/
├── mqtt_service.py # MQTT 订阅服务
├── alert_service.py # 告警业务逻辑
── storage.py # 存储服务
├── config/
└── config.yaml # 配置文件
├── data/ # SQLite 数据库
├── logs/ # 日志文件
├── docs/ # 文档
├── requirements.txt
│ ├── main.py # FastAPI 入口 + lifespan + 路由注册
│ ├── config.py # 13 个配置段dataclass + dotenv
│ ├── models.py # SQLAlchemy ORM9 张表)
│ ├── schemas.py # Pydantic 请求/响应模型
── yudao_compat.py # 芋道平台兼容层(响应格式 + 认证)
├── routers/ # 路由模块
── edge_compat.py # 边缘端上报(/api/ai/alert/edge/*,无认证)
│ │ ├── yudao_aiot_alarm.py # 告警管理(/admin-api/aiot/alarm/*
│ ├── yudao_aiot_edge.py # 设备管理(/admin-api/aiot/edge/*
│ │ ├── yudao_aiot_storage.py # 存储代理(截图下载)
├── yudao_auth.py # 认证(登录 + 权限)
├── yudao_alert.py # 旧版告警路由(兼容保留)
│ │ ├── wechat_callback.py # 企微回调(消息加解密 + 分发)
│ │ ├── wechat_notify_api.py # 企微通知 API
│ │ ├── notify_manage.py # 通知区域管理
│ │ └── work_order_api.py # 工单 CRUD
│ │
│ ├── services/ # 业务服务(全局单例模式)
│ │ ├── alarm_event_service.py # 核心:告警三表 CRUD + 分级 + 去重
│ │ ├── alert_service.py # 旧版告警服务(兼容保留)
│ │ ├── notification_service.py # WebSocket 连接管理 + 广播
│ │ ├── vlm_service.py # VLM 视觉复核Qwen3-VL
│ │ ├── wechat_service.py # 企微消息发送(私聊卡片 + 群聊)
│ │ ├── wechat_crypto.py # 企微消息加解密AES-128-CBC
│ │ ├── notify_dispatch.py # 告警通知调度VLM → 企微 → 工单)
│ │ ├── agent_dispatcher.py # 交互 AgentFunction Calling 多轮)
│ │ ├── work_order_service.py # 工单业务逻辑
│ │ ├── work_order_client.py # AIoT 工单开放接口客户端
│ │ ├── camera_name_service.py # 摄像头名称解析WVP API + 缓存)
│ │ ├── daily_report_service.py # 每日告警日报(定时推送群聊)
│ │ ├── device_service.py # 边缘设备管理
│ │ ├── oss_storage.py # 腾讯云 COS 存储CVM 角色认证)
│ │ ├── ai_analyzer.py # 旧版 AI 分析触发器
│ │ ├── report_generator.py # 报表生成
│ │ └── session_manager.py # Agent 会话管理
│ │
│ ├── utils/
│ │ ├── logger.py # 日志配置(控制台 + 文件)
│ │ └── timezone.py # 北京时间工具beijing_now
│ │
│ └── migrations/
│ └── migrate_to_alarm_event.py # 旧表 → 新三表迁移脚本
├── data/ # SQLite 数据库(开发环境)
├── logs/ # 日志文件
├── uploads/ # 本地截图存储COS 降级)
├── docs/ # 设计文档
│ ├── architecture.md # 系统架构设计
│ ├── API_SECURITY.md # 安全实践文档
│ ├── camera_name_config.md # 摄像头名称配置
│ └── 芋道前端对接文档.md # 前端对接指南
├── requirements.txt # Python 依赖20 个包)
├── .env.example # 环境变量模板
├── Dockerfile
└── README.md
```
## 数据模型
### 告警三表结构
```
┌─────────────────────┐ ┌──────────────────────┐ ┌───────────────────────┐
│ alarm_event │ │ alarm_event_ext │ │ alarm_llm_analysis │
│ ─────────────────── │ │ ──────────────────── │ │ ──────────────────── │
│ alarm_id (PK) │←─1:N─│ alarm_id (FK) │ │ alarm_id (FK) │
│ alarm_type │ │ ext_type │ │ analysis_type │
│ device_id │ │ ext_data (JSON) │ │ is_false_alarm │
│ scene_id │ │ roi_config (JSON) │ │ risk_score │
│ event_time │ └──────────────────────┘ │ summary │
│ alarm_level (0-3) │ │ suggestion │
│ alarm_status │←─1:1─────────────────────────────── │ confidence_score │
│ handle_status │ └───────────────────────┘
│ snapshot_url │
│ confidence_score │
│ duration_ms │
│ handler / handled_at │
└─────────────────────┘
```
**alarm_status**: `NEW``CONFIRMED``RESOLVED` / `FALSE` / `CLOSED`
**handle_status**: `UNHANDLED``HANDLING``DONE` / `IGNORED`
**alarm_level**: `0`=紧急 / `1`=重要 / `2`=普通 / `3`=轻微(根据类型+置信度+持续时长动态计算)
### 工单系统
| 表 | 说明 |
|---|---|
| `security_work_order` | 工单主表(关联 alarm_id状态流转 |
| `security_user` | 安保人员(角色、企微 UID、班组 |
| `work_order_log` | 工单操作日志CREATE/DISPATCH/ACCEPT/FINISH/CLOSE |
### 通知配置
| 表 | 说明 |
|---|---|
| `notify_area` | 通知区域 |
| `camera_area_binding` | 摄像头 → 区域绑定 |
| `area_person_binding` | 区域 → 负责人绑定(决定通知谁) |
## API 接口
### 告警管理
### 边缘端上报(无需认证)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/alerts` | 告警列表(分页、筛选 |
| GET | `/api/v1/alerts/{id}` | 告警详情 |
| PUT | `/api/v1/alerts/{id}/handle` | 处理告警 |
| GET | `/api/v1/alerts/statistics` | 告警统计 |
| POST | `/api/ai/alert/edge/report` | 告警上报(幂等,相同 alarm_id 跳过 |
| POST | `/api/ai/alert/edge/resolve` | 告警结束通知(更新持续时长 + 状态) |
**上报请求体**
```json
{
"alarm_id": "edge_device001_20260325120000_a1b2c3",
"alarm_type": "leave_post",
"device_id": "camera_001",
"scene_id": "roi_001",
"event_time": "2026-03-25T12:00:00",
"alarm_level": 2,
"snapshot_url": "https://cos.ap-beijing.myqcloud.com/...",
"confidence_score": 0.92,
"ext_data": {"bind_id": "bind_123", "bbox": [100, 100, 300, 400]}
}
```
### 告警管理(芋道兼容,需认证)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin-api/aiot/alarm/alert/page` | 分页查询(支持类型/状态/时间/设备筛选) |
| GET | `/admin-api/aiot/alarm/alert/get` | 告警详情(含扩展信息 + VLM 分析) |
| PUT | `/admin-api/aiot/alarm/alert/handle` | 处理告警(状态流转) |
| DELETE | `/admin-api/aiot/alarm/alert/delete` | 删除告警 |
| GET | `/admin-api/aiot/alarm/alert/statistics` | 告警统计 |
| GET | `/admin-api/aiot/alarm/device-summary/page` | 设备告警汇总 |
### 设备管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/v1/devices` | 设备列表 |
| GET | `/api/v1/devices/{id}` | 设备详情 |
| GET | `/api/v1/devices/statistics` | 设备统计 |
| GET | `/admin-api/aiot/edge/device/page` | 设备列表(含告警计数) |
### WebSocket
| 路径 | 说明 |
|------|------|
| `/ws/alerts` | 告警实时推送 |
### 健康检查
### 认证
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/health` | 服务健康状态 |
| POST | `/admin-api/system/auth/login` | 登录DEV_MODE 下 admin/admin |
| GET | `/admin-api/system/auth/get-permission-info` | 获取用户权限 |
## MQTT 消息格式
### 企微回调 & 通知
### 告警消息(边缘端发布)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET/POST | `/wechat/callback` | 企微消息回调(验签 + 加解密) |
| POST | `/api/notify/test-send` | 测试发送企微通知 |
| CRUD | `/admin-api/aiot/notify/area/*` | 通知区域管理 |
| CRUD | `/admin-api/aiot/notify/bindCamera/*` | 摄像头-区域绑定 |
| CRUD | `/admin-api/aiot/notify/bindPerson/*` | 区域-人员绑定 |
Topic: `edge/alert/{camera_id}/{roi_id}`
### 工单
```json
{
"camera_id": "cam_001",
"roi_id": "roi_001",
"device_id": "edge_device_001",
"alert_type": "leave_post",
"algorithm": "YOLO",
"confidence": 0.92,
"duration_minutes": 15,
"trigger_time": "2026-02-05T12:00:00",
"message": "检测到离岗行为",
"bbox": [100, 100, 300, 400]
}
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/admin-api/aiot/work-order/create` | 创建工单 |
| GET | `/admin-api/aiot/work-order/page` | 工单列表 |
| PUT | `/admin-api/aiot/work-order/update-status` | 更新工单状态 |
### WebSocket & 健康检查
| 路径 | 说明 |
|------|------|
| `ws://host:8000/ws/alerts` | 实时告警推送(支持 ping/pong 心跳) |
| `GET /health` | 服务健康状态DB + WebSocket 连接数) |
## 核心业务流程
### 告警处理全链路
```
边缘端 HTTP POST /api/ai/alert/edge/report
AlarmEventService.create_from_edge_report()
├── 幂等检查alarm_id 去重)
├── 动态计算 alarm_level
├── 写入 alarm_event + alarm_event_ext
├── WebSocket 实时推送
└── 异步通知链 (notify_dispatch.py)
├── VLM 复核(截图分析 → is_false_alarm / risk_score
├── 企微私聊卡片推送(绑定区域 → 负责人)
├── 企微群聊告警(截图 + Markdown 详情)
└── 自动创建工单POST AIoT 开放接口)
```
### 心跳消息(边缘端发布)
### 企微消息交互
Topic: `edge/alert/heartbeat/{device_id}`
```json
{
"device_id": "edge_device_001",
"status": "online",
"uptime": 3600,
"frames_processed": 10000,
"alerts_generated": 5,
"timestamp": "2026-02-05T12:00:00"
}
```
用户收到告警卡片
├── 点击「去处理」→ H5 详情页
│ ├── 标记处理中 → PUT /handle (HANDLING)
│ ├── 完成处理 → PUT /handle (DONE)
│ └── 忽略/误报 → PUT /handle (IGNORED)
└── 回复文字消息 → Agent 多轮对话
├── 查询告警统计
├── 查看设备告警
└── 创建工单
```
## 与 wvp-platform 集成
## 服务初始化流程
本服务与 wvp-platform视频监控平台配合使用
```python
# app/main.py lifespan
init_db() # 1. 数据库表创建
notification_service.set_event_loop() # 2. WebSocket 事件循环
vlm_svc.init() # 3. VLM 视觉模型
wechat_svc.init() # 4. 企微服务
agent.init() # 5. 交互 Agent
wo_client.init() # 6. 工单客户端
start_daily_report_scheduler() # 7. 日报定时任务(可选)
```
1. **wvp-platform**:管理摄像头、配置 ROI 区域、推送算法配置
2. **ai_edge**:接收配置、执行推理、上报告警
3. **本服务**:接收告警、存储管理、实时推送
所有服务为**全局单例模式**(模块级实例化),通过 `get_xxx_service()` 工厂函数获取。
## 环境变量
### 必选
| 变量 | 说明 | 示例 |
|------|------|------|
| `DATABASE_URL` | 数据库连接 | `mysql+pymysql://user:pass@host/db` |
### 云存储COS
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `COS_ENABLED` | 启用 COS | `false` |
| `COS_BUCKET` | 存储桶 | — |
| `COS_REGION` | 区域 | `ap-beijing` |
| `COS_UPLOAD_PREFIX` | Key 前缀 | `alerts` |
| `COS_PRESIGN_EXPIRE` | 预签名有效期(秒) | `1800` |
> COS 认证优先使用 CVM 角色(免密钥),容器内自动从元数据服务获取临时凭证。
### 企微通知
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `WECHAT_ENABLED` | 启用企微 | `false` |
| `WECHAT_CORP_ID` | 企业 ID | — |
| `WECHAT_AGENT_ID` | 应用 ID | — |
| `WECHAT_SECRET` | 应用密钥 | — |
| `WECHAT_TOKEN` | 回调 Token | — |
| `WECHAT_ENCODING_AES_KEY` | 回调加密密钥 | — |
| `WECHAT_GROUP_CHAT_ID` | 告警群聊 ID | — |
| `WECHAT_TEST_UIDS` | 演示模式用户(逗号分隔) | — |
| `SERVICE_BASE_URL` | 公网地址H5 页面) | — |
### VLM 智能复核
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `VLM_ENABLED` | 启用 VLM | `false` |
| `DASHSCOPE_API_KEY` | Dashscope API Key | — |
| `VLM_MODEL` | 模型名称 | `qwen3-vl-flash-2026-01-22` |
| `VLM_TIMEOUT` | 超时(秒) | `10` |
### 交互 Agent
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `AGENT_ENABLED` | 启用 Agent | `false` |
| `AGENT_MODEL` | 文本模型 | `qwen3.5-plus` |
| `AGENT_TIMEOUT` | FC 超时(秒) | `30` |
### 工单对接
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `WORK_ORDER_ENABLED` | 启用工单 | `false` |
| `WORK_ORDER_BASE_URL` | AIoT 平台地址 | — |
| `WORK_ORDER_APP_ID` | 应用 ID | — |
| `WORK_ORDER_APP_SECRET` | 应用密钥 | — |
| `WORK_ORDER_TENANT_ID` | 租户编号 | `1` |
### 每日日报
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `DAILY_REPORT_ENABLED` | 启用日报 | `false` |
| `DAILY_REPORT_HOUR` | 发送小时 | `9` |
| `DAILY_REPORT_MINUTE` | 发送分钟 | `0` |
### 边缘认证
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `EDGE_AUTH_ENABLED` | 启用边缘 Token 校验 | `false` |
| `EDGE_AUTH_TOKEN` | 共享 Bearer Token | — |
### 其他
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `DEV_MODE` | 开发模式(跳过认证) | `true` |
| `DEBUG` | 调试模式(自动重载) | `true` |
| `WVP_API_BASE` | WVP 平台地址(摄像头名称) | `http://localhost:18080` |
| `REDIS_HOST` / `REDIS_PORT` | Redis 连接 | `localhost:6379` |
## 与其他项目的集成
| 对接方 | 协议 | 说明 |
|--------|------|------|
| **security-ai-edge** → 本服务 | HTTP POST | 边缘端告警上报 + 告警结束通知 |
| **wvp-platform** ← 本服务 | HTTP GET | 查询摄像头名称(/api/camera/{id} |
| 本服务 → **腾讯云 COS** | SDK | 告警截图上传 + 预签名下载 |
| 本服务 → **企业微信** | HTTP API | 消息推送 + 回调验签 |
| 本服务 → **AIoT 运维平台** | HTTP POST | 工单创建(签名认证) |
| 本服务 → **Dashscope** | OpenAI 兼容 | VLM 截图复核 |
| **aiot-web-antd** ← 本服务 | REST + WS | 前端数据访问 + 实时推送 |
## 环境要求
- Python 3.8+
- MQTT Broker推荐 EMQX
## License
MIT
- MySQL 8生产或 SQLite开发
- 腾讯云 COS截图存储
- 企业微信自建应用(通知推送,可选)
- Dashscope API KeyVLM 复核,可选)