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;
31 auto ret = esp_ble_gattc_app_register(this->
app_id);
33 ESP_LOGE(TAG,
"gattc app register failed. app_id=%d code=%d", this->
app_id, ret);
40 if (this->
state_ == espbt::ClientState::READY_TO_CONNECT) {
54 this->
set_state(espbt::ClientState::DISCOVERED);
77 this->
set_state(espbt::ClientState::CONNECTING);
93 if (this->
state_ == espbt::ClientState::SEARCHING || this->
state_ == espbt::ClientState::READY_TO_CONNECT ||
94 this->
state_ == espbt::ClientState::DISCOVERED) {
98 this->
set_state(espbt::ClientState::DISCONNECTING);
105 this->services_.clear();
106 #ifndef CONFIG_BT_GATTC_CACHE_NVS_FLASH 112 esp_ble_gattc_cb_param_t *param) {
113 if (event == ESP_GATTC_REG_EVT && this->
app_id != param->reg.app_id)
115 if (event != ESP_GATTC_REG_EVT && esp_gattc_if != ESP_GATT_IF_NONE && esp_gattc_if != this->
gattc_if_)
118 ESP_LOGV(TAG,
"[%d] [%s] gattc_event_handler: event=%d gattc_if=%d", this->
connection_index_,
122 case ESP_GATTC_REG_EVT: {
123 if (param->reg.status == ESP_GATT_OK) {
128 ESP_LOGE(TAG,
"[%d] [%s] gattc app registration failed id=%d code=%d", this->
connection_index_,
129 this->
address_str_.c_str(), param->reg.app_id, param->reg.status);
133 case ESP_GATTC_OPEN_EVT: {
135 this->
conn_id_ = param->open.conn_id;
137 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
143 auto ret = esp_ble_gattc_send_mtu_req(this->
gattc_if_, param->open.conn_id);
145 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_send_mtu_req failed, status=%x", this->
connection_index_,
151 this->
state_ = espbt::ClientState::ESTABLISHED;
154 esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id,
nullptr);
157 case ESP_GATTC_CFG_MTU_EVT: {
158 if (param->cfg_mtu.status != ESP_GATT_OK) {
159 ESP_LOGW(TAG,
"[%d] [%s] cfg_mtu failed, mtu %d, status %d", this->
connection_index_,
160 this->
address_str_.c_str(), param->cfg_mtu.mtu, param->cfg_mtu.status);
165 param->cfg_mtu.status, param->cfg_mtu.mtu);
166 this->
mtu_ = param->cfg_mtu.mtu;
169 case ESP_GATTC_DISCONNECT_EVT: {
170 if (memcmp(param->disconnect.remote_bda, this->remote_bda_, 6) != 0)
172 ESP_LOGV(TAG,
"[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->
connection_index_,
178 case ESP_GATTC_SEARCH_RES_EVT: {
187 ble_service->
start_handle = param->search_res.start_handle;
188 ble_service->
end_handle = param->search_res.end_handle;
189 ble_service->
client =
this;
193 case ESP_GATTC_SEARCH_CMPL_EVT: {
197 svc->uuid.to_string().c_str());
198 ESP_LOGV(TAG,
"[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->
connection_index_,
199 this->
address_str_.c_str(), svc->start_handle, svc->end_handle);
203 this->
state_ = espbt::ClientState::ESTABLISHED;
206 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
213 esp_gattc_descr_elem_t desc_result;
215 esp_gatt_status_t descr_status =
217 NOTIFY_DESC_UUID, &desc_result, &count);
218 if (descr_status != ESP_GATT_OK) {
219 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_descr_by_char_handle error, status=%d", this->
connection_index_,
223 esp_gattc_char_elem_t char_result;
224 esp_gatt_status_t char_status =
226 param->reg_for_notify.handle, &char_result, &count, 0);
227 if (char_status != ESP_GATT_OK) {
228 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->
connection_index_,
237 uint16_t notify_en = char_result.properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY ? 1 : 2;
239 esp_ble_gattc_write_char_descr(this->
gattc_if_, this->
conn_id_, desc_result.handle,
sizeof(notify_en),
240 (uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
242 ESP_LOGW(TAG,
"[%d] [%s] esp_ble_gattc_write_char_descr error, status=%d", this->
connection_index_,
257 case ESP_GAP_BLE_SEC_REQ_EVT:
258 if (memcmp(param->ble_security.auth_cmpl.bd_addr, this->remote_bda_, 6) != 0)
261 esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr,
true);
264 case ESP_GAP_BLE_AUTH_CMPL_EVT:
265 if (memcmp(param->ble_security.auth_cmpl.bd_addr, this->remote_bda_, 6) != 0)
267 esp_bd_addr_t bd_addr;
268 memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr,
sizeof(esp_bd_addr_t));
271 if (!param->ble_security.auth_cmpl.success) {
273 param->ble_security.auth_cmpl.fail_reason);
276 ESP_LOGV(TAG,
"[%d] [%s] auth success. address type = %d auth mode = %d", this->
connection_index_,
277 this->
address_str_.c_str(), param->ble_security.auth_cmpl.addr_type,
278 param->ble_security.auth_cmpl.auth_mode);
295 return (
float) ((uint8_t) value[0]);
302 return (
float) ((uint8_t) value[1]);
316 return (
float)
encode_uint32(value[1], value[2], value[3], value[4]);
320 return (
float) ((int8_t) value[1]);
324 return (
float) ((int16_t) (value[1] << 8) + (int16_t) value[2]);
329 return (
float) ((int32_t) (value[1] << 16) + (int32_t) (value[2] << 8) + (int32_t) (value[3]));
334 return (
float) ((int32_t) (value[1] << 24) + (int32_t) (value[2] << 16) + (int32_t) (value[3] << 8) +
335 (int32_t) (value[4]));
338 ESP_LOGW(TAG,
"[%d] [%s] Cannot parse characteristic value of type 0x%x length %d", this->
connection_index_,
345 if (svc->uuid == uuid)
357 return svc->get_characteristic(chr);
367 svc->parse_characteristics();
368 for (
auto *chr : svc->characteristics) {
369 if (chr->handle == handle)
378 if (chr !=
nullptr) {
380 chr->parse_descriptors();
381 for (
auto &desc : chr->descriptors) {
382 if (desc->uuid.get_uuid().uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG)
393 auto *ch = svc->get_characteristic(chr);
396 return ch->get_descriptor(descr);
407 svc->parse_characteristics();
408 for (
auto *chr : svc->characteristics) {
410 chr->parse_descriptors();
411 for (
auto *desc : chr->descriptors) {
412 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)