ESPHome  2024.6.1
esp32_ble_tracker.h
Go to the documentation of this file.
1 #pragma once
2 
5 #include "esphome/core/defines.h"
6 #include "esphome/core/helpers.h"
7 
8 #include <array>
9 #include <string>
10 #include <vector>
11 
12 #ifdef USE_ESP32
13 
14 #include <esp_gap_ble_api.h>
15 #include <esp_gattc_api.h>
16 #include <esp_bt_defs.h>
17 
18 #include <freertos/FreeRTOS.h>
19 #include <freertos/semphr.h>
20 
23 
24 namespace esphome {
25 namespace esp32_ble_tracker {
26 
27 using namespace esp32_ble;
28 
29 using adv_data_t = std::vector<uint8_t>;
30 
34 };
35 
36 struct ServiceData {
39 };
40 
42  public:
43  ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); }
44  ESPBLEiBeacon(const uint8_t *data);
45  static optional<ESPBLEiBeacon> from_manufacturer_data(const ServiceData &data);
46 
47  uint16_t get_major() { return ((this->beacon_data_.major & 0xFF) << 8) | (this->beacon_data_.major >> 8); }
48  uint16_t get_minor() { return ((this->beacon_data_.minor & 0xFF) << 8) | (this->beacon_data_.minor >> 8); }
49  int8_t get_signal_power() { return this->beacon_data_.signal_power; }
50  ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(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;
59  int8_t signal_power;
60  } PACKED beacon_data_;
61 };
62 
63 class ESPBTDevice {
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 
79  const optional<uint16_t> &get_appearance() const { return appearance_; }
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_{};
110  optional<uint16_t> appearance_{};
111  optional<uint8_t> ad_flag_{};
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 
118 class 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  };
129  };
130  void set_parent(ESP32BLETracker *parent) { parent_ = parent; }
131 
132  protected:
133  ESP32BLETracker *parent_{nullptr};
134 };
135 
136 enum 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.
146  DISCOVERED,
147  // Device is discovered and the scanner is stopped
149  // Connection in progress.
150  CONNECTING,
151  // Initial connection established.
152  CONNECTED,
153  // The client and sub-clients have completed setup.
154  ESTABLISHED,
155 };
156 
157 enum class ConnectionType {
158  // The default connection type, we hold all the services in ram
159  // for the duration of the connection.
160  V1,
161  // The client has a cache of the services and mtu so we should not
162  // fetch them again
164  // The client does not need the services and mtu once we send them
165  // so we should wipe them from memory as soon as we send them
167 };
168 
170  public:
171  virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
172  esp_ble_gattc_cb_param_t *param) = 0;
173  virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0;
174  virtual void connect() = 0;
175  virtual void set_state(ClientState st) { this->state_ = st; }
176  ClientState state() const { return state_; }
177  int app_id;
178 
179  protected:
181 };
182 
183 class ESP32BLETracker : public Component,
184  public GAPEventHandler,
185  public GATTcEventHandler,
186  public BLEStatusEventHandler,
187  public Parented<ESP32BLE> {
188  public:
189  void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; }
190  void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
191  void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
192  void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
193  void set_scan_continuous(bool scan_continuous) { scan_continuous_ = scan_continuous; }
194 
196  void setup() override;
197  void dump_config() override;
198  float get_setup_priority() const override;
199 
200  void loop() override;
201 
202  void register_listener(ESPBTDeviceListener *listener);
203  void register_client(ESPBTClient *client);
204  void recalculate_advertisement_parser_types();
205 
206  void print_bt_device_info(const ESPBTDevice &device);
207 
208  void start_scan();
209  void stop_scan();
210 
211  void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
212  esp_ble_gattc_cb_param_t *param) override;
213  void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
214  void ble_before_disabled_event_handler() override;
215 
216  protected:
217  void stop_scan_();
219  void start_scan_(bool first);
221  void end_of_scan_();
223  void gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
225  void gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param);
227  void gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param);
229  void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param &param);
230 
231  int app_id_;
232 
234  std::vector<uint64_t> already_discovered_;
235  std::vector<ESPBTDeviceListener *> listeners_;
237  std::vector<ESPBTClient *> clients_;
239  esp_ble_scan_params_t scan_params_;
241  uint32_t scan_duration_;
242  uint32_t scan_interval_;
243  uint32_t scan_window_;
248  bool ble_was_disabled_{true};
249  bool raw_advertisements_{false};
250  bool parse_advertisements_{false};
251  SemaphoreHandle_t scan_result_lock_;
252  SemaphoreHandle_t scan_end_lock_;
253  size_t scan_result_index_{0};
254 #ifdef USE_PSRAM
255  const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 32;
256 #else
257  const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 16;
258 #endif // USE_PSRAM
259  esp_ble_gap_cb_param_t::ble_scan_result_evt_param *scan_result_buffer_;
260  esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
261  esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
262 };
263 
264 // NOLINTNEXTLINE
266 
267 } // namespace esp32_ble_tracker
268 } // namespace esphome
269 
270 #endif
void setup()
optional< ESPBLEiBeacon > get_ibeacon() const
void loop()
struct esphome::sen5x::Sen5xBaselines PACKED
const std::vector< int8_t > & get_tx_powers() const
const optional< uint16_t > & get_appearance() const
const std::vector< ServiceData > & get_manufacturer_datas() const
const std::vector< ESPBTUUID > & get_service_uuids() const
esp_ble_scan_params_t scan_params_
A structure holding the ESP BLE scan parameters.
ESP32BLETracker * global_esp32_ble_tracker
virtual void set_state(ClientState st)
esp_ble_gap_cb_param_t::ble_scan_result_evt_param * scan_result_buffer_
const std::vector< ServiceData > & get_service_datas() const
esp_ble_addr_type_t get_address_type() const
const esp_ble_gap_cb_param_t::ble_scan_result_evt_param & get_scan_result() const
virtual AdvertisementParserType get_advertisement_parser_type()
uint32_t scan_duration_
The interval in seconds to perform scans.
std::vector< uint8_t > adv_data_t
std::vector< uint64_t > already_discovered_
Vector of addresses that have already been printed in print_bt_device_info.
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
virtual bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count)
void set_scan_duration(uint32_t scan_duration)
static ESPBTUUID from_raw(const uint8_t *data)
Definition: ble_uuid.cpp:28
const std::string & get_name() const
void set_scan_interval(uint32_t scan_interval)
static optional< ESPBLEiBeacon > from_manufacturer_data(const ServiceData &data)
void set_scan_continuous(bool scan_continuous)
std::vector< ESPBTDeviceListener * > listeners_
std::vector< ESPBTClient * > clients_
Client parameters.
Helper class to easily give an object a parent of type T.
Definition: helpers.h:521
const optional< uint8_t > & get_ad_flag() const