ESPHome  2022.5.1
esp32_ble_tracker.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "esphome/core/helpers.h"
5 #include "queue.h"
6 
7 #ifdef USE_ESP32
8 
9 #include <string>
10 #include <array>
11 #include <esp_gap_ble_api.h>
12 #include <esp_gattc_api.h>
13 #include <esp_bt_defs.h>
14 
15 namespace esphome {
16 namespace esp32_ble_tracker {
17 
18 class ESPBTUUID {
19  public:
20  ESPBTUUID();
21 
22  static ESPBTUUID from_uint16(uint16_t uuid);
23 
24  static ESPBTUUID from_uint32(uint32_t uuid);
25 
26  static ESPBTUUID from_raw(const uint8_t *data);
27 
28  static ESPBTUUID from_raw(const std::string &data);
29 
30  static ESPBTUUID from_uuid(esp_bt_uuid_t uuid);
31 
32  ESPBTUUID as_128bit() const;
33 
34  bool contains(uint8_t data1, uint8_t data2) const;
35 
36  bool operator==(const ESPBTUUID &uuid) const;
37  bool operator!=(const ESPBTUUID &uuid) const { return !(*this == uuid); }
38 
39  esp_bt_uuid_t get_uuid() const;
40 
41  std::string to_string() const;
42 
43  protected:
44  esp_bt_uuid_t uuid_;
45 };
46 
47 using adv_data_t = std::vector<uint8_t>;
48 
49 struct ServiceData {
52 };
53 
55  public:
56  ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); }
57  ESPBLEiBeacon(const uint8_t *data);
58  static optional<ESPBLEiBeacon> from_manufacturer_data(const ServiceData &data);
59 
60  uint16_t get_major() { return ((this->beacon_data_.major & 0xFF) << 8) | (this->beacon_data_.major >> 8); }
61  uint16_t get_minor() { return ((this->beacon_data_.minor & 0xFF) << 8) | (this->beacon_data_.minor >> 8); }
62  int8_t get_signal_power() { return this->beacon_data_.signal_power; }
63  ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(this->beacon_data_.proximity_uuid); }
64 
65  protected:
66  struct {
67  uint8_t sub_type;
68  uint8_t length;
69  uint8_t proximity_uuid[16];
70  uint16_t major;
71  uint16_t minor;
72  int8_t signal_power;
73  } PACKED beacon_data_;
74 };
75 
76 class ESPBTDevice {
77  public:
78  void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
79 
80  std::string address_str() const;
81 
82  uint64_t address_uint64() const;
83 
84  const uint8_t *address() const { return address_; }
85 
86  esp_ble_addr_type_t get_address_type() const { return this->address_type_; }
87  int get_rssi() const { return rssi_; }
88  const std::string &get_name() const { return this->name_; }
89 
90  const std::vector<int8_t> &get_tx_powers() const { return tx_powers_; }
91 
92  const optional<uint16_t> &get_appearance() const { return appearance_; }
93  const optional<uint8_t> &get_ad_flag() const { return ad_flag_; }
94  const std::vector<ESPBTUUID> &get_service_uuids() const { return service_uuids_; }
95 
96  const std::vector<ServiceData> &get_manufacturer_datas() const { return manufacturer_datas_; }
97 
98  const std::vector<ServiceData> &get_service_datas() const { return service_datas_; }
99 
100  const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &get_scan_result() const { return scan_result_; }
101 
103  for (auto &it : this->manufacturer_datas_) {
105  if (res.has_value())
106  return *res;
107  }
108  return {};
109  }
110 
111  protected:
112  void parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
113 
114  esp_bd_addr_t address_{
115  0,
116  };
117  esp_ble_addr_type_t address_type_{BLE_ADDR_TYPE_PUBLIC};
118  int rssi_{0};
119  std::string name_{};
120  std::vector<int8_t> tx_powers_{};
121  optional<uint16_t> appearance_{};
122  optional<uint8_t> ad_flag_{};
123  std::vector<ESPBTUUID> service_uuids_;
124  std::vector<ServiceData> manufacturer_datas_{};
125  std::vector<ServiceData> service_datas_{};
126  esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_{};
127 };
128 
129 class ESP32BLETracker;
130 
132  public:
133  virtual void on_scan_end() {}
134  virtual bool parse_device(const ESPBTDevice &device) = 0;
135  void set_parent(ESP32BLETracker *parent) { parent_ = parent; }
136 
137  protected:
138  ESP32BLETracker *parent_{nullptr};
139 };
140 
141 enum class ClientState {
142  // Connection is idle, no device detected.
143  IDLE,
144  // Device advertisement found.
145  DISCOVERED,
146  // Connection in progress.
147  CONNECTING,
148  // Initial connection established.
149  CONNECTED,
150  // The client and sub-clients have completed setup.
151  ESTABLISHED,
152 };
153 
155  public:
156  virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
157  esp_ble_gattc_cb_param_t *param) = 0;
158  virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0;
159  virtual void connect() = 0;
160  void set_state(ClientState st) { this->state_ = st; }
161  ClientState state() const { return state_; }
162  int app_id;
163 
164  protected:
166 };
167 
168 class ESP32BLETracker : public Component {
169  public:
170  void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; }
171  void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
172  void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
173  void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
174 
176  void setup() override;
177  void dump_config() override;
178  float get_setup_priority() const override;
179 
180  void loop() override;
181 
183  listener->set_parent(this);
184  this->listeners_.push_back(listener);
185  }
186 
187  void register_client(ESPBTClient *client);
188 
189  void print_bt_device_info(const ESPBTDevice &device);
190 
191  protected:
193  static bool ble_setup();
195  void start_scan_(bool first);
197  static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
198  void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
200  void gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param);
202  void gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param);
204  void gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param);
206  void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param &param);
207 
208  int app_id_;
210  static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
211  void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
212 
214  std::vector<uint64_t> already_discovered_;
215  std::vector<ESPBTDeviceListener *> listeners_;
217  std::vector<ESPBTClient *> clients_;
219  esp_ble_scan_params_t scan_params_;
221  uint32_t scan_duration_;
222  uint32_t scan_interval_;
223  uint32_t scan_window_;
225  SemaphoreHandle_t scan_result_lock_;
226  SemaphoreHandle_t scan_end_lock_;
227  size_t scan_result_index_{0};
228  esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_buffer_[16];
229  esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
230  esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
231 
233 };
234 
235 // NOLINTNEXTLINE
237 
238 } // namespace esp32_ble_tracker
239 } // namespace esphome
240 
241 #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
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)
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)