Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a second recovery path if BLE stack stops being able to receive adverts #20365

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ uint64_t BLELastLoopTime = 0;
int BLEScanTimeS = 20; // scan duraiton in S
int BLEMaxTimeBetweenAdverts = 120; // we expect an advert at least this frequently, else restart BLE (in S)
uint64_t BLEScanLastAdvertismentAt = 0;
uint32_t BLEScanLastAdvertisementAtResets = 0;
uint32_t lastopid = 0; // incrementing uinique opid
uint32_t BLEResets = 0;
// controls request of details about one device
Expand Down Expand Up @@ -1333,6 +1334,7 @@ class BLEAdvCallbacks: public NimBLEAdvertisedDeviceCallbacks {
TasAutoMutex localmutex(&BLEOperationsRecursiveMutex, "BLEAddCB");
uint64_t now = esp_timer_get_time();
BLEScanLastAdvertismentAt = now; // note the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // note the number of resets when the last advertisement occurred

uint32_t totalCount = BLEAdvertisment.totalCount;
memset(&BLEAdvertisment, 0, sizeof(BLEAdvertisment));
Expand Down Expand Up @@ -1604,6 +1606,7 @@ static void BLEInit(void) {

uint64_t now = esp_timer_get_time();
BLEScanLastAdvertismentAt = now; // initialise the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // initialise the number of resets for the last advertisement
BLELastLoopTime = now;

BLEInitState = 1;
Expand Down Expand Up @@ -1692,6 +1695,7 @@ static void BLETaskStopStartNimBLE(NimBLEClient **ppClient, bool start = true){
// don't restart because of these for a while
BLELastLoopTime = now; // initialise the time of the last advertisment
BLEScanLastAdvertismentAt = now; // initialise the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // initialise the number of resets for the last advertisement

}

Expand Down Expand Up @@ -1839,6 +1843,7 @@ static void BLETaskRunCurrentOperation(BLE_ESP32::generic_sensor_t** pCurrentOpe
// set the last advert time each time we start an operation
uint64_t now = esp_timer_get_time();
BLEScanLastAdvertismentAt = now; // initialise the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // initialise the number of resets for the last advertisement


generic_sensor_t* op = *pCurrentOperation;
Expand Down Expand Up @@ -2718,6 +2723,7 @@ void CmndBLEMode(void){
} break;
}
BLEScanLastAdvertismentAt = now; // note the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // note the number of resets when the last advertisement occurred
} break;
case BLEModeRegularScan:{
uint64_t now = esp_timer_get_time();
Expand All @@ -2737,6 +2743,7 @@ void CmndBLEMode(void){
} break;
}
BLEScanLastAdvertismentAt = now; // note the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // note the number of resets when the last advertisement occurred
} break;
default:
ResponseCmndChar("InvalidIndex");
Expand Down Expand Up @@ -3244,6 +3251,7 @@ static void mainThreadBLETimeouts() {
if (!BLERunning){
BLELastLoopTime = now; // initialise the time of the last advertisment
BLEScanLastAdvertismentAt = now; // initialise the time of the last advertisment
BLEScanLastAdvertisementAtResets = BLEResets; // initialise the number of resets when the last advertisement
return;
}

Expand All @@ -3260,14 +3268,22 @@ static void mainThreadBLETimeouts() {
// if no adverts for 120s, and BLE is running, retsart NimBLE.
// belt and braces....
uint64_t adTimeout = ((uint64_t)BLEMaxTimeBetweenAdverts)*1000L*1000L;
if (BLEScanLastAdvertismentAt + adTimeout < now){
BLEScanLastAdvertismentAt = now; // initialise the time of the last advertisment
if ((BLEScanLastAdvertisementAtResets == BLEResets) && (BLEScanLastAdvertismentAt + adTimeout < now)){
BLERestartNimBLE = 1;
AddLog(LOG_LEVEL_ERROR,PSTR("BLE: scan stall? no adverts > 120s, restart BLE"));

BLERestartBLEReason = BLE_RESTART_BLE_REASON_ADVERT_BLE_TIMEOUT;
}

// if no adverts for 240s, and NimBLE restart didn't fix the problem, restart Tasmota.
if ((BLEScanLastAdvertisementAtResets != BLEResets) && (BLEScanLastAdvertismentAt + (2L*adTimeout) < now))
{
BLERestartTasmota = 10;
AddLog(LOG_LEVEL_ERROR, PSTR("BLE: scan still stall? no adverts > 240s, restart Tasmota in 10s"));

BLERestartBLEReason = BLE_RESTART_BLE_REASON_ADVERT_BLE_TIMEOUT;
}

// if stuck and have not done task for 120s, something is seriously wrong.
// restart Tasmota completely. (belt and braces)
uint64_t bleLoopTimeout = ((uint64_t)BLEMaxTaskLoopTime)*1000L*1000L;
Expand Down