fastbee/上电触发响应处理优化说明.md
2025-12-30 08:02:52 +08:00

4.7 KiB
Raw Permalink Blame History

上电触发响应处理优化说明

优化目标

在上电触发场景下,在协议解码之前拦截设备回复,直接匹配到等待的requestR()调用,避免走完整的协议解码和MQ流程,减少通信负担,提高响应速度。

实现方案

1. 新增Handler:PowerOnTriggerResponseHandler

位置: fastbee-server/iot-server-core/src/main/java/com/fastbee/server/handler/PowerOnTriggerResponseHandler.java

功能:

  • 在协议解码之前拦截设备回复的原始ByteBuf数据
  • 创建简单的Message对象(不解析内容)
  • 调用Session.response()尝试匹配到等待的requestR()调用
  • 如果匹配成功,requestR()会立即返回,无需等待协议解码

2. Handler链顺序

TCPMessageAdapter (接收原始ByteBuf)
  ↓
PowerOnTriggerResponseHandler (拦截并匹配响应) ← 新增
  ↓
MessageDecoderWrapper (协议解码)
  ↓
DispatcherHandler (消息分发)

3. 工作原理

1. 平台下发指令
   PowerOnTriggerTaskExecutor.execute()
     → MessageManager.requestR()
       → Session.request() 订阅等待响应

2. 设备回复原始字节数据
   设备发送:ByteBuf (例如:7E 01 03 00 00 00 02 C4 0B 7E)

3. PowerOnTriggerResponseHandler拦截
   - 接收原始ByteBuf
   - 创建简单的Message对象(不解析内容)
   - 调用Session.response()尝试匹配

4. 匹配成功
   - Session.response()找到等待的request
   - 立即唤醒等待的Mono
   - requestR()返回成功(code=200, data=Message对象)
   - PowerOnTriggerTaskExecutor收到响应,更新任务状态

5. 继续传递(可选)
   - 如果继续传递,协议解码也会处理(但上电触发任务已完成)
   - 如果不想走协议解码,可以注释掉ctx.fireChannelRead(msg)

优势

  1. 减少通信负担

    • 不需要走完整的协议解码流程
    • 不需要发送到MQ异步处理
    • 直接同步匹配,响应更快
  2. 提高精准度

    • 直接匹配等待的request,不依赖协议特征识别
    • 避免协议解码误判导致的问题
  3. 降低延迟

    • 200ms内设备回复,立即匹配成功
    • 无需等待协议解码和MQ处理

代码修改

1. PowerOnTriggerResponseHandler.java

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    Packet packet = (Packet) msg;
    Session session = packet.session;
    ByteBuf byteBuf = packet.byteBuf;

    // 创建简单的Message对象,只用于匹配响应
    Message responseMessage = new Message();
    responseMessage.setClientId(session.getClientId());
    responseMessage.setPayload(byteBuf.retain());

    // 尝试匹配到等待的request
    boolean matched = session.response(responseMessage);
    
    if (matched) {
        log.debug("=>上电触发-设备回复已匹配,设备编号:{}", session.getClientId());
        // 匹配成功,继续传递(可选)
        ctx.fireChannelRead(msg);
    } else {
        // 没有匹配到,继续正常流程
        responseMessage.getPayload().release();
        ctx.fireChannelRead(msg);
    }
}

2. TCPServer.java

channel.pipeline()
    .addLast(FastBeeConstant.SERVER.ADAPTER, adapter)
    .addLast("powerOnTriggerHandler", powerOnTriggerHandler) // 新增
    .addLast(FastBeeConstant.SERVER.DECODER, decoder)
    // ...

使用说明

当前实现

  • 匹配成功:requestR()立即返回,PowerOnTriggerTaskExecutor收到响应
  • 继续传递:消息继续传递给协议解码器(可选,如果不想走协议解码可以注释掉)

如果不想走协议解码

如果完全不想走协议解码,可以修改PowerOnTriggerResponseHandler:

if (matched) {
    log.debug("=>上电触发-设备回复已匹配,设备编号:{}", session.getClientId());
    // 匹配成功,直接消费掉,不走协议解码
    byteBuf.release(); // 释放ByteBuf
    return; // 不继续传递
}

注意事项

  1. ByteBuf引用计数

    • 使用byteBuf.retain()增加引用计数
    • 如果匹配失败,需要release()释放
    • 如果匹配成功,后续处理器会负责释放
  2. 兼容性

    • 如果匹配失败,继续走正常流程(协议解码等)
    • 不影响其他功能
  3. 性能

    • 只在上电触发场景下生效
    • 其他场景继续走正常流程

测试建议

  1. 验证匹配成功

    • 下发上电触发指令
    • 设备回复后,检查requestR()是否立即返回
    • 检查PowerOnTriggerTaskExecutor是否正确更新任务状态
  2. 验证性能

    • 对比优化前后的响应时间
    • 检查是否减少了MQ消息量
  3. 验证兼容性

    • 确保其他功能不受影响
    • 确保协议解码仍然正常工作