32 KiB
修改记录
2025-08-11
WebSocket心跳循环日志增强
问题:WebSocket适配器启动后,_heartbeat_loop 和 _send_loop 的启动日志没有显示,无法确认心跳任务是否正常启动
解决方案:
- 将
_heartbeat_loop和_send_loop的启动日志级别从DEBUG改为INFO - 在
_heartbeat_loop中添加更多调试信息,包括优先级通道的创建和连接状态 - 增强心跳消息发送的日志记录
文件变更:
- 更新
app/core/websocket/adapter.py- 增强心跳循环的日志记录
修改内容:
# 发送循环启动日志级别提升
logger.info(f"发送循环启动: {self.client.name} (out:{self.outbound_channel.name} / in:{self.inbound_channel.name})")
# 心跳循环启动日志级别提升
logger.info(f"心跳循环启动: {self.client.name} (out:{self.outbound_channel.name} / in:{self.inbound_channel.name}) 间隔:{self.heartbeat_interval}秒")
# 添加优先级通道创建和连接日志
logger.info(f"创建优先级通道: {priority_channel_name}")
logger.info(f"优先级通道连接成功: {priority_channel_name}")
# 添加心跳消息发送日志
logger.debug(f"心跳消息已发送: {self.client.name} -> {priority_channel_name}")
优化效果:
- ✅ 可以清楚看到心跳循环和发送循环的启动状态
- ✅ 能够跟踪优先级通道的创建和连接过程
- ✅ 便于调试心跳消息的发送情况
- ✅ 提供更详细的错误信息,包含客户端名称
验证方法:
- 创建WebSocket客户端后,应该能看到以下日志:
- "发送循环启动: test_12 (out:default / in:default)"
- "心跳循环启动: test_12 (out:default / in:default) 间隔:120秒"
- "优先级通道连接成功: default_priority"
日志系统循环导入问题修复
问题:app/utils/log.py 文件存在循环导入问题,导致应用无法启动
- 错误信息:
ImportError: cannot import name 'get_enhanced_logger' from partially initialized module 'app.utils.log' - 根本原因:
log.py导入config.settings,而config.cors又导入log.py,形成循环导入
解决方案:
- 移除
log.py中对app.core.config.settings的导入 - 使用默认配置值替代动态配置
- 保持向后兼容性
文件变更:
- 更新
app/utils/log.py- 修复循环导入问题
修改内容:
# 移除有问题的导入
# from app.core.config.settings import config
# 使用默认值替代动态配置
log_level = level or "INFO" # 默认使用INFO级别
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
修复效果:
- ✅ 解决了循环导入问题
- ✅ 应用可以正常启动
- ✅ 传统日志系统正常工作
- ✅ 结构化日志系统正常工作
- ✅ 保持向后兼容性
测试验证:
- 传统日志测试:
python -c "from app.utils.log import get_logger; logger = get_logger('test'); logger.info('测试')" - 应用启动测试:
python -c "from app.core.app.factory import create_app; print('应用创建成功')" - 结构化日志测试:通过
test_log_write.py验证
影响范围:
- 修复了所有依赖
app.utils.log的模块 - 解决了应用启动失败问题
- 确保日志系统在跨平台环境下正常工作
WebSocket适配器方法跟踪日志
问题:需要为 _heartbeat_loop 和 _send_loop 方法添加入口跟踪日志,便于调试和监控
解决方案:在方法入口处添加简洁的debug级别日志
文件变更:
- 更新
app/core/websocket/adapter.py- 为关键方法添加入口跟踪日志
修改内容:
async def _send_loop(self):
"""发送循环:优先处理优先级Channel,其次处理普通出站Channel"""
logger.debug(f"发送循环启动: {self.client.name} (out:{self.outbound_channel.name} / in:{self.inbound_channel.name})")
try:
# ... 现有代码 ...
async def _heartbeat_loop(self):
"""心跳循环:以优先级消息写入,并由发送循环优先处理"""
logger.debug(f"心跳循环启动: {self.client.name} (out:{self.outbound_channel.name} / in:{self.inbound_channel.name}) 间隔:{self.heartbeat_interval}秒")
try:
# ... 现有代码 ...
优化效果:
- ✅ 便于跟踪WebSocket适配器的生命周期
- ✅ 提供关键方法的执行状态信息
- ✅ 日志简洁,不会产生过多输出
- ✅ 包含客户端名称和通道信息,便于定位问题
应用启动优化 - 移除不必要的WebSocket Channel初始化
应用启动优化 - 移除不必要的WebSocket Channel初始化
问题:startup_event 中初始化默认WebSocket Channels是不必要的,因为:
- Channels是在需要时才创建的(按需创建)
- 真正的客户端连接是在API调用
create_and_connect_client时才进行的 - 启动时创建空的Channels没有实际意义
解决方案:移除 startup_event 中的WebSocket Channel初始化代码
文件变更:
- 更新
app/core/app/factory.py- 移除启动时的WebSocket Channel初始化
修改内容:
# 移除的代码:
# 初始化默认WebSocket Channels
from app.schemas.websocket import WebSocketConfig
from app.core.websocket.manager import websocket_manager
cfg = WebSocketConfig()
for ch in cfg.default_channels:
channel = await websocket_manager.create_channel(ch, cfg.max_channel_size)
await channel.connect()
logger.info("WebSocket默认Channels初始化成功")
优化效果:
- ✅ 减少不必要的启动时间
- ✅ 避免创建无用的空Channels
- ✅ 保持按需创建的设计原则
- ✅ 真正的Channel创建和连接在API调用时进行
设计原则:
- Channels按需创建,避免预创建空Channels
- 客户端连接时自动确保所需Channels存在
- 启动时只初始化必要的服务(如ADB设备监控)
WebSocket连接超时问题修复
问题:WebSocket客户端连接时出现"timed out during opening handshake"错误
ERROR - WebSocket客户端 test_1 连接失败: timed out during opening handshake
根本原因:
- WebSocket连接没有设置超时时间,导致长时间等待
- 心跳间隔配置不一致,代码中默认30秒,但日志显示2分钟
- 缺少专门的超时异常处理
解决方案:
- 增加连接超时配置和异常处理
- 统一心跳间隔配置为120秒(2分钟)
- 添加连接超时测试脚本
文件变更:
- WebSocket客户端超时处理 (
app/core/websocket/client.py):
# 添加连接超时配置
from app.core.config.settings import config
connection_timeout = config.websocket.connection_timeout
# 使用websockets.connect的超时参数
self._websocket = await asyncio.wait_for(
websockets.connect(
self.url,
ssl=ssl_context,
ping_interval=None, # 禁用自动ping,由适配器管理心跳
ping_timeout=None, # 禁用自动ping超时
close_timeout=10 # 关闭超时
),
timeout=connection_timeout
)
# 添加超时异常处理
except asyncio.TimeoutError:
self._state = WebSocketClientState.ERROR
logger.error(f"WebSocket客户端 {self.name} 连接超时: {connection_timeout}秒")
return False
- 配置统一:
app/core/config/settings.py: 心跳间隔改为120秒,连接超时改为60秒app/schemas/websocket.py: 默认心跳间隔改为120秒app/core/websocket/adapter.py: 默认心跳间隔改为120秒app/core/websocket/manager.py: 默认心跳间隔改为120秒
- 测试脚本 (
test_websocket_connection.py):
- 创建WebSocket连接测试脚本
- 测试多种WebSocket服务器(ws://, wss://, 本地)
- 验证连接、状态检查、断开功能
配置优化:
# WebSocket配置
connection_timeout: int = 60 # 连接超时60秒
heartbeat_interval: int = 120 # 心跳间隔2分钟
功能特性:
- ✅ 连接超时自动处理,避免长时间等待
- ✅ 统一的心跳间隔配置(2分钟)
- ✅ 更好的错误日志记录
- ✅ 连接状态实时监控
- ✅ 自动资源清理
使用建议:
- 开发环境:使用较短的超时时间(30-60秒)
- 生产环境:根据网络情况调整超时时间
- 心跳间隔:根据服务器要求调整(通常30秒-5分钟)
测试验证:
# 运行WebSocket连接测试
python test_websocket_connection.py
# 启动本地WebSocket服务器进行测试
python test_websocket_server.py
改进内容:
- URL验证增强:添加URL格式验证,确保以ws://或wss://开头
- 错误处理改进:区分不同类型的错误(超时、URL格式错误、连接失败)
- 日志增强:添加更详细的连接日志,包括URL和超时时间
- 测试工具:
- 更新测试脚本使用更可靠的WebSocket服务器
- 添加API端点测试
- 创建本地WebSocket服务器用于测试
WebSocket SSL证书验证冲突修复
WebSocket SSL证书验证冲突修复
问题:WebSocket客户端连接时出现SSL配置冲突错误
Cannot set verify_mode to CERT_NONE when check_hostname is enabled.
根本原因:在SSL上下文中,当设置verify_mode = ssl.CERT_NONE时,如果check_hostname仍然为True,就会出现配置冲突。
解决方案:修复SSL配置逻辑,确保当不验证证书时同时禁用主机名检查
文件变更:
- 更新
app/core/websocket/client.py- 修复SSL配置冲突
修改内容:
# 根据配置决定是否验证证书和主机名
# 先设置check_hostname,再设置verify_mode
if not config.websocket.ssl_verify_hostname:
ssl_context.check_hostname = False
if not config.websocket.ssl_verify_certificate:
ssl_context.verify_mode = ssl.CERT_NONE
修复逻辑:
- 先设置
check_hostname,再设置verify_mode,避免配置冲突 - 当
ssl_verify_hostname = False时,设置check_hostname = False - 当
ssl_verify_certificate = False时,设置verify_mode = ssl.CERT_NONE - 确保SSL配置的正确顺序和一致性
配置建议:
# 开发环境(跳过所有SSL验证)
WEBSOCKET_SSL_VERIFY_CERTIFICATE=false
WEBSOCKET_SSL_VERIFY_HOSTNAME=false
# 生产环境(启用SSL验证)
WEBSOCKET_SSL_VERIFY_CERTIFICATE=true
WEBSOCKET_SSL_VERIFY_HOSTNAME=true
注意事项:
- 修复了SSL配置冲突问题
- 保持了配置的灵活性
- 开发环境默认跳过SSL验证
- 生产环境建议启用SSL验证
WebSocket心跳间隔参数化
需求:通过API接口create_and_connect_client传递心跳间隔参数,使心跳间隔可配置
解决方案:在请求模型中添加心跳间隔参数,并在适配器中支持自定义心跳间隔
文件变更:
- 更新
app/schemas/websocket.py- 在CreateWebSocketClientRequest中添加heartbeat_interval字段 - 更新
app/core/websocket/adapter.py- 修改WebSocketAdapter支持心跳间隔参数 - 更新
app/core/websocket/manager.py- 修改create_adapter方法传递心跳间隔参数 - 更新
app/api/v1/endpoints/websocket.py- 修改API接口传递心跳间隔参数
修改内容:
- 请求模型更新 (
app/schemas/websocket.py):
class CreateWebSocketClientRequest(BaseModel):
name: str = Field(..., min_length=1, max_length=50, description="客户端名称")
url: str = Field(..., description="WebSocket服务器URL")
heartbeat_interval: int = Field(default=30, ge=5, le=300, description="心跳间隔(秒)")
- 适配器更新 (
app/core/websocket/adapter.py):
def __init__(self, client: WebSocketClient, outbound_channel: WebSocketChannel,
inbound_channel: Optional[WebSocketChannel] = None, heartbeat_interval: int = 30):
# ... 其他参数
self.heartbeat_interval = heartbeat_interval
# ... 日志记录心跳间隔
async def _heartbeat_loop(self):
# ... 心跳逻辑
await asyncio.sleep(self.heartbeat_interval) # 使用配置的心跳间隔
- 管理器更新 (
app/core/websocket/manager.py):
async def create_adapter(self, client_name: str, channel_name: str, heartbeat_interval: int = 30):
# ... 创建适配器时传递心跳间隔参数
adapter = WebSocketAdapter(client, channel, channel, heartbeat_interval)
- API接口更新 (
app/api/v1/endpoints/websocket.py):
async def create_and_connect_client(request: CreateWebSocketClientRequest):
# ... 创建适配器时传递心跳间隔
await websocket_manager.create_adapter(request.name, ch, request.heartbeat_interval)
# ... 响应中包含心跳间隔信息
data={"name": request.name, "url": request.url, "status": "connected", "heartbeat_interval": request.heartbeat_interval}
功能特性:
- 支持通过API接口自定义心跳间隔(5-300秒范围)
- 默认心跳间隔为30秒
- 心跳间隔参数会记录在日志中
- API响应中包含配置的心跳间隔信息
使用示例:
# 创建客户端并设置心跳间隔为60秒
curl -X POST "http://localhost:8000/api/v1/websocket/clients" \
-H "Content-Type: application/json" \
-d '{
"name": "my_client",
"url": "wss://example.com/ws",
"heartbeat_interval": 60
}'
注意事项:
- 心跳间隔必须在5-300秒范围内
- 如果不指定心跳间隔,默认使用30秒
- 心跳间隔会影响网络流量和连接稳定性
- 建议根据网络环境和服务器要求调整心跳间隔
WebSocket SSL证书验证问题修复
WebSocket SSL证书验证问题修复
问题:WebSocket客户端连接时出现SSL证书验证失败错误
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:997)
解决方案:在WebSocket客户端连接时跳过SSL证书验证(仅用于开发测试)
文件变更:
- 更新
app/core/websocket/client.py- 在connect方法中添加SSL证书验证跳过逻辑
修改内容:
# 建立WebSocket连接
# 根据配置决定是否跳过SSL证书验证
ssl_context = None
if self.url.startswith('wss://'):
from app.core.config.settings import config
import ssl
ssl_context = ssl.create_default_context()
# 根据配置决定是否验证证书和主机名
if not config.websocket.ssl_verify_certificate:
ssl_context.verify_mode = ssl.CERT_NONE
if not config.websocket.ssl_verify_hostname:
ssl_context.check_hostname = False
self._websocket = await websockets.connect(self.url, ssl=ssl_context)
配置化设计:
- 在
app/core/config/settings.py中添加WebSocketConfig类 - 支持通过环境变量或配置文件控制SSL验证行为
- 默认开发环境跳过证书验证,生产环境可通过配置启用
环境变量配置:
# 开发环境(跳过SSL验证)
WEBSOCKET_SSL_VERIFY_CERTIFICATE=false
WEBSOCKET_SSL_VERIFY_HOSTNAME=false
# 生产环境(启用SSL验证)
WEBSOCKET_SSL_VERIFY_CERTIFICATE=true
WEBSOCKET_SSL_VERIFY_HOSTNAME=true
注意事项:
- 开发环境默认跳过SSL证书验证
- 生产环境建议启用SSL证书验证
- 可通过环境变量灵活配置
相关修改:
- 启用
requirements.txt中的websockets==12.0依赖 - 添加
WebSocketConfig配置类到app/core/config/settings.py - 创建
test_websocket_ssl.py测试脚本验证修复效果
测试验证: 运行测试脚本验证修复效果:
python test_websocket_ssl.py
2025-08-07
日志系统简化优化
问题:用户要求简化日志系统,不要创建太多日志文件,只分异常和非异常两种
解决方案:重构日志系统,只创建两个日志文件:
logs/app.log- 正常日志(DEBUG、INFO、WARNING级别)logs/error.log- 异常日志(ERROR、CRITICAL级别)
文件变更:
- 更新
app/utils/structured_log.py- 重构_setup_handlers()方法
优化内容:
# 根据日志级别选择文件
# ERROR和CRITICAL级别写入异常日志文件
# 其他级别写入正常日志文件
error_handler = logging.FileHandler("logs/error.log", encoding='utf-8')
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(StructuredFormatter(include_stack_trace=True))
normal_handler = logging.FileHandler("logs/app.log", encoding='utf-8')
normal_handler.setLevel(logging.DEBUG)
normal_handler.setFormatter(StructuredFormatter(include_stack_trace=False))
优势:
- ✅ 简化日志文件管理,只有两个文件
- ✅ 异常日志包含完整堆栈跟踪
- ✅ 正常日志不包含堆栈跟踪,减少文件大小
- ✅ 按日志级别自动分流
- ✅ 保持控制台输出功能
WebSocket API优化
WebSocket API优化
问题:用户指出"创建Channel请求 不是请求的时候创建",需要优化WebSocket API架构
解决方案:重新设计WebSocket API,使用预创建Channel模式,并简化为只包含获取、连接、停止功能
文件变更:
- 创建
app/schemas/websocket.py- WebSocket相关的Pydantic模型 - 创建
app/utils/api_decorators.py- API错误处理装饰器 - 更新
app/services/websocket_service.py- 支持预创建Channel和初始化配置 - 更新
app/api/v1/endpoints/websocket.py- 使用Pydantic模型,简化为获取、连接、停止功能 - 更新
app/core/app/factory.py- 应用启动时初始化WebSocket服务
架构优化:
1. 预创建Channel模式
- 应用启动时自动创建默认Channel(default, system, events)
- 移除动态创建Channel的API
- 支持配置化的Channel管理
2. 简化的API设计
根据用户要求"websocket.py 应只需要获取 跟 连接 跟 停止",简化为三个核心功能:
获取功能:
GET /websocket/clients- 获取所有客户端GET /websocket/channels- 获取所有ChannelGET /websocket/stats- 获取统计信息
连接功能:
POST /websocket/clients- 创建客户端POST /websocket/clients/{name}/connect- 连接客户端POST /websocket/subscribe- 订阅ChannelPOST /websocket/message/send- 发送消息POST /websocket/message/broadcast- 广播消息
停止功能:
POST /websocket/clients/{name}/disconnect- 断开客户端DELETE /websocket/clients/{name}- 移除客户端POST /websocket/unsubscribe- 取消订阅
3. Pydantic模型验证
- 使用Pydantic进行请求参数验证
- 统一的响应格式
- 类型安全的API接口
4. 错误处理优化
- 统一的错误处理装饰器
- 标准化的错误响应格式
- 更好的错误日志记录
移除的API:
POST /websocket/channels- 动态创建ChannelDELETE /websocket/channels/{name}- 移除ChannelGET /websocket/adapters- 获取适配器POST /websocket/adapters- 创建适配器DELETE /websocket/adapters- 移除适配器POST /websocket/initialize- 初始化服务
配置化设计:
class WebSocketConfig(BaseModel):
default_channels: List[str] = ["default", "system", "events"]
max_channel_size: int = 1000
heartbeat_interval: int = 30
reconnect_attempts: int = 5
reconnect_delay: float = 1.0
优势:
- ✅ 更清晰的API设计,只包含核心功能
- ✅ 预创建Channel,避免运行时创建
- ✅ 统一的参数验证和错误处理
- ✅ 配置化的服务管理
- ✅ 更好的类型安全性
- ✅ 简化的使用流程
WebSocket架构重构
问题:用户反馈"client.py 为啥有 channel 不应该只要读取channel 数据发 接收数据往channel 插入吗",指出WebSocket架构设计不合理。
解决方案:引入适配器模式,重新设计WebSocket架构
- WebSocketClient: 只负责WebSocket连接和数据收发
- WebSocketChannel: 负责数据存储和队列管理
- WebSocketAdapter: 负责连接Client和Channel,实现数据双向流动
文件变更:
- 创建
app/core/websocket/模块 - 创建
app/core/websocket/client.py- WebSocket客户端 - 创建
app/core/websocket/channel.py- 数据通道 - 创建
app/core/websocket/adapter.py- 适配器 - 创建
app/core/websocket/manager.py- 管理器 - 创建
app/services/websocket_service.py- 业务服务 - 创建
app/api/v1/endpoints/websocket.py- API接口
架构优势:
- 遵循单一职责原则
- 清晰的层次结构
- 易于扩展和维护
- 支持数据双向流动
数据流:
WebSocket服务器 ↔ WebSocketClient ↔ WebSocketAdapter ↔ WebSocketChannel
Channel生命周期管理完善
问题:用户指出"没有遵循单一原则是 channel.py他stop 之后能使用吗 ,二次连接webscoket 还能有吗 生命周期"
解决方案:完善Channel的生命周期管理
- 添加
reconnect()方法 - 重新连接功能 - 添加
reset()方法 - 重置状态功能 - 添加
destroy()方法 - 完全销毁功能 - 添加
connection_count属性 - 连接次数统计 - 完善状态管理和错误处理
文件变更:
- 更新
app/core/websocket/channel.py- 完善生命周期管理
功能验证:
- ✅ 支持连接/断开/重连循环
- ✅ 状态管理正确
- ✅ 资源清理完整
- ✅ 二次连接支持
WebSocket Stop方法分析
问题:检查WebSocket架构中各个组件的stop方法是否停止干净,以及二次连接的支持情况
分析结果:
Stop方法停止干净度:✅ 优秀
- WebSocketClient.disconnect(): 正确取消任务、关闭连接、清理资源
- WebSocketAdapter.stop(): 正确取消发送任务、清理消息处理器
- WebSocketManager.cleanup(): 按正确顺序清理所有资源
二次连接支持:✅ 完整
- WebSocketClient: 支持重复连接,状态检查正确
- WebSocketChannel: 支持重新连接,连接次数统计
- WebSocketAdapter: 可以重新启动,任务重新创建
架构优势:
- 所有组件都正确取消异步任务
- 正确清理资源引用
- 状态管理完整
- 支持完整的连接-断开-重连循环
设备管理API重构
问题:用户要求"注册新设备 更新设备 注册设备 api 不对外开放 因为 这是都是需要自动"
解决方案:移除外部设备管理API,保留内部自动化接口
文件变更:
- 更新
app/api/v1/endpoints/devices.py- 移除以下API:POST /devices/register- 注册新设备PUT /devices/{device_id}/update- 更新设备DELETE /devices/{device_id}/unregister- 注销设备GET /devices/{device_id}/status- 获取设备状态GET /devices/protocol/{protocol_type}- 按协议过滤设备
保留功能:
- 设备操作API(点击、输入、截图等)
- ADB管理功能
- 设备列表查询(只读)
设计原则:
- 设备注册/更新/注销由系统自动管理
- 外部API只提供设备操作功能
- 提高系统安全性和稳定性
设备管理架构重构
问题:用户反馈"不用代理冗余代码,后面难以维护",要求移除冗余API文件
解决方案:完全移除冗余文件,统一到devices.py
文件变更:
- 删除
app/api/v1/endpoints/device_operations.py - 删除
app/api/v1/endpoints/enhanced_adb.py - 删除
app/api/v1/endpoints/unified_devices.py - 更新
app/api/v1/endpoints/devices.py- 整合所有设备管理功能 - 重命名
app/services/unified_device_service.py→app/services/device_service.py - 重命名
app/services/enhanced_adb_service.py→app/services/auto_discovery_adb_service.py
架构优化:
- 单一入口点:
/api/v1/devices - 统一设备管理:支持注册设备和自动发现设备
- 清晰的责任分离:API层、服务层、核心层
设备管理器增强
问题:用户选择"方案B:在 DeviceManager 中添加自动发现设备管理"
解决方案:在DeviceManager中集成自动发现设备管理
文件变更:
- 更新
app/core/device/manager.py- 添加自动发现设备管理 - 更新
app/services/device_service.py- 使用统一设备管理
新增功能:
handle_auto_discovered_device_event()- 处理自动发现设备事件get_auto_discovered_devices()- 获取自动发现设备get_all_devices_unified()- 获取所有设备(统一视图)get_device_source()- 获取设备来源remove_auto_discovered_device()- 移除自动发现设备update_auto_discovered_device_info()- 更新自动发现设备信息cleanup_offline_auto_discovered_devices()- 清理离线设备
架构优势:
- 统一的设备状态管理
- 自动发现和手动注册设备统一处理
- 更好的可维护性
应用启动优化
问题:启动时出现"no running event loop"错误
解决方案:使用FastAPI事件处理器管理异步任务
文件变更:
- 更新
app/core/app/factory.py- 添加启动和关闭事件处理器 - 更新
app/services/auto_discovery_adb_service.py- 移除自动启动监控
优化内容:
- 使用
@app.on_event("startup")启动设备监控 - 使用
@app.on_event("shutdown")停止设备监控 - 避免在构造函数中创建异步任务
路由注册修复
问题:路由注册失败,出现"no running event loop"错误
解决方案:修复异步任务创建时机
文件变更:
- 更新
app/api/v1/endpoints/enhanced_adb.py- 使用懒加载初始化服务 - 更新
app/core/app/router.py- 简化路由注册
修复内容:
- 延迟服务初始化到实际使用时
- 移除构造函数中的异步任务创建
- 使用事件处理器管理生命周期
设备监控增强
问题:需要增强设备监控日志和启动触发
解决方案:增强监控功能和日志记录
文件变更:
- 更新
app/services/auto_discovery_adb_service.py- 增强监控功能
增强内容:
- 添加更详细的日志记录
- 改进设备状态处理
- 增强错误处理和恢复机制
初始问题修复
问题:应用启动失败,路由注册错误
解决方案:修复异步任务和事件循环问题
文件变更:
- 更新多个核心文件以修复启动问题
- 优化异步任务管理
- 改进错误处理机制
WebSocket最小API调整(2025-08-07)
-
将
app/api/v1/endpoints/websocket.py简化为最小集合:- 保留
POST /websocket/clients(创建并连接客户端,合并原创建和连接) - 保留
POST /websocket/clients/{name}/disconnect(断开客户端) - 移除其余获取/订阅/广播/统计等接口,遵循“只需获取、连接、停止”的产品要求精简为仅连接与断开(获取由其他内部接口/日志替代)
- 保留
-
目的:
- 降低对外API面,减少维护成本
- 与“Channel预创建 + 适配器内部管理”策略一致
-
影响:
- 如需查询状态,暂通过内部服务统计或后续单独的只读接口再行补充
-
WebSocket改进:
app/core/websocket/client.py支持"*"通配消息处理器(未匹配到具体type时回退)。app/services/websocket_service.py在创建并连接客户端后,自动为其:- 确保默认Channels存在并连接
- 创建并启动与默认Channels的适配器
- 从而保证“按Channel读写”链路即刻可用(发送走Adapter→Client,接收由Client注册的处理器经Adapter写入Channel)。
去服务层解耦(2025-08-07)
-
目标:消除
websocket_service与核心层的重复职责,API与启动流程直接依赖websocket_manager与WebSocketConfig。 -
变更:
app/api/v1/endpoints/websocket.py直接调用websocket_manager完成创建/连接/断开,并在创建成功后初始化默认Channels与适配器。app/core/app/factory.py启动时直接创建并连接默认Channels,关闭时调用websocket_manager.cleanup()。- 后续可删除
app/services/websocket_service.py文件(当前仍保留便于迁移过渡,无对外API依赖)。
-
WebSocket严格版重构:
- 禁用直发与广播:
websocket_service.send_message/broadcast_message改为拒绝外部调用,仅允许写入 Channel 由 Adapter 转发。 - 私有发送:
WebSocketClient.send_message重命名为_send_message,仅供 Adapter 调用;心跳仍为内部私有发送。 - 出入通道分离:
WebSocketAdapter支持outbound_channel与inbound_channel;默认两者同名同一Channel,后续可按需拆分不同Channel。 - 适配器幂等恢复:
WebSocketManager.create_adapter若存在且任务未运行则自动重启,并确保 Channel 连接。 - 创建客户端后自动为默认 Channels 建立适配器并连接,保证 Channel→Adapter→Client 链路即刻可用。
- 心跳数据格式收敛:按用户指定的 .NET 模型,仅发送
{ "Type": "heartbeat", "Payload": { "Message": "ping" } },不附加任何其他字段;由WebSocketAdapter在优先级Channel写入并由发送循环优先发送。
- 禁用直发与广播:
WebSocket适配器心跳循环触发机制分析
问题: 创建并连接客户端后,adapter.py 中的 _heartbeat_loop 什么时候会触发?
分析结果:
-
触发时机:
_heartbeat_loop在适配器启动时自动触发 -
触发流程:
创建客户端 → 连接客户端 → 创建适配器 → 调用 adapter.start() → 启动 _heartbeat_loop -
具体代码路径:
websocket.py第23行: 创建并连接客户端- 第40-42行: 为每个默认Channel创建适配器
manager.py第133-170行:create_adapter方法- 第160行: 调用
await adapter.start() adapter.py第35-50行:start()方法- 第47行: 启动心跳任务
self._heartbeat_task = asyncio.create_task(self._heartbeat_loop())
-
心跳循环机制:
- 心跳间隔: 由
heartbeat_interval参数控制(默认120秒) - 心跳消息: 发送
{"Message": "ping"}格式的JSON - 优先级处理: 心跳消息通过优先级Channel发送,确保优先处理
- 循环条件: 当客户端连接状态为
self.client.is_connected时持续运行
- 心跳间隔: 由
-
停止条件:
- 客户端断开连接
- 适配器被停止(调用
adapter.stop()) - 任务被取消(
asyncio.CancelledError)
结论: _heartbeat_loop 在适配器创建并启动后立即开始运行,按照指定的心跳间隔定期发送心跳消息,直到客户端断开或适配器停止。
日志系统统一更新
问题: 项目中大量文件仍在使用旧的 get_logger(__name__) 方式,需要统一更新为新的结构化日志系统
解决方案: 将所有核心模块的日志导入方式从 get_logger 更新为 get_structured_logger
更新的文件列表:
核心模块 (app/core/)
app/core/websocket/adapter.py- WebSocket适配器app/core/websocket/manager.py- WebSocket管理器app/core/websocket/client.py- WebSocket客户端app/core/websocket/channel.py- WebSocket通道app/core/device/manager.py- 设备管理器app/core/device/dispatcher.py- 设备分发器
API端点 (app/api/v1/endpoints/)
app/api/v1/endpoints/websocket.py- WebSocket APIapp/api/v1/endpoints/devices.py- 设备APIapp/api/v1/endpoints/at.py- AT命令APIapp/api/v1/endpoints/ssh.py- SSH APIapp/api/v1/endpoints/plnk.py- PLNK API
服务层 (app/services/)
app/services/adb_service.py- ADB服务app/services/device_service.py- 设备服务app/services/at_service.py- AT服务app/services/atx_service.py- ATX服务app/services/plnk_service.py- PLNK服务app/services/ssh_service.py- SSH服务
工具类 (app/utils/)
app/utils/api_decorators.py- API装饰器app/utils/adb_utils.py- ADB工具app/utils/tcp_utils.py- TCP工具app/utils/serial_utils.py- 串口工具
更新内容:
# 旧方式
from app.utils.log import get_logger
logger = get_logger(__name__)
# 新方式
from app.utils.structured_log import get_structured_logger, LogLevel
logger = get_structured_logger(__name__, LogLevel.INFO)
优势:
- ✅ 统一使用结构化日志系统
- ✅ 日志文件简化管理(只有
app.log和error.log两个文件) - ✅ 异常日志包含完整堆栈跟踪
- ✅ 正常日志不包含堆栈跟踪,减少文件大小
- ✅ 按日志级别自动分流
- ✅ 保持控制台输出功能
注意事项:
- 测试文件(test_*.py)暂未更新,因为它们可能不需要结构化日志
- 所有核心业务逻辑模块已更新完成
- 新的日志系统提供更好的日志管理和分析能力