У меня проблема с соединением Gatt между приложением Android (Java) и сервером ESP32 BLE.

Я пытаюсь подключить свое Android-приложение к gatt-серверу ESP32 BLE и получить некоторые целочисленные значения через характеристики этого сервера после получения уведомления

Однако, похоже, это не работает

Это мой Java-код:

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());
            }
        }
    }
}

А это мой логкэт:

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

И, наконец, это мой код ESP32:

#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;
    }
}

Интересно, что когда я подключаюсь через приложение nRF Connect, оно работает и получает значение моей характеристики. Я начинающий программист, буду признателен за любую помощь. Заранее спасибо!!


person Атанас Донев    schedule 20.03.2021    source источник


Ответы (2)


Ваше соединение завершается с ошибкой со статусом 133. Здесь много вопросов по этой теме. Это известная проблема с андроидом. В этом ответе предлагается использовать другую версию connectGatt, который для вас будет выглядеть следующим образом:

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

Это потребует от вас использования Android 6.0 (API 23) или новее, но это должно устранить вашу проблему. Если вам нужно использовать более раннюю версию Android, вы можете просто повторить попытку подключения, пока она не заработает.

person Michael Kotzjan    schedule 22.03.2021

Я предлагаю начать использовать: https://github.com/NordicSemiconductor/Android-nRF-Toolbox там вы можете найти код, а также устранение неполадок в разделе «Проблемы». Затем вы изменяете код и делаете свою собственную версию, взгляните на структуру файлов .java, используя Singleton. Совет, лучше начать с того, что вы знаете, это работает.

person LucasRT    schedule 23.03.2021