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

React Native通过BLE NUS向树莓派发送Base64数据解码失败问题

问题解决:Nordic UART BLE传输拆包导致Base64解码失败

核心问题

React Native通过Nordic UART服务和树莓派GATT服务器通信时,retrieveHubConfig指令、Base64编码的JSON数据会被拆成100字符的小包传输,导致树莓派解码时出现填充错误、UTF-8无效字节、Base64字符数不符合规则等问题。

根本原因

Nordic UART的默认分包阈值通常设为100字符,而BLE传输本身是流式的,不会自动帮你拼接数据包,必须在应用层实现分包重组逻辑,不然只解码片段肯定会出错。


解决方案

两端配合处理:发送端给完整消息加结束标记,接收端先缓存拼接完整数据包,再解码处理。

1. React Native发送端修改

给每个要发送的完整消息加个结束标记(比如换行符\n),让接收端能识别出完整数据包:

// React Native发送函数示例
const sendDataToHub = async (data) => {
  // 字符串指令直接用,JSON先转Base64
  let encodedData = typeof data === 'string' ? data : btoa(JSON.stringify(data));
  // 加结束标记
  encodedData += '\n';
  // 走Nordic UART发送
  await bleManager.writeCharacteristicForDevice(
    deviceId,
    NUS_SERVICE_UUID,
    NUS_TX_CHARACTERISTIC_UUID,
    encodedData
  );
};

// 发送指令示例
sendDataToHub('retrieveHubConfig');
// 发送JSON数据示例
sendDataToHub({ wifiSSID: "MyWiFi", password: "123456" });

2. 树莓派接收端修改

在接收回调里先缓存字节流,检测到结束标记后再取出完整消息解码:

import base64
import json

# 全局缓存,存未拼接完的数据包
received_buffer = ""

def handle_received_data(data):
    global received_buffer
    # 字节转字符串,统一用UTF-8编码
    received_str = data.decode('utf-8')
    received_buffer += received_str
    
    # 循环处理所有已完成的数据包
    while '\n' in received_buffer:
        # 拆分出完整消息和剩余缓存
        full_msg, received_buffer = received_buffer.split('\n', 1)
        process_full_message(full_msg)

def process_full_message(msg):
    try:
        # 判断是指令还是Base64 JSON
        if msg == 'retrieveHubConfig':
            # 执行读取.ini文件逻辑
            print("收到读取配置指令")
            # 这里加你的.ini读取代码
        else:
            # 解码Base64,开启校验确保格式正确
            decoded_bytes = base64.b64decode(msg, validate=True)
            # 转JSON
            json_data = json.loads(decoded_bytes.decode('utf-8'))
            # 执行写入.ini逻辑
            print("收到配置JSON:", json_data)
            # 这里加你的.ini写入代码
    except base64.binascii.Error as e:
        print(f"Base64解码失败: {e}")
    except json.JSONDecodeError as e:
        print(f"JSON解析失败: {e}")
    except UnicodeDecodeError as e:
        print(f"UTF-8解码失败: {e}")

# GATT接收回调里调用handle_received_data(根据你的框架调整)
def on_characteristic_write_request(char, value, options):
    handle_received_data(value)
    return char.RESULT_SUCCESS

3. 额外优化:协商更大MTU

如果数据包比较大,连接成功后协商更大的MTU,减少分包次数:

React Native端协商MTU

// 设备连接成功后调用
await bleManager.requestMtu(deviceId, 512); // 最大支持512字节,看硬件能力

树莓派端开启MTU支持

用bluetoothctl配置:

bluetoothctl
menu gatt
set mtu 512
exit

对应报错的解决逻辑

  • 填充错误/Base64字符数异常:之前只解码了片段,拼接成完整消息后字符数自然是4的倍数,不用手动补填充符。
  • UTF-8无效字节:分包的字节可能不是完整的UTF-8字符,拼接成完整字符串后再解码就不会出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:22:34