esp32 ble suspend inside registerForNotify
Posted: Sun Nov 24, 2024 1:52 pm
Hi
I am newbie in esp32.
I would like connect to BLE device make few requests and disconnect, and repeat it periodically.
The main problem is - device freeze inside BLE api registerForNotify , it happens seldom if signal good and often(on 3-5 request) if poor .
I think problem happen when we inside registerForNotify and callback disconnect event happen.
Board: ESP32 LILYGO T-Display v1.1 4MB.
Code:
Connection log:
[ 72991][D][BLE_BMS.cpp:181] connect(): [BLE_BMS] canNotify
[ 72996][D][BLE_BMS.cpp:187] connect(): [BLE_BMS] registerForNotify
[ 73002][V][BLERemoteCharacteristic.cpp:452] registerForNotify(): >> registerForNotify(): .....
[ 73085][V][BLERemoteDescriptor.cpp:162] writeValue(): >> writeValue: handle: 19, uuid: 00002902-0000-1000-8000-00805f9b34fb
[ 73146][V][FreeRTOS.cpp:59] wait(): >> wait: Semaphore waiting: name: WriteDescrEvt (0x3ffe6240), owner: writeValue for writeValue
[ 85886][BLE_BMS.cpp:89] onDisconnect(): [BLE_BMS] onDisconnect
[ 85946][V][BLEUtils.cpp:1214] dumpGattClientEvent(): [status: ESP_GATT_OK, reason:ESP_GATT_CONN_TIMEOUT, conn_id: 0]
*/
I am newbie in esp32.
I would like connect to BLE device make few requests and disconnect, and repeat it periodically.
The main problem is - device freeze inside BLE api registerForNotify , it happens seldom if signal good and often(on 3-5 request) if poor .
I think problem happen when we inside registerForNotify and callback disconnect event happen.
Board: ESP32 LILYGO T-Display v1.1 4MB.
Code:
Code: Select all
void loop() {
// if ( stop_work )
// return ;
uint32_t cur_ms = millis();
switch( status ){
case(0):
if ( JkBms.connect() ){
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0);
tft.printf( "connected. up:%dmin\n", (millis() - uptime)/60000);
status = 1;
}else{
tft.printf( "fail conn. up:%dmin\n", (millis() - uptime)/60000);
if ( printLinCur >= 13 ){
tft.fillScreen(TFT_BLACK);
printLinCur = 0;
}
ESP_LOGD("", "fail conn. up:%dmin\n", (millis() - uptime)/60000);
printLinCur += 1;
}
delay(1500);
last_event_ms = millis();
break;
case(1):
if (cur_ms - last_event_ms > 30000){
ESP_LOGD("", "disconnect, uptime %dmin", (cur_ms - uptime)/60000);
tft.printf( "disconnect, uptime %dmin\n", (cur_ms - uptime)/60000);
JkBms.disconnect();
last_event_ms = millis();
status = 2;
}
break;
case(2):
if (cur_ms - last_event_ms > 20000){
ESP_LOGD("", "restart switch, uptime %dmin", (cur_ms - uptime)/60000);
tft.printf("restart switch, uptime %dmin\n", (cur_ms - uptime)/60000);
status = 0;
last_event_ms = cur_ms;
delay(1500);
}
break;
default:
break;
};
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
ESP_LOGD(TAG, "Advertised Device: %s \n", advertisedDevice.toString().c_str());
if (!advertisedDevice.getAddress().equals(BLE_JKBMS_ADDR)) {
ESP_LOGI(TAG, "Skip: %s", advertisedDevice.toString().c_str());
return ;
};
for (int i = 0; i < advertisedDevice.getServiceUUIDCount(); ++i) {
if (advertisedDevice.getServiceUUID(i).equals(jkbms_service_UUID)) {
ESP_LOGD(TAG, "found device, stop scan.");
pBLEScan->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
ESP_LOGI(TAG, "Choice %s", advertisedDevice.toString().c_str());
break;
}
}
}
};
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
connected = true;
ESP_LOGI(TAG, "onConnect %s", pclient->toString().c_str());
}
void onDisconnect(BLEClient* pclient) {
connected = false;
ESP_LOGI(TAG, "onDisconnect");
}
};
void BLE_BMS_JK::setup() {
BLEDevice::init("");
if (pMyAdvertisedDeviceCallbacks != nullptr) {
ESP_LOGE(TAG, "already called setup");
return;
}
pMyAdvertisedDeviceCallbacks = new MyAdvertisedDeviceCallbacks();
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(pMyAdvertisedDeviceCallbacks);
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(300);
pBLEScan->setWindow(200); // less or equal setInterval value
};
bool BLE_BMS_JK::connect() {
if ( pClient ){
if ( pClient->isConnected() ){
return true;
}
}
ESP_LOGD(TAG, "Forming a connection");
connected = false;
pBLEScan->clearResults();
if ( !pBLEScan->start(m_scanTime) )
return false;
if ( !myDevice )
return false;
int status = -1;
do{
if ( !pMyClientCallback )
pMyClientCallback = new MyClientCallback();
if ( !pClient )
pClient = BLEDevice::createClient();
if ( !pMyClientCallback || !pClient){
ESP_LOGE(TAG, "fail create ClientCallback or Client");
break;
}
pClient->setClientCallbacks(pMyClientCallback);
ESP_LOGD(TAG, "pClient->connect");
if (!pClient->connect(myDevice)){
ESP_LOGI(TAG, "Fail connect");
break;
}
delay(100);
BLERemoteService* pRemoteService = pClient->getService(jkbms_service_UUID);
if (pRemoteService == nullptr) {
ESP_LOGE(TAG, "Failed to find our service UUID: %s", jkbms_service_UUID.toString().c_str());
break;
}
ESP_LOGD(TAG, " - Found our service");
delay(100);
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
ESP_LOGE(TAG, "Failed to find our characteristic UUID: %s", charUUID.toString().c_str());
break;
}
ESP_LOGD(TAG, "pRemoteCharacteristic = %s", pRemoteCharacteristic->toString().c_str());
delay(100);
if ( !connected )
{
ESP_LOGI(TAG, "not connected");
break;
}
ESP_LOGD(TAG, "canNotify");
if ([b]!pRemoteCharacteristic->canNotify()[/b]){
ESP_LOGE(TAG, "No notify characteristic");
break;
}
ESP_LOGD(TAG, "registerForNotify");
pRemoteCharacteristic->registerForNotify(notifyCallback);
ESP_LOGD(TAG, "conn status OK");
status = 0;
}while(0);
if ( status != 0)
{
if ( pClient )
{
if ( pClient->isConnected() )
pClient->disconnect();
}
if ( pRemoteCharacteristic != nullptr)
pRemoteCharacteristic->registerForNotify(nullptr);
pRemoteCharacteristic = nullptr;
if (myDevice != nullptr){
delete myDevice;
myDevice = nullptr;
}
}
else
{
ESP_LOGD(TAG, "GetDevInfo");
getDeviceInfo(pRemoteCharacteristic);
}
return status == 0;
}
void BLE_BMS_JK::disconnect(){
if ( pClient == nullptr )
return ;
ESP_LOGD(TAG, "disconnect: %s", myDevice->toString().c_str());
if ( pRemoteCharacteristic != nullptr)
pRemoteCharacteristic->registerForNotify(nullptr); // unregister callback ?
pClient->disconnect();
pRemoteCharacteristic = nullptr;
if ( myDevice != nullptr )
{
delete myDevice;
myDevice = nullptr;
}
}
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify)
{
tLastNotify_ms = millis();
// Flush buffer on every preamble
if (pData[0] == 0x55 && pData[1] == 0xAA && pData[2] == 0xEB && pData[3] == 0x90) {
frame_buffer.clear();
}
frame_buffer.insert(frame_buffer.end(), pData, pData + length);
if (frame_buffer.size() >= MIN_RESPONSE_SIZE) {
const uint8_t *raw = &frame_buffer[0];
// Even if the frame is 320 bytes long the CRC is at position 300 in front of 0xAA 0x55 0x90 0xEB
const uint16_t frame_size = MIN_RESPONSE_SIZE; // this->frame_buffer_.size();
uint8_t computed_crc = crc(raw, frame_size - 1);
uint8_t remote_crc = raw[frame_size - 1];
if (computed_crc != remote_crc) {
ESP_LOGE(TAG, "CRC check failed! 0x%02X != 0x%02X", computed_crc, remote_crc);
frame_buffer.clear();
return;
}
std::vector<uint8_t> data(frame_buffer.begin(), frame_buffer.end());
decode(data);
frame_buffer.clear();
// status_notify = 1;
}
}
Connection log:
[ 72991][D][BLE_BMS.cpp:181] connect(): [BLE_BMS] canNotify
[ 72996][D][BLE_BMS.cpp:187] connect(): [BLE_BMS] registerForNotify
[ 73002][V][BLERemoteCharacteristic.cpp:452] registerForNotify(): >> registerForNotify(): .....
[ 73085][V][BLERemoteDescriptor.cpp:162] writeValue(): >> writeValue: handle: 19, uuid: 00002902-0000-1000-8000-00805f9b34fb
[ 73146][V][FreeRTOS.cpp:59] wait(): >> wait: Semaphore waiting: name: WriteDescrEvt (0x3ffe6240), owner: writeValue for writeValue
[ 85886][BLE_BMS.cpp:89] onDisconnect(): [BLE_BMS] onDisconnect
[ 85946][V][BLEUtils.cpp:1214] dumpGattClientEvent(): [status: ESP_GATT_OK, reason:ESP_GATT_CONN_TIMEOUT, conn_id: 0]
Code: Select all
[ 72764][D][BLE_BMS.cpp:162] connect(): [BLE_BMS] - Found our service
[ 72870][D][BLE_BMS.cpp:172] connect(): [BLE_BMS] pRemoteCharacteristic = Characteristic: uuid: 0000ffe1-0000-1000-8000-00805f9b34fb, handle: 18 0x0012, props: broadcast: 0, read: 0, write_nr: 1, write: 1, noti0
[ 72991][D][BLE_BMS.cpp:181] connect(): [BLE_BMS] canNotify
[ 72996][D][BLE_BMS.cpp:187] connect(): [BLE_BMS] registerForNotify
[ 73002][V][BLERemoteCharacteristic.cpp:452] registerForNotify(): >> registerForNotify(): Characteristic: uuid: 0000ffe1-0000-1000-8000-00805f9b34fb, handle: 18 0x0012, props: broadcast: 0, read: 0, write_nr: 10
[ 73025][V][FreeRTOS.cpp:179] take(): Semaphore taking: name: RegForNotifyEvt (0x3ffe6074), owner: <N/A> for registerForNotify
[ 73036][V][FreeRTOS.cpp:188] take(): Semaphore taken: name: RegForNotifyEvt (0x3ffe6074), owner: registerForNotify
[ 73047][V][BLERemoteCharacteristic.cpp:331] getDescriptor(): >> getDescriptor: uuid: 00002902-0000-1000-8000-00805f9b34fb
[ 73047][D][BLEDevice.cpp:138] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_REG_FOR_NOTIFY_EVT
[ 73069][V][BLERemoteCharacteristic.cpp:335] getDescriptor(): << getDescriptor: found
[ 73069][V][BLEUtils.cpp:1202] dumpGattClientEvent(): GATT Event: ESP_GATTC_REG_FOR_NOTIFY_EVT
[ 73085][V][BLEUtils.cpp:1368] dumpGattClientEvent(): [status: ESP_GATT_OK, handle: 18 0x12]
[ 73085][V][BLERemoteDescriptor.cpp:162] writeValue(): >> writeValue: handle: 19, uuid: 00002902-0000-1000-8000-00805f9b34fb
[ 73104][V][FreeRTOS.cpp:179] take(): Semaphore taking: name: WriteDescrEvt (0x3ffe6240), owner: <N/A> for writeValue
[ 73104][D][BLEClient.cpp:185] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_REG_FOR_NOTIFY_EVT
[ 73126][V][FreeRTOS.cpp:188] take(): Semaphore taken: name: WriteDescrEvt (0x3ffe6240), owner: writeValue
[ 73126][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: RegForNotifyEvt (0x3ffe6074), owner: registerForNotify
[ 73146][V][FreeRTOS.cpp:59] wait(): >> wait: Semaphore waiting: name: WriteDescrEvt (0x3ffe6240), owner: writeValue for writeValue
[ 76072][V][BLEUtils.cpp:967] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[ 76081][V][BLEUtils.cpp:1170] dumpGapEvent(): [status: 0, bd_addr: c8:47:80:19:16:25, min_int: 12, max_int: 16, latency: 0, conn_int: 16, timeout: 600]
[ 76094][D][BLEClient.cpp:496] handleGAPEvent(): BLEClient ... handling GAP event!
llcp prog: 438 1 269 0 0
[ 85810][D][BLEDevice.cpp:138] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_DISCONNECT_EVT
[ 85821][V][BLEUtils.cpp:1202] dumpGattClientEvent(): GATT Event: ESP_GATTC_DISCONNECT_EVT
[ 85829][V][BLEUtils.cpp:1241] dumpGattClientEvent(): [reason: ESP_GATT_CONN_TIMEOUT, conn_id: 0, remote_bda: c8:47:80:19:16:25]
[ 85840][D][BLEClient.cpp:185] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_DISCONNECT_EVT
[ 85852][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: OpenEvt (0x3ffe261c), owner: <N/A>
[ 85860][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: RssiCmplEvt (0x3ffe2720), owner: <N/A>
[ 85869][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: SearchCmplEvt (0x3ffe2680), owner: <N/A>
[ 85878][I][BLEDevice.cpp:609] removePeerDevice(): remove: 1, GATT role client
[ 85886][I][BLE_BMS.cpp:89] onDisconnect(): [BLE_BMS] onDisconnect
[ 85891][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: ReadCharEvt (0x3ffe5d2c), owner: <N/A>
[ 85900][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: WriteCharEvt (0x3ffe5df4), owner: <N/A>
[ 85910][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: ReadCharEvt (0x3ffe6010), owner: <N/A>
[ 85919][V][FreeRTOS.cpp:136] give(): Semaphore giving: name: WriteCharEvt (0x3ffe60d8), owner: <N/A>
[ 85928][D][BLEDevice.cpp:138] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_CLOSE_EVT
[ 85938][V][BLEUtils.cpp:1202] dumpGattClientEvent(): GATT Event: ESP_GATTC_CLOSE_EVT
[ 85946][V][BLEUtils.cpp:1214] dumpGattClientEvent(): [status: ESP_GATT_OK, reason:ESP_GATT_CONN_TIMEOUT, conn_id: 0]
[ 85957][D][BLEDevice.cpp:138] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_UNREG_EVT
[ 85967][V][BLEUtils.cpp:1202] dumpGattClientEvent(): GATT Event: ESP_GATTC_UNREG_EVT
no any responses ...
*/
Code: Select all
void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications) {
ESP_LOGD(LOG_TAG, ">> registerForNotify(): %s", toString().c_str());
m_notifyCallback = notifyCallback; // Save the notification callback.
if (notifyCallback != nullptr) { // If we have a callback function, then this is a registration.
esp_err_t errRc = ::esp_ble_gattc_register_for_notify(
m_pRemoteService->getClient()->getGattcIf(),
*m_pRemoteService->getClient()->getPeerAddress().getNative(),
getHandle()
);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_for_notify: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
}
uint8_t val[] = {0x01, 0x00};
if(!notifications) val[0] = 0x02;
BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902));
if(desc != nullptr)
desc->writeValue(val, 2);
} // End Register
m_semaphoreRegForNotifyEvt.wait("registerForNotify"); /// Looks Like suspend here
ESP_LOGD(LOG_TAG, "<< registerForNotify()");
} // registerForNotify