diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 5b6f4211f2..878d3cd44e 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -674,7 +674,27 @@ void BluetoothProxy::loop() { } #endif +#ifdef USE_WIFI + // Wi-Fi (or a coexistence build that can fall back to it): every other + // non-empty 100 ms tick (~200 ms) gives partial batches time to fill + // toward BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE, so the air gets fewer, + // fuller frames. Full batches still ship immediately from the queueing + // path, and the owed-reply drains above keep the 100 ms cadence. + if (this->response_.advertisements_len != 0) { + if (this->adv_flush_toggle_) { + this->flush_pending_advertisements_(); + } + this->adv_flush_toggle_ = !this->adv_flush_toggle_; + } else { + // Nothing pending (idle, or a full batch just shipped inline): arm so + // the next batch ships on the next tick. + this->adv_flush_toggle_ = true; + } +#else + // No Wi-Fi in the build (ethernet): no airtime worth trading latency for, + // so partial batches flush every tick. this->flush_pending_advertisements_(); +#endif } void BluetoothProxy::reset_owed_replies_() { diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index 5d2605e761..e233c38b56 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -348,6 +348,12 @@ class BluetoothProxy final : public Component { uint8_t connection_count_{0}; #endif bool configured_scan_active_{false}; // Configured scan mode from YAML +#ifdef USE_WIFI + /// Wi-Fi only: flush on every other non-empty tick (~200 ms) so partial + /// batches fill; an idle tick re-arms, so the first batch after a gap + /// still ships on the next tick. See loop(). + bool adv_flush_toggle_{false}; +#endif #ifdef USE_BLE_SCANNER_STATE_CALLBACK // A dropped push (full TX buffer) is re-queried from the hub and resent // from loop(); the hub's current state is idempotent by construction.