9 namespace esp32_ble_client {
11 static const char *
const TAG =
"esp32_ble_client";
12 static const esp_bt_uuid_t NOTIFY_DESC_UUID = {
13 .len = ESP_UUID_LEN_16,
16 .uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,
21 static uint8_t connection_index = 0;
24 auto ret = esp_ble_gattc_app_register(this->
app_id);
26 ESP_LOGE(TAG,
"gattc app register failed. app_id=%d code=%d", this->
app_id, ret);
35 if (this->
state_ == espbt::ClientState::READY_TO_CONNECT) {
49 this->
set_state(espbt::ClientState::DISCOVERED);
72 this->
set_state(espbt::ClientState::CONNECTING);
88 if (this->
state_ == espbt::ClientState::SEARCHING || this->
state_ == espbt::ClientState::READY_TO_CONNECT ||
89 this->
state_ == espbt::ClientState::DISCOVERED) {
93 this->
set_state(espbt::ClientState::DISCONNECTING);
100 this->services_.clear();
101 #ifndef CONFIG_BT_GATTC_CACHE_NVS_FLASH 107 esp_ble_gattc_cb_param_t *param) {
108 if (event == ESP_GATTC_REG_EVT && this->
app_id != param->reg.app_id)
110 if (event != ESP_GATTC_REG_EVT && esp_gattc_if != ESP_GATT_IF_NONE && esp_gattc_if != this->
gattc_if_)
113 ESP_LOGV(TAG,
"[%d] [%s] gattc_event_handler: event=%d gattc_if=%d", this->
connection_index_,
117 case ESP_GATTC_REG_EVT: {
118 if (param->reg.status == ESP_GATT_OK) {
123 ESP_LOGE(TAG,
"[%d] [%s] gattc app registration failed id=%d code=%d", this->
connection_index_,
124 this->
address_str_.c_str(), param->reg.app_id, param->reg.status);
128 case ESP_GATTC_OPEN_EVT: {
130 this->
conn_id_ = param->open.conn_id;
132 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
138 auto ret = esp_ble_gattc_send_mtu_req(this->
gattc_if_, param->open.conn_id);
140 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_send_mtu_req failed, status=%x", this->
connection_index_,
146 this->
state_ = espbt::ClientState::ESTABLISHED;
149 esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id,
nullptr);
152 case ESP_GATTC_CFG_MTU_EVT: {
153 if (param->cfg_mtu.status != ESP_GATT_OK) {
154 ESP_LOGW(TAG,
"[%d] [%s] cfg_mtu failed, mtu %d, status %d", this->
connection_index_,
155 this->
address_str_.c_str(), param->cfg_mtu.mtu, param->cfg_mtu.status);
160 param->cfg_mtu.status, param->cfg_mtu.mtu);
161 this->
mtu_ = param->cfg_mtu.mtu;
164 case ESP_GATTC_DISCONNECT_EVT: {
165 if (memcmp(param->disconnect.remote_bda, this->remote_bda_, 6) != 0)
167 ESP_LOGV(TAG,
"[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->
connection_index_,
173 case ESP_GATTC_SEARCH_RES_EVT: {
182 ble_service->
start_handle = param->search_res.start_handle;
183 ble_service->
end_handle = param->search_res.end_handle;
184 ble_service->
client =
this;
188 case ESP_GATTC_SEARCH_CMPL_EVT: {
192 svc->uuid.to_string().c_str());
193 ESP_LOGV(TAG,
"[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->
connection_index_,
194 this->
address_str_.c_str(), svc->start_handle, svc->end_handle);
198 this->
state_ = espbt::ClientState::ESTABLISHED;
201 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
208 esp_gattc_descr_elem_t desc_result;
210 esp_gatt_status_t descr_status =
212 NOTIFY_DESC_UUID, &desc_result, &count);
213 if (descr_status != ESP_GATT_OK) {
214 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_descr_by_char_handle error, status=%d", this->
connection_index_,
218 esp_gattc_char_elem_t char_result;
219 esp_gatt_status_t char_status =
221 param->reg_for_notify.handle, &char_result, &count, 0);
222 if (char_status != ESP_GATT_OK) {
223 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->
connection_index_,
232 uint16_t notify_en = char_result.properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY ? 1 : 2;
234 esp_ble_gattc_write_char_descr(this->
gattc_if_, this->
conn_id_, desc_result.handle,
sizeof(notify_en),
235 (uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
237 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_write_char_descr error, status=%d", this->
connection_index_,
252 case ESP_GAP_BLE_SEC_REQ_EVT:
253 if (memcmp(param->ble_security.auth_cmpl.bd_addr, this->remote_bda_, 6) != 0)
256 esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr,
true);
259 case ESP_GAP_BLE_AUTH_CMPL_EVT:
260 if (memcmp(param->ble_security.auth_cmpl.bd_addr, this->remote_bda_, 6) != 0)
262 esp_bd_addr_t bd_addr;
263 memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr,
sizeof(esp_bd_addr_t));
266 if (!param->ble_security.auth_cmpl.success) {
268 param->ble_security.auth_cmpl.fail_reason);
271 ESP_LOGV(TAG,
"[%d] [%s] auth success. address type = %d auth mode = %d", this->
connection_index_,
272 this->
address_str_.c_str(), param->ble_security.auth_cmpl.addr_type,
273 param->ble_security.auth_cmpl.auth_mode);
290 return (
float) ((uint8_t) value[0]);
297 return (
float) ((uint8_t) value[1]);
311 return (
float)
encode_uint32(value[1], value[2], value[3], value[4]);
315 return (
float) ((int8_t) value[1]);
319 return (
float) ((int16_t) (value[1] << 8) + (int16_t) value[2]);
324 return (
float) ((int32_t) (value[1] << 16) + (int32_t) (value[2] << 8) + (int32_t) (value[3]));
329 return (
float) ((int32_t) (value[1] << 24) + (int32_t) (value[2] << 16) + (int32_t) (value[3] << 8) +
330 (int32_t) (value[4]));
333 ESP_LOGW(TAG,
"[%d] [%s] Cannot parse characteristic value of type 0x%x length %d", this->
connection_index_,
340 if (svc->uuid == uuid)
352 return svc->get_characteristic(chr);
362 svc->parse_characteristics();
363 for (
auto *chr : svc->characteristics) {
364 if (chr->handle == handle)
373 if (chr !=
nullptr) {
375 chr->parse_descriptors();
376 for (
auto &desc : chr->descriptors) {
377 if (desc->uuid.get_uuid().uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG)
388 auto *ch = svc->get_characteristic(chr);
391 return ch->get_descriptor(descr);
402 svc->parse_characteristics();
403 for (
auto *chr : svc->characteristics) {
405 chr->parse_descriptors();
406 for (
auto *desc : chr->descriptors) {
407 if (desc->handle == handle)
BLEDescriptor * get_descriptor(espbt::ESPBTUUID service, espbt::ESPBTUUID chr, espbt::ESPBTUUID descr)
BLEService * get_service(espbt::ESPBTUUID uuid)
std::string format_hex(const uint8_t *data, size_t length)
Format the byte array data of length len in lowercased hex.
std::vector< BLEService * > services_
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
float get_setup_priority() const override
const float AFTER_BLUETOOTH
BLEDescriptor * get_config_descriptor(uint16_t handle)
esp_bd_addr_t remote_bda_
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid)
virtual void set_state(ClientState st)
uint8_t connection_index_
espbt::ConnectionType connection_type_
static ESPBTUUID from_uint16(uint16_t uuid)
constexpr uint32_t encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3)
Encode a 24-bit value given three bytes in most to least significant byte order.
esp_ble_addr_type_t remote_addr_type_
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
esp_ble_addr_type_t get_address_type() const
uint64_t address_uint64() const
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
BLECharacteristic * get_characteristic(espbt::ESPBTUUID service, espbt::ESPBTUUID chr)
void set_address(uint64_t address)
virtual void mark_failed()
Mark this component as failed.
Implementation of SPI Controller mode.
bool parse_device(const espbt::ESPBTDevice &device) override
bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
float parse_char_value(uint8_t *value, uint16_t length)