目录

如何解决蓝牙/星闪协商MTU参数失败的问题

问题现象

在蓝牙/星闪功能开发过程中,协商MTU时,有时会出现2900099/1009700099错误的问题,该如何解决?

背景知识

问题定位

分析结论

修改建议

协商MTU前,需保证client端同server端处于连接的状态,且协商的MTU参数需要设置在取值范围内。蓝牙/星闪端代码参考如下:

import { ble, constant } from '@kit.ConnectivityKit';
import { ssap } from '@kit.NearLinkKit';

@Entry
@Component
struct BleAndSsapSetMtu {
  @State gattClient: ble.GattClientDevice | undefined = undefined;
  @State ssapClient: ssap.Client | undefined = undefined;

  // 设置ble端mtu
  setBleMtu() {
    // 创建client端实例,bleMac为server端虚拟mac地址,需要提前获取
    this.gattClient = ble.createGattClientDevice('bleMac');
    // 订阅ble蓝牙连接状态监听事件
    this.onBLEConnectionStateChange();
    // 订阅MTU协商结果监听事件
    this.BLEMtuChange();
    // 连接server端ble蓝牙
    this.gattClient.connect();
  }

  onBLEConnectionStateChange() {
    this.gattClient?.on('BLEConnectionStateChange', (state: ble.BLEConnectionChangeState) => {
      // state.state返回结果为2时,表示client端同server端成功建立了连接。
      if (state.state === constant.ProfileConnectionState.STATE_CONNECTED) {
        // 调用setBLEMtuSize接口,同server端协商MTU,参数取值范围23~517。
        this.gattClient?.setBLEMtuSize(128);
      }
    });
  }

  BLEMtuChange() {
    this.gattClient?.on('BLEMtuChange', (mtu: number) => {
      // MTU协商结果监听回调,回调触发,表示协商成功。
      console.info(`BLEMtuChange, mtu: ${mtu}`);
    });
  }

  // 设置星闪端mtu
  setSsapMtu() {
    // 创建client端实例,ssapMac为server端虚拟mac地址,需要提前获取
    this.ssapClient = ssap.createClient('ssapMac');
    // 订阅ble蓝牙连接状态监听事件
    this.onConnectionStateChange();
    // 订阅MTU协商结果监听事件
    this.ssapMtuChange();
    // 连接server端ble蓝牙
    this.ssapClient.connect();
  }

  onConnectionStateChange() {
    this.ssapClient?.on('connectionStateChange', (state: ssap.ConnectionChangeState) => {
      // state.state返回结果为1时,表示client端同server端成功建立了连接。
      if (state.state === 1) {
        // 调用requestMtuSize接口,同server端协商MTU,参数取值范围22~512,默认值为256字节。
        this.ssapClient?.requestMtuSize(128);
      }
    });
  }

  ssapMtuChange() {
    this.ssapClient?.on('mtuChange', (mtu: number) => {
      // MTU协商结果监听回调,回调触发,表示协商成功。
      console.info(`mtuChange, mtu:  ${mtu}`);
    });
  }

  build() {
    Column() {
      Button('连接ble蓝牙,并协商MTU').onClick(() => {
        // 连接ble蓝牙,并协商MTU
        this.setBleMtu();
      }).margin(15);

      Button('连接星闪,并协商MTU').onClick(() => {
        // 连接星闪,并协商MTU
        this.setSsapMtu();
      });
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.SpaceAround);
  }
}

常见FAQ

Q:在BLE蓝牙开发流程中,setBLEMtuSize()接口在什么时候调用最合适?

A:setBLEMtuSize()方法只能在调用connect()接口成功连接上蓝牙之后调用。建议在调用getServices()接口获取server端支持的所有服务能力之前调用。