Xianghui
Xianghui

Reputation: 19

BLE on android cannot call onCharacteristicChanged()

I'm tring to develope a demo of bel communication BLE server runs on a linux board with BT module, the server is developed with python-dbus, and the part of Characteristic is shown as below

class DapUsrInfoCharacteristic(bluetooth_gatt.Characteristic):
    bonded = False
    def __init__(self, bus, index, service):
        bluetooth_gatt.Characteristic.__init__(
                self, bus, index,
                bluetooth_constants.DAP_CHR_UUID,
                ['read', 'write', 'notify'],
                service)
                # ['encrypt-authenticated-read', 'encrypt-authenticated-write', 
                #  'notify'],
                # service)

    def ReadValue(self, options):
        # Replace this with the actual value to be read
        show_log(LOG_LEVEL.INFO, "Reading value from client")
        return dbus.ByteArray([0x01])
    
    def WriteValue(self, value, options):
        # self.do_notify(value)
        self.callback(CallbackType.BLE_RECVD_MSG, value)
        # self.parse_msg_from_client(value)
    
    def StartNotify(self):
        show_log(LOG_LEVEL.INFO, "starting notifications")
        self.notifying = True

    def StopNotify(self):
        show_log(LOG_LEVEL.INFO, "stopping notifications")
        self.notifying = False

    def register_callback(self, callback):
        self.callback = callback

    def do_notify(self, value):
        self.StartNotify()
        if not self.notifying:
            show_log(LOG_LEVEL.INFO, "Not notifying")
            return
        show_log(LOG_LEVEL.INFO, f"Sending message to client: {value}")
        
        self.PropertiesChanged(bluetooth_constants.GATT_CHARACTERISTIC_INTERFACE, {'Value': value}, [])
        show_log(LOG_LEVEL.INFO, f"Message sent to client: {value}")

    def parse_msg_from_client(self, value):
        msg_type = int(value[0])
        if msg_type == BLE_MSG_TYPE.BONDED.value:
            self.bonded = bool(value[1])
            show_log(LOG_LEVEL.INFO, f"Bond status: {self.bonded}")
            self.callback(CallbackType.BLE_BONDED, None)
        else:
            show_log(LOG_LEVEL.INFO, f"Unknown message type: {value}")

BLE client is a Android phone, I can read and write value of the characteristic on the BLE server. However, It does not work when I want to subscribe the notification for the characteristic, the most related part code of Android is shown as below:

/* Gatt call back */
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        ...

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            Log.d(TAG, "Descriptor write status: " + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "Descriptor written");
                mainHandler.post(() ->  eventSink.success("Descriptor written"));
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            Log.d(TAG, "------------------");
            byte[] value = characteristic.getValue();
            Log.d(TAG, "Characteristic changed: " + Arrays.toString(value));
            mainHandler.post(() ->  eventSink.success("Characteristic changed: " + Arrays.toString(value) + "\n"));
        }
    };

/*Enable characteristic notification*/
boolean isEnableNotification =  bluetoothGatt.setCharacteristicNotification(targetCharacteristic, true);
if (!isEnableNotification) {
                    Log.e(TAG, "Failed to enable notification");
                    return;
                }
                Log.d(TAG, "Characteristic notification enabled");

                List<BluetoothGattDescriptor> descriptors = targetCharacteristic.getDescriptors();
                Log.d(TAG,"Total descriptors: " + descriptors.size());
                for (BluetoothGattDescriptor descriptor : descriptors) {
                    Log.d(TAG, "Descriptor: " + descriptor.getUuid().toString());
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    boolean isWriteDesp = bluetoothGatt.writeDescriptor(descriptor);
                    Log.d(TAG, "Descriptor write status: " + isWriteDesp);
                }
                Log.d(TAG, "Finished writing descriptors");        

Could you plz give some advice? Thanks very much!

Could you plz give some advice? Thanks very much!

Upvotes: -1

Views: 54

Answers (1)

Alan Lu
Alan Lu

Reputation: 111

Try to writeDescriptor after you setCharacteristicNotification and choose the UUID you want to subscribe, for example:

val descriptor: BluetoothGattDescriptor =
                characteristic.getDescriptor(convertFromInteger(0x2902))

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
    descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
    gatt.writeDescriptor(descriptor)
} else
    gatt.writeDescriptor(descriptor, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)

Upvotes: 0

Related Questions