Files

136 lines
4.2 KiB
Python
Raw Permalink Normal View History

"""
配置管理
"""
import os
from pathlib import Path
from typing import Optional
from dataclasses import dataclass
from pydantic import BaseModel
@dataclass
class DatabaseConfig:
"""数据库配置"""
url: str = "sqlite:///./data/alert_platform.db"
@dataclass
class COSConfig:
"""腾讯云 COS 存储配置(通过 CVM 角色认证,无需密钥)"""
region: str = "ap-beijing"
bucket: str = "" # 格式: bucketname-appid
upload_prefix: str = "alerts" # 对象 Key 前缀
presign_expire: int = 1800 # 预签名URL有效期默认30分钟
enabled: bool = False # 是否启用 COS
@dataclass
class AppConfig:
"""应用配置"""
host: str = "0.0.0.0"
port: int = 8000
debug: bool = True
dev_mode: bool = True # 开发模式:跳过认证验证,返回超级管理员权限
@dataclass
class AIModelConfig:
"""AI 模型配置"""
endpoint: str = ""
api_key: str = ""
@dataclass
class RedisConfig:
"""Redis 配置"""
host: str = "localhost"
port: int = 6379
password: str = ""
db: int = 0
max_connections: int = 50
decode_responses: bool = True
enabled: bool = True
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
@dataclass
class CameraNameConfig:
"""摄像头名称格式化配置"""
# WVP API基础URL
wvp_api_base: str = "http://localhost:18080"
# 显示格式模板(支持变量:{camera_code}, {name}, {stream}
# 可选格式:
perf(alarm): 批量查询优化 + 仅显示中文名称 问题: 1. 告警列表超时:每条告警单独查询WVP,20条=20次HTTP请求 2. 用户需求:仅显示中文名称,不要编号 优化方案: 1. 批量查询优化 - 添加 get_camera_infos_batch 方法 - 自动去重:多个告警同一摄像头只查一次 - 并发查询:所有摄像头并发查询 - 请求内缓存:查询结果复用 2. 修改默认格式 - display_format: "{name}" (仅中文名称) - 支持环境变量覆盖 性能对比: - 优化前:20条告警 = 20次WVP查询 = 4.5秒 - 优化后:20条告警 = N次WVP查询(N=唯一camera数)= 1.2秒 - 性能提升:73% 代码改进: 1. CameraNameService 新增方法 + get_camera_infos_batch - 批量查询 + get_display_names_batch - 批量获取显示名称 2. 告警列表路由优化 - 提取所有唯一device_id - 批量查询一次 - 使用name_map缓存 - _alarm_to_camel 改用 name_map 参数 3. 默认配置修改 - CAMERA_NAME_FORMAT="{name}" - 用户可通过环境变量改回完整格式 测试结果: - 告警列表: ✓ 显示"大堂吧台3"(1.2秒) - 设备汇总: ✓ 显示"大堂吧台1" - 超时问题: ✓ 已解决 修改文件: ~ app/services/camera_name_service.py + get_camera_infos_batch + get_display_names_batch ~ format_display_name - 支持仅{name}格式 ~ app/routers/yudao_aiot_alarm.py ~ get_alert_page - 使用批量查询 ~ get_alert - 使用name_map ~ _alarm_to_camel - 参数改为name_map ~ app/config.py ~ display_format 默认值改为 "{name}"
2026-02-24 14:08:36 +08:00
# - "{name}" - 仅名称(推荐,告警列表使用)
# - "{camera_code} {name}/{stream}" - cam_xxx 名称/流id完整格式
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
# - "{name}/{stream}" - 名称/流id
# - "{camera_code}" - 仅code
perf(alarm): 批量查询优化 + 仅显示中文名称 问题: 1. 告警列表超时:每条告警单独查询WVP,20条=20次HTTP请求 2. 用户需求:仅显示中文名称,不要编号 优化方案: 1. 批量查询优化 - 添加 get_camera_infos_batch 方法 - 自动去重:多个告警同一摄像头只查一次 - 并发查询:所有摄像头并发查询 - 请求内缓存:查询结果复用 2. 修改默认格式 - display_format: "{name}" (仅中文名称) - 支持环境变量覆盖 性能对比: - 优化前:20条告警 = 20次WVP查询 = 4.5秒 - 优化后:20条告警 = N次WVP查询(N=唯一camera数)= 1.2秒 - 性能提升:73% 代码改进: 1. CameraNameService 新增方法 + get_camera_infos_batch - 批量查询 + get_display_names_batch - 批量获取显示名称 2. 告警列表路由优化 - 提取所有唯一device_id - 批量查询一次 - 使用name_map缓存 - _alarm_to_camel 改用 name_map 参数 3. 默认配置修改 - CAMERA_NAME_FORMAT="{name}" - 用户可通过环境变量改回完整格式 测试结果: - 告警列表: ✓ 显示"大堂吧台3"(1.2秒) - 设备汇总: ✓ 显示"大堂吧台1" - 超时问题: ✓ 已解决 修改文件: ~ app/services/camera_name_service.py + get_camera_infos_batch + get_display_names_batch ~ format_display_name - 支持仅{name}格式 ~ app/routers/yudao_aiot_alarm.py ~ get_alert_page - 使用批量查询 ~ get_alert - 使用name_map ~ _alarm_to_camel - 参数改为name_map ~ app/config.py ~ display_format 默认值改为 "{name}"
2026-02-24 14:08:36 +08:00
display_format: str = "{name}"
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
# 名称字段优先级(从高到低)
# 从StreamProxy对象中提取名称时的字段优先级
# 注意gb_name 可能包含 "/" 后缀,会自动去除
name_field_priority: list = None
# 查询超时(秒)
query_timeout: int = 15
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
def __post_init__(self):
if self.name_field_priority is None:
# 默认优先级gb_name > app > stream
self.name_field_priority = ["gbName", "app", "stream"]
class Settings(BaseModel):
"""全局配置"""
database: DatabaseConfig = DatabaseConfig()
cos: COSConfig = COSConfig()
app: AppConfig = AppConfig()
ai_model: AIModelConfig = AIModelConfig()
redis: RedisConfig = RedisConfig()
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
camera_name: CameraNameConfig = CameraNameConfig()
def load_settings() -> Settings:
"""从环境变量加载配置"""
from dotenv import load_dotenv
load_dotenv()
return Settings(
database=DatabaseConfig(
url=os.getenv("DATABASE_URL", "sqlite:///./data/alert_platform.db"),
),
cos=COSConfig(
region=os.getenv("COS_REGION", "ap-beijing"),
bucket=os.getenv("COS_BUCKET", ""),
upload_prefix=os.getenv("COS_UPLOAD_PREFIX", "alerts"),
presign_expire=int(os.getenv("COS_PRESIGN_EXPIRE", "1800")),
enabled=os.getenv("COS_ENABLED", "false").lower() == "true",
),
app=AppConfig(
host=os.getenv("APP_HOST", "0.0.0.0"),
port=int(os.getenv("APP_PORT", "8000")),
debug=os.getenv("DEBUG", "true").lower() == "true",
dev_mode=os.getenv("DEV_MODE", "true").lower() == "true",
),
ai_model=AIModelConfig(
endpoint=os.getenv("AI_MODEL_ENDPOINT", ""),
api_key=os.getenv("AI_MODEL_API_KEY", ""),
),
redis=RedisConfig(
host=os.getenv("REDIS_HOST", "localhost"),
port=int(os.getenv("REDIS_PORT", "6379")),
password=os.getenv("REDIS_PASSWORD", ""),
db=int(os.getenv("REDIS_DB", "0")),
max_connections=int(os.getenv("REDIS_MAX_CONNECTIONS", "50")),
enabled=os.getenv("REDIS_ENABLED", "true").lower() == "true",
),
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
camera_name=CameraNameConfig(
wvp_api_base=os.getenv("WVP_API_BASE", "http://localhost:18080"),
perf(alarm): 批量查询优化 + 仅显示中文名称 问题: 1. 告警列表超时:每条告警单独查询WVP,20条=20次HTTP请求 2. 用户需求:仅显示中文名称,不要编号 优化方案: 1. 批量查询优化 - 添加 get_camera_infos_batch 方法 - 自动去重:多个告警同一摄像头只查一次 - 并发查询:所有摄像头并发查询 - 请求内缓存:查询结果复用 2. 修改默认格式 - display_format: "{name}" (仅中文名称) - 支持环境变量覆盖 性能对比: - 优化前:20条告警 = 20次WVP查询 = 4.5秒 - 优化后:20条告警 = N次WVP查询(N=唯一camera数)= 1.2秒 - 性能提升:73% 代码改进: 1. CameraNameService 新增方法 + get_camera_infos_batch - 批量查询 + get_display_names_batch - 批量获取显示名称 2. 告警列表路由优化 - 提取所有唯一device_id - 批量查询一次 - 使用name_map缓存 - _alarm_to_camel 改用 name_map 参数 3. 默认配置修改 - CAMERA_NAME_FORMAT="{name}" - 用户可通过环境变量改回完整格式 测试结果: - 告警列表: ✓ 显示"大堂吧台3"(1.2秒) - 设备汇总: ✓ 显示"大堂吧台1" - 超时问题: ✓ 已解决 修改文件: ~ app/services/camera_name_service.py + get_camera_infos_batch + get_display_names_batch ~ format_display_name - 支持仅{name}格式 ~ app/routers/yudao_aiot_alarm.py ~ get_alert_page - 使用批量查询 ~ get_alert - 使用name_map ~ _alarm_to_camel - 参数改为name_map ~ app/config.py ~ display_format 默认值改为 "{name}"
2026-02-24 14:08:36 +08:00
display_format=os.getenv("CAMERA_NAME_FORMAT", "{name}"),
query_timeout=int(os.getenv("CAMERA_QUERY_TIMEOUT", "15")),
refactor(alarm): 模块化摄像头名称格式化服务 问题: - 硬编码字段映射(gbName、name、app) - 逻辑重复散落多处 - 格式写死无法配置 - 未基于数据库实际表结构 - 可扩展性差 重构方案: 1. 创建配置类 CameraNameConfig - 显示格式模板(支持变量:{camera_code}, {name}, {stream}) - 字段优先级配置 - WVP API配置 - 查询超时配置 2. 创建服务类 CameraNameService - 查询摄像头信息(get_camera_info) - 提取名称字段(extract_name) - 格式化显示名称(format_display_name) - 一站式方法(get_display_name) 3. 重构路由层 - 移除硬编码逻辑 - 使用camera_name_service统一处理 - 删除旧的_get_camera_info函数 - 简化代码结构 架构优势: - 配置驱动:格式通过环境变量控制 - 单一职责:服务只负责名称处理 - 可扩展:新增格式无需改代码 - 可测试:服务独立易于测试 - 模块化:逻辑集中便于维护 配置示例: ```bash WVP_API_BASE=http://localhost:18080 CAMERA_NAME_FORMAT={camera_code} {name}/{stream} CAMERA_QUERY_TIMEOUT=5 ``` 修改文件: + app/config.py - 添加CameraNameConfig配置 + app/services/camera_name_service.py - 新建服务 + docs/camera_name_config.md - 配置文档 ~ app/routers/yudao_aiot_alarm.py - 使用新服务 测试结果: - 告警列表: cam_1f0e3dad9990 → cam_1f0e3dad9990 大堂吧台3/012 ✓ - 设备汇总: cam_c51ce410c124 → cam_c51ce410c124 大堂吧台1/008 ✓
2026-02-24 13:59:13 +08:00
),
)
settings = load_settings()