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);
        }
    });
...
  1. Сначала убедитесь, что у вас никогда не было более одного невыполненного запроса GATT за раз. См. Android BLE BluetoothGatt.writeDescriptor() иногда возвращает false.

  2. Когда вы получаете onCharacteristicChanged, вы можете использовать getValue непосредственно для объекта признака, чтобы получить заявленное значение.

  3. После вызова readCharacteristic вам нужно дождаться onCharacteristicRead, прежде чем вы сможете вызвать getValue.

Другие вопросы по тегам