You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

26 KiB

修改记录

2025-08-11

应用启动优化 - 移除不必要的WebSocket Channel初始化

问题startup_event 中初始化默认WebSocket Channels是不必要的,因为:

  1. Channels是在需要时才创建的(按需创建)
  2. 真正的客户端连接是在API调用 create_and_connect_client 时才进行的
  3. 启动时创建空的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

根本原因

  1. WebSocket连接没有设置超时时间,导致长时间等待
  2. 心跳间隔配置不一致,代码中默认30秒,但日志显示2分钟
  3. 缺少专门的超时异常处理

解决方案

  1. 增加连接超时配置和异常处理
  2. 统一心跳间隔配置为120秒(2分钟)
  3. 添加连接超时测试脚本

文件变更

  1. 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
  1. 配置统一
  • app/core/config/settings.py: 心跳间隔改为120秒,连接超时改为60秒
  • app/schemas/websocket.py: 默认心跳间隔改为120秒
  • app/core/websocket/adapter.py: 默认心跳间隔改为120秒
  • app/core/websocket/manager.py: 默认心跳间隔改为120秒
  1. 测试脚本 (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

改进内容

  1. URL验证增强:添加URL格式验证,确保以ws://或wss://开头
  2. 错误处理改进:区分不同类型的错误(超时、URL格式错误、连接失败)
  3. 日志增强:添加更详细的连接日志,包括URL和超时时间
  4. 测试工具
    • 更新测试脚本使用更可靠的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接口传递心跳间隔参数

修改内容

  1. 请求模型更新 (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="心跳间隔(秒)")
  1. 适配器更新 (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)  # 使用配置的心跳间隔
  1. 管理器更新 (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)
  1. 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 - 获取所有Channel
  • GET /websocket/stats - 获取统计信息

连接功能

  • POST /websocket/clients - 创建客户端
  • POST /websocket/clients/{name}/connect - 连接客户端
  • POST /websocket/subscribe - 订阅Channel
  • POST /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 - 动态创建Channel
  • DELETE /websocket/channels/{name} - 移除Channel
  • GET /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.pyapp/services/device_service.py
  • 重命名 app/services/enhanced_adb_service.pyapp/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_managerWebSocketConfig

  • 变更:

    • 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_channelinbound_channel;默认两者同名同一Channel,后续可按需拆分不同Channel。
    • 适配器幂等恢复:WebSocketManager.create_adapter 若存在且任务未运行则自动重启,并确保 Channel 连接。
    • 创建客户端后自动为默认 Channels 建立适配器并连接,保证 Channel→Adapter→Client 链路即刻可用。
    • 心跳数据格式收敛:按用户指定的 .NET 模型,仅发送 { "Type": "heartbeat", "Payload": { "Message": "ping" } },不附加任何其他字段;由 WebSocketAdapter 在优先级Channel写入并由发送循环优先发送。

WebSocket适配器心跳循环触发机制分析

问题: 创建并连接客户端后,adapter.py 中的 _heartbeat_loop 什么时候会触发?

分析结果:

  1. 触发时机: _heartbeat_loop 在适配器启动时自动触发

  2. 触发流程:

    创建客户端 → 连接客户端 → 创建适配器 → 调用 adapter.start() → 启动 _heartbeat_loop
    
  3. 具体代码路径:

    • 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())
  4. 心跳循环机制:

    • 心跳间隔: 由 heartbeat_interval 参数控制(默认120秒)
    • 心跳消息: 发送 {"Message": "ping"} 格式的JSON
    • 优先级处理: 心跳消息通过优先级Channel发送,确保优先处理
    • 循环条件: 当客户端连接状态为 self.client.is_connected 时持续运行
  5. 停止条件:

    • 客户端断开连接
    • 适配器被停止(调用 adapter.stop()
    • 任务被取消(asyncio.CancelledError

结论: _heartbeat_loop 在适配器创建并启动后立即开始运行,按照指定的心跳间隔定期发送心跳消息,直到客户端断开或适配器停止。