uni-app 蓝牙4.0接收数据 setbiemtu回调成功 仍然只能接收20字节数据

uni-app 蓝牙4.0接收数据 setbiemtu回调成功 仍然只能接收20字节数据

开发环境 版本号 项目创建方式
Windows 1909 HBuilderX
### 操作步骤:
蓝牙芯片XC620(ble4.0),连接由设备发送20字节以上数据,真机调试只能接受20字节数据

### 预期结果:
setblemtu设置后   服务端26字节数据可全部接收 

### 实际结果:
前20字节数据被接受  后6字节数据丢失  无法触发特征值监听

### bug描述:
应用插件 微信小程序转UNIAPP  
设备端(蓝牙4.0)发送26字节数据  uniapp运行至手机只能接受20字节  且特征值监听只能触发一次   已调用blesetmtu且success回调  
测试蓝牙5.0   uniapp运行至手机 数据接收无误  
更换软件NRFconnect    (蓝牙4.0)不请求MTU   26字节log打印分两次接收    请求MTU后  可一次接收26字节

更多关于uni-app 蓝牙4.0接收数据 setbiemtu回调成功 仍然只能接收20字节数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html

9 回复

微信小程序可以用 蓝牙5.0也ok 到4.0就出问题 换NRFCONNECT调试也可以 没人遇到这种情况嘛?

更多关于uni-app 蓝牙4.0接收数据 setbiemtu回调成功 仍然只能接收20字节数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html


真机运行

微信小程序log

蓝牙4.0是这种差异 所以有常识拼包 但是后六个字节无法触发特征值监听

NRFCONNECT测试 MTU23

监听是两次 MTU507 一次接收全部

都没有遇到这个问题嘛?实在不行就要搞Android了

题主,你那时有弄出来吗,同样的问题设置了也是只能最大26不知道为什么,如果不设置只能20

回复 木杉丶: 解决这个问题了吗?

回复 1***@qq.com: 官方给的就是不行的,直接去市场买了个原生插件用了,原生的可以 https://ext.dcloud.net.cn/plugin?id=4945

回复 1***@qq.com: 其实你要是用官方的也行,只是要分段发送,比如最大20就每次20字节20字节的发送,但是官方的这个东西又有个bug就是每次发送间隔太长了。要是字节数据多这分段发送就慢太多了,当然你要是不要求速率你可以直接用官方的也行,但是那个最大字节设置是没用的只能做分段发送。

这是一个典型的蓝牙4.0 MTU限制问题。虽然你调用了setBLEMTU并收到success回调,但实际MTU协商可能并未真正生效。

问题分析:

  1. 蓝牙4.0默认MTU为23字节,扣除3字节ATT头后,有效载荷只有20字节
  2. 即使MTU协商成功,部分安卓设备对蓝牙4.0的MTU扩展支持不完善
  3. 蓝牙5.0由于原生支持更大MTU,所以工作正常

解决方案:

  1. 分片接收处理 在特征值变化的回调中,不要依赖单次完整数据,而是实现数据拼接:
let receivedData = new Uint8Array(0);

function onCharacteristicValueChange(res) {
  const newData = new Uint8Array(res.value);
  // 合并数据
  const mergedData = new Uint8Array(receivedData.length + newData.length);
  mergedData.set(receivedData);
  mergedData.set(newData, receivedData.length);
  receivedData = mergedData;
  
  // 根据协议判断数据完整性
  if (/* 数据完整判断条件 */) {
    // 处理完整数据
    processCompleteData(receivedData);
    receivedData = new Uint8Array(0); // 清空缓存
  }
}
  1. 优化MTU设置时机 在连接建立后立即设置MTU,并添加重试机制:
uni.setBLEMTU({
  deviceId: deviceId,
  mtu: 128, // 尝试设置较大值
  success: () => {
    console.log('MTU设置成功');
    // 延迟等待MTU生效
    setTimeout(() => {
      // 开始监听特征值
    }, 200);
  },
  fail: () => {
    // 即使失败也不影响分片接收
  }
});
回到顶部