ESPHome  2023.8.3
ble.cpp
Go to the documentation of this file.
1 #ifdef USE_ESP32
2 
3 #include "ble.h"
5 #include "esphome/core/log.h"
6 
7 #include <esp_bt.h>
8 #include <esp_bt_main.h>
9 #include <esp_bt_device.h>
10 #include <esp_gap_ble_api.h>
11 #include <freertos/FreeRTOS.h>
12 #include <freertos/FreeRTOSConfig.h>
13 #include <freertos/task.h>
14 #include <nvs_flash.h>
15 
16 #ifdef USE_ARDUINO
17 #include <esp32-hal-bt.h>
18 #endif
19 
20 namespace esphome {
21 namespace esp32_ble {
22 
23 static const char *const TAG = "esp32_ble";
24 
26  global_ble = this;
27  ESP_LOGCONFIG(TAG, "Setting up BLE...");
28 
29  if (!ble_setup_()) {
30  ESP_LOGE(TAG, "BLE could not be set up");
31  this->mark_failed();
32  return;
33  }
34 
35 #ifdef USE_ESP32_BLE_SERVER
36  this->advertising_ = new BLEAdvertising(); // NOLINT(cppcoreguidelines-owning-memory)
37 
38  this->advertising_->set_scan_response(true);
40  this->advertising_->start();
41 #endif // USE_ESP32_BLE_SERVER
42 
43  ESP_LOGD(TAG, "BLE setup complete");
44 }
45 
47  esp_err_t err = nvs_flash_init();
48  if (err != ESP_OK) {
49  ESP_LOGE(TAG, "nvs_flash_init failed: %d", err);
50  return false;
51  }
52 
53 #ifdef USE_ARDUINO
54  if (!btStart()) {
55  ESP_LOGE(TAG, "btStart failed: %d", esp_bt_controller_get_status());
56  return false;
57  }
58 #else
59  if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
60  // start bt controller
61  if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
62  esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
63  err = esp_bt_controller_init(&cfg);
64  if (err != ESP_OK) {
65  ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err));
66  return false;
67  }
68  while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
69  ;
70  }
71  if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
72  err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
73  if (err != ESP_OK) {
74  ESP_LOGE(TAG, "esp_bt_controller_enable failed: %s", esp_err_to_name(err));
75  return false;
76  }
77  }
78  if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
79  ESP_LOGE(TAG, "esp bt controller enable failed");
80  return false;
81  }
82  }
83 #endif
84 
85  esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
86 
87  err = esp_bluedroid_init();
88  if (err != ESP_OK) {
89  ESP_LOGE(TAG, "esp_bluedroid_init failed: %d", err);
90  return false;
91  }
92  err = esp_bluedroid_enable();
93  if (err != ESP_OK) {
94  ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", err);
95  return false;
96  }
97 
98  if (!this->gap_event_handlers_.empty()) {
99  err = esp_ble_gap_register_callback(ESP32BLE::gap_event_handler);
100  if (err != ESP_OK) {
101  ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err);
102  return false;
103  }
104  }
105 
106  if (!this->gatts_event_handlers_.empty()) {
107  err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler);
108  if (err != ESP_OK) {
109  ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err);
110  return false;
111  }
112  }
113 
114  if (!this->gattc_event_handlers_.empty()) {
115  err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler);
116  if (err != ESP_OK) {
117  ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err);
118  return false;
119  }
120  }
121 
122  std::string name = App.get_name();
123  if (name.length() > 20) {
125  name.erase(name.begin() + 13, name.end() - 7); // Remove characters between 13 and the mac address
126  } else {
127  name = name.substr(0, 20);
128  }
129  }
130 
131  err = esp_ble_gap_set_device_name(name.c_str());
132  if (err != ESP_OK) {
133  ESP_LOGE(TAG, "esp_ble_gap_set_device_name failed: %d", err);
134  return false;
135  }
136 
137  err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_), sizeof(uint8_t));
138  if (err != ESP_OK) {
139  ESP_LOGE(TAG, "esp_ble_gap_set_security_param failed: %d", err);
140  return false;
141  }
142 
143  // BLE takes some time to be fully set up, 200ms should be more than enough
144  delay(200); // NOLINT
145 
146  return true;
147 }
148 
150  BLEEvent *ble_event = this->ble_events_.pop();
151  while (ble_event != nullptr) {
152  switch (ble_event->type_) {
153  case BLEEvent::GATTS:
154  this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if,
155  &ble_event->event_.gatts.gatts_param);
156  break;
157  case BLEEvent::GATTC:
158  this->real_gattc_event_handler_(ble_event->event_.gattc.gattc_event, ble_event->event_.gattc.gattc_if,
159  &ble_event->event_.gattc.gattc_param);
160  break;
161  case BLEEvent::GAP:
162  this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param);
163  break;
164  default:
165  break;
166  }
167  delete ble_event; // NOLINT(cppcoreguidelines-owning-memory)
168  ble_event = this->ble_events_.pop();
169  }
170 }
171 
172 void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
173  BLEEvent *new_event = new BLEEvent(event, param); // NOLINT(cppcoreguidelines-owning-memory)
174  global_ble->ble_events_.push(new_event);
175 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
176 
177 void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
178  ESP_LOGV(TAG, "(BLE) gap_event_handler - %d", event);
179  for (auto *gap_handler : this->gap_event_handlers_) {
180  gap_handler->gap_event_handler(event, param);
181  }
182 }
183 
184 void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
185  esp_ble_gatts_cb_param_t *param) {
186  BLEEvent *new_event = new BLEEvent(event, gatts_if, param); // NOLINT(cppcoreguidelines-owning-memory)
187  global_ble->ble_events_.push(new_event);
188 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
189 
190 void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
191  esp_ble_gatts_cb_param_t *param) {
192  ESP_LOGV(TAG, "(BLE) gatts_event [esp_gatt_if: %d] - %d", gatts_if, event);
193  for (auto *gatts_handler : this->gatts_event_handlers_) {
194  gatts_handler->gatts_event_handler(event, gatts_if, param);
195  }
196 }
197 
198 void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
199  esp_ble_gattc_cb_param_t *param) {
200  BLEEvent *new_event = new BLEEvent(event, gattc_if, param); // NOLINT(cppcoreguidelines-owning-memory)
201  global_ble->ble_events_.push(new_event);
202 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
203 
204 void ESP32BLE::real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
205  esp_ble_gattc_cb_param_t *param) {
206  ESP_LOGV(TAG, "(BLE) gattc_event [esp_gatt_if: %d] - %d", gattc_if, event);
207  for (auto *gattc_handler : this->gattc_event_handlers_) {
208  gattc_handler->gattc_event_handler(event, gattc_if, param);
209  }
210 }
211 
213 
215  const uint8_t *mac_address = esp_bt_dev_get_address();
216  if (mac_address) {
217  const char *io_capability_s;
218  switch (this->io_cap_) {
219  case ESP_IO_CAP_OUT:
220  io_capability_s = "display_only";
221  break;
222  case ESP_IO_CAP_IO:
223  io_capability_s = "display_yes_no";
224  break;
225  case ESP_IO_CAP_IN:
226  io_capability_s = "keyboard_only";
227  break;
228  case ESP_IO_CAP_NONE:
229  io_capability_s = "none";
230  break;
231  case ESP_IO_CAP_KBDISP:
232  io_capability_s = "keyboard_display";
233  break;
234  default:
235  io_capability_s = "invalid";
236  break;
237  }
238  ESP_LOGCONFIG(TAG, "ESP32 BLE:");
239  ESP_LOGCONFIG(TAG, " MAC address: %02X:%02X:%02X:%02X:%02X:%02X", mac_address[0], mac_address[1], mac_address[2],
240  mac_address[3], mac_address[4], mac_address[5]);
241  ESP_LOGCONFIG(TAG, " IO Capability: %s", io_capability_s);
242  } else {
243  ESP_LOGCONFIG(TAG, "ESP32 BLE: bluetooth stack is not enabled");
244  }
245 }
246 
247 uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) {
248  uint64_t u = 0;
249  u |= uint64_t(address[0] & 0xFF) << 40;
250  u |= uint64_t(address[1] & 0xFF) << 32;
251  u |= uint64_t(address[2] & 0xFF) << 24;
252  u |= uint64_t(address[3] & 0xFF) << 16;
253  u |= uint64_t(address[4] & 0xFF) << 8;
254  u |= uint64_t(address[5] & 0xFF) << 0;
255  return u;
256 }
257 
258 ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
259 
260 } // namespace esp32_ble
261 } // namespace esphome
262 
263 #endif
const char * name
Definition: stm32flash.h:78
uint64_t ble_addr_to_uint64(const esp_bd_addr_t address)
Definition: ble.cpp:247
void set_min_preferred_interval(uint16_t interval)
ESP32BLE * global_ble
Definition: ble.cpp:258
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
Definition: ble.cpp:184
struct esphome::esp32_ble::BLEEvent::@76::gattc_event gattc
std::vector< GAPEventHandler * > gap_event_handlers_
Definition: ble.h:81
std::vector< GATTcEventHandler * > gattc_event_handlers_
Definition: ble.h:82
Queue< BLEEvent > ble_events_
Definition: ble.h:85
std::vector< GATTsEventHandler * > gatts_event_handlers_
Definition: ble.h:83
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
Definition: ble.cpp:172
static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
Definition: ble.cpp:198
void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
Definition: ble.cpp:204
struct esphome::esp32_ble::BLEEvent::@76::gap_event gap
float get_setup_priority() const override
Definition: ble.cpp:212
void real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
Definition: ble.cpp:190
void setup() override
Definition: ble.cpp:25
Application App
Global storage of Application pointer - only one Application can exist.
enum esphome::esp32_ble::BLEEvent::ble_event_t type_
union esphome::esp32_ble::BLEEvent::@76 event_
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Definition: application.h:152
bool is_name_add_mac_suffix_enabled() const
Definition: application.h:159
void dump_config() override
Definition: ble.cpp:214
void loop() override
Definition: ble.cpp:149
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:112
esp_ble_io_cap_t io_cap_
Definition: ble.h:87
void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
Definition: ble.cpp:177
struct esphome::esp32_ble::BLEEvent::@76::gatts_event gatts
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:28
BLEAdvertising * advertising_
Definition: ble.h:86
void set_scan_response(bool scan_response)