mirror of
https://github.com/esphome/esphome.git
synced 2026-08-24 07:06:20 +00:00
Hold off reconnects after materializer failures on the esp32 bridge
A peer that reliably fails discovery (walk error, allocation failure) would otherwise reconnect on its next sighting forever, holding a controller slot each cycle - the neutral engine already backs off on this path.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "esphome/components/esp32_ble_client/ble_client_base.h"
|
||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
@@ -16,6 +17,13 @@ namespace esphome::ble_client {
|
||||
|
||||
static const char *const TAG = "ble_client";
|
||||
|
||||
#ifdef USE_BLE_CLIENT_GATT_NODES
|
||||
// Hold-off step per consecutive materializer failure, capped so a flapping
|
||||
// peer retries within a minute at worst (neutral-engine parity).
|
||||
static const uint32_t GATT_FAILURE_HOLD_OFF_STEP_MS = 10000;
|
||||
static const uint8_t GATT_FAILURE_HOLD_OFF_MAX_STEPS = 6;
|
||||
#endif
|
||||
|
||||
void BLEClient::setup() {
|
||||
BLEClientBase::setup();
|
||||
this->enabled = true;
|
||||
@@ -35,6 +43,11 @@ void BLEClient::dump_config() {
|
||||
bool BLEClient::parse_device(const espbt::ESPBTDevice &device) {
|
||||
if (!this->enabled)
|
||||
return false;
|
||||
#ifdef USE_BLE_CLIENT_GATT_NODES
|
||||
if (this->gatt_hold_off_ms_ != 0 && millis() - this->gatt_hold_off_start_ < this->gatt_hold_off_ms_ &&
|
||||
device.address_uint64() == this->address_)
|
||||
return false;
|
||||
#endif
|
||||
return BLEClientBase::parse_device(device);
|
||||
}
|
||||
|
||||
@@ -202,6 +215,7 @@ void BLEClient::handle_gatt_search_cmpl_(esp_gatt_status_t status) {
|
||||
// Distinguishes a failed search/count from a genuinely service-less peer.
|
||||
ESP_LOGW(TAG, "[%s] Service table unavailable (status=%d, services=%u); treating as failed discovery",
|
||||
this->address_str(), status, service_total);
|
||||
this->register_gatt_failure_();
|
||||
this->disconnect();
|
||||
return;
|
||||
}
|
||||
@@ -220,6 +234,17 @@ void BLEClient::handle_gatt_search_cmpl_(esp_gatt_status_t status) {
|
||||
// nodes just made hold it via the pending notify-registration count.
|
||||
for (auto *node : this->gatt_nodes_)
|
||||
node->node_state = espbt::ClientState::ESTABLISHED;
|
||||
this->gatt_consecutive_failures_ = 0;
|
||||
this->gatt_hold_off_ms_ = 0;
|
||||
}
|
||||
|
||||
void BLEClient::register_gatt_failure_() {
|
||||
if (this->gatt_consecutive_failures_ < GATT_FAILURE_HOLD_OFF_MAX_STEPS)
|
||||
this->gatt_consecutive_failures_++;
|
||||
this->gatt_hold_off_start_ = millis();
|
||||
this->gatt_hold_off_ms_ = this->gatt_consecutive_failures_ * GATT_FAILURE_HOLD_OFF_STEP_MS;
|
||||
ESP_LOGW(TAG, "[%s] Holding off reconnect for %u s", this->address_str(),
|
||||
this->gatt_consecutive_failures_ * (GATT_FAILURE_HOLD_OFF_STEP_MS / 1000));
|
||||
}
|
||||
|
||||
void BLEClient::on_disconnect_complete(esp_err_t reason) {
|
||||
|
||||
@@ -70,6 +70,7 @@ class BLEClient final : public BLEClientBase {
|
||||
void maybe_release_services_();
|
||||
#ifdef USE_BLE_CLIENT_GATT_NODES
|
||||
int check_gatt_op_(const char *operation, esp_err_t err);
|
||||
void register_gatt_failure_();
|
||||
void dispatch_gatt_event_(esp_gattc_cb_event_t event, esp_ble_gattc_cb_param_t *param);
|
||||
void handle_gatt_search_cmpl_(esp_gatt_status_t status);
|
||||
bool take_pending_gatt_reg_(uint16_t handle);
|
||||
@@ -87,6 +88,12 @@ class BLEClient final : public BLEClientBase {
|
||||
uint8_t pending_gatt_reg_count_{0};
|
||||
// on_connected fan-out started; on_disconnected is owed at teardown.
|
||||
bool gatt_connected_{false};
|
||||
// Backoff after materializer failures so a peer that reliably fails
|
||||
// discovery cannot produce an unbounded reconnect loop (neutral-engine
|
||||
// parity; wrap-safe start+duration pair).
|
||||
uint32_t gatt_hold_off_start_{0};
|
||||
uint32_t gatt_hold_off_ms_{0};
|
||||
uint8_t gatt_consecutive_failures_{0};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user