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

460 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AI 告警平台后端服务vsp-service
基于 FastAPI 的 AI 安防告警平台后端。接收边缘 AI 设备 HTTP 上报的告警事件,通过 VLM 视觉模型复核推送企微通知管理安保工单WebSocket 实时推送到前端。
## 功能特性
- **边缘告警接收**HTTP 接口接收边缘端 AI 推理结果,幂等去重,自动分级
- **VLM 智能复核**Dashscope Qwen3-VL 对告警截图二次分析,识别误报,评估风险
- **企微通知推送**:企微应用消息卡片 + 群聊告警,支持 H5 详情页状态流转
- **每日告警日报**:定时生成前日告警汇总(类型分布、设备 Top5、环比变化推送到企微群聊
- **安保工单对接**:告警自动/手动创建工单,对接 AIoT 运维平台(开放接口)
- **交互式 Agent**:基于 Function Calling 的多轮对话,自然语言查询告警、创建工单
- **WebSocket 实时推送**:告警事件实时推送到前端
- **截图云存储**:腾讯云 COS 存储告警截图CVM 角色认证免密钥
- **芋道平台兼容**:双 API 层(原生 + 芋道格式),无缝对接 Vue 3 前端
## 系统架构
```
┌──────────────────────────────────────────┐
│ 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 0.109 + Uvicorn |
| 数据库 | MySQL 8生产/ SQLite开发|
| ORM | SQLAlchemy 2.0 |
| 实时推送 | WebSocket |
| 云存储 | 腾讯云 COScos-python-sdk-v5|
| AI 复核 | Dashscope Qwen3-VLOpenAI 兼容接口)|
| 企微集成 | 企业微信应用消息 + 群聊 + 回调 |
| Agent | Qwen3.5-Plus Function Calling |
| 加密 | pycryptodome企微消息加解密|
| HTTP 客户端 | httpx异步|
| 配置管理 | dataclass + dotenv 环境变量 |
## 快速开始
### 1. 安装依赖
```bash
pip install -r requirements.txt
```
### 2. 配置环境变量
```bash
cp .env.example .env
# 编辑 .env至少配置
# DATABASE_URL — 数据库连接
# COS_ENABLED + COS_BUCKET + COS_REGION — 截图存储
```
### 3. 启动服务
```bash
# 开发模式自动重载DEV_MODE=true 跳过认证)
python -m app.main
# 生产模式
uvicorn app.main:app --host 0.0.0.0 --port 8000
```
### 4. 访问
- 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
```
## 项目结构
```
iot-device-management-service/
├── app/
│ ├── 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 接口
### 边缘端上报(无需认证)
| 方法 | 路径 | 说明 |
|------|------|------|
| 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 | `/admin-api/aiot/edge/device/page` | 设备列表(含告警计数) |
### 认证
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/admin-api/system/auth/login` | 登录DEV_MODE 下 admin/admin |
| GET | `/admin-api/system/auth/get-permission-info` | 获取用户权限 |
### 企微回调 & 通知
| 方法 | 路径 | 说明 |
|------|------|------|
| 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/*` | 区域-人员绑定 |
### 工单
| 方法 | 路径 | 说明 |
|------|------|------|
| 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 开放接口)
```
### 企微消息交互
```
用户收到告警卡片
├── 点击「去处理」→ H5 详情页
│ ├── 标记处理中 → PUT /handle (HANDLING)
│ ├── 完成处理 → PUT /handle (DONE)
│ └── 忽略/误报 → PUT /handle (IGNORED)
└── 回复文字消息 → Agent 多轮对话
├── 查询告警统计
├── 查看设备告警
└── 创建工单
```
## 服务初始化流程
```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. 日报定时任务(可选)
```
所有服务为**全局单例模式**(模块级实例化),通过 `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+
- MySQL 8生产或 SQLite开发
- 腾讯云 COS截图存储
- 企业微信自建应用(通知推送,可选)
- Dashscope API KeyVLM 复核,可选)