简体   繁体   English

写特征始终为假

[英]Write characteristic always false

Now I know this question has been asked about a billion times. 现在我知道这个问题已经被询问了十亿次。

I've read through most of them(this website hasn't been that helpful for my problem), I've read through the docs and I've read through the examples and tutorials. 我已经阅读了大多数内容(这个网站对我的问题没有帮助),我阅读了所有文档以及所有示例和教程。

What I'm trying to do is: 我想做的是:

Send hello world to a BLE device(Connected to an arduino) 向BLE设备发送问候世界(已连接到arduino)

What I've done so far: 到目前为止,我所做的是:

Paired with the device using the inbuilt settings(no programmed logic in my app) 使用内置设置与设备配对(我的应用中未编程逻辑)

Connected with the device using the GATT server. 使用GATT服务器连接到设备。

However when I try to write a characteristic, the corresponding status return boolean is always false. 但是,当我尝试编写特征时,相应的状态返回布尔值始终为false。 This is the most relevant code: 这是最相关的代码:

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);
    }

These are my permissions: 这些是我的权限:

    <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" />

And this is the rest of the relevant code 这是相关代码的其余部分

    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;
}

I've gotten bUUID using the app BLEScanner, which showed a UUID for read and write. 我已经使用BLEScanner应用程序获得了bUUID,该应用程序显示了用于读写的UUID。 The goal of my application is to mirror the functionality of that app, but I'm starting to lose my mind. 我的应用程序的目标是反映该应用程序的功能,但是我开始失去理智。 I can't even send a simple hello world yet. 我什至无法发送一个简单的hello世界。

Android Studio output: Android Studio输出:

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

The client is a simple HM-10 Bluetooth module and I want to mirror what I send in the app on the serial monitor using ARDUINO IDE for now. 客户端是一个简单的HM-10蓝牙模块,我现在想使用ARDUINO IDE在串行监视器上镜像我在应用程序中发送的内容。

I hope I've given you all the context, because I'm losing hope. 希望我能给您所有背景信息,因为我失去了希望。 I'm not manually checking for permissions because I've set them up using the system dialogue, however, there was only "location" to enable? 我不是手动检查权限,因为我已经使用系统对话框设置了权限,但是只有“位置”要启用吗? Could this be the root of my issue? 这可能是我问题的根源吗? Checking with checkSelfPermission for bluetooth, bluetooth admin returns true though, so I dont think that is it: 使用checkSelfPermission检查蓝牙,虽然蓝牙管理员返回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");
    }

Seems my issue was in creating a new service, instead of using discover services then parsing the discovered services. 似乎我的问题是创建新服务,而不是先使用发现服务然后解析发现的服务。 So what you do,algorithmically is: 1. Trigger discoverServices(), which in turn triggers onServicesDiscovered() in the callback 2. After that, create a service out of the discovered service and a characteristic out of the service. 因此,您要做的是:1.触发discoverServices(),这又会在回调中触发onServicesDiscovered()2.之后,从发现的服务中创建服务,并从服务中创建特征。 Because my current hardware only supports one characteristic, I can only take out the first(and only) service. 因为我当前的硬件仅支持一个特性,所以我只能取出第一个(也是唯一一个)服务。 3. Set value to the service with setValue 4. Add characteristic to the service 3.使用setValue将值设置为服务4.为服务添加特征

I won't be explaining what my readData code does in depth, but it might help someone figure out how to trigger notifications and read data from those. 我不会深入解释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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM