ESP32 Bluetooth Low Energy Tracker

Example Usage

auto *tracker = App.make_esp32_ble_tracker();
// MAC address AC:37:43:77:5F:4C
App.register_binary_sensor(tracker->make_device("ESP32 Bluetooth Beacon", {
        0xAC, 0x37, 0x43, 0x77, 0x5F, 0x4C
}));

See Application::make_esp32_ble_tracker().

API Reference

class ESP32BLETracker : public Component

The ESP32BLETracker class is a hub for all ESP32 Bluetooth Low Energy devices.

The implementation uses a lightweight version of the amazing ESP32 BLE Arduino library by Neil Kolban. This was done because the ble library was quite huge and esphomelib would only ever use a small part of it anyway. Still though, when this component is used, the required flash size increases by a lot (about 500kB). As the BLE stack uses humongous amounts of stack size, this component creates a separate FreeRTOS task to handle all BLE stuff with its own stack.

Public Functions

ESP32BLEPresenceDevice *make_presence_sensor(const std::string &name, std::array<uint8_t, 6> address)

Create a simple binary sensor for a MAC address.

Each time a BLE scan yields the MAC address in the address parameter, the binary sensor will immediately go to true. When a whole scan interval does not discover a device with this MAC address, the binary sensor will be set to false.

The address parameter accepts a MAC address as an array of length 6 with each MAC address part in an unsigned int. To set it up, do something like this:

// MAC address AC:37:43:77:5F:4C
App.register_binary_sensor(tracker->make_device("ESP32 BLE Device", {
   0xAC, 0x37, 0x43, 0x77, 0x5F, 0x4C
}));

You can get this MAC address by navigating to the bluetooth screen of your device and looking for an advanced settings screen, you can usually find the MAC address there. Alternatively, you can set the global debug level to DEBUG and observe the logs. Then you will find messages like this:

Found device AC:37:43:77:5F:4C RSSI=-80
    Address Type: PUBLIC
    Name: 'Google Home Mini'

If the Address Type shown in the logs is RANDOM, you unfortunately can’t track that device at the moment as the device constantly changes its MAC address as a “security” feature.

See
set_scan_interval
Return
Parameters
  • name: The name of the binary sensor to create.
  • address: The MAC address to match.

ESP32BLERSSISensor *make_rssi_sensor(const std::string &name, std::array<uint8_t, 6> address)
XiaomiDevice *make_xiaomi_device(std::array<uint8_t, 6> address)
void set_scan_interval(uint32_t scan_interval)

Set the number of seconds (!) that a single BLE scan should take.

This parameter is useful when adjusting how long it should take for a bluetooth device to be marked as disconnected.

Parameters
  • scan_interval: The interval in seconds to reset the scan.

void setup()

Setup the FreeRTOS task and the Bluetooth stack.

void loop()

This method will be called repeatedly.

Analogous to Arduino’s loop(). setup() is guaranteed to be called before this. Defaults to doing nothing.

uint32_t get_scan_interval() const

Protected Functions

void start_scan(bool first)

Start a single scan by setting up the parameters and doing some esp-idf calls.

void gap_scan_result(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param)

Called when a ESP_GAP_BLE_SCAN_RESULT_EVT event is received.

void gap_scan_set_param_complete(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param)

Called when a ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT event is received.

void gap_scan_start_complete(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param)

Called when a ESP_GAP_BLE_SCAN_START_COMPLETE_EVT event is received.

void parse_presence_sensors_(const ESPBTDevice &device)
void parse_rssi_sensors_(const ESPBTDevice &device)
void parse_xiaomi_sensors_(const ESPBTDevice &device)
bool parse_already_discovered_(const ESPBTDevice &device)
bool has_already_discovered_(uint64_t address)

Protected Attributes

std::vector<uint64_t> already_discovered_

An array of MAC addresses discovered during this scan. Used to mark registered devices as undiscovered.

std::vector<ESP32BLEPresenceDevice *> presence_sensors_

An array of registered devices to track.

std::vector<ESP32BLERSSISensor *> rssi_sensors_
std::vector<XiaomiDevice *> xiaomi_devices_
esp_ble_scan_params_t scan_params_

A structure holding the ESP BLE scan parameters.

uint32_t scan_interval_ = {300}

The interval in seconds to perform scans.

SemaphoreHandle_t scan_result_lock_
SemaphoreHandle_t scan_end_lock_
size_t scan_result_index_ = {0}
esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_buffer_[16]
esp_bt_status_t scan_start_failed_ = {ESP_BT_STATUS_SUCCESS}
esp_bt_status_t scan_set_param_failed_ = {ESP_BT_STATUS_SUCCESS}

Protected Static Functions

bool ble_setup()

The FreeRTOS task managing the bluetooth interface.

void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)

Callback that will handle all GAP events and redistribute them to other callbacks.

class ESP32BLEPresenceDevice : public binary_sensor::BinarySensor

Simple helper class to expose an BLE device as a binary sensor.

Public Functions

ESP32BLEPresenceDevice(const std::string &name, uint64_t address)

Protected Functions

std::string device_class()

Get the default device class for this sensor, or empty string for no default.

Protected Attributes

friend ESP32BLEPresenceDevice::ESP32BLETracker
uint64_t address_
class ESP32BLERSSISensor : public sensor::Sensor

Public Functions

