简体   繁体   English

使用多个 BLE 外设连接处理 Android 上的通知

[英]Handling Notifications on Android with Multiple BLE Peripheral Connections

So, I am new to Android development and I am trying to connect my device to multiple BLE devices ( T-Wristband ) to receive frequent notifications (IMU sensor data less than 20 bytes at 50Hz ).因此,我是 Android 开发的新手,我正在尝试将我的设备连接到多个 BLE 设备( T-Wristband )以接收频繁的通知(IMU 传感器数据在50Hz时少于 20 个字节)。

When connecting to multiple devices, I miss data from one or more devices .连接到多个设备时,我丢失了一个或多个设备的数据 I suspect the reason is that my BluetoothGattCallback method, onCharacteristicChanged , is working on the same thread for all devices ( Note: I have checked that by logging Thread.currentThread.getName() ).我怀疑原因是我的BluetoothGattCallback方法onCharacteristicChanged正在为所有设备在同一个线程上工作(注意:我已经通过记录Thread.currentThread.getName()进行了检查)。

What I have tried:我试过的:

1. Android 4.3: How to connect to multiple Bluetooth Low Energy devices 1. Android 4.3:如何连接多个低功耗蓝牙设备

I suspect everyone adding delays is just allowing the BLE system to complete the action you have asked before you submit another one.我怀疑每个人添加延迟只是为了让 BLE 系统在您提交另一个之前完成您要求的操作。

Problem: I cannot add delays when receiving notifications since it would interfere with my sampling rate, and I am not sure when I might receive new notifications from another device, or even the same device.问题:我无法在接收通知时添加延迟,因为这会干扰我的采样率,而且我不确定何时可以从另一台设备甚至是同一台设备接收到新通知。

2. Android BLE multiple connections 2. Android BLE多连接

To achieve multiple BLE connections you have to store multiple BluetoothGatt objects and use those objects for a different device .要实现多个 BLE 连接,您必须存储多个BluetoothGatt对象并将这些对象用于不同的device

In this regard: I have tried writing a custom class for my device, TTGODevice , which saves an instance of the corresponding BluetoothGatt upon connection:在这方面:我尝试为我的设备 TTGODevice 编写自定义TTGODevice ,它在连接时保存相应BluetoothGatt的实例:

public class TTGODevice {
  /* Bunch of psf constants */
  private BluetoothDevice device;
  private Context context;
  private Accelerometer acc;
  private BluetoothGatt server;
  private int deviceStatus;

  private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { ...
  };

  public TTGODevice(Context context, BluetoothDevice device) {
    this.device = device;
    this.context = context;
    this.acc = new Accelerometer(); // My custom class for accelerometer on the T-Wristband device(s)
  }

  public void connect(boolean autoConnect) {
    server = device.connectGatt(context, false, bluetoothGattCallback);
  }

  /*Getters for device, server, and deviceStatus*/
}

In the BluetoothGattCallback , I override my onCharacteristicChanged as below:BluetoothGattCallback中,我重写我的onCharacteristicChanged如下:

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

  byte[] bytes = characteristic.getValue();

  // updating the Accelerometer
  acc.update(bytes);
  Log.d(TAG, "onCharacteristicChanged: " + Thread.currentThread().getName());
}

I have also tried using the exact instance of my server in the callback above, but I am out of luck.我也尝试在上面的回调中使用我的server的确切实例,但我运气不好。

byte[] bytes = server.getService(SERVICE_UUID).getCharacteristic(CHARACTERISTIC_UUID).getValue();

Long story short, I have been unsuccessful.长话短说,我一直没有成功。 I would appreciate any other relevant threads.我将不胜感激任何其他相关线程。

[ Note: I have been suggested to use Fragments and/or ViewModels . [注意:有人建议我使用Fragments和/或ViewModels I am not sure how they are relevant.]我不确定它们是如何相关的。]

It seems that BLE on Android cannot handle sampling rates at 50Hz and higher. Android 上的 BLE 似乎无法处理50Hz及更高的采样率。 I am not sure if this is a BLE-related problem or if it has something to do with the onCharacteristicCHanged method being called too frequently.我不确定这是 BLE 相关的问题,还是与onCharacteristicCHanged方法调用过于频繁有关。 I solved this by sending larger packets of data every 50ms , contrary to my original case at every 20ms .我通过每50 毫秒发送更大的数据包来解决这个问题,这与我原来每 20毫秒发送一次的情况相反。 Larger BLE data packets are possible starting from Bluetooth 4.2 , which is controlled using the MTU , Maximum Throughput Unit .蓝牙 4.2开始,可以使用更大的 BLE 数据包,它使用MTU最大吞吐量单位)进行控制。 This blog helped me a lot in understanding the underlying mechanism. 这个博客帮助我理解了底层机制。

When receiving large packets of data over BLE at high sampling rates, it is best to use gatt.requestMtu(MY_DESIRED_MTU) with MY_DESIRED_MTU > 20Bytes inside the corresponding BluetoothGattCallback on Android. It should be noted that larger MTU means it takes longer for the data to be written on the BLE characteristic for the server device.当通过 BLE 以高采样率接收大数据包时,最好在 Android 上相应的BluetoothGattCallback中使用MY_DESIRED_MTU > 20Bytesgatt.requestMtu(MY_DESIRED_MTU) 。应该注意的是,较大的 MTU 意味着数据需要更长的时间写在服务器设备的 BLE 特征上。

In short, I am using larger data packets and a larger delay to make up for the limitations in the sampling rate.总之,我是用更大的数据包和更大的延迟来弥补采样率的限制。 For a sampling rate of 100Hz on the IMU in the T-Wristband, I am using an MTU of 95 Bytes , requested by the Android device, and a 50ms delay on the timer on the T-Wristband.对于 T 腕带中 IMU 上100Hz的采样率,我使用95 字节的 MTU,由 Android 设备请求,并且 T 腕带上的计时器有50 毫秒的延迟。 This allows me to receive five consecutive data samples every 50ms .这允许我每50 毫秒接收五个连续的数据样本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM