我正在构建一个应用程序,它可以从BLE设备中提取所有特性。该设备在本地存储器中存储10个不同的双值,每3ms。
因此,在1秒内,BLE设备具有存储333行(每行有10个值)。
我的Android应用程序,下载此值但我可以下载一行秒或更少。在这种模式下,我永远不能下载这个BLE设备的所有信息。
现在有什么方法可以增加扫描频率o读取这个特性?
这是我的服务,它降低了BLE设备的特性:
public class BlePowerService extends Service {
public DbLayer db;
Setting settingApp;
List<ScanFilter> filters;
String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING, CHARACTERISTIC_TEMPERATURA_STRING};
BluetoothAdapter mBluetoothAdapter;
BluetoothGatt mGatt;
BluetoothDevice currDevice;
static final long SCAN_PERIOD = 500;
static String SPLIT_CHAR =";";
BluetoothLeScanner mLEScanner;
Handler mHandler;
int ReadQueueIndex;
List<BluetoothGattCharacteristic> ReadQueue;
BluetoothGattCharacteristic caratteristicaDaLeggere;
ScanSettings settings;
Integer ultimaForzaLetta,ultimaTemperaturaLetta;
boolean continuaLetturaForza, continuaLetturaTemperatura;
boolean isReading = true;
String LOG_CODE = "NOTIFSRV";
GattClientCallback gattClientCallback;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
public BlePowerService() {
}
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
Context sharedContext = null;
try {
sharedContext = this.createPackageContext(
"com.care.devicesensor",
Context.CONTEXT_INCLUDE_CODE);
if (sharedContext == null) {
return;
}
db=new DbLayer(sharedContext);
db.open();
} catch (Exception e) {
String error = e.getMessage();
// Log.d(LOG_CODE,"DB error : " + error);
return;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
settingApp = db.fetchSetting();
if (settingApp != null && settingApp.getAddressBleSX()!=null) {
//POSSO FILTRARE DIRETTAMENTE PER L'UUID DEL DISPOSITIVO MEMORIZZATO
//DALL'UTENTE
ScanFilter.Builder scanFilterMac =
null;
scanFilterMac = new ScanFilter.Builder().setDeviceAddress(settingApp.getAddressBleSX());
if(filters==null)
filters = new ArrayList<ScanFilter>();
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
filters.add(scanFilterMac.build());
//}
//FILTRO ANCHE PER LA CARATTERISTICA DI FORZA
ScanFilter filter = null;
filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(CHARACTERISTIC_FORZA_STRING)).build();
filters.add(filter);
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
scanLeDevice(true);
mTimer = new Timer();
//ogni 2 ore
continuaLetturaForza = true;
continuaLetturaTemperatura = true;
int nSecondi = settingApp.getFrequenzaDownload()!= null ? settingApp.getFrequenzaDownload() : 1;
mTimer.schedule(timerTask,5000);
//mTimer.schedule(timerTask, 10000, 1000 * nSecondi);
//mTimer.scheduleAtFixedRate (timerTask, 10000, 1000 * nSecondi);
}
} catch (Exception e) {
// Log.e("POWER_SERVICE", e.getMessage());
}
return super.onStartCommand(intent, flags, startId);
}
private Timer mTimer;
TimerTask timerTask = new TimerTask() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void run() {
//LEGGO TUTTI I DATI DAL SENSORE FINCHE CI SONO VALORI
int counter = 0;
while(continuaLetturaForza || continuaLetturaTemperatura){
counter++;
//Log.v("CICLO WHILE", counter+"");
if (currDevice != null) {
if(ReadQueue!= null && ReadQueue.size()>0){
int index =0;
for(index=0; index < ReadQueue.size(); index++){
if(mGatt!=null){
isReading = mGatt.readCharacteristic(ReadQueue.get(index));
while(isReading){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}else{
continuaLetturaForza = false;
continuaLetturaTemperatura = false;
}
}
}
}else{
//provo a ricollegarmi al dispositivo probabile, abbia perso la connessione con esso
scanLeDevice(true);
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(currDevice == null && counter == 25){
//in questo caso non è riuscito a trovare il dispositivo BLE
//esco dal ciclo
continuaLetturaForza = false;
continuaLetturaTemperatura = false;
continue;
}
}
}
if(gattClientCallback!=null && mGatt != null)
gattClientCallback.disconnectGattServer();
mTimer.cancel();
stopSelf();
EventBus.getDefault().post(new MessageEvent("stopService"));
}
public void stopTask() {
if (timerTask != null) {
Log.d("TIMER", "timer canceled");
timerTask.cancel();
}
}
};
public void connectToDevice(BluetoothDevice device) {
//VERIFICO SE IL DEVICE è QUELLO CHE VOGLIO IO
if (mGatt == null && settingApp != null
&& device.getAddress().equals(settingApp.getAddressBleSX())) {
currDevice = device;
gattClientCallback = new GattClientCallback();
mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
Handler h = new Handler(getApplicationContext().getMainLooper());
// Although you need to pass an appropriate context
h.post(new Runnable() {
@Override
public void run() {
// Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};
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 = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
// Log.i("callbackType", String.valueOf(callbackType));
// Log.i("result", result.toString());
BluetoothDevice btDevice = null;
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 class GattClientCallback extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
try{
super.onConnectionStateChange(gatt, status, newState);
//Log.i("tag", "onConnectionStateChange newState: " + newState);
if (status == BluetoothGatt.GATT_FAILURE) {
Log.e("ERROR_SERVICE", "Connection Gatt failure status " + status);
if(mGatt == null){
}else{
try {
gatt.close();
} catch (Exception e) {
Log.d("", "close ignoring: " + e);
}
mGatt = null;
}
return;
} else if (status != BluetoothGatt.GATT_SUCCESS) {
// handle anything not SUCCESS as failure
Log.e("ERROR_SERVICE", "Connection not GATT sucess status " + status);
if(mGatt == null){
}else{
try {
gatt.close();
} catch (Exception e) {
Log.d("", "close ignoring: " + e);
}
mGatt = null;
}
return;
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
//Log.i("INFO", "Connected to device " + gatt.getDevice().getAddress());
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i("INFO", "Disconnected from device");
if(mGatt == null){
}else{
try {
mGatt.close();
mGatt = null;
currDevice = null;
} catch (Exception e) {
Log.d("", "close ignoring: " + e);
}
mGatt = null;
}
}
}catch(Exception e){
Log.e("tag", e.getMessage());
continuaLetturaForza = true;
continuaLetturaTemperatura = true;
}
}
public void disconnectGattServer() {
continuaLetturaForza = true;
continuaLetturaTemperatura = true;
isReading = false;
if (mGatt == null) {
}
else{
try{
mGatt.disconnect();
// mGatt.close();
}catch(Exception e){
mGatt = null;
}
}
//mGatt = null;
//currDevice = null;
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status != BluetoothGatt.GATT_SUCCESS) {
// Log.i("INFO", "Device service discovery unsuccessful, status " + status);
return;
}
List<BluetoothGattCharacteristic> matchingCharacteristics =
BluetoothUtils.findCharacteristics(gatt,stringSequence);
if (matchingCharacteristics.isEmpty()) {
// Log.e("ERROR_SERVICE","Unable to find characteristics.");
return;
}else {
ReadQueue = new ArrayList<>();
for (BluetoothGattCharacteristic characterist : matchingCharacteristics) {
ReadQueue.add(characterist);
}
//ReadQueueIndex = 0;
//ReadCharacteristics(ReadQueueIndex);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
String valoreRestituito = characteristic.getStringValue(0);
if(valoreRestituito==null){
int i = 0;
i = i + 1;
return;
}
//SPLITTO PER IL CARATTERE ;
String[] arrayValori = valoreRestituito.split(SPLIT_CHAR);
//1 valore è l ID
try{
int id = new Integer(arrayValori[0]);
//VERIFICO SE STO LEGGENDO TEMPERATURA O FORZA
if(characteristic.getUuid().equals(CHARACTERISTIC_FORZA_UUID)){
/*Log.v("CARATTERISTICA", "*****************************************");
Log.v("FORZA", "*****************************************");*/
if(ultimaForzaLetta!= null && ultimaForzaLetta == id){
continuaLetturaForza = false;
isReading = false;
return;
}
ultimaForzaLetta = id;
}else if(characteristic.getUuid().equals( CHARACTERISTIC_TEMPERATURA_UUID)){
/*Log.v("CARATTERISTICA", "*****************************************");
Log.v("TEMPERATURA", "*****************************************");*/
if(ultimaTemperaturaLetta!= null && ultimaTemperaturaLetta == id){
continuaLetturaTemperatura = false;
isReading = false;
return;
}
ultimaTemperaturaLetta = id;
}
SensorData mSenData = new SensorData();
mSenData.setIdType(id);
mSenData.setValue1(arrayValori[1]);
mSenData.setValue2(arrayValori[2]);
mSenData.setValue3(arrayValori[3]);
mSenData.setValue4(arrayValori[4]);
mSenData.setValue5(arrayValori[5]);
mSenData.setValue6(arrayValori[6]);
mSenData.setValue7(arrayValori[7]);
mSenData.setValue8(arrayValori[8]);
//TO-DO HO COMMENTATO QUESTA RIGA DI CODICE
// mSenData.setIdType(st.getId());
mSenData.setCharacteristic(characteristic.getUuid().toString());
mSenData.setValueTimestamp(db.getDateTime(true));
db.insertSensorData(mSenData);
EventBus.getDefault().post(new MessageEvent("update"));
}catch (Exception e){
Log.e("ERROR", e.getMessage());
}
isReading = false;
} else {
isReading = false;
Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
disconnectGattServer();
return;
}
}
}
public void onDestroy() {
try {
db.close();
Log.d(LOG_CODE,"DB connection closed" );
mTimer.cancel();
timerTask.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务正常但速度慢。
答案 0 :(得分:1)
每个连接间隔不能执行多个读取请求。由于3 ms远小于允许的最小连接间隔,因此您尝试做的事情似乎不可能。您必须使协议更有效,例如让外围设备发送通知流。这样,您可以在每个连接事件中实现多个pecket。