Use a queue and separate task to process BLE devices. (#1110)
This avoids excess processing in the BLE advertised device callback and prevents overflowing the BLE host stack.
This commit is contained in:
1 parent
d590c34c03
commit
8e6ebe87c9
1 file changed
+36
-6
+36
-6
@@ -35,6 +35,7 @@ Thanks to wolass https://github.com/wolass for suggesting me HM 10 and dinosd ht
|
|||||||
# ifdef ESP32
|
# ifdef ESP32
|
||||||
# include "FreeRTOS.h"
|
# include "FreeRTOS.h"
|
||||||
SemaphoreHandle_t semaphoreCreateOrUpdateDevice;
|
SemaphoreHandle_t semaphoreCreateOrUpdateDevice;
|
||||||
|
QueueHandle_t BLEQueue;
|
||||||
// Headers used for deep sleep functions
|
// Headers used for deep sleep functions
|
||||||
# include <NimBLEAdvertisedDevice.h>
|
# include <NimBLEAdvertisedDevice.h>
|
||||||
# include <NimBLEDevice.h>
|
# include <NimBLEDevice.h>
|
||||||
@@ -127,6 +128,7 @@ void PublishDeviceData(JsonObject& BLEdata, bool processBLEData = true);
|
|||||||
|
|
||||||
# ifdef ESP32
|
# ifdef ESP32
|
||||||
static TaskHandle_t xCoreTaskHandle;
|
static TaskHandle_t xCoreTaskHandle;
|
||||||
|
static TaskHandle_t xProcBLETaskHandle;
|
||||||
|
|
||||||
atomic_int forceBTScan;
|
atomic_int forceBTScan;
|
||||||
|
|
||||||
@@ -352,16 +354,28 @@ void DT24Discovery(const char* mac, const char* sensorModel_id) {}
|
|||||||
static int taskCore = 0;
|
static int taskCore = 0;
|
||||||
|
|
||||||
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
||||||
std::string convertServiceData(std::string deviceServiceData) {
|
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
||||||
|
if (xQueueSend(BLEQueue, &advertisedDevice, 0) != pdTRUE) {
|
||||||
|
Log.error(F("BLEQueue full" CR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string convertServiceData(std::string deviceServiceData) {
|
||||||
int serviceDataLength = (int)deviceServiceData.length();
|
int serviceDataLength = (int)deviceServiceData.length();
|
||||||
char spr[2 * serviceDataLength + 1];
|
char spr[2 * serviceDataLength + 1];
|
||||||
for (int i = 0; i < serviceDataLength; i++) sprintf(spr + 2 * i, "%.2x", (unsigned char)deviceServiceData[i]);
|
for (int i = 0; i < serviceDataLength; i++) sprintf(spr + 2 * i, "%.2x", (unsigned char)deviceServiceData[i]);
|
||||||
spr[2 * serviceDataLength] = 0;
|
spr[2 * serviceDataLength] = 0;
|
||||||
Log.trace("Converted service data (%d) to %s" CR, serviceDataLength, spr);
|
Log.trace("Converted service data (%d) to %s" CR, serviceDataLength, spr);
|
||||||
return spr;
|
return spr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void procBLETask(void* pvParameters) {
|
||||||
|
BLEAdvertisedDevice* advertisedDevice = nullptr;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
xQueueReceive(BLEQueue, &advertisedDevice, portMAX_DELAY);
|
||||||
|
|
||||||
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
|
||||||
if (!ProcessLock) {
|
if (!ProcessLock) {
|
||||||
Log.trace(F("Creating BLE buffer" CR));
|
Log.trace(F("Creating BLE buffer" CR));
|
||||||
JsonObject& BLEdata = getBTJsonObject();
|
JsonObject& BLEdata = getBTJsonObject();
|
||||||
@@ -374,7 +388,7 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
|||||||
# if BLE_FILTER_CONNECTABLE
|
# if BLE_FILTER_CONNECTABLE
|
||||||
if (device->connect) {
|
if (device->connect) {
|
||||||
Log.notice(F("Filtered connectable device" CR));
|
Log.notice(F("Filtered connectable device" CR));
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@@ -415,12 +429,16 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLEscan used to retrieve BLE advertized data from devices without connection
|
* BLEscan used to retrieve BLE advertized data from devices without connection
|
||||||
*/
|
*/
|
||||||
void BLEscan() {
|
void BLEscan() {
|
||||||
|
// Don't start the next scan until processing of previous results is complete.
|
||||||
|
while (uxQueueMessagesWaiting(BLEQueue)) {
|
||||||
|
yield();
|
||||||
|
}
|
||||||
disableCore0WDT();
|
disableCore0WDT();
|
||||||
Log.notice(F("Scan begin" CR));
|
Log.notice(F("Scan begin" CR));
|
||||||
BLEScan* pBLEScan = BLEDevice::getScan();
|
BLEScan* pBLEScan = BLEDevice::getScan();
|
||||||
@@ -433,6 +451,7 @@ void BLEscan() {
|
|||||||
scanCount++;
|
scanCount++;
|
||||||
Log.notice(F("Found %d devices, scan number %d end" CR), foundDevices.getCount(), scanCount);
|
Log.notice(F("Found %d devices, scan number %d end" CR), foundDevices.getCount(), scanCount);
|
||||||
enableCore0WDT();
|
enableCore0WDT();
|
||||||
|
Log.trace(F("Process BLE stack free: %u" CR), uxTaskGetStackHighWaterMark(xProcBLETaskHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -585,14 +604,25 @@ void setupBT() {
|
|||||||
semaphoreCreateOrUpdateDevice = xSemaphoreCreateBinary();
|
semaphoreCreateOrUpdateDevice = xSemaphoreCreateBinary();
|
||||||
xSemaphoreGive(semaphoreCreateOrUpdateDevice);
|
xSemaphoreGive(semaphoreCreateOrUpdateDevice);
|
||||||
|
|
||||||
|
BLEQueue = xQueueCreate(32, sizeof(NimBLEAdvertisedDevice*));
|
||||||
|
|
||||||
BLEDevice::setScanDuplicateCacheSize(BLEScanDuplicateCacheSize);
|
BLEDevice::setScanDuplicateCacheSize(BLEScanDuplicateCacheSize);
|
||||||
BLEDevice::init("");
|
BLEDevice::init("");
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
procBLETask, /* Function to implement the task */
|
||||||
|
"procBLETask", /* Name of the task */
|
||||||
|
5120, /* Stack size in bytes */
|
||||||
|
NULL, /* Task input parameter */
|
||||||
|
2, /* Priority of the task (set higher than core task) */
|
||||||
|
&xProcBLETaskHandle, /* Task handle. */
|
||||||
|
1); /* Core where the task should run */
|
||||||
|
|
||||||
// we setup a task with priority one to avoid conflict with other gateways
|
// we setup a task with priority one to avoid conflict with other gateways
|
||||||
xTaskCreatePinnedToCore(
|
xTaskCreatePinnedToCore(
|
||||||
coreTask, /* Function to implement the task */
|
coreTask, /* Function to implement the task */
|
||||||
"coreTask", /* Name of the task */
|
"coreTask", /* Name of the task */
|
||||||
10000, /* Stack size in words */
|
10000, /* Stack size in bytes */
|
||||||
NULL, /* Task input parameter */
|
NULL, /* Task input parameter */
|
||||||
1, /* Priority of the task */
|
1, /* Priority of the task */
|
||||||
&xCoreTaskHandle, /* Task handle. */
|
&xCoreTaskHandle, /* Task handle. */
|
||||||
|
|||||||
Reference in new issue
Block a user