ESPHome  2025.2.0
ble_server.cpp
Go to the documentation of this file.
1 #include "ble_server.h"
2 
4 #include "esphome/core/log.h"
6 #include "esphome/core/version.h"
7 
8 #ifdef USE_ESP32
9 
10 #include <nvs_flash.h>
11 #include <freertos/FreeRTOSConfig.h>
12 #include <esp_bt_main.h>
13 #include <esp_bt.h>
14 #include <freertos/task.h>
15 #include <esp_gap_ble_api.h>
16 
17 namespace esphome {
18 namespace esp32_ble_server {
19 
20 static const char *const TAG = "esp32_ble_server";
21 
23  if (this->parent_->is_failed()) {
24  this->mark_failed();
25  ESP_LOGE(TAG, "BLE Server was marked failed by ESP32BLE");
26  return;
27  }
28  global_ble_server = this;
29 }
30 
32  if (!this->parent_->is_active()) {
33  return;
34  }
35  switch (this->state_) {
36  case RUNNING: {
37  // Start all services that are pending to start
38  if (!this->services_to_start_.empty()) {
39  uint16_t index_to_remove = 0;
40  // Iterate over the services to start
41  for (unsigned i = 0; i < this->services_to_start_.size(); i++) {
42  BLEService *service = this->services_to_start_[i];
43  if (service->is_created()) {
44  service->start(); // Needs to be called once per characteristic in the service
45  } else {
46  index_to_remove = i + 1;
47  }
48  }
49  // Remove the services that have been started
50  if (index_to_remove > 0) {
51  this->services_to_start_.erase(this->services_to_start_.begin(),
52  this->services_to_start_.begin() + index_to_remove - 1);
53  }
54  }
55  break;
56  }
57  case INIT: {
58  esp_err_t err = esp_ble_gatts_app_register(0);
59  if (err != ESP_OK) {
60  ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err);
61  this->mark_failed();
62  return;
63  }
64  this->state_ = REGISTERING;
65  break;
66  }
67  case REGISTERING: {
68  if (this->registered_) {
69  // Create the device information service first so
70  // it is at the top of the GATT table
72  // Create all services previously created
73  for (auto &pair : this->services_) {
74  if (pair.second == this->device_information_service_) {
75  continue;
76  }
77  pair.second->do_create(this);
78  }
79  this->state_ = STARTING_SERVICE;
80  }
81  break;
82  }
83  case STARTING_SERVICE: {
85  this->state_ = RUNNING;
86  this->restart_advertising_();
87  ESP_LOGD(TAG, "BLE server setup successfully");
88  } else if (this->device_information_service_->is_created()) {
90  }
91  break;
92  }
93  }
94 }
95 
96 bool BLEServer::is_running() { return this->parent_->is_active() && this->state_ == RUNNING; }
97 
98 bool BLEServer::can_proceed() { return this->is_running() || !this->parent_->is_active(); }
99 
101  if (this->is_running()) {
102  this->parent_->advertising_set_manufacturer_data(this->manufacturer_data_);
103  }
104 }
105 
106 BLEService *BLEServer::create_service(ESPBTUUID uuid, bool advertise, uint16_t num_handles) {
107  ESP_LOGV(TAG, "Creating BLE service - %s", uuid.to_string().c_str());
108  // Calculate the inst_id for the service
109  uint8_t inst_id = 0;
110  for (; inst_id < 0xFF; inst_id++) {
111  if (this->get_service(uuid, inst_id) == nullptr) {
112  break;
113  }
114  }
115  if (inst_id == 0xFF) {
116  ESP_LOGW(TAG, "Could not create BLE service %s, too many instances", uuid.to_string().c_str());
117  return nullptr;
118  }
119  BLEService *service = // NOLINT(cppcoreguidelines-owning-memory)
120  new BLEService(uuid, num_handles, inst_id, advertise);
121  this->services_.emplace(BLEServer::get_service_key(uuid, inst_id), service);
122  if (this->parent_->is_active() && this->registered_) {
123  service->do_create(this);
124  }
125  return service;
126 }
127 
128 void BLEServer::remove_service(ESPBTUUID uuid, uint8_t inst_id) {
129  ESP_LOGV(TAG, "Removing BLE service - %s %d", uuid.to_string().c_str(), inst_id);
130  BLEService *service = this->get_service(uuid, inst_id);
131  if (service == nullptr) {
132  ESP_LOGW(TAG, "BLE service %s %d does not exist", uuid.to_string().c_str(), inst_id);
133  return;
134  }
135  service->do_delete();
136  delete service; // NOLINT(cppcoreguidelines-owning-memory)
137  this->services_.erase(BLEServer::get_service_key(uuid, inst_id));
138 }
139 
140 BLEService *BLEServer::get_service(ESPBTUUID uuid, uint8_t inst_id) {
141  BLEService *service = nullptr;
142  if (this->services_.count(BLEServer::get_service_key(uuid, inst_id)) > 0) {
143  service = this->services_.at(BLEServer::get_service_key(uuid, inst_id));
144  }
145  return service;
146 }
147 
148 std::string BLEServer::get_service_key(ESPBTUUID uuid, uint8_t inst_id) {
149  return uuid.to_string() + std::to_string(inst_id);
150 }
151 
152 void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
153  esp_ble_gatts_cb_param_t *param) {
154  switch (event) {
155  case ESP_GATTS_CONNECT_EVT: {
156  ESP_LOGD(TAG, "BLE Client connected");
157  this->add_client_(param->connect.conn_id);
158  this->emit_(BLEServerEvt::EmptyEvt::ON_CONNECT, param->connect.conn_id);
159  break;
160  }
161  case ESP_GATTS_DISCONNECT_EVT: {
162  ESP_LOGD(TAG, "BLE Client disconnected");
163  this->remove_client_(param->disconnect.conn_id);
164  this->parent_->advertising_start();
165  this->emit_(BLEServerEvt::EmptyEvt::ON_DISCONNECT, param->disconnect.conn_id);
166  break;
167  }
168  case ESP_GATTS_REG_EVT: {
169  this->gatts_if_ = gatts_if;
170  this->registered_ = true;
171  break;
172  }
173  default:
174  break;
175  }
176 
177  for (const auto &pair : this->services_) {
178  pair.second->gatts_event_handler(event, gatts_if, param);
179  }
180 }
181 
183  // Delete all clients
184  this->clients_.clear();
185  // Delete all services
186  for (auto &pair : this->services_) {
187  pair.second->do_delete();
188  }
189  this->registered_ = false;
190  this->state_ = INIT;
191 }
192 
194 
195 void BLEServer::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 BLE Server:"); }
196 
197 BLEServer *global_ble_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
198 
199 } // namespace esp32_ble_server
200 } // namespace esphome
201 
202 #endif
BLEService * get_service(ESPBTUUID uuid, uint8_t inst_id=0)
Definition: ble_server.cpp:140
const char * to_string(SHTCXType type)
Definition: shtcx.cpp:16
float get_setup_priority() const override
Definition: ble_server.cpp:193
const float AFTER_BLUETOOTH
Definition: component.cpp:22
std::unordered_map< std::string, BLEService * > services_
Definition: ble_server.h:81
static std::string get_service_key(ESPBTUUID uuid, uint8_t inst_id)
Definition: ble_server.cpp:148
void remove_client_(uint16_t conn_id)
Definition: ble_server.h:74
enum esphome::esp32_ble_server::BLEServer::State INIT
void add_client_(uint16_t conn_id)
Definition: ble_server.h:73
std::unordered_set< uint16_t > clients_
Definition: ble_server.h:80
void ble_before_disabled_event_handler() override
Definition: ble_server.cpp:182
void do_create(BLEServer *server)
Definition: ble_service.cpp:44
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) override
Definition: ble_server.cpp:152
std::vector< BLEService * > services_to_start_
Definition: ble_server.h:82
void remove_service(ESPBTUUID uuid, uint8_t inst_id=0)
Definition: ble_server.cpp:128
std::string to_string() const
Definition: ble_uuid.cpp:171
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
void emit_(BLEServerEvt::EmptyEvt event, Args... args)
Definition: event_emitter.h:32
BLEService * create_service(ESPBTUUID uuid, bool advertise=false, uint16_t num_handles=15)
Definition: ble_server.cpp:106
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
std::vector< uint8_t > manufacturer_data_
Definition: ble_server.h:76