mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 08:55:22 +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.codegen as cg
|
||||||
import esphome.config_validation as cv
|
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
|
from esphome.core import coroutine
|
||||||
|
|
||||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
AUTO_LOAD = ['xiaomi_ble']
|
AUTO_LOAD = ['xiaomi_ble']
|
||||||
|
|
||||||
CONF_ESP32_BLE_ID = 'esp32_ble_id'
|
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')
|
esp32_ble_tracker_ns = cg.esphome_ns.namespace('esp32_ble_tracker')
|
||||||
ESP32BLETracker = esp32_ble_tracker_ns.class_('ESP32BLETracker', cg.Component)
|
ESP32BLETracker = esp32_ble_tracker_ns.class_('ESP32BLETracker', cg.Component)
|
||||||
ESPBTDeviceListener = esp32_ble_tracker_ns.class_('ESPBTDeviceListener')
|
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({
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
cv.GenerateID(): cv.declare_id(ESP32BLETracker),
|
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)
|
}).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
ESP_BLE_DEVICE_SCHEMA = cv.Schema({
|
ESP_BLE_DEVICE_SCHEMA = cv.Schema({
|
||||||
|
@ -24,7 +53,11 @@ ESP_BLE_DEVICE_SCHEMA = cv.Schema({
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
yield cg.register_component(var, config)
|
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
|
@coroutine
|
||||||
|
|
|
@ -150,21 +150,16 @@ void ESP32BLETracker::start_scan(bool first) {
|
||||||
listener->on_scan_end();
|
listener->on_scan_end();
|
||||||
}
|
}
|
||||||
this->already_discovered_.clear();
|
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_.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
|
||||||
this->scan_params_.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
|
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
|
this->scan_params_.scan_interval = this->scan_interval_;
|
||||||
// Ideally, these values should both be quite low, especially scan window. 0x10/0x10 is the esp-idf
|
this->scan_params_.scan_window = this->scan_window_;
|
||||||
// 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;
|
|
||||||
|
|
||||||
esp_ble_gap_set_scan_params(&this->scan_params_);
|
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...");
|
ESP_LOGW(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack...");
|
||||||
App.reboot();
|
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 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_; }
|
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() {
|
void ESP32BLETracker::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "BLE Tracker:");
|
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) {
|
void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) {
|
||||||
const uint64_t address = device.address_uint64();
|
const uint64_t address = device.address_uint64();
|
||||||
|
|
|
@ -107,7 +107,10 @@ class ESPBTDeviceListener {
|
||||||
|
|
||||||
class ESP32BLETracker : public Component {
|
class ESP32BLETracker : public Component {
|
||||||
public:
|
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.
|
/// Setup the FreeRTOS task and the Bluetooth stack.
|
||||||
void setup() override;
|
void setup() override;
|
||||||
|
@ -142,7 +145,10 @@ class ESP32BLETracker : public Component {
|
||||||
/// A structure holding the ESP BLE scan parameters.
|
/// A structure holding the ESP BLE scan parameters.
|
||||||
esp_ble_scan_params_t scan_params_;
|
esp_ble_scan_params_t scan_params_;
|
||||||
/// The interval in seconds to perform scans.
|
/// 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_result_lock_;
|
||||||
SemaphoreHandle_t scan_end_lock_;
|
SemaphoreHandle_t scan_end_lock_;
|
||||||
size_t scan_result_index_{0};
|
size_t scan_result_index_{0};
|
||||||
|
|
|
@ -364,7 +364,6 @@ CONF_RX_PIN = 'rx_pin'
|
||||||
CONF_SAFE_MODE = 'safe_mode'
|
CONF_SAFE_MODE = 'safe_mode'
|
||||||
CONF_SAMSUNG = 'samsung'
|
CONF_SAMSUNG = 'samsung'
|
||||||
CONF_SCAN = 'scan'
|
CONF_SCAN = 'scan'
|
||||||
CONF_SCAN_INTERVAL = 'scan_interval'
|
|
||||||
CONF_SCL = 'scl'
|
CONF_SCL = 'scl'
|
||||||
CONF_SCL_PIN = 'scl_pin'
|
CONF_SCL_PIN = 'scl_pin'
|
||||||
CONF_SDA = 'sda'
|
CONF_SDA = 'sda'
|
||||||
|
|
|
@ -197,7 +197,6 @@ remote_receiver:
|
||||||
dump: []
|
dump: []
|
||||||
|
|
||||||
esp32_ble_tracker:
|
esp32_ble_tracker:
|
||||||
scan_interval: 300s
|
|
||||||
|
|
||||||
#esp32_ble_beacon:
|
#esp32_ble_beacon:
|
||||||
# type: iBeacon
|
# type: iBeacon
|
||||||
|
|
Loading…
Reference in a new issue