ESP32BLERSSISensor(ESP32BLETracker *parent, const std::string &name, uint64_t address)
std::string unit_of_measurement()

Override this to set the Home Assistant unit of measurement for this sensor.

Return “” to disable this feature.

Return
The icon of this sensor, for example “°C”.

std::string icon()

Override this to set the Home Assistant icon for this sensor.

Return “” to disable this feature.

Return
The icon of this sensor, for example “mdi:battery”.

int8_t accuracy_decimals()

Return the accuracy in decimals for this sensor.

std::string unique_id()

A unique ID for this sensor, empty for no unique id.

See unique ID requirements: https://developers.home-assistant.io/docs/en/entity_registry_index.html#unique-id-requirements

Return
The unique id as a string.

uint32_t update_interval()

Return with which interval the sensor is polled. Return 0 for non-polling mode.

Protected Attributes

friend ESP32BLERSSISensor::ESP32BLETracker
uint64_t address_
ESP32BLETracker *parent_
class XiaomiSensor : public sensor::Sensor

Public Types

enum Type

Values:

TYPE_TEMPERATURE = 0
TYPE_HUMIDITY
TYPE_MOISTURE
TYPE_ILLUMINANCE
TYPE_CONDUCTIVITY
TYPE_BATTERY_LEVEL

Public Functions

XiaomiSensor(XiaomiDevice *parent, Type type, const std::string &name)
std::string unit_of_measurement()

Override this to set the Home Assistant unit of measurement for this sensor.

Return “” to disable this feature.

Return
The icon of this sensor, for example “°C”.

std::string icon()

Override this to set the Home Assistant icon for this sensor.

Return “” to disable this feature.

Return
The icon of this sensor, for example “mdi:battery”.

uint32_t update_interval()

Return with which interval the sensor is polled. Return 0 for non-polling mode.

int8_t accuracy_decimals()

Return the accuracy in decimals for this sensor.

std::string unique_id()

A unique ID for this sensor, empty for no unique id.

See unique ID requirements: https://developers.home-assistant.io/docs/en/entity_registry_index.html#unique-id-requirements

Return
The unique id as a string.

Protected Attributes

XiaomiDevice *parent_
Type type_
class XiaomiDevice

Public Functions

XiaomiDevice(ESP32BLETracker *parent, uint64_t address)
XiaomiSensor *get_temperature_sensor() const
XiaomiSensor *get_humidity_sensor() const
XiaomiSensor *get_moisture_sensor() const
XiaomiSensor *get_illuminance_sensor() const
XiaomiSensor *get_conductivity_sensor() const
XiaomiSensor *get_battery_level_sensor() const
XiaomiSensor *make_temperature_sensor(const std::string &name)
XiaomiSensor *make_humidity_sensor(const std::string &name)
XiaomiSensor *make_moisture_sensor(const std::string &name)
XiaomiSensor *make_illuminance_sensor(const std::string &name)
XiaomiSensor *make_conductivity_sensor(const std::string &name)
XiaomiSensor *make_battery_level_sensor(const std::string &name)
uint32_t update_interval() const
std::string unique_id() const

Protected Attributes

friend XiaomiDevice::ESP32BLETracker
ESP32BLETracker *parent_
uint64_t address_
XiaomiSensor *temperature_sensor_ = {nullptr}
XiaomiSensor *humidity_sensor_ = {nullptr}
XiaomiSensor *moisture_sensor_ = {nullptr}
XiaomiSensor *illuminance_sensor_ = {nullptr}
XiaomiSensor *conductivity_sensor_ = {nullptr}
XiaomiSensor *battery_level_sensor_ = {nullptr}
class ESPBTDevice

Public Functions

void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param)
void parse_adv(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param)
std::string address_str() const
uint64_t address_uint64() const
esp_ble_addr_type_t get_address_type() const
int get_rssi() const
const std::string &get_name() const
const optional<int8_t> &get_tx_power() const
const optional<uint16_t> &get_appearance() const
const optional<uint8_t> &get_ad_flag() const
const std::vector<ESPBTUUID> &get_service_uuids() const
const std::string &get_manufacturer_data() const
const std::string &get_service_data() const
const optional<ESPBTUUID> &get_service_data_uuid() const

Protected Attributes

esp_bd_addr_t address_ = {0, }
esp_ble_addr_type_t address_type_ = {BLE_ADDR_TYPE_PUBLIC}
int rssi_ = {0}
std::string name_ = {}
optional<int8_t> tx_power_ = {}
optional<uint16_t> appearance_ = {}
optional<uint8_t> ad_flag_ = {}
std::vector<ESPBTUUID> service_uuids_
std::string manufacturer_data_ = {}
std::string service_data_ = {}
optional<ESPBTUUID> service_data_uuid_ = {}
ESP32BLETracker *global_esp32_ble_tracker

Warning

doxygenvariable: Cannot find variable “semaphore_scan_end” in doxygen xml output for project “esphomelib” from directory: ./_doxyxml/

class ESPBTUUID

Public Functions

ESPBTUUID()
bool contains(uint8_t data1, uint8_t data2) const
std::string to_string()

Public Static Functions

ESPBTUUID from_uint16(uint16_t uuid)
ESPBTUUID from_uint32(uint32_t uuid)
ESPBTUUID from_raw(const uint8_t *data)

Protected Attributes

esp_bt_uuid_t uuid_