ESPHome  2025.2.0
bluetooth_connection.cpp
Go to the documentation of this file.
1 #include "bluetooth_connection.h"
2 
4 #include "esphome/core/helpers.h"
5 #include "esphome/core/log.h"
6 
7 #ifdef USE_ESP32
8 
9 #include "bluetooth_proxy.h"
10 
11 namespace esphome {
12 namespace bluetooth_proxy {
13 
14 static const char *const TAG = "bluetooth_proxy.connection";
15 
17  ESP_LOGCONFIG(TAG, "BLE Connection:");
19 }
20 
21 bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
22  esp_ble_gattc_cb_param_t *param) {
23  if (!BLEClientBase::gattc_event_handler(event, gattc_if, param))
24  return false;
25 
26  switch (event) {
27  case ESP_GATTC_DISCONNECT_EVT: {
28  this->proxy_->send_device_connection(this->address_, false, 0, param->disconnect.reason);
29  this->set_address(0);
31  break;
32  }
33  case ESP_GATTC_CLOSE_EVT: {
34  this->proxy_->send_device_connection(this->address_, false, 0, param->close.reason);
35  this->set_address(0);
37  break;
38  }
39  case ESP_GATTC_OPEN_EVT: {
40  if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
41  this->proxy_->send_device_connection(this->address_, false, 0, param->open.status);
42  this->set_address(0);
44  } else if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
45  this->proxy_->send_device_connection(this->address_, true, this->mtu_);
47  }
48  this->seen_mtu_or_services_ = false;
49  break;
50  }
51  case ESP_GATTC_CFG_MTU_EVT:
52  case ESP_GATTC_SEARCH_CMPL_EVT: {
53  if (!this->seen_mtu_or_services_) {
54  // We don't know if we will get the MTU or the services first, so
55  // only send the device connection true if we have already received
56  // the services.
57  this->seen_mtu_or_services_ = true;
58  break;
59  }
60  this->proxy_->send_device_connection(this->address_, true, this->mtu_);
62  break;
63  }
64  case ESP_GATTC_READ_DESCR_EVT:
65  case ESP_GATTC_READ_CHAR_EVT: {
66  if (param->read.status != ESP_GATT_OK) {
67  ESP_LOGW(TAG, "[%d] [%s] Error reading char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
68  this->address_str_.c_str(), param->read.handle, param->read.status);
69  this->proxy_->send_gatt_error(this->address_, param->read.handle, param->read.status);
70  break;
71  }
73  resp.address = this->address_;
74  resp.handle = param->read.handle;
75  resp.data.reserve(param->read.value_len);
76  for (uint16_t i = 0; i < param->read.value_len; i++) {
77  resp.data.push_back(param->read.value[i]);
78  }
80  break;
81  }
82  case ESP_GATTC_WRITE_CHAR_EVT:
83  case ESP_GATTC_WRITE_DESCR_EVT: {
84  if (param->write.status != ESP_GATT_OK) {
85  ESP_LOGW(TAG, "[%d] [%s] Error writing char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
86  this->address_str_.c_str(), param->write.handle, param->write.status);
87  this->proxy_->send_gatt_error(this->address_, param->write.handle, param->write.status);
88  break;
89  }
91  resp.address = this->address_;
92  resp.handle = param->write.handle;
94  break;
95  }
96  case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
97  if (param->unreg_for_notify.status != ESP_GATT_OK) {
98  ESP_LOGW(TAG, "[%d] [%s] Error unregistering notifications for handle 0x%2X, status=%d",
99  this->connection_index_, this->address_str_.c_str(), param->unreg_for_notify.handle,
100  param->unreg_for_notify.status);
101  this->proxy_->send_gatt_error(this->address_, param->unreg_for_notify.handle, param->unreg_for_notify.status);
102  break;
103  }
105  resp.address = this->address_;
106  resp.handle = param->unreg_for_notify.handle;
108  break;
109  }
110  case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
111  if (param->reg_for_notify.status != ESP_GATT_OK) {
112  ESP_LOGW(TAG, "[%d] [%s] Error registering notifications for handle 0x%2X, status=%d", this->connection_index_,
113  this->address_str_.c_str(), param->reg_for_notify.handle, param->reg_for_notify.status);
114  this->proxy_->send_gatt_error(this->address_, param->reg_for_notify.handle, param->reg_for_notify.status);
115  break;
116  }
118  resp.address = this->address_;
119  resp.handle = param->reg_for_notify.handle;
121  break;
122  }
123  case ESP_GATTC_NOTIFY_EVT: {
124  ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_NOTIFY_EVT: handle=0x%2X", this->connection_index_, this->address_str_.c_str(),
125  param->notify.handle);
127  resp.address = this->address_;
128  resp.handle = param->notify.handle;
129  resp.data.reserve(param->notify.value_len);
130  for (uint16_t i = 0; i < param->notify.value_len; i++) {
131  resp.data.push_back(param->notify.value[i]);
132  }
134  break;
135  }
136  default:
137  break;
138  }
139  return true;
140 }
141 
142 void BluetoothConnection::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
143  BLEClientBase::gap_event_handler(event, param);
144 
145  switch (event) {
146  case ESP_GAP_BLE_AUTH_CMPL_EVT:
147  if (memcmp(param->ble_security.auth_cmpl.bd_addr, this->remote_bda_, 6) != 0)
148  break;
149  if (param->ble_security.auth_cmpl.success) {
150  this->proxy_->send_device_pairing(this->address_, true);
151  } else {
152  this->proxy_->send_device_pairing(this->address_, false, param->ble_security.auth_cmpl.fail_reason);
153  }
154  break;
155  default:
156  break;
157  }
158 }
159 
160 esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
161  if (!this->connected()) {
162  ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT characteristic, not connected.", this->connection_index_,
163  this->address_str_.c_str());
164  return ESP_GATT_NOT_CONNECTED;
165  }
166 
167  ESP_LOGV(TAG, "[%d] [%s] Reading GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
168  handle);
169 
170  esp_err_t err = esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
171  if (err != ERR_OK) {
172  ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char error, err=%d", this->connection_index_,
173  this->address_str_.c_str(), err);
174  return err;
175  }
176  return ESP_OK;
177 }
178 
179 esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::string &data, bool response) {
180  if (!this->connected()) {
181  ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT characteristic, not connected.", this->connection_index_,
182  this->address_str_.c_str());
183  return ESP_GATT_NOT_CONNECTED;
184  }
185  ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
186  handle);
187 
188  esp_err_t err =
189  esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
190  response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
191  if (err != ERR_OK) {
192  ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char error, err=%d", this->connection_index_,
193  this->address_str_.c_str(), err);
194  return err;
195  }
196  return ESP_OK;
197 }
198 
199 esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
200  if (!this->connected()) {
201  ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT descriptor, not connected.", this->connection_index_,
202  this->address_str_.c_str());
203  return ESP_GATT_NOT_CONNECTED;
204  }
205  ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
206  handle);
207 
208  esp_err_t err = esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
209  if (err != ERR_OK) {
210  ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char_descr error, err=%d", this->connection_index_,
211  this->address_str_.c_str(), err);
212  return err;
213  }
214  return ESP_OK;
215 }
216 
217 esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data, bool response) {
218  if (!this->connected()) {
219  ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
220  this->address_str_.c_str());
221  return ESP_GATT_NOT_CONNECTED;
222  }
223  ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
224  handle);
225 
226  esp_err_t err = esp_ble_gattc_write_char_descr(
227  this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
228  response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
229  if (err != ERR_OK) {
230  ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, err=%d", this->connection_index_,
231  this->address_str_.c_str(), err);
232  return err;
233  }
234  return ESP_OK;
235 }
236 
237 esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enable) {
238  if (!this->connected()) {
239  ESP_LOGW(TAG, "[%d] [%s] Cannot notify GATT characteristic, not connected.", this->connection_index_,
240  this->address_str_.c_str());
241  return ESP_GATT_NOT_CONNECTED;
242  }
243 
244  if (enable) {
245  ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications handle %d", this->connection_index_,
246  this->address_str_.c_str(), handle);
247  esp_err_t err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, handle);
248  if (err != ESP_OK) {
249  ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_register_for_notify failed, err=%d", this->connection_index_,
250  this->address_str_.c_str(), err);
251  return err;
252  }
253  } else {
254  ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
255  this->address_str_.c_str(), handle);
256  esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
257  if (err != ESP_OK) {
258  ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_unregister_for_notify failed, err=%d", this->connection_index_,
259  this->address_str_.c_str(), err);
260  return err;
261  }
262  }
263  return ESP_OK;
264 }
265 
267  return this->proxy_->get_advertisement_parser_type();
268 }
269 
270 } // namespace bluetooth_proxy
271 } // namespace esphome
272 
273 #endif // USE_ESP32
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
void send_device_pairing(uint64_t address, bool paired, esp_err_t error=ESP_OK)
bool send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg)
bool send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg)
esp_err_t write_descriptor(uint16_t handle, const std::string &data, bool response)
esp_err_t write_characteristic(uint16_t handle, const std::string &data, bool response)
bool send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &msg)
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override
void send_device_connection(uint64_t address, bool connected, uint16_t mtu=0, esp_err_t error=ESP_OK)
bool send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &msg)
bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void send_gatt_error(uint64_t address, uint16_t handle, esp_err_t error)
bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
esp_err_t notify_characteristic(uint16_t handle, bool enable)