gpt4 book ai didi

Android BLE 通知丢包

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:02:11 25 4
gpt4 key购买 nike

我正在开发一种硬件设备,它通过 BLE 向 Android 应用程序发送连续的数据流。 Android 应用程序接收此数据作为 GATT 通知,然后处理此数据并将其保存到数据库中。

项目详细配置如下:

  1. 手机 - Moto E 第一代
  2. Android 版本 - Android 5.1 - Lollipop
  3. iOS - iPhone 4 和 5,在 iOS 7 和 8 上测试
  4. 硬件 - CC2541
  5. Connection_Interval:40 ms(在硬件固件中设置)。
  6. 每个连接间隔发送的数据包数:4(在硬件固件中设置)。

问题

当数据从硬件设备传输到Android手机上运行的BLE数据捕获应用程序时,没有收到所有数据包。它只收到大约 35-45 个数据包,而预期的数据包数量是 50。

更令人惊讶的是,当我们使用BLE数据包嗅探器时,Android手机嗅探和显示的数据(不完整/不正确的数据)之间存在完美匹配。这让我相信硬件在连接到 Android 手机而不是发送所有数据时表现不同。

当我们将相同的硬件与 iOS BLE 数据捕获应用程序一起使用时,可以正确接收数据。

我对Android中BLE数据捕获的这种行为感到困惑和无能为力。 iOS 设备上的应用程序如何能够正确捕获所有数据,而安卓手机上的应用程序根本无法正确捕获数据?

有没有人在安卓上使用BLE app遇到过这种丢包/数据不正确的问题?欢迎任何意见。非常感谢您的提前帮助。

Android 应用程序使用标准 BLE 代码通过 BLE 连接到设备。我使用的 Android 代码如下所示:

import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.nfc.Tag;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

@TargetApi(21)
public class BLETestActivity extends Activity {
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bletest);
mHandler = new Handler();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE Not Supported",
Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

}

@Override
protected void onResume() {
super.onResume();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
if (Build.VERSION.SDK_INT >= 21) {
Log.i("innnnn","spinnnn - " + Build.VERSION.SDK_INT);
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<ScanFilter>();
}
scanLeDevice(true);
}
}

@Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}

@Override
protected void onDestroy() {
if (mGatt == null) {
return;
}
mGatt.close();
mGatt = null;
super.onDestroy();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
//Bluetooth not enabled.
finish();
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}

private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);

}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}


private ScanCallback mScanCallback = null;/* new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}

@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}

@Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};*/

private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};

public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
mGatt = device.connectGatt(this, false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}

private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}

}

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
// Log.i("onServicesDiscovered", services.toString());

for(int i=0;i<services.size();i++) {
List<BluetoothGattCharacteristic> charList = services.get(i).getCharacteristics();
for (int j = 0; j < charList.size();j++) {
BluetoothGattCharacteristic characteristic = charList.get(j);
if (characteristic.getUuid().compareTo(Constants.HEART_DATA_UUID) == 0) {
Log.i(BLETestActivity.class.getSimpleName(), "Characteristic UUID is " + characteristic.getUuid());
mGatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(Constants.HEART_DATA_DESCRIPTOR_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mGatt.writeDescriptor(descriptor);
}
}
}
}

public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
// Retrieve the byte values
// Convert them to hex values
byte[] data = characteristic.getValue();

// The following array contains data in the follwing form:
// 0-1 - running counter counts
// 2-4, 5-7, 8-10 - Sample 1 data for channel 1, channel2 and channel 3
// 11-13, 14-16, 17-19 - Sample 2 data for channel 1, channel 2 and channel 3

// Log.i(TAG," ------ " + Thread.currentThread().getId());
String heartBeatDataInHex = bytesToHex(data);


// An error packet is received after every 17 samples.
// Checking to make sure that this is not an error packet

if (!(heartBeatDataInHex.substring(4, 10).equalsIgnoreCase("FFFFFF") && heartBeatDataInHex.substring(26, 40).equalsIgnoreCase("FFFFFFFFFFFFFF"))) {
Log.i("testdata", heartBeatDataInHex + " ---- " + Thread.currentThread().getId());
}
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
gatt.disconnect();
}

};

private String bytesToHex(byte[] bytes) {
final char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}

最佳答案

我遇到过类似的问题!我进行了一些测试,确定最小连接间隔为 48 毫秒,android api 级别 18。(connection interval for BLE on Galaxy S3 Android 4.3)。

可能的解决方案:

  1. 使连接间隔变慢(小于 48ms)。

  2. 从 api 级别 21 到更高级别,您可以更改 CONNECTION_PRIORITY android developer修改间隔连接,但这意味着更多的能量消耗。

关于Android BLE 通知丢包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31778872/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com