mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 15:08:10 +01:00
Add BLE scan parameters (#769)
* Add BLE parameters Fixes https://github.com/esphome/issues/issues/735 * Fix
This commit is contained in:
parent
aebb6d2fcc
commit
4310c14497
5 changed files with 53 additions and 19 deletions
|
@ -1,19 +1,48 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
|
||||
from esphome.const import CONF_ID, ESP_PLATFORM_ESP32, CONF_INTERVAL, \
|
||||
CONF_DURATION
|
||||
from esphome.core import coroutine
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
AUTO_LOAD = ['xiaomi_ble']
|
||||
|
||||
CONF_ESP32_BLE_ID = 'esp32_ble_id'
|
||||
CONF_SCAN_PARAMETERS = 'scan_parameters'
|
||||
CONF_WINDOW = 'window'
|
||||
CONF_ACTIVE = 'active'
|
||||
esp32_ble_tracker_ns = cg.esphome_ns.namespace('esp32_ble_tracker')
|
||||
ESP32BLETracker = esp32_ble_tracker_ns.class_('ESP32BLETracker', cg.Component)
|
||||
ESPBTDeviceListener = esp32_ble_tracker_ns.class_('ESPBTDeviceListener')
|
||||
|
||||
|
||||
def validate_scan_parameters(config):
|
||||
duration = config[CONF_DURATION]
|
||||
interval = config[CONF_INTERVAL]
|
||||
window = config[CONF_WINDOW]
|
||||
|
||||
if window > interval:
|
||||
raise cv.Invalid("Scan window ({}) needs to be smaller than scan interval ({})"
|
||||
"".format(window, interval))
|
||||
|
||||
if interval.total_milliseconds * 3 > duration.total_milliseconds:
|
||||
raise cv.Invalid("Scan duration needs to be at least three times the scan interval to"
|
||||
"cover all BLE channels.")
|
||||
|
||||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(ESP32BLETracker),
|
||||
cv.Optional(CONF_SCAN_INTERVAL, default='300s'): cv.positive_time_period_seconds,
|
||||
cv.Optional(CONF_SCAN_PARAMETERS, default={}): cv.All(cv.Schema({
|
||||
cv.Optional(CONF_DURATION, default='5min'): cv.positive_time_period_seconds,
|
||||
cv.Optional(CONF_INTERVAL, default='320ms'): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_WINDOW, default='200ms'): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_ACTIVE, default=True): cv.boolean,
|
||||
}), validate_scan_parameters),
|
||||
|
||||
cv.Optional('scan_interval'): cv.invalid("This option has been removed in 1.14 (Reason: "
|
||||
"it never had an effect)"),
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
ESP_BLE_DEVICE_SCHEMA = cv.Schema({
|
||||
|
@ -24,7 +53,11 @@ ESP_BLE_DEVICE_SCHEMA = cv.Schema({
|
|||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
cg.add(var.set_scan_interval(config[CONF_SCAN_INTERVAL]))
|
||||
params = config[CONF_SCAN_PARAMETERS]
|
||||
cg.add(var.set_scan_duration(params[CONF_DURATION]))
|
||||
cg.add(var.set_scan_interval(int(params[CONF_INTERVAL].total_milliseconds / 0.625)))
|
||||
cg.add(var.set_scan_window(int(params[CONF_WINDOW].total_milliseconds / 0.625)))
|
||||
cg.add(var.set_scan_active(params[CONF_ACTIVE]))
|
||||
|
||||
|
||||
@coroutine
|
||||
|
|
|
@ -150,21 +150,16 @@ void ESP32BLETracker::start_scan(bool first) {
|
|||
listener->on_scan_end();
|
||||
}
|
||||
this->already_discovered_.clear();
|
||||
this->scan_params_.scan_type = BLE_SCAN_TYPE_ACTIVE;
|
||||
this->scan_params_.scan_type = this->scan_active_ ? BLE_SCAN_TYPE_ACTIVE : BLE_SCAN_TYPE_PASSIVE;
|
||||
this->scan_params_.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
|
||||
this->scan_params_.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
|
||||
// Values determined empirically, higher scan intervals and lower scan windows make the ESP more stable
|
||||
// Ideally, these values should both be quite low, especially scan window. 0x10/0x10 is the esp-idf
|
||||
// default and works quite well. 0x100/0x50 discovers a few less BLE broadcast packets but is a lot
|
||||
// more stable (order of several hours). The old ESPHome default (1600/1600) was terrible with
|
||||
// crashes every few minutes
|
||||
this->scan_params_.scan_interval = 0x200;
|
||||
this->scan_params_.scan_window = 0x30;
|
||||
this->scan_params_.scan_interval = this->scan_interval_;
|
||||
this->scan_params_.scan_window = this->scan_window_;
|
||||
|
||||
esp_ble_gap_set_scan_params(&this->scan_params_);
|
||||
esp_ble_gap_start_scanning(this->scan_interval_);
|
||||
esp_ble_gap_start_scanning(this->scan_duration_);
|
||||
|
||||
this->set_timeout("scan", this->scan_interval_ * 2000, []() {
|
||||
this->set_timeout("scan", this->scan_duration_ * 2000, []() {
|
||||
ESP_LOGW(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack...");
|
||||
App.reboot();
|
||||
});
|
||||
|
@ -454,10 +449,12 @@ const std::string &ESPBTDevice::get_manufacturer_data() const { return this->man
|
|||
const std::string &ESPBTDevice::get_service_data() const { return this->service_data_; }
|
||||
const optional<ESPBTUUID> &ESPBTDevice::get_service_data_uuid() const { return this->service_data_uuid_; }
|
||||
|
||||
void ESP32BLETracker::set_scan_interval(uint32_t scan_interval) { this->scan_interval_ = scan_interval; }
|
||||
void ESP32BLETracker::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "BLE Tracker:");
|
||||
ESP_LOGCONFIG(TAG, " Scan Interval: %u s", this->scan_interval_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Duration: %u s", this->scan_duration_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Interval: %u ms", this->scan_interval_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Window: %u ms", this->scan_window_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Type: %s", this->scan_active_ ? "ACTIVE" : "PASSIVE");
|
||||
}
|
||||
void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) {
|
||||
const uint64_t address = device.address_uint64();
|
||||
|
|
|
@ -107,7 +107,10 @@ class ESPBTDeviceListener {
|
|||
|
||||
class ESP32BLETracker : public Component {
|
||||
public:
|
||||
void set_scan_interval(uint32_t scan_interval);
|
||||
void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; }
|
||||
void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
|
||||
void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
|
||||
void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
|
||||
|
||||
/// Setup the FreeRTOS task and the Bluetooth stack.
|
||||
void setup() override;
|
||||
|
@ -142,7 +145,10 @@ class ESP32BLETracker : public Component {
|
|||
/// A structure holding the ESP BLE scan parameters.
|
||||
esp_ble_scan_params_t scan_params_;
|
||||
/// The interval in seconds to perform scans.
|
||||
uint32_t scan_interval_{300};
|
||||
uint32_t scan_duration_;
|
||||
uint32_t scan_interval_;
|
||||
uint32_t scan_window_;
|
||||
bool scan_active_;
|
||||
SemaphoreHandle_t scan_result_lock_;
|
||||
SemaphoreHandle_t scan_end_lock_;
|
||||
size_t scan_result_index_{0};
|
||||
|
|
|
@ -364,7 +364,6 @@ CONF_RX_PIN = 'rx_pin'
|
|||
CONF_SAFE_MODE = 'safe_mode'
|
||||
CONF_SAMSUNG = 'samsung'
|
||||
CONF_SCAN = 'scan'
|
||||
CONF_SCAN_INTERVAL = 'scan_interval'
|
||||
CONF_SCL = 'scl'
|
||||
CONF_SCL_PIN = 'scl_pin'
|
||||
CONF_SDA = 'sda'
|
||||
|
|
|
@ -197,7 +197,6 @@ remote_receiver:
|
|||
dump: []
|
||||
|
||||
esp32_ble_tracker:
|
||||
scan_interval: 300s
|
||||
|
||||
#esp32_ble_beacon:
|
||||
# type: iBeacon
|
||||
|
|
Loading…
Reference in a new issue