Reputation: 3
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!!
Upvotes: 0
Views: 1205
Reputation: 179
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.
Upvotes: 0
Reputation: 2673
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.
Upvotes: 0