androidarduinobluetooth-lowenergygatt

Android between Arduino BLE communication onCharacteristicChanged not call problem


I am making Android app which can make communication with Arduino. This program is simple echo service. if Android app send a data, Arduino return the data by BLE. I have successed to make Android app send data, and it's time to send back data to Android. I made a descriptor on Arduino, so Android can detect the characteristic value change.

but here is the problem. BluetoothGattCallback method's onCharacteristicChanged method never called.

I checked code several times but cannot found where is wrong...

This is the code setCharacteristicNotification. I put it in the onServicesDiscovered.

if(charService.equals("741c12b9-e13c-4992-8a5e-fce46dec0bff")){
    btGattCharacteristic = btGattService.getCharacteristic(UUID.fromString(charService));
    if(btGattCharacteristic == null)
    {
       MainThreadPrint("btGattCharacteristic failed");
    }
    else
    {
       MainThreadPrint("1 - btGattCharacteristic success");
       BluetoothGattDescriptor bluetoothGattDescriptor = btGattCharacteristic.getDescriptor(UUID.fromString("beca6057-955c-4f8a-e1e3-56a1633f04b1"));
       MainThreadPrint("2 - Descriptor found! : beca6057-955c-4f8a-e1e3-56a1633f04b1");
       bluetoothGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
       MainThreadPrint("3 - Descriptor set value done.");
       btGatt.writeDescriptor(bluetoothGattDescriptor);
       MainThreadPrint("4 - descriptor setting finished.");
    }
}

I have confirmed above codes are viable.

And this is BluetoothGattCallBack's onCharacteristicChanged code.

I just temporary put MainThreadPrint for see onCharacteristicChanged method works or not

 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            runOnUiThread(new Runnable() {
                public void run() {
                    logAdapter.add("BluetoothCallBack - newState : " + String.valueOf(newState));
                }
            });
            switch (newState){
                case 0:
                    runOnUiThread(new Runnable() {
                        public void run() {
                            logAdapter.add("device disconnected");
                        }
                    });
                    break;
                case 2:
                    runOnUiThread(new Runnable() {
                        public void run() {
                            logAdapter.add("device connected");
                        }
                    });
                    btGatt.discoverServices();
                    break;
                default:
                    runOnUiThread(new Runnable() {
                        public void run() {
                            logAdapter.add("unknown error : " + String.valueOf(newState));
                        }
                    });
                    break;
            }
            logAdapter.notifyDataSetChanged();
        }
        @Override
        public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
            // this will get called after the client initiates a BluetoothGatt.discoverServices() call
            MainActivity.this.runOnUiThread(new Runnable() {
                public void run() {
                    tvState.setText("device services have been discovered");
                }
            });
            //displayGattServices(btGatt.getServices());
            ProfileInitializer(btGatt.getServices());
        }
        @Override
        public void onCharacteristicChanged (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic){
            super.onCharacteristicChanged(gatt, characteristic);
            MainThreadPrint("onCharacteristicChanged");

        }
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            MainThreadPrint("onCharacteristicRead");
        }

    };

but it still not calling onCharacteristicChanged.

this is my Arduino code.

#include <ArduinoBLE.h>

BLEService echoService("00000000-0000-1000-8000-00805f9b34fb");
BLEStringCharacteristic charac ("741c12b9-e13c-4992-8a5e-fce46dec0bff", BLERead | BLEWrite | BLENotify,40);
BLEDescriptor Descriptor("beca6057-955c-4f8a-e1e3-56a1633f04b1","characDescriptor");
String var = "";

void setup(){
  Serial.begin(9600);
  while(!Serial);

  if(!BLE.begin()){
    Serial.println("starting BLE failed.");
    while(1);
  }

  BLE.setLocalName("Arduino BLE Echo");
  BLE.setAdvertisedService(echoService);
  charac.addDescriptor(Descriptor);
  echoService.addCharacteristic(charac);
  BLE.addService(echoService);
  BLE.advertise();
  Serial.println("Bluetooth device active, waiting for connections...");
  Serial.println(" ");

}

void loop(){
  BLEDevice central = BLE.central();
  if(central){
    Serial.println("* Connected to central device!");
    Serial.print("Connected to central : ");
    Serial.println(central.address());
    Serial.println(" ");

    while(central.connected()){
      if(charac.written()){
        var = charac.value();
        Serial.println(var);
        delay(500);
        charac.writeValue(var);
        Serial.println("write stringCharacteristic");
      }
      
    }
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());   
  }
}

I also used nRFConnect App to check it works properly or not.

enter image description here

can some one tell me the reason why my onCharacteristicChanged not calling?


Solution

  • As nRFConnect clearly states notifications an indications are disabled.

    Instead of ENABLE_NOTIFICATION_VALUE for "beca6057-955c-4f8a-e1e3-56a1633f04b1" you need to do this for the "Client Characteristic Configuration (0x2902)"