# 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` — 实时告警推送