ESPHome 2025.5.0
Loading...
Searching...
No Matches
esp32_ble_tracker.h
Go to the documentation of this file.
1#pragma once
2
7
8#include <array>
9#include <string>
10#include <vector>
11
12#ifdef USE_ESP32
13
14#include <esp_bt_defs.h>
15#include <esp_gap_ble_api.h>
16#include <esp_gattc_api.h>
17
18#include <freertos/FreeRTOS.h>
19#include <freertos/semphr.h>
20
23
24namespace esphome {
25namespace esp32_ble_tracker {
26
27using namespace esp32_ble;
28
29using adv_data_t = std::vector<uint8_t>;
30
35
40
42 public:
43 ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); }
44 ESPBLEiBeacon(const uint8_t *data);
46
47 uint16_t get_major() { return byteswap(this->beacon_data_.major); }
48 uint16_t get_minor() { return byteswap(this->beacon_data_.minor); }
49 int8_t get_signal_power() { return this->beacon_data_.signal_power; }
50 ESPBTUUID get_uuid() { return ESPBTUUID::from_raw_reversed(this->beacon_data_.proximity_uuid); }
51
52 protected:
53 struct {
54 uint8_t sub_type;
55 uint8_t length;
56 uint8_t proximity_uuid[16];
57 uint16_t major;
58 uint16_t minor;
60 } PACKED beacon_data_;
61};
62
64 public:
65 void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
66
67 std::string address_str() const;
68
69 uint64_t address_uint64() const;
70
71 const uint8_t *address() const { return address_; }
72
73 esp_ble_addr_type_t get_address_type() const { return this->address_type_; }
74 int get_rssi() const { return rssi_; }
75 const std::string &get_name() const { return this->name_; }
76
77 const std::vector<int8_t> &get_tx_powers() const { return tx_powers_; }
78
80 const optional<uint8_t> &get_ad_flag() const { return ad_flag_; }
81 const std::vector<ESPBTUUID> &get_service_uuids() const { return service_uuids_; }
82
83 const std::vector<ServiceData> &get_manufacturer_datas() const { return manufacturer_datas_; }
84
85 const std::vector<ServiceData> &get_service_datas() const { return service_datas_; }
86
87 const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &get_scan_result() const { return scan_result_; }
88
89 bool resolve_irk(const uint8_t *irk) const;
90
92 for (auto &it : this->manufacturer_datas_) {
94 if (res.has_value())
95 return *res;
96 }
97 return {};
98 }
99
100 protected:
101 void parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
102
103 esp_bd_addr_t address_{
104 0,
105 };
106 esp_ble_addr_type_t address_type_{BLE_ADDR_TYPE_PUBLIC};
107 int rssi_{0};
108 std::string name_{};
109 std::vector<int8_t> tx_powers_{};
112 std::vector<ESPBTUUID> service_uuids_{};
113 std::vector<ServiceData> manufacturer_datas_{};
114 std::vector<ServiceData> service_datas_{};
115 esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_{};
116};
117
118class ESP32BLETracker;
119
121 public:
122 virtual void on_scan_end() {}
123 virtual bool parse_device(const ESPBTDevice &device) = 0;
124 virtual bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) {
125 return false;
126 };
130 void set_parent(ESP32BLETracker *parent) { parent_ = parent; }
131
132 protected:
134};
135
136enum class ClientState {
137 // Connection is allocated
138 INIT,
139 // Client is disconnecting
141 // Connection is idle, no device detected.
142 IDLE,
143 // Searching for device.
144 SEARCHING,
145 // Device advertisement found.
147 // Device is discovered and the scanner is stopped
149 // Connection in progress.
151 // Initial connection established.
152 CONNECTED,
153 // The client and sub-clients have completed setup.
155};
156
157enum class ScannerState {
158 // Scanner is idle, init state, set from the main loop when processing STOPPED
159 IDLE,
160 // Scanner is starting, set from the main loop only
161 STARTING,
162 // Scanner is running, set from the ESP callback only
163 RUNNING,
164 // Scanner failed to start, set from the ESP callback only
165 FAILED,
166 // Scanner is stopping, set from the main loop only
167 STOPPING,
168 // Scanner is stopped, set from the ESP callback only
169 STOPPED,
170};
171
172enum class ConnectionType {
173 // The default connection type, we hold all the services in ram
174 // for the duration of the connection.
175 V1,
176 // The client has a cache of the services and mtu so we should not
177 // fetch them again
179 // The client does not need the services and mtu once we send them
180 // so we should wipe them from memory as soon as we send them
182};
183
185 public:
186 virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
187 esp_ble_gattc_cb_param_t *param) = 0;
188 virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0;
189 virtual void connect() = 0;
190 virtual void disconnect() = 0;
191 bool disconnect_pending() const { return this->want_disconnect_; }
193 virtual void set_state(ClientState st) {
194 this->state_ = st;
195 if (st == ClientState::IDLE) {
196 this->want_disconnect_ = false;
197 }
198 }
199 ClientState state() const { return state_; }
201
202 protected:
204 // want_disconnect_ is set to true when a disconnect is requested
205 // while the client is connecting. This is used to disconnect the
206 // client as soon as we get the connection id (conn_id_) from the
207 // ESP_GATTC_OPEN_EVT event.
208 bool want_disconnect_{false};
209};
210
212 public GAPEventHandler,
213 public GATTcEventHandler,
215 public Parented<ESP32BLE> {
216 public:
217 void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; }
218 void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
219 void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
220 void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
221 bool get_scan_active() const { return scan_active_; }
222 void set_scan_continuous(bool scan_continuous) { scan_continuous_ = scan_continuous; }
223
225 void setup() override;
226 void dump_config() override;
227 float get_setup_priority() const override;
228
229 void loop() override;
230
232 void register_client(ESPBTClient *client);
234
235 void print_bt_device_info(const ESPBTDevice &device);
236
237 void start_scan();
238 void stop_scan();
239
240 void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
241 esp_ble_gattc_cb_param_t *param) override;
242 void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
243 void ble_before_disabled_event_handler() override;
244
245 void add_scanner_state_callback(std::function<void(ScannerState)> &&callback) {
246 this->scanner_state_callbacks_.add(std::move(callback));
247 }
249
250 protected:
251 void stop_scan_();
253 void start_scan_(bool first);
255 void end_of_scan_();
257 void gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
259 void gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param);
261 void gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param);
263 void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param &param);
266
267 int app_id_{0};
268
270 std::vector<uint64_t> already_discovered_;
271 std::vector<ESPBTDeviceListener *> listeners_;
273 std::vector<ESPBTClient *> clients_;
275 esp_ble_scan_params_t scan_params_;
279 uint32_t scan_window_;
288 SemaphoreHandle_t scan_result_lock_;
290#ifdef USE_PSRAM
291 const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 32;
292#else
293 const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 20;
294#endif // USE_PSRAM
295 esp_ble_gap_cb_param_t::ble_scan_result_evt_param *scan_result_buffer_;
296 esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
297 esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
302#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
303 bool coex_prefer_ble_{false};
304#endif
305};
306
307// NOLINTNEXTLINE
308extern ESP32BLETracker *global_esp32_ble_tracker;
309
310} // namespace esp32_ble_tracker
311} // namespace esphome
312
313#endif
Helper class to easily give an object a parent of type T.
Definition helpers.h:538
static ESPBTUUID from_raw_reversed(const uint8_t *data)
Definition ble_uuid.cpp:34
std::vector< uint64_t > already_discovered_
Vector of addresses that have already been printed in print_bt_device_info.
void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param &param)
Called when a ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT event is received.
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
esp_ble_gap_cb_param_t::ble_scan_result_evt_param * scan_result_buffer_
esp_ble_scan_params_t scan_params_
A structure holding the ESP BLE scan parameters.
void register_listener(ESPBTDeviceListener *listener)
CallbackManager< void(ScannerState)> scanner_state_callbacks_
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.
uint32_t scan_duration_
The interval in seconds to perform scans.
void setup() override
Setup the FreeRTOS task and the Bluetooth stack.
void set_scanner_state_(ScannerState state)
Called to set the scanner state. Will also call callbacks to let listeners know when state is changed...
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
void print_bt_device_info(const ESPBTDevice &device)
void set_scan_duration(uint32_t scan_duration)
void set_scan_interval(uint32_t scan_interval)
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.
std::vector< ESPBTClient * > clients_
Client parameters.
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 add_scanner_state_callback(std::function< void(ScannerState)> &&callback)
std::vector< ESPBTDeviceListener * > listeners_
void start_scan_(bool first)
Start a single scan by setting up the parameters and doing some esp-idf calls.
struct esphome::esp32_ble_tracker::ESPBLEiBeacon::@78 beacon_data_
static optional< ESPBLEiBeacon > from_manufacturer_data(const ServiceData &data)
virtual void set_state(ClientState st)
virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)=0
virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)=0
esp_ble_addr_type_t get_address_type() const
void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param)
const esp_ble_gap_cb_param_t::ble_scan_result_evt_param & get_scan_result() const
std::vector< ServiceData > manufacturer_datas_
const optional< uint8_t > & get_ad_flag() const
const std::vector< int8_t > & get_tx_powers() const
const std::vector< ServiceData > & get_service_datas() const
const optional< uint16_t > & get_appearance() const
esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_
const std::vector< ServiceData > & get_manufacturer_datas() const
bool resolve_irk(const uint8_t *irk) const
void parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param)
const std::vector< ESPBTUUID > & get_service_uuids() const
std::vector< ServiceData > service_datas_
optional< ESPBLEiBeacon > get_ibeacon() const
virtual AdvertisementParserType get_advertisement_parser_type()
virtual bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count)
virtual bool parse_device(const ESPBTDevice &device)=0
bool state
Definition fan.h:0
ESP32BLETracker * global_esp32_ble_tracker
std::vector< uint8_t > adv_data_t
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void byteswap()