简体   繁体   中英

I have a problem with Gatt connection between Android app(Java) and ESP32 BLE Server

I'm trying to connect my Android application to a ESP32 BLE gatt server and to receive some integer values through the characteristics of that server after being notified

However it doesn't seem to work

This is my Java Code:

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import com.example.logintask.R;

import java.util.ArrayList;
import java.util.List;


public class BluetoothConnection  extends AppCompatActivity {

    String TAG = "ScanActivity";
    BluetoothAdapter mBluetoothAdapter;
    BluetoothGatt mBluetoothGatt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);

        Button bt = findViewById(R.id.button);
        bt.setOnClickListener(v -> {
            final BluetoothManager bluetoothManager =  (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();
            for(BluetoothDevice dt : mBluetoothAdapter.getBondedDevices()){
                if(dt.getName().equals("ISCOPE")){
                    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(dt.getAddress());
                    BluetoothGatt bluetoothGatt = device.connectGatt(getApplicationContext(), false, mGattCallback);
                    Log.d("Result",String.valueOf(bluetoothGatt.connect()));
                }
            }
        });
    }
    BluetoothGattCallback mGattCallback =
            new BluetoothGattCallback() {
                @Override
                public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                    if (newState == BluetoothProfile.STATE_CONNECTED) {
                        Log.i(TAG, "DEVICE CONNECTED. DISCOVERING SERVICES...");
                        mBluetoothGatt.discoverServices();
                    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                        Log.i(TAG, "DEVICE DISCONNECTED");
                    }
                }
                @Override
                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        Log.i(TAG, "SERVICES DISCOVERED. PARSING...");
                        displayGattServices(gatt.getServices());
                    } else {
                        Log.i(TAG, "FAILED TO DISCOVER SERVICES");
                    }
                }
                @Override
                public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        Log.i(TAG, "ON CHARACTERISTIC READ SUCCESSFUL");
                    } else {
                        Log.i(TAG, "ERROR READING CHARACTERISTIC");
                    }
                }
                @Override
                public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                    super.onCharacteristicWrite(gatt, characteristic, status);
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        Log.i(TAG, "ON CHARACTERISTIC WRITE SUCCESSFUL");
                    } else {
                        Log.i(TAG, "ERROR WRITING CHARACTERISTIC");
                    }
                }
                @Override
                public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                    Log.i(TAG, "NEW NOTIFICATION RECEIVED");
                }
                @Override
                public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
                    Log.i(TAG, "NEW RSSI VALUE RECEIVED");
                }
            };
    private void displayGattServices(List<BluetoothGattService> gattServices) {
        if (gattServices == null) return;
        for (BluetoothGattService gattService : gattServices) {
            Log.i(TAG, "SERVICE FOUND: " + gattService.getUuid().toString());
            for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
                Log.i(TAG, "  CHAR. FOUND: " + gattCharacteristic.getUuid().toString());
            }
        }
    }
}

And this is my Logcat:

2021-03-20 20:49:19.651 30080-30080/com.example.logintask D/BluetoothGatt: registerApp()
2021-03-20 20:49:19.651 30080-30080/com.example.logintask D/BluetoothGatt: registerApp() - UUID=2318d701-b8f5-4cd9-be2c-cd83fee35f8d
2021-03-20 20:49:19.654 30080-30080/com.example.logintask D/Result: true
2021-03-20 20:49:19.654 30080-30116/com.example.logintask D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
2021-03-20 20:49:24.812 30080-30116/com.example.logintask D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=6 device=9C:9C:1F:C9:B5:72
2021-03-20 20:49:24.812 30080-30116/com.example.logintask D/State: 0
2021-03-20 20:49:24.812 30080-30116/com.example.logintask I/ScanActivity: DEVICE DISCONNECTED

And finally this is my ESP32 Code:

#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      BLEDevice::startAdvertising();
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};



void setup() {
  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init("ISCOPE");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(false);
  pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  BLEDevice::startAdvertising();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
    // notify changed value
    if (deviceConnected) {
        pCharacteristic->setValue((uint8_t*)&value, 4);
        pCharacteristic->notify();
        value++;
        delay(10); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
    }
    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
        // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}

Interestingly when I connect through the nRF Connect app it works and it get the value of my characteristic. I am a newbie programmer so any help will be appreciated. Thanks in advance!!

Your connection fails with status 133. There are many questions on here regarding that topic. It's a known issue with android. This answer suggest to use a different version of the connectGatt method which would look like this for you:

BluetoothGatt bluetoothGatt = device.connectGatt(getApplicationContext(), false, mGattCallback, BluetoothDevice.TRANSPORT_LE);

This would require you to use Android 6.0 (API 23) or newer but should eliminate your problem. If you need to use an earlier version of Android you could just retry to connect until it works.

I suggest to start using: https://github.com/NordicSemiconductor/Android-nRF-Toolbox there you can find code and also troubleshooting in the Issues section. Then you modify the code and make your own version, take a look at the structure of the.java files, using Singleton. The advice, is better to start with something you know it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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