Files
iot-device-management-service/CLAUDE.md
16337 b14ac9eea7 文档:更新 CLAUDE.md 反映生产环境部署
主要更新:
- 添加生产部署信息(容器名称、端口、部署位置)
- 更新 Docker 部署命令(反映真实的 vsp-service 容器)
- 数据库从 SQLite 改为腾讯云 MySQL
- 补充关键接口说明(边缘端上报、前端访问、WebSocket)
- 移除过时的 MQTT 相关说明
- 强调使用 python -m app.main 作为入口

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 16:26:27 +08:00

144 lines
6.3 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.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 项目概述
AI 告警平台后端服务,基于 FastAPI 构建。接收边缘 AI 设备通过 HTTP 上报的告警,存储截图到腾讯云 COS通过 WebSocket 实时推送告警事件,为芋道 Vue 3 前端提供 REST API。
**生产部署信息:**
- **容器名称:** `vsp-service`
- **端口映射:** 8000:8000
- **部署位置:** 腾讯云服务器 `/opt/vsp-platform`
- **存储:** 腾讯云 MySQL + 腾讯云 COS
- **访问地址:** http://服务器IP:8000
## 常用命令
### 本地开发
```bash
# 安装依赖
pip install -r requirements.txt
# 环境配置
cp .env.example .env
# 编辑 .env
# DATABASE_URL=mysql+pymysql://user:pass@localhost/dbname
# COS_SECRET_ID=your_secret_id
# COS_SECRET_KEY=your_secret_key
# COS_BUCKET=your-bucket
# COS_REGION=ap-beijing
# 运行开发服务器(自动重载,监听 8000 端口)
python -m app.main
# 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@云端MySQL/dbname \
-e COS_BUCKET=腾讯云COS桶名 \
-e COS_REGION=ap-beijing \
-e COS_SECRET_ID=your_id \
-e COS_SECRET_KEY=your_key \
vsp-service:latest
# 查看日志
docker logs -f vsp-service
# 重启容器
docker restart vsp-service
# 进入容器调试
docker exec -it vsp-service /bin/bash
```
### 测试
```bash
# 如果添加测试,使用 pytest
pytest tests/
```
**重要提示:** 根目录的 `main.py` 是 PyCharm 模板文件,不是真正的入口。**务必使用 `python -m app.main` 启动服务**。
## Architecture
### Data Flow
```
Edge Devices ──MQTT──→ EMQX Broker ──subscribe──→ MQTTService ──→ AlertService ──→ DB
Edge Devices ──HTTP POST──→ /api/v1/alerts ────────────→│
NotificationService ──WebSocket──→ Frontend
```
### Dual API Surface
The app exposes two parallel API layers hitting the same services and database:
1. **Native API** (`/api/v1/`) — endpoints defined inline in `app/main.py`. Standard REST responses.
2. **Yudao-compat API** (`/admin-api/`) — routers in `app/routers/yudao_alert.py` and `yudao_auth.py`. Wraps responses in `{"code": 0, "data": ..., "msg": ""}` format expected by the Yudao Vue frontend. Auth/permissions handled by `app/yudao_compat.py` (stub in dev mode: `DEV_MODE=true` skips token validation, returns mock admin).
### Services (Global Singletons)
All services are instantiated as module-level singletons, not injected via FastAPI `Depends()`. Access them via factory functions (`get_alert_service()`, `get_mqtt_service()`, etc.) or import the global directly.
- **AlertService** (`app/services/alert_service.py`) — CRUD, filtering/pagination, statistics, AI analysis update. Handles both HTTP (`create_alert`) and MQTT (`create_alert_from_mqtt`) creation paths. Alert numbers: `ALT` + timestamp + uuid fragment.
- **MQTTService** (`app/services/mqtt_service.py`) — paho-mqtt client subscribing to `edge/alert/#`. Routes messages to registered callbacks for alerts vs heartbeats. Compatible with paho-mqtt 1.x and 2.x APIs.
- **DeviceService** (`app/services/device_service.py`) — Tracks edge device status from MQTT heartbeats. In-memory cache + DB persistence. Marks devices offline after 90s without heartbeat.
- **NotificationService** (`app/services/notification_service.py`) — WebSocket connection manager + broadcast. Bridges sync MQTT callbacks to async WebSocket sends via `asyncio.run_coroutine_threadsafe()`.
- **OSSStorage** (`app/services/oss_storage.py`) — Image storage. Currently local-only (`uploads/` dir); Aliyun OSS stubbed but not implemented.
- **AIAnalyzer** (`app/services/ai_analyzer.py`) — Async httpx client for optional big-model analysis. Fire-and-forget via `asyncio.create_task()`.
### Lifecycle (`app/main.py` lifespan)
Startup: init DB → set async event loop on NotificationService → register MQTT handlers → start MQTT.
Shutdown: stop MQTT.
### Database生产环境使用腾讯云 MySQL
三个核心 ORM 模型在 `app/models.py`
- **AlarmEvent** — 告警事件主表。字段alarm_id (PK), alarm_type, device_id, scene_id, event_time, alarm_level (1-4), alarm_status (NEW/CONFIRMED/RESOLVED), handle_status, snapshot_url 等。索引alarm_id, device_id, alarm_status, event_time。
- **AlarmEventExt** — 告警扩展信息表。存储 ext_data JSON 字段(边缘端上报的 bbox, bind_id 等)。
- **AlarmLlmAnalysis** — 大模型分析结果表(可选功能)。
- **EdgeDevice** — 边缘设备表(用于设备列表展示,无心跳机制)。
数据库连接通过 `get_session()` 获取。服务层使用 try/finally 管理会话生命周期。
### Config
`app/config.py` — dataclass-based config loaded from `.env` via `os.getenv()`. Sections: `DatabaseConfig`, `OSSConfig`, `AppConfig` (includes `dev_mode`), `AIModelConfig`, `MQTTConfig`. Global `settings` instance created at module load.
### 关键接口
**边缘端告警上报(无需认证):**
- `POST /api/ai/alert/edge/report` — 边缘端告警上报
- 请求体:`{alarm_id, alarm_type, device_id, scene_id, event_time, alarm_level, snapshot_url, confidence_score, ext_data}`
- 幂等性:相同 alarm_id 会跳过创建
- 成功后触发 WebSocket 推送
- `POST /api/ai/alert/edge/resolve` — 告警结束通知(离岗算法)
- 请求体:`{alarm_id, duration_ms, last_frame_time, resolve_type}`
- 更新告警持续时长和结束时间
**前端访问接口(需要认证,通过 aiot-gateway 48080 访问):**
- `GET /admin-api/aiot/alarm/event/page` — 分页查询告警事件
- `GET /admin-api/aiot/alarm/event/get` — 获取告警详情
- `PUT /admin-api/aiot/alarm/event/handle` — 处理告警
- `GET /admin-api/aiot/alarm/event/statistics` — 告警统计
- `GET /admin-api/aiot/edge/device/page` — 分页查询边缘设备
**WebSocket 实时推送:**
- `ws://服务器IP:8000/ws/alerts` — 实时告警推送