Запись характеристики всегда ложная

Теперь я знаю, что этот вопрос задавали около миллиарда раз.

Я прочитал большинство из них (этот веб-сайт не помог мне в решении моей проблемы), я прочитал документы, примеры и учебные пособия.

Я пытаюсь сделать следующее:

Отправьте привет, мир на устройство BLE (подключенное к Arduino)

Что я сделал до сих пор:

Сопряжение с устройством с использованием встроенных настроек (в моем приложении нет запрограммированной логики)

Подключен к устройству с помощью сервера GATT.

Однако, когда я пытаюсь написать характеристику, соответствующее логическое значение возврата статуса всегда ложно. Это самый актуальный код:

private void setupServer(BluetoothAdapter bAdapter) {
    Log.d(TAG, "Started setting up server");

    BluetoothLeAdvertiser bAdvertiser = bAdapter.getBluetoothLeAdvertiser();
    if (bAdapter != null) {
        bGattServer = bManager.openGattServer(getApplicationContext(), new BluetoothGattServerCallback() {
            @Override
            public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
                super.onConnectionStateChange(device, status, newState);
            }
        });
        //Create a service using a random UUID
        //Create characteristics with WRITE property and write a value
        BluetoothGattService service = new BluetoothGattService(UUID.randomUUID(), BluetoothGattService.SERVICE_TYPE_PRIMARY);
        BluetoothGattCharacteristic bluetoothGattCharacteristic = new BluetoothGattCharacteristic(bUUID, BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE);
        Log.d(TAG, "Adding characteristic to service " + service.addCharacteristic(bluetoothGattCharacteristic));
        bluetoothGattCharacteristic.setValue("hello");
        Log.d(TAG, "Trying to write characteristic..., first value: " + bluetoothGattCharacteristic.getValue()[0]);
        if (bGatt != null) {
            boolean success = bGatt.writeCharacteristic(bluetoothGattCharacteristic);
            if (success) {
                Log.d(TAG, "Successfuly wrote characteristic to" + bUUID);
            } else {
                 //THIS ALWAYS EXECUTES??
                Log.e(TAG, "Failed to write to characteristic");
            }
        } else {
            Log.e(TAG, "BGATT IS NULL");
        }
        service.addCharacteristic(bluetoothGattCharacteristic);
        bGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);
        bGattServer.addService(service);
    }

Это мои разрешения:

    <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

И это остальная часть соответствующего кода

    private boolean scanBluetooth(final BluetoothAdapter bAdapter, final BluetoothDevice[] bDevice) {

    final BluetoothLeScanner bScanner = bAdapter.getBluetoothLeScanner();
    final boolean[] stopCallback = {false};
    Log.d(TAG,"Started scanning");
    bScanner.startScan(new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            bDevice[0] = result.getDevice();
            if (bDevice[0] == null || stopCallback[0]) {
                Toast.makeText(getApplicationContext(), "Didn't find a device", Toast.LENGTH_LONG);

            } else {
                stopCallback[0] = true;
                System.out.println("DEVICE" + bDevice[0]);
                bGatt = bDevice[0].connectGatt(getApplicationContext(), true, new BluetoothGattCallback() {
                    @Override
                    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                        super.onConnectionStateChange(gatt, status, newState);
                        if(status == BluetoothGatt.GATT_SUCCESS){
                            Log.d(TAG, "Successful GATT " + newState);
                            setupServer(bAdapter);
                            return;
                        }
                        if(status == BluetoothGatt.GATT_FAILURE){
                            Log.e(TAG,"Bigg error boi");
                            System.exit(1);
                        }
                        else{
                            Log.w(TAG,"Oh no, gatt failed " + status + " retrying");
                            return;
                        }

                    }
                    @Override
                    public void onCharacteristicWrite(BluetoothGatt gatt,
                                                      BluetoothGattCharacteristic characteristic, int status) {
                        Log.d(TAG, "Characteristic written" + status);
                    }

                }, BluetoothDevice.TRANSPORT_LE);
                Log.d(TAG, "Bgatt value:" + bGatt);


            }
        }
    });
    if(bGatt==null){
        Log.w(TAG, "BGATT IS NULL WHILE SCANNING");
    }
    Log.d(TAG, "Finished scanning...");
    return true;
}

Я получил bUUID с помощью приложения BLEScanner, которое показало UUID для чтения и записи. Цель моего приложения — отразить функциональность этого приложения, но я начинаю сходить с ума. Я пока даже не могу отправить простое приветствие, мир.

Выход Android-студии:

018-12-01 23:58:56.214 25024-25136/com.iopt.davidv7.iopt W/DBG: Oh no, gatt failed 22 retrying
2018-12-01 23:58:56.675 25024-25136/com.iopt.davidv7.iopt D/DBG: Successful GATT 2
2018-12-01 23:58:56.675 25024-25136/com.iopt.davidv7.iopt D/DBG: Started setting up server
2018-12-01 23:58:56.692 25024-25136/com.iopt.davidv7.iopt D/DBG: Adding characteristic to service true
2018-12-01 23:58:56.693 25024-25136/com.iopt.davidv7.iopt D/DBG: Trying to write characteristic..., first value: 104
2018-12-01 23:58:56.693 25024-25136/com.iopt.davidv7.iopt E/DBG: Failed to write to characteristic

Клиент представляет собой простой Bluetooth-модуль HM-10, и я хочу отразить то, что я отправляю в приложении, на серийный монитор с помощью ARDUINO IDE.

Надеюсь, я дал вам весь контекст, потому что я теряю надежду. Я не проверяю разрешения вручную, потому что я настроил их с помощью системного диалога, однако нужно было включить только «местоположение»? Может ли это быть корнем моей проблемы? При проверке bluetooth с помощью checkSelfPermission администратор bluetooth возвращает true, поэтому я не думаю, что это так:

        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_ADMIN)
            != PackageManager.PERMISSION_GRANTED) {
        Log.e(TAG,"No permission for bluetooth");
        // Permission is not granted
    }
    else{
        Log.d(TAG,"Bluetooth permission granted");
    }

person Nephilim    schedule 01.12.2018    source источник
comment
Немного сложно понять, что вы пытаетесь сделать. Вы создаете GATT SERVER и определяете для него характеристику. Но затем вы используете объект GATT CLIENT bGatt и думаете, что можете написать объект Characteristic, определенный для экземпляра сервера, в качестве клиента. Чтобы получить характерные объекты, привязанные к gatt-клиенту bGatt, вам необходимо вызвать discoveryServices для этого объекта. Но опять же, почему вы смешиваете сервер gatt с клиентом gatt?   -  person Emil    schedule 02.12.2018
comment
вы тоже настроили дескриптор?   -  person Augusto    schedule 02.12.2018
comment
@Emil Я понятия не имел, что bGatt был клиентом, я в основном собирал код из разных источников, и я должен признать, что все еще довольно запутался во всем этом. Из того что я понял нужно прописать характеристику в соединение а bGatt тот что подключается к устройству?   -  person Nephilim    schedule 02.12.2018
comment
@Augusto Нет, нет дескриптора, честно говоря, не знаю, что это исправит или какие данные использовать...   -  person Nephilim    schedule 02.12.2018
comment
Первый раз, когда вы пытаетесь сделать это? Если да, я могу объяснить вам мой код, который отлично работает.   -  person Augusto    schedule 02.12.2018
comment
@Augusto, да, я впервые делаю что-либо, связанное с Bluetooth, где бы то ни было.   -  person Nephilim    schedule 03.12.2018
comment
Я помогу тебе, только подожди, у меня есть немного времени. Вы хотите подключиться к другому смартфону?   -  person Augusto    schedule 03.12.2018
comment
@Augusto нет, я подключаюсь к устройству BLE на Arduino.   -  person Nephilim    schedule 03.12.2018
comment
Отлично, просто подожди. Позвольте мне увидеть ваш код Arduino   -  person Augusto    schedule 03.12.2018
comment
Давайте продолжим обсуждение в чате.   -  person Nephilim    schedule 03.12.2018


Ответы (1)


Кажется, моя проблема заключалась в создании новой службы вместо использования служб обнаружения, а затем анализа обнаруженных служб. Алгоритмически вы делаете следующее: 1. Инициируете discoveryServices(), которая, в свою очередь, вызывает onServicesDiscovered() в обратном вызове 2. После этого создаете службу из обнаруженной службы и характеристику из службы. Поскольку мое текущее оборудование поддерживает только одну характеристику, я могу использовать только первую (и единственную) службу. 3. Установить значение службы с помощью setValue 4. Добавить характеристику службе

Я не буду подробно объяснять, что делает мой код readData, но это может помочь кому-то понять, как запускать уведомления и считывать данные из них.

private boolean scanBluetooth(final BluetoothAdapter bAdapter, final BluetoothDevice[] bDevice) {

    final BluetoothLeScanner bScanner = bAdapter.getBluetoothLeScanner();
    final boolean[] stopCallback = {false};
    Log.d(TAG,"Started scanning");
    bScanner.startScan(new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            bDevice[0] = result.getDevice();
            if (bDevice[0] == null || stopCallback[0]) {
                Toast.makeText(getApplicationContext(), "Didn't find a device", Toast.LENGTH_LONG);

            } else {
                stopCallback[0] = true;
                System.out.println("DEVICE" + bDevice[0]);
                bGatt = bDevice[0].connectGatt(getApplicationContext(), true, new BluetoothGattCallback() {
                    @Override
                    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                        super.onConnectionStateChange(gatt, status, newState);
                        if(status == BluetoothGatt.GATT_SUCCESS){
                            Log.d(TAG, "Successful GATT " + newState);
                            //Simply triggers a discoverService method, which in return triggers onServiceDiscovered, which writes sample data into the characteristic
                            setupClient(bAdapter);
                            return;

                        }
                        if(status == BluetoothGatt.GATT_FAILURE){
                            Log.e(TAG,"Bigg error boi");
                            System.exit(1);
                        }
                        else{
                            Log.w(TAG,"Oh no, gatt failed " + status + " retrying");
                            return;
                        }

                    }
                    @Override
                    //Triggered after we write data in a characteristic
                    public void onCharacteristicWrite(BluetoothGatt gatt,
                                                      BluetoothGattCharacteristic characteristic, int status) {
                        Log.d(TAG, "Characteristic written" + status);
                    }
                    //Triggered when someone(the remote device if everything is set up correctly) changes a characteristic!

                    public void onCharacteristicChanged(BluetoothGatt gatt,
                                                        BluetoothGattCharacteristic characteristic) {
                        Log.w(TAG,"Characteristic changed");
                        try {
                            Log.d(TAG,"Change characteristic" + new String(characteristic.getValue(),"UTF-8"));
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                    }
                    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                        Log.d(TAG,"Size of discovered" + gatt.getServices().size());
                        getData(gatt);
                        writeCharacteristic(gatt);
                        Log.d(TAG,"Services discovered");
                    }


                }, BluetoothDevice.TRANSPORT_LE);
                Log.d(TAG, "Bgatt value:" + bGatt);


            }
        }
    });
    if(bGatt==null){
        Log.w(TAG, "BGATT IS NULL WHILE SCANNING");
    }
    Log.d(TAG, "Finished scanning...");
    return true;
}
//Doesn't do much, starts discovering services, which triggers onServicesDiscovered
private void setupClient(BluetoothAdapter bAdapter) {
    Log.d(TAG, "Started setting up server");

    if (bAdapter != null) {
        Log.d(TAG, "SERVICE DISCOVERED" + bGatt.discoverServices());

    }
}
//Write characteristic into the discovered service
//There is only one characteristic, so we can just take the first index
private void writeCharacteristic(BluetoothGatt gatt){
                                BluetoothGattService bService = gatt.getService(bUUID);
                        BluetoothGattCharacteristic bChars = bService.getCharacteristics().get(0);

                        if(bChars != null){
                            bChars.setValue("Hello");
                            bService.addCharacteristic(bChars);
                            boolean success = gatt.writeCharacteristic(bChars);
                            if(success){
                                Log.d(TAG, "Write characteristic successful");
                            }
                            else{
                                Log.e(TAG, "Write characteristic failed");
                            }
                        }
                        else{
                            Log.e(TAG,"Characteristic not found");
                        }
}
//Set up notifications for the discovered service!
    private void getData(BluetoothGatt gatt){

        BluetoothGattService bService = gatt.getService(bUUID);
        BluetoothGattCharacteristic bChars = bService.getCharacteristics().get(0);
        gatt.setCharacteristicNotification(bChars,true);
    }
person Nephilim    schedule 03.12.2018