启用通知后,BLE读取常量数据流

时间:2018-03-23 19:46:48

标签: android android-studio bluetooth-lowenergy

更新

我正在尝试从连接到arduino设置的HM-10蓝牙设备接收恒定的串行数据流。我在Google Play商店中使用BLE扫描仪查找MAC地址和UUID。有一个特征可以读,写和通知。在应用程序上启用通知允许显示恒定的数据流,同时读取显示地址。我无法弄清楚启用通知如何允许访问数据流。我编写的代码使我能够连续阅读(显示地址,就像应用程序一样),并且我想知道如何访问通知数据。对不起,如果我的术语有误,我就不太了解BLE通知。这是我的Connect,Runnable和Callback代码:

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void Connect(View view) throws InterruptedException {

    Device = Adapter.getRemoteDevice("3C:A3:08:94:C3:11");

    Gatt = Device.connectGatt(this, true, GattCallback);


}

private final BluetoothGattCallback GattCallback = new BluetoothGattCallback() {
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Gatt.discoverServices();


        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Service = Gatt.getService(UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB"));
            Characteristic = Service.getCharacteristic(UUID.fromString("0000FFE1-0000-1000-8000-00805F9B34FB"));
            Gatt.setCharacteristicNotification(Characteristic, true);
            thread.start();


        } else {
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            for (byte byteChar : data) {
                stringBuilder.append(String.format("%02X ", byteChar));
            }


            final String strReceived = stringBuilder.toString();

            ErrorID.setText(strReceived);

        }


    }

};

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void run() {
        UUID uuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
        BluetoothGattDescriptor descriptor = Characteristic.getDescriptor(uuid);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        Gatt.writeDescriptor(descriptor);
        while (true) {
            Gatt.readCharacteristic(Characteristic);

        }
    }

很抱歉,如果代码不是很清楚",

谢谢!

3 个答案:

答案 0 :(得分:1)

删除读取具有100%cpu使用率的特征的while循环。编写描述符后写的setCharacteristicNotification就是为通知做准备所需的全部内容。

只需实现onCharacteristicChanged回调,然后在每次通知时调用它。

答案 1 :(得分:0)

<强>更新

所以我现在让textView显示来自蓝牙模块的数据。现在的问题是除非调用Connect方法,否则值不会更新(我按下连接按钮)。我怀疑这是因为达到了20个字节的限制。有没有办法让我在不重新连接的情况下不断更新数值?我还试图在显示时将值保存在文本文件中,但我的文本文件为空。这是我更新的代码:

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void Connect(View view) throws InterruptedException {

    Device = Adapter.getRemoteDevice("3C:A3:08:94:C3:11");

    Gatt = Device.connectGatt(this, true, GattCallback);


}

private final BluetoothGattCallback GattCallback = new BluetoothGattCallback() {
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Gatt.discoverServices();


        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Service = Gatt.getService(UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB"));
            Characteristic = Service.getCharacteristic(UUID.fromString("0000FFE1-0000-1000-8000-00805F9B34FB"));
            UUID uuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
            descriptor = Characteristic.getDescriptor(uuid);
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            Gatt.setCharacteristicNotification(Characteristic, true);
            Gatt.writeDescriptor(descriptor);


        }

    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

        final String strReceived = characteristic.getStringValue(0);

        try {
            FileOutputStream fos = new FileOutputStream(myFile);
            OutputStreamWriter osw = new OutputStreamWriter(openFileOutput("Test.txt", MODE_APPEND));
            osw.write(strReceived);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ErrorID.setText(strReceived);

    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            for (byte byteChar : data) {
                stringBuilder.append(String.format("%02X ", byteChar));
            }


            final String strReceived = stringBuilder.toString();

            ErrorID.setText(strReceived);

        }


    }

};

答案 2 :(得分:0)

你可以增加最大值。使用OnServicesDiscovered Callback方法中的以下代码行对数据包进行字符限制:

mBluetoothGatt.requestMtu(80); 

代替&#39; 80&#39;输入您计划接收的最大字节数。

然后在BluetoothGattCallback中,您希望包含以下案例和系统日志打印,以确认您已成功更新字符限制:

public void onMtuChanged(BluetoothGatt bluetoothGatt, int mtu, int status){

    System.out.println(" +++++++ MTU CHANGE SUCCESSFUL +++++++");
}

至于通过通知接收串行数据&#39;我无法帮助,因为我一直在努力寻找一个简单的解释,说明如何做好这几周......