I'm developing a joint work Android app/ESP32 application to communicate via BLE. The goal is to be able to advertise, and to manage connections to exchange specific data for each android phone. On my ESP32, I want to be able to have a callback for GATT characteristic, and another one for the server. The first one for advertising data, the second for managing indicate feature and communicate though a connection. If a set one just for the characteristic, it works fine but I cannot access the state of the connection (whether a device is connected or not), if a set just one just for the server I get a guru meditation error, probably because I'm advertising at the same time ...
As a result, in my Android code, I never get into the method onCharacteristicChanged().
Is it possible to achieve my goal? If yes, how?
I mainly follow this example : https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/examples/BLE_notify/BLE_notify.ino
ESP32
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE_Carousel.h>
#include <BLE2902.h>
#include <iostream>
#include <algorithm>
#include <ArduinoJson.h>
using namespace std;
#define PACKET_SIZE 24
#define HEADER_SIZE 3 // Object ID 1 byte, Object size 1 byte Packet Number 1 byte
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" // UUID dedicated to consent transmission
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" // Characterisitic that will receive the consent
int idx = 0;
BLEAdvertising *pAdvertising;
BLEServer *pServer = NULL;
BLE_Carousel carousel = BLE_Carousel(PACKET_SIZE, HEADER_SIZE);
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
uint32_t value = 0;
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
std::cout << "1" << "\n";
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
std::cout << "0" << "\n";
}
};
class MyCallBack: public BLECharacteristicCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
std::cout << "1" << "\n";
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
std::cout << "0" << "\n";
}
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if ((rxValue.length() > 0) && (rxValue.find ('&') == std::string::npos)) {
Serial.println("*********");
}
}
}; //end of callback
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
BLEDevice::init("InCon_Beacon");
pServer = BLEDevice::createServer();
//pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pCharacteristic->addDescriptor(new BLE2902());
// Configure the characteristic
// The maximum length of an attribute value shall be 512 octets.
pCharacteristic->setValue("Value");
pCharacteristic->setCallbacks(new MyCallBack());
Serial.println("Characteristic defined!");
// Allocate the buffer that will contain the privacy policy
byte pp[pp_size] = { ... };
// Initialize the Carousel
carousel.set_Data(pp, pp_size);
// Configure the payload of advertising packets
byte* packet = (byte*)carousel.get_Packet( 0);
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04
//std::string strServiceData = "";
std::string strServiceData = "";
strServiceData += (char)11; // Len
strServiceData += (char)0xFF; // Type
strServiceData += "0123456789";
oAdvertisementData.addData(strServiceData);
pAdvertising = pServer->getAdvertising();
//Serial.println("Payload:");
//Serial.println(oAdvertisementData.getPayload().c_str());
//pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
set_new_adv_payload(idx);
// Start service and advertising
pService->start();
pAdvertising->start();
}
void set_new_adv_payload(int idx) {
//Serial.println(idx);
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04
std::string strServiceData = "";
//Serial.println(carousel.get_Nb_Packets());
strServiceData += (char)(PACKET_SIZE + 1); // Len
strServiceData += (char)0xFF; // Type
byte* packet = (byte*)carousel.get_Packet( idx);
for (int i = 0; i < PACKET_SIZE; i++) {
strServiceData += (char) packet[i];
}
free(packet);
//Serial.println(idx);
oAdvertisementData.addData(strServiceData);
pAdvertising->setAdvertisementData(oAdvertisementData);
}
void loop() {
delay(200);
//Serial.println(idx);
set_new_adv_payload(idx);
idx = (idx + 1) % carousel.get_Nb_Packets();
if (deviceConnected) {
pCharacteristic->setValue((uint8_t*)&value, 4);
pCharacteristic->notify();
value++;
std::cout << value << "\n";
delay(3); // 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
}
}
Dealing with notify/indicate
BluetoothGatt bleGatt;
BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic characteristic =
gatt.getService(UUID.fromString("4fafc201-1fb5-459e-8fcc-c5c9c331914b"))
.getCharacteristic(UUID.fromString("beb5483e-36e1-4688-b7f5-ea07361b26a8"));
characteristic.setValue(new byte[]{1, 1});
gatt.writeCharacteristic(characteristic);
// String test = "test";
// characteristic.setValue(test);
// gatt.writeCharacteristic(characteristic);
gatt.disconnect();
}
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == STATE_CONNECTED){
gatt.discoverServices();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status){
BluetoothGattCharacteristic characteristic =
gatt.getService(UUID.fromString("4fafc201-1fb5-459e-8fcc-c5c9c331914b"))
.getCharacteristic(UUID.fromString("beb5483e-36e1-4688-b7f5-ea07361b26a8"));
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));//enable gattcharac to have indication
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
characteristic.getValue();
Log.i("ohyes",characteristic.getValue().toString());
}
};
bleGatt = mDeviceStore.getDeviceList().get(0).getDevice().connectGatt(this, true, gattCallback);
When dealing with regular GATT
BGS = mBluetoothLeService.getSupportedGattServices();
for (BluetoothGattService gattService : BGS) {
if (gattService.getUuid().toString().equals("4fafc201-1fb5-459e-8fcc-c5c9c331914b")) {
List<BluetoothGattCharacteristic> BGC = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharac : BGC) {
if (gattCharac.getUuid().toString().equals("beb5483e-36e1-4688-b7f5-ea07361b26a8")) {
//String s = PolicyEngine.policyModelToProto(intersection).toString();
PilotPolicyProto.PilotPolicy.Builder pol = PolicyEngine.policyModelToBuilder(DSP);
try {
String s = JsonFormat.printer().print(pol);
// s = s.substring(s.indexOf('\n')+1);
// s = s+"{";
Log.i("dede", s);
gattCharac.setValue("&" + s);
boolean consent = mBluetoothLeService.mBluetoothGatt.writeCharacteristic(gattCharac);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
}
}
}
Core 1 register dump:
PC : 0x40166dc5 PS : 0x00060330 A0 : 0x800d6ae5 A1 : 0x3ffc9af0
A2 : 0x00000074 A3 : 0x3ffc9b24 A4 : 0x3ffc4e70 A5 : 0x00000000
A6 : 0x00000001 A7 : 0x3ffe05e4 A8 : 0x3ffc9b30 A9 : 0x3ffc9ad0
A10 : 0x3ffc9b2c A11 : 0x3ffc4e6c A12 : 0x3ffc4e70 A13 : 0x3f401c72
A14 : 0x00000002 A15 : 0x00000001 SAR : 0x00000008 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000074 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
User contributions licensed under CC BY-SA 3.0