BLE Данные теряются при чтении характеристики, когда устройство часто отправляет данные
Android BLE Данные теряются при чтении характеристики, когда устройство часто отправляет данные.
Byte Array конвертируется из Big endian
Каждые 4 байта делают One
Ячейка, которую я должен преобразовать в decimal
Вот мой код:
device.connectGatt(context, true, new BluetoothGattCallback() {
//region onServicesDiscovered
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
Log.d(TAG, "onServicesDiscovered --> Status : " + status);
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService mBluetoothGattService = mBluetoothGatt.getService(convertUuidFromInteger(0x181D));
if (mBluetoothGattService == null) {
Log.e(TAG, "onServicesDiscovered --> Service characteristic not found for UUID : " + SERVICE_UUID);
return;
}
Log.d(TAG, "onServicesDiscovered --> Service characteristic UUID found : " + mBluetoothGattService.getUuid().toString());
// read the characteristic from the service
BluetoothGattCharacteristic mBluetoothGattCharacteristic = mBluetoothGattService.getCharacteristic(CHARACTERISTIC_UUID);
boolean bcn = mBluetoothGatt.setCharacteristicNotification(mBluetoothGattCharacteristic, true);
Log.d(TAG, "onServicesDiscovered --> Is Characteristic Notification setted : " + bcn);
BluetoothGattDescriptor descriptor = mBluetoothGattCharacteristic.getDescriptor(DESCRIPTOR_UUID);
Log.w(TAG, "onServicesDiscovered --> Descriptor : " + (descriptor != null));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
boolean readDescriptor = mBluetoothGatt.readDescriptor(descriptor);
Log.e(TAG, "onServicesDiscovered --> Succeed to read descriptor : " + readDescriptor);
}
}
//endregion onServicesDiscovered
//region onDescriptorWrite
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
Log.w(TAG, "onDescriptorWrite --> ******************************");
if (DESCRIPTOR_UUID.equals(descriptor.getUuid())) {
Log.d(TAG, "onDescriptorWrite --> Equals");
BluetoothGattCharacteristic characteristic = gatt
.getService(SERVICE_UUID)
.getCharacteristic(CHARACTERISTIC_UUID);
boolean characteristicRead = gatt.readCharacteristic(characteristic);
Log.d(TAG, "onDescriptorWrite --> Characteristic read : " + characteristicRead);
boolean characteristWrite = gatt.writeCharacteristic(characteristic);
Log.d(TAG, "onDescriptorWrite --> Characteristic write : " + characteristWrite);
}
}
//endregion onDescriptorWrite
//region onDescriptorRead
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
Log.w(TAG, "onDescriptorRead --> ******************************");
if (DESCRIPTOR_UUID.equals(descriptor.getUuid())) {
Log.d(TAG, "onDescriptorRead --> Equals");
BluetoothGattCharacteristic characteristic = gatt
.getService(SERVICE_UUID)
.getCharacteristic(CHARACTERISTIC_UUID);
boolean characteristicRead = gatt.readCharacteristic(characteristic);
Log.d(TAG, "onDescriptorRead --> Characteristic read : " + characteristicRead);
boolean characteristWrite = gatt.writeCharacteristic(characteristic);
Log.d(TAG, "onDescriptorRead --> Characteristic write : " + characteristWrite);
}
}
//endregion onDescriptorRead
//region onCharacteristicChanged
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
Log.w(TAG, "onCharacteristicRead ******************************");
readCharacteristic(gatt, characteristic);
}
//endregion onDescriptorRead
//region onCharacteristicRead
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.w(TAG, "onCharacteristicRead ******************************");
readCharacteristic(gatt, characteristic);
}
//endregion onCharacteristicRead
//region onCharacteristicWrite
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.w(TAG, "onCharacteristicWrite ******************************");
readCharacteristic(gatt, characteristic);
}
//endregion onCharacteristicWrite
//region onConnectionStateChange
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothGatt.STATE_CONNECTED) {
Log.d(TAG, "onConnectionStateChange CONNECTED.");
boolean isDiscoverable = gatt.discoverServices(); // Essential to declare right Here
Log.w(TAG, "onConnectionStateChange --> Discover Services : " + isDiscoverable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
gatt.requestMtu(512);
}
}
mBluetoothGatt = gatt;
Log.d(TAG, "onConnectionStateChange --> discoverServices Size : " + mBluetoothGatt.getServices().size());
for (BluetoothGattService s : mBluetoothGatt.getServices()) {
Log.d(TAG, "onConnectionStateChange --> discoverServices : found " + s.getUuid());
for (BluetoothGattCharacteristic c : s.getCharacteristics()) {
Log.d(TAG, "onConnectionStateChange --> characteristic : " + c.getUuid() + ":" + String.format("%x", c.getInstanceId()));
}
}
super.onConnectionStateChange(gatt, status, newState);
Log.d(TAG, "onConnectionStateChange connectGatt.");
// readCustomCharacteristic(mBluetoothAdapter, mBluetoothGatt);
}
//endregion onConnectionStateChange
private void readCharacteristic(@NonNull BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("RawData", Arrays.toString(characteristic.getValue()));
Log.w(TAG, "readCharacteristic --> ******************************");
if (!gatt.readCharacteristic(characteristic)) {
Log.w(TAG, "readCharacteristic --> Failed to read characteristic");
return;
}
byte[] value = characteristic.getValue();
// Log.i(TAG, "readCharacteristic --> Succeed to read characteristic");
if (characteristic.getValue() == null || characteristic.getValue().length < 68) {
Log.e(TAG, "readCharacteristic --> Characteristic Bytes null / Bytes < 68");
return;
}
prepareToWrite(context, characteristic.getValue());
}
private void prepareToWrite(@NonNull Context context, @NonNull byte[] value) {
StringBuilder strRow = new StringBuilder();
strRow.append(context.getString(R.string.timestump_line_prefix))
.append(System.currentTimeMillis());
for (int i = 0; i < value.length; i += 4) {
// Log.i(TAG, "prepareToWrite index #" + i);
// Log.w(TAG, "prepareToWrite Step #" + 0);
byte[] b1 = {value[i + 3],
value[i + 2],
value[i + 1],
value[i]};
if (i % 16 / 4 == 0) {
strRow.append("\n");
} else {
strRow.append(" ");
}
if (i == 64) {
Log.w(TAG, "prepareToWrite --> Hex : " + toHexString(b1) + " , Decimal : " + Long.parseLong(toHexString(b1), 16));
}
strRow.append(context.getString(R.string.counter_line_prefix));
String strLong = String.valueOf(Long.parseLong(toHexString(b1), 16));
strRow.append(strLong);
Log.w(TAG, "prepareToWrite --> Here I am : " + strLong);
}
strRow.append("\n")
.append(context.getString(R.string.new_line));
Log.w(TAG, "prepareToWrite --> Row : " + strRow.toString());
try {
/*PackageManager m = context.getPackageManager();
PackageInfo p = m.getPackageInfo(context.getPackageName(), 0);
String dataDir = p.applicationInfo.dataDir;*/
/*String dataDir = context.getApplicationInfo().dataDir;*/
String dataDir = Environment.getExternalStorageDirectory().getAbsolutePath() +
File.separator + "Android" + File.separator + "data" + File.separator + context.getPackageName();
// Log.d(TAG, "prepareToWrite --> Create File 'Data Dir' : " + new File(dataDir).mkdirs() + " : " + dataDir);
// Log.w(TAG, "prepareToWrite Data Dir : " + dataDir);
File storeDir = new File(dataDir + File.separator + "files" + File.separator + context.getString(R.string.store_dir_name));
// Log.d(TAG, "prepareToWrite --> Create File 'Store Dir' : " + storeDir.mkdirs());
// storeDir.mkdirs();
File destinationFile = new File(storeDir.getAbsolutePath(), "Force_Plate.txt");
if (!destinationFile.exists() || destinationFile.isDirectory()) {
if (destinationFile.createNewFile()) {
// Log.w(TAG, "prepareToWrite --> Create File Succeed : " + destinationFile.getAbsolutePath());
} else {
// Log.w(TAG, "prepareToWrite --> Create File Failed : " + destinationFile.getAbsolutePath());
}
}
// Log.i(TAG, "prepareToWrite readFromFile : " + readFromFile(context, destinationFile.getAbsolutePath()));
writeToFile(destinationFile, strRow.toString());
}/* catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "prepareToWrite --> PackageManager NameNotFoundException : " + e.getMessage(), e);
} */ catch (IOException e) {
Log.e(TAG, "prepareToWrite --> IOException : " + e.getMessage(), e);
}
}
});
LogCat показывает:
W: prepareToWrite -> шестнадцатеричный: 00000b7e, десятичный: 2942
W: prepareToWrite -> шестнадцатеричный: 00000b87, десятичный: 2951
W: prepareToWrite -> шестнадцатеричный: 00000b90, десятичный: 2960
W: prepareToWrite -> шестнадцатеричный: 00000b97, десятичный: 2967
W: prepareToWrite -> шестнадцатеричный: 00000b9e, десятичный: 2974
...
Это должно быть как:
W: prepareToWrite -> шестнадцатеричный: 00000b7e, десятичный: 2942
W: prepareToWrite -> шестнадцатеричный: 00000b7e, десятичный: 2943
W: prepareToWrite -> шестнадцатеричный: 00000b7e, десятичный: 2944
W: prepareToWrite -> шестнадцатеричный: 00000b7e, десятичный: 2945
...
2 ответа
Объявил эти строки раньше device.connectGatt()
AdvertiseSettings advertiseSettings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
.setConnectable(true)
.setTimeout(0)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
.build();
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.setIncludeTxPowerLevel(false)
.addServiceUuid(new ParcelUuid(FP_SERVICE_UUID))
.build();
mBluetoothAdapter.getBluetoothLeAdvertiser().startAdvertising(advertiseSettings, advertiseData, new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
// Log.d(TAG, "BluetoothLeAdvertiser, onStartSuccess --> $isConnectable : " + settingsInEffect.isConnectable());
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
// Log.d(TAG, "BluetoothLeAdvertiser, onStartSuccess --> errorCode : " + errorCode);
}
});
...
Сначала убедитесь, что у вас никогда не было более одного невыполненного запроса GATT за раз. См. Android BLE BluetoothGatt.writeDescriptor() иногда возвращает false.
Когда вы получаете onCharacteristicChanged, вы можете использовать getValue непосредственно для объекта признака, чтобы получить заявленное значение.
После вызова readCharacteristic вам нужно дождаться onCharacteristicRead, прежде чем вы сможете вызвать getValue.