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