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

安卓与Ublox NINA B1 BLE通知配置及数据丢包问题求助

正确设置Indication的方案

  1. 不要同时开启通知和指示:Ublox NINA B1的SPS服务FIFO特征值仅支持Notification,你当前写死0x03同时开启两种模式的操作会导致外设配置失败,正确的做法是先判断特征值的属性再设置描述符值:
    • 若特征值含BluetoothGattCharacteristic.PROPERTY_NOTIFY,描述符设为BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE(即0x01, 0x00)
    • 若含BluetoothGattCharacteristic.PROPERTY_INDICATE,设为BluetoothGattDescriptor.ENABLE_INDICATION_VALUE(即0x02, 0x00)
  2. 移除延迟写描述符的逻辑:Android BLE栈要求所有GATT操作串行执行,靠延迟保证顺序不可靠,你需要在onDescriptorWrite回调中监听配置结果,确认返回BluetoothGatt.GATT_SUCCESS后,再开始数据收发,否则说明通知未正常开启。
  3. 增加描述符存在性校验:你当前的代码没有判断getDescriptor返回是否为null,若特征值不存在对应CCC描述符,后续操作会直接空崩。

正确的设置代码示例:

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    // 先设置本机的通知开关
    boolean setSuccess = mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    if (!setSuccess) {
        Log.e(TAG, "开启本地通知失败");
        return;
    }
    // 校验CCC描述符存在
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(getString(R.string.CLIENT_CHARACTERISTIC_CONFIG)));
    if (descriptor == null) {
        Log.e(TAG, "未找到CCC描述符");
        return;
    }
    // 根据特征属性设置描述符值
    if (enabled) {
        int props = characteristic.getProperties();
        if ((props & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else if ((props & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        } else {
            Log.e(TAG, "特征值不支持通知/指示");
            return;
        }
    } else {
        descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    }
    // 直接执行写描述符,不要加延迟,在回调中判断结果
    mBluetoothGatt.writeDescriptor(descriptor);
}

数据丢失的常见原因及修复方案

  • GATT操作并发导致通知配置失败:你当前在enableNotification方法中同时触发了读特征值、开通知两个GATT操作,Android BLE栈不支持并发GATT请求,会直接丢弃后续请求,导致通知未正常开启。需要将所有GATT操作加入串行队列,等上一个操作的回调返回后再执行下一个。
  • SPS流控未实现:Ublox NINA B1的SPS服务依赖Credits特征值做流控,你需要每收到20字节数据就给外设返还一个Credit,否则外设的发送缓冲区满后会主动丢包,这是SPS场景下丢包的最常见原因。
  • 接收逻辑缺陷:
    1. 你当前仅在request_flag为true时才存储接收数据,若外设提前返回数据、或上一次请求的残留数据未处理,会直接丢弃有效数据。
    2. 你对rx_Data执行Arrays.fill(rx_Data, (byte) 0)的操作会导致部分复用数组的Android BLE实现后续返回空数据,直接移除该行即可。
    3. 缓冲区缺少超时机制:如果只收到部分报文,既没达到预期长度也没超过长度,会一直占用缓冲区,导致后续接收的数据全部错位丢包,需要增加超时判断,超过100ms没收到完整报文就清空缓冲区。
  • 连接参数不合理:主动请求BLE连接间隔为10~20ms,避免手机或外设自动拉长连接间隔导致缓冲区溢出丢包。
  • MTU未协商:虽然你当前报文小于20字节,但可以主动协商更大的MTU(比如247),减少分片概率,进一步降低丢包可能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:45:01