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