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

Android蓝牙向ESP32传输文件时数据不一致问题求助

蓝牙OBEX传输图片到ESP32时数据损坏问题排查

场景与代码修改

我通过蓝牙OBEX协议,使用ESP32-Bluetooth-FTP库实现从Android手机向ESP32传输图片文件,在接收文件内容的代码段中添加了逐包写入本地文件的逻辑:

// Contains file contents
            else if (packet[i] == 0x48)
            {
                uint16_t head_len = packet[i + 1] * 256 + packet[i + 2];

                // MY OWN LINES
                if (out_file != NULL) {
                    fwrite(&packet[i+3], sizeof(char), head_len - 3, out_file);
                }
                // MY OWN LINES

                // printf("File contents : \n");
                // Just suming the file contents
                for (int j = i + 3; j < head_len + i; j++)
                {
                    file_sum += packet[j];
                    // printf("%c", packet[j]);
                }
                i += head_len;
            }

问题现象

接收的数据始终存在损坏:

  • 发送蓝色位图文件后,ESP32收到的文件出现规律的红绿线条,说明字节模式发生移位,且线条长度固定,疑似数据包起始位置偏移;
  • 查看字节序列发现,某位置少了一个0字节,故障末尾多了一个0字节后恢复正常;
  • 少数情况下损坏始于位图头,导致文件无法读取;
  • 从未成功从Windows 10传输文件。

怀疑方向

已排除数据完整性问题(数据仅含0和FF字节),目前怀疑:

  • fwrite操作是否会延迟中断服务程序,导致丢包?
  • 代码中索引位置计算是否偶尔出错?

可能的问题点与测试方案

1. 中断上下文的文件IO阻塞问题

ESP32的蓝牙OBEX回调大概率运行在中断上下文,而fwrite是阻塞式文件IO操作,会占用大量CPU时间,导致后续蓝牙数据包接收中断被延迟或丢失,进而引发字节移位。

  • 测试方案:
    • 将文件写入逻辑移出中断上下文:在中断中仅将数据包数据缓存到内存队列(比如FreeRTOS队列),创建独立任务从队列读取数据并写入文件;
    • 对比修改前后的文件完整性,验证是否是IO阻塞导致丢包。

2. 数据包长度计算错误

代码中head_len = packet[i + 1] * 256 + packet[i + 2]是大端转小端的计算,但需确认OBEX协议中0x48(Body Header)的长度字段定义:如果协议中head_len是整个头的总长度,那么head_len - 3是正确的内容长度;如果head_len已经是内容长度,会导致写入长度错误引发移位。

  • 测试方案:
    • 对照OBEX协议规范,确认0x48头的长度字段定义;
    • 在代码中打印head_len和实际数据包长度,对比计算出的内容长度是否与实际接收的字节数匹配;
    • 传输已知长度的测试文件(如1024字节全0文件),查看写入文件的实际长度是否正确。

3. 内存/队列溢出问题

如果缓存数据包的内存区域大小不足,或者队列长度不够,会导致后续数据包覆盖之前的数据,引发字节错乱。

  • 测试方案:
    • 检查packet数组的定义,确认其大小是否能容纳OBEX协议允许的最大数据包;
    • 若使用队列缓存,调整队列长度和元素大小,确保能容纳传输峰值的数据包数量;
    • 传输过程中打印数据包序号和长度,查看是否有数据包丢失或重复。

4. Windows传输的兼容性问题

Windows的OBEX实现可能与Android存在差异(如数据包大小、头字段格式),导致ESP32库无法正确解析,进而引发兼容性问题。

  • 测试方案:
    • 抓包对比Windows和Android的蓝牙OBEX传输包,查看协议头、数据包长度、字段顺序的差异;
    • 修改ESP32代码的OBEX头解析逻辑,兼容Windows格式,测试是否能正常接收;
    • 先解决Android传输的损坏问题,再单独排查Windows的兼容性。

5. 文件写入的类型匹配问题

如果packet是uint8_t类型,强制转为char*调用fwrite可能存在潜在问题(虽然0和FF字节不受符号扩展影响),可验证写入逻辑的准确性。

  • 测试方案:
    • 将fwrite的第二个参数改为sizeof(uint8_t)(若packet是uint8_t数组);
    • 对比原文件和接收文件的MD5值,定位损坏的具体位置,确认是否与某个数据包的写入长度相关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:25:12