Charge-BleMessage

作用

将硬件发来的原始字节流(List<int>)解析成结构化的消息对象,并处理可能的分包(多个数据包拼成一条完整消息)。

分包机制解析

Dart 复制代码
假设要发送100字节的数据,但蓝牙MTU限制每次只能传20字节
硬件会把数据分成5个包发送

第1包: size=5, offset=1, data=[前20字节]
第2包: size=5, offset=2, data=[第21-40字节]
第3包: size=5, offset=3, data=[第41-60字节]
第4包: size=5, offset=4, data=[第61-80字节]
第5包: size=5, offset=5, data=[第81-100字节]

BleMessage 的工作:
1. 从第一包知道总共有5包
2. 接收每一包,把数据合并到 payload
3. 当 size == offset 时,说明接收完成

定义变量,根据需要和协议的协定,定义变量

Dart 复制代码
  late int cmd; //命令类型

  List<int> payload = []; //实际数据内容

  late int len; //数据长度

  bool _response = false; //判断是否为回复

  bool success = true; //通信是否成功

  late final List<int> raw; //原始数据

  /// 总包数
  int size = 0;
  /// 当前包
  int offset = 0;

构造函数

Dart 复制代码
  BleMessage.from(List<int> data) {
    //协议头
    cmd = data[1] & 0xFF; //命令类型

    _response = data[2] == 0x02; //判断是否为回复

    size = (data[3] & 0xF0) >> 4; //前四位为总帧数

    offset = data[3] & 0x0F; //后四位为帧序号

    len = data[4] & 0xFF; //数据长度

    //提取实际数据
    payload.addAll( data.sublist(5));
    //如果是回复包,检查最后一个字节
    if(_response ) {
      success = data.last == 0; //协议协定
    }
    raw = data;
    Log.d("size: $size length: $len");

  }

合并后续分片的方法

Dart 复制代码
  void contact(List<int> data) {

    raw.addAll(data); //保存原始数据

    //空安全检查
    if(size == 0 || data[1] != cmd || data[3] & 0x0F == 0) {
      Log.d("message contact error");
      return;
    }

    Log.d("size: $size offset $offset");

    offset = data[3] & 0x0F; //更新当前包序号

    payload.addAll(data.sublist(5)); //合并数据
  }

提供给外部的get方法

Dart 复制代码
  //判断是否已接收完所有分片
  bool get isAll =>  size == offset;

  //命令执行是否成功
  bool get isSuccess {
    if(_response ) {
      if(payload.last != 0) {
        return false;
      }
    }
    return true;
  }

代码示例

Dart 复制代码
import '../log.dart';
import 'cmd_type.dart';

///蓝牙接收类(处理分包)

// enum  ErrorCode{  //OTA项目,与充电宝项目无关
//   success,
//   failed,
//   lengthError,
//   cmdError,
//   indexError,
//   notSupport,
//   switchError,
//   checkError,
//   packetLost,
// }


class BleMessage {

  //变量定义
  late int cmd; //命令类型

  List<int> payload = []; //实际数据内容

  late int len; //数据长度

  bool _response = false; //判断是否为回复

  bool success = true; //通信是否成功

  late final List<int> raw; //原始数据

  /// 总包数
  int size = 0;
  /// 当前包
  int offset = 0;


  // bool get response {  //耳机项目,与充电宝无关
  //   if(payload.isNotEmpty &&
  //       payload.length > 1 &&
  //       (payload[0] == DeviceInfoType.battery ||
  //           payload[0] == DeviceInfoType.firmware ||
  //           payload[0] == DeviceInfoType.port ||
  //           payload[0] == DeviceInfoType.capacity ||
  //           payload[0] == DeviceInfoType.model ||
  //           payload[0] == DeviceInfoType.temperature
  //           payload[0] == DeviceInfoType.mtu ||
  //           payload[0] == DeviceInfoType.tws ||
  //           payload[0] == DeviceInfoType.twsState ||
  //           payload[0] == DeviceInfoType.eq ||
  //           payload[0] == DeviceInfoType.noiseLevel ||
  //           payload[0] == DeviceInfoType.noiseLevelCount ||
  //           payload[0] == DeviceInfoType.transparentLevel ||
  //           payload[0] == DeviceInfoType.transparentLevelCount ||
  //           payload[0] == DeviceInfoType.name ||
  //           payload[0] == DeviceInfoType.version ||
  //           payload[0] == DeviceInfoType.button ||
  //           payload[0] == DeviceInfoType.language ||
  //           payload[0] == DeviceInfoType.autoAnswer ||
  //           payload[0] == DeviceInfoType.led ||
  //           payload[0] == DeviceInfoType.mode ||
  //           payload[0] == DeviceInfoType.face
  //       )) {
  //     return false;
  //   }
  //   return _response;
  // }

  //构造函数
  BleMessage.from(List<int> data) {
    //协议头
    cmd = data[1] & 0xFF; //命令类型

    _response = data[2] == 0x02; //判断是否为回复

    size = (data[3] & 0xF0) >> 4; //前四位为总帧数

    offset = data[3] & 0x0F; //后四位为帧序号

    len = data[4] & 0xFF; //数据长度

    //提取实际数据
    payload.addAll( data.sublist(5));
    //如果是回复包,检查最后一个字节
    if(_response ) {
      success = data.last == 0; //协议协定
    }
    raw = data;
    Log.d("size: $size length: $len");

  }

  //合并后续分片数据
  void contact(List<int> data) {

    raw.addAll(data); //保存原始数据

    //空安全检查
    if(size == 0 || data[1] != cmd || data[3] & 0x0F == 0) {
      Log.d("message contact error");
      return;
    }

    Log.d("size: $size offset $offset");

    offset = data[3] & 0x0F; //更新当前包序号

    payload.addAll(data.sublist(5)); //合并数据
  }

  //判断是否已接收完所有分片
  bool get isAll =>  size == offset;

  //命令执行是否成功
  bool get isSuccess {
    if(_response ) {
      if(payload.last != 0) {
        return false;
      }
    }
    return true;
  }

 // int get errorCode => payload.last; //OTA项目,与充电宝项目无关



}
相关推荐
开发小程序的之朴8 小时前
安企CMS的安装-PHPStudy(小皮面板)部署
windows·mysql·nginx
love530love8 小时前
【硬核排障 & 猴子补丁 & 幽灵节点】SageAttention GQA 崩溃与 Flash Attention 兼容性修复全记录
ide·人工智能·windows·comfyui·sageattention·windows cuda
John Song18 小时前
ansible-playbook常用的检查命令
windows·ansible
视觉AI19 小时前
VS Code Remote-SSH 连接Jetson踩坑完整解决记录(网段不通+主机密钥变更双重故障)
运维·网络·人工智能·windows·ssh·边缘计算
观远数据1 天前
从离线开发到实时同步:DataFlow如何支撑企业级数据治理闭环
java·windows·microsoft·excel
绀目澄清1 天前
私服网游云加速程序劫持流量排查与修复总结
windows·安全
FL16238631291 天前
Windows手动下载安装配置uv 0.11.29配置国内源含安装包和安装教程
windows·uv
Jelena157795857921 天前
淘宝商品详情API接口开发指南:应用市场选品比价实战
windows·microsoft
乖巧的妹子1 天前
刷题总结知识
linux·服务器·windows