如何按顺序连接到蓝牙GATT设备的正确方法



我已经实现了低功耗蓝牙设备扫描逻辑,但我在蓝牙Gatt服务使用方面有点挣扎。我想做的是从我的 Android 手机依次连接到我的每个 ESP32 设备,这样我就可以接收数据,然后继续到下一个设备(并与以前的设备断开连接)。因此,ESP32和Android手机之间只有一个活动连接。ESP32 已经编程,因此如果安卓手机使用蓝牙 Gatt 连接到它,那么它会发送数据(最大 20 字节)。

真正的困难是了解如何管理这些连接以正确关闭/释放资源。

管理这些BluetoothGatt连接的正确/最简单的方法是什么?

我的实现基本上是在发送的数据"end"时连接到新设备 Gatt 服务。问题是,如果一台 ESP32 设备处于活动状态,则此方法有效。如果更多设备处于活动状态,则会发生某些情况,并且不会从 Gatt 服务接收数据。

这是我实现的一部分(抱歉,我无法进一步减小代码大小):

1)我使用BLE扫描仪发现新设备

private Handler _leScanHandler = new Handler();
private final BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final int newRSSI = rssi;
_leScanHandler.post(new Runnable() {
@Override
public void run() {
addDeviceToListOnLEScan(device, newRSSI);
}
});
}
};

2)被调用的方法基本上管理BluetoothGatt连接。

public void addDeviceToListOnLEScan(BluetoothDevice device, int rssi) {
// Gets only user defined devices
boolean isUserDefinedDevice = _definedDevicesHashMap.containsKey(device.getAddress());
if (!isUserDefinedDevice) {
return;
}
// Adds device and updates 'LastModifiedTime = Date(System.currentTimeMillis())'
addOrUpdateDevice(device.getAddress(), _scannedDevices);
// Called only once on each connect button press to enable gatt operations
if (!_isInitialConnectionHasBeenMade) {
_isDataSendingCompleteFromCurrentGatt = true;
_isInitialConnectionHasBeenMade = true;
}
// Sequential BLE device connect/disconnect operations
if (_isDataSendingCompleteFromCurrentGatt) {
BluetoothGatt previousGatt = _definedDevicesHashMap(previousAddress);
if (previousGatt != null) {
previousGatt.disconnect(); // ?
}
BluetoothGatt nextGatt = _definedDevicesHashMap(nextAddress);
if (/* Checks if 'nextAddress' is in _scannedDevices */
/* And whether device 'IsActive()' */) {
if (nextGatt == null) {
nextGatt = connectToDeviceGattService(nextGatt)     
}
else {
// Do something here ?
}
_isDataSendingCompleteFromCurrentGatt = false;  
}
}
}

3)我正在使用的以下变量/类

private boolean _isDataSendingCompleteFromCurrentGatt = false;
private boolean _isInitialConnectionHasBeenMade = false;
private HashMap<String, BluetoothGatt> _definedDevicesHashMap;
_definedDevicesHashMap.put("ff:ff:9f:c8:c2:93", null);
_definedDevicesHashMap.put("ff:ff:9f:c8:c4:91", null);
...
private HashMap<String, MyBLEDevice> _scannedDevices;
public class MyBLEDevice
{
private final int deviceInactivityTimeout = 10;
private String MacAddress;
private Date _lastModifiedDate;
public boolean isDeviceActive() {
// Just gets the time difference (DateNow - lastModified) / 1000 < 10s
}
}

4)我用来连接到设备的方法

public BluetoothGatt connectToDeviceGattService(BluetoothGatt currentGatt, BluetoothDevice device, BluetoothGattCallback callback) {
_bluetoothAdapter.cancelDiscovery();
if (currentGatt == null) {
currentGatt = device.connectGatt(_activity, true, callback);
}
else {
// Is anything here needed ?
}
return currentGatt;
}

5)BluetoothGatt回调

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
// Discover services ?
} else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
// Do nothing ?
} else if (status != BluetoothGatt.GATT_SUCCESS) {
// Disconnect from current BluetoothGatt instance? 
// Also close the connection ?
_isDataSendingCompleteFromCurrentGatt = true;
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
enableGattConfigurationCharacteristic();
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
_gattServiceHandler.post(new Runnable() {
@Override
public void run() {
handleMessage(Message.obtain(null, MSG_CHARACTERISTIC_CHANGE, characteristic));
}
});
}
};

6)最后,用于从 Gatt 回调接收数据的处理程序

private static final int MSG_CHARACTERISTIC_CHANGE = 0;
private Handler _gattServiceHandler = new Handler();
private void handleMessage(Message msg) {
BluetoothGattCharacteristic characteristic;
switch (msg.what) {
case MSG_CHARACTERISTIC_CHANGE: {
characteristic = (BluetoothGattCharacteristic) msg.obj;
if (BLELogic.PROPERTY_NOTIFY_CHAR_UUID.equals(characteristic.getUuid())) {
String notification = BluetoothExtension.getCharacteristicValue(characteristic);
if (notification.equals("end")) {
_isDataSendingCompleteFromCurrentGatt = true;           
} else {
UpdateViewOnGattNotificationSent(notification);
}
}
}
default:
return;
}
}

一开始我想简化所有的逻辑,但看起来在使用 BLE/GATT 服务连接时,这并不简单。

这是一个您可能感兴趣的问题和答案

简短的答案:

要实现多个BLE连接,您必须存储多个 蓝牙 Gatt 对象并将这些对象用于不同的开发。自 存储您可以使用Map的蓝牙Gatt的多个连接对象<>

私有地图连接设备地图;.............

相关内容

最新更新