You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript通过BLE发送大数据块?p5.ble.js图片发送异常求助

JavaScript通过BLE发送大数据块的问题排查与修复

核心错误原因

  1. 二进制数据转字符串的损坏:你用TextDecoder把图片的二进制数据解码成字符串,但图片数据并非合法的UTF-8文本序列。解码器遇到无法识别的字节时,会自动替换成替换字符�(对应的UTF-8编码就是你看到的239,191,189),直接破坏了原始二进制数据。
  2. 数组类型不兼容:最初尝试直接发送img.slice(0,127)失败,是因为img是普通数组,而p5.ble.js的write方法需要接收ArrayBuffer或TypedArray(比如Uint8Array)类型的二进制数据,而非普通数组。
  3. 分块逻辑的问题:slice(128,255)的索引范围有误差——slice是左闭右开,这个范围实际只包含127个字节,和第一个块长度不一致;另外用setTimeout控制发送顺序不可靠,容易出现时序问题或外设处理不过来的情况。

修复后的代码示例

首先把存储图片数据的容器改成Uint8Array(二进制数据的标准容器),然后用异步方式分块发送,确保每块发送完成后再发下一块:

let myBLE;
let img;

function setup() {
    myBLE = new p5ble();

    // 创建写入按钮
    const writeButton = createButton('Write');
    writeButton.mousePressed(writeToBle);

    // 用Uint8Array存储15000字节的二进制数据
    img = new Uint8Array(15000);
    for(let i = 0; i < 15000; i++) {
      img[i] = i;
    }
}

async function writeToBle() {
  // 每块的有效负载大小,根据你的BLE外设MTU调整(这里假设支持127字节)
  const chunkSize = 127;
  let currentOffset = 0;
  const totalLength = img.length;

  while(currentOffset < totalLength) {
    // 计算当前块的结束位置,避免超出数组长度
    const endOffset = Math.min(currentOffset + chunkSize, totalLength);
    // 截取当前块的Uint8Array
    const currentChunk = img.slice(currentOffset, endOffset);

    // 等待当前块发送完成再继续,确保顺序和可靠性
    await myBLE.write(myCharacteristic, currentChunk);

    // 更新偏移量,准备发送下一块
    currentOffset = endOffset;
    
    // 可选:添加短延迟,给外设留处理时间
    await new Promise(resolve => setTimeout(resolve, 100));
  }
}

关键说明

  • 直接传递Uint8Array给myBLE.write,绕过字符串转换,保证二进制数据的完整性。
  • 使用async/await替代setTimeout,确保分块发送的顺序和可靠性,避免丢包或乱序。
  • chunkSize需要根据你的BLE外设支持的MTU调整:BLE的MTU包含ATT层的3字节开销,所以有效负载大小是MTU - 3(比如MTU=130的话,有效负载就是127字节)。

内容的提问来源于stack exchange,提问作者Salahuddin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:21:20