ESPHome  2022.12.8
esp32_ble_tracker.h
Go to the documentation of this file.
1 #pragma once
2 
5 #include "esphome/core/helpers.h"
6 #include "queue.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 namespace esphome {
19 namespace esp32_ble_tracker {
20 
21 class ESPBTUUID {
22  public:
23  ESPBTUUID();
24 
25  static ESPBTUUID from_uint16(uint16_t uuid);
26 
27  static ESPBTUUID from_uint32(uint32_t uuid);
28 
29  static ESPBTUUID from_raw(const uint8_t *data);
30 
31  static ESPBTUUID from_raw(const std::string &data);
32 
33  static ESPBTUUID from_uuid(esp_bt_uuid_t uuid);
34 
35  ESPBTUUID as_128bit() const;
36 
37  bool contains(uint8_t data1, uint8_t data2) const;
38 
39  bool operator==(const ESPBTUUID &uuid) const;
40  bool operator!=(const ESPBTUUID &uuid) const { return !(*this == uuid); }
41 
42  esp_bt_uuid_t get_uuid() const;
43 
44  std::string to_string() const;
45 
46  uint64_t get_128bit_high() const;
47  uint64_t get_128bit_low() const;
48 
49  protected:
50  esp_bt_uuid_t uuid_;
51 };
52 
53 using adv_data_t = std::vector<uint8_t>;
54 
55 struct ServiceData {
58 };
59 
61  public:
62  ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); }
63  ESPBLEiBeacon(const uint8_t *data);
64  static optional<ESPBLEiBeacon> from_manufacturer_data(const ServiceData &data);
65 
66  uint16_t get_major() { return ((this->beacon_data_.major & 0xFF) << 8) | (this->beacon_data_.major >> 8); }
67  uint16_t get_minor() { return ((this->beacon_data_.minor & 0xFF) << 8) | (this->beacon_data_.minor >> 8); }
68  int8_t get_signal_power() { return this->beacon_data_.signal_power; }
69  ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(this->beacon_data_.proximity_uuid); }
70 
71  protected:
72  struct {
73  uint8_t sub_type;
74  uint8_t length;
75  uint8_t proximity_uuid[16];
76  uint16_t major;
77  uint16_t minor;
78  int8_t signal_power;
79  } PACKED beacon_data_;
80 };
81 
82 class ESPBTDevice {
83  public:
84  void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
85 
86  std::string address_str() const;
87 
88  uint64_t address_uint64() const;
89 
90  const uint8_t *address() const { return address_; }
91 
92  esp_ble_addr_type_t get_address_type() const { return this->address_type_; }
93  int get_rssi() const { return rssi_; }
94  const std::string &get_name() const { return this->name_; }
95 
96  const std::vector<int8_t> &get_tx_powers() const { return tx_powers_; }
97 
98  const optional<uint16_t> &get_appearance() const { return appearance_; }
99  const optional<uint8_t> &get_ad_flag() const { return ad_flag_; }
100  const std::vector<ESPBTUUID> &get_service_uuids() const { return service_uuids_; }
101 
102  const std::vector<ServiceData> &get_manufacturer_datas() const { return manufacturer_datas_; }
103 
104  const std::vector<ServiceData> &get_service_datas() const { return service_datas_; }
105 
106  const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &get_scan_result() const { return scan_result_; }
107 
109  for (auto &it : this->manufacturer_datas_) {
111  if (res.has_value())
112  return *res;
113  }
114  return {};
115  }
116 
117  protected:
118  void parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
119 
120  esp_bd_addr_t address_{
121  0,
122  };
123  esp_ble_addr_type_t address_type_{BLE_ADDR_TYPE_PUBLIC};
124  int rssi_{0};
125  std::string name_{};
126  std::vector<int8_t> tx_powers_{};
127  optional<uint16_t> appearance_{};
128  optional<uint8_t> ad_flag_{};
129  std::vector<ESPBTUUID> service_uuids_;
130  std::vector<ServiceData> manufacturer_datas_{};
131  std::vector<ServiceData> service_datas_{};
132  esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_{};
133 };
134 
135 class ESP32BLETracker;
136 
138  public:
139  virtual void on_scan_end() {}
140  virtual bool parse_device(const ESPBTDevice &device) = 0;
141  void set_parent(ESP32BLETracker *parent) { parent_ = parent; }
142 
143  protected:
144  ESP32BLETracker *parent_{nullptr};
145 };
146 
147 enum class ClientState {
148  // Connection is allocated
149  INIT,
150  // Client is disconnecting
152  // Connection is idle, no device detected.
153  IDLE,
154  // Searching for device.
155  SEARCHING,
156  // Device advertisement found.
157  DISCOVERED,
158  // Device is discovered and the scanner is stopped
160  // Connection in progress.
161  CONNECTING,
162  // Initial connection established.
163  CONNECTED,
164  // The client and sub-clients have completed setup.
165  ESTABLISHED,
166 };
167 
168 enum class ConnectionType {
169  // The default connection type, we hold all the services in ram
170  // for the duration of the connection.
171  V1,
172  // The client has a cache of the services and mtu so we should not
173  // fetch them again
175  // The client does not need the services and mtu once we send them
176  // so we should wipe them from memory as soon as we send them
178 };
179 
181  public:
182  virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
183  esp_ble_gattc_cb_param_t *param) = 0;
184  virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0;
185  virtual void connect() = 0;
186  virtual void set_state(ClientState st) { this->state_ = st; }
187  ClientState state() const { return state_; }
188  int app_id;
189 
190  protected:
192 };
193 
194 class ESP32BLETracker : public Component {
195  public:
196  void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; }
197  void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
198  void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
199  void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
200  void set_scan_continuous(bool scan_continuous) { scan_continuous_ = scan_continuous; }
201 
203  void setup() override;
204  void dump_config() override;
205  float get_setup_priority() const override;
206 
207  void loop() override;
208 
210  listener->set_parent(this);
211  this->listeners_.push_back(listener);
212  }
213 
214  void register_client(ESPBTClient *client);
215 
216  void print_bt_device_info(const ESPBTDevice &device);
217 
218  void start_scan();
219  void stop_scan();
220 
221  protected:
223  static bool ble_setup();
225  void start_scan_(bool first);
227  void end_of_scan_();
229  static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
230  void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
232  void gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
234  void gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param);
236  void gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param);
238  void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param &param);
239 
240  int app_id_;
242  static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
243  void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
244 
246  std::vector<uint64_t> already_discovered_;
247  std::vector<ESPBTDeviceListener *> listeners_;
249  std::vector<ESPBTClient *> clients_;
251  esp_ble_scan_params_t scan_params_;
253  uint32_t scan_duration_;
254  uint32_t scan_interval_;
255  uint32_t scan_window_;
260  SemaphoreHandle_t scan_result_lock_;
261  SemaphoreHandle_t scan_end_lock_;
262  size_t scan_result_index_{0};
263  esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_buffer_[16];
264  esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
265  esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
266 
268 };
269 
270 // NOLINTNEXTLINE
272 
273 } // namespace esp32_ble_tracker
274 } // namespace esphome
275 
276 #endif
void setup()
optional< ESPBLEiBeacon > get_ibeacon() const
void loop()
struct esphome::sen5x::Sen5xBaselines PACKED
void register_listener(ESPBTDeviceListener *listener)
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.
static ESPBTUUID from_raw(const uint8_t *data)
ESP32BLETracker * global_esp32_ble_tracker
virtual void set_state(ClientState st)
bool operator!=(const ESPBTUUID &uuid) const
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
bool contains(uint8_t data1, uint8_t data2) const
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.
static ESPBTUUID from_uint16(uint16_t uuid)
static ESPBTUUID from_uint32(uint32_t uuid)
Definition: a4988.cpp:4
void set_scan_duration(uint32_t scan_duration)
const std::string & get_name() const
void set_scan_interval(uint32_t scan_interval)
bool operator==(const ESPBTUUID &uuid) const
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.
const optional< uint8_t > & get_ad_flag() const
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid)