diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index bd51cfbd0a..9c24a91a05 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_IBEACON_MINOR, CONF_IBEACON_UUID, CONF_MIN_RSSI, + CONF_TIMEOUT, ) CONF_IRK = "irk" @@ -41,6 +42,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_IBEACON_MAJOR): cv.uint16_t, cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t, cv.Optional(CONF_IBEACON_UUID): cv.uuid, + cv.Optional(CONF_TIMEOUT, default="5min"): cv.positive_time_period, cv.Optional(CONF_MIN_RSSI): cv.All( cv.decibel, cv.int_range(min=-100, max=-30) ), @@ -60,6 +62,7 @@ async def to_code(config): await cg.register_component(var, config) await esp32_ble_tracker.register_ble_device(var, config) + cg.add(var.set_timeout(config[CONF_TIMEOUT].total_milliseconds)) if min_rssi := config.get(CONF_MIN_RSSI): cg.add(var.set_minimum_rssi(min_rssi)) diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index 84753d5420..0d86f6a40d 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -59,11 +59,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, this->check_minimum_rssi_ = true; this->minimum_rssi_ = rssi; } - void on_scan_end() override { - if (!this->found_) - this->publish_state(false); - this->found_ = false; - } + void set_timeout(uint32_t timeout) { this->timeout_ = timeout; } bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { if (this->check_minimum_rssi_ && this->minimum_rssi_ > device.get_rssi()) { return false; @@ -71,8 +67,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, switch (this->match_by_) { case MATCH_BY_MAC_ADDRESS: if (device.address_uint64() == this->address_) { - this->publish_state(true); - this->found_ = true; + this->set_found_(true); return true; } break; @@ -86,8 +81,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, case MATCH_BY_SERVICE_UUID: for (auto uuid : device.get_service_uuids()) { if (this->uuid_ == uuid) { - this->publish_state(true); - this->found_ = true; + this->set_found_(true); return true; } } @@ -111,16 +105,26 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, return false; } - this->publish_state(true); - this->found_ = true; + this->set_found_(true); return true; } return false; } + + void loop() override { + if (this->found_ && this->last_seen_ + this->timeout_ < millis()) + this->set_found_(false); + } void dump_config() override; float get_setup_priority() const override { return setup_priority::DATA; } protected: + void set_found_(bool state) { + this->found_ = state; + if (state) + this->last_seen_ = millis(); + this->publish_state(state); + } enum MatchType { MATCH_BY_MAC_ADDRESS, MATCH_BY_IRK, MATCH_BY_SERVICE_UUID, MATCH_BY_IBEACON_UUID }; MatchType match_by_; @@ -177,6 +181,8 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, } bool found_{false}; + uint32_t last_seen_{}; + uint32_t timeout_{}; }; } // namespace ble_presence diff --git a/tests/test2.yaml b/tests/test2.yaml index f7a690709a..217a4c8feb 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -501,6 +501,7 @@ binary_sensor: - platform: ble_presence mac_address: AC:37:43:77:5F:4C name: ESP32 BLE Tracker Google Home Mini + timeout: 30s - platform: ble_presence service_uuid: 11aa name: BLE Test Service 16 Presence