-
-
Save chegewara/d3ed0e3365407f6d3abcffc486b2c462 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <freertos/FreeRTOS.h> | |
#include <freertos/task.h> | |
#include <esp_log.h> | |
#include <string> | |
#include <sstream> | |
#include <sys/time.h> | |
#include "BLEDevice.h" | |
#include "FreeRTOS.h" | |
#include <nvs_flash.h> | |
#include "BLEAdvertisedDevice.h" | |
#include "BLEClient.h" | |
#include "BLEScan.h" | |
#include "BLEUtils.h" | |
#include "Task.h" | |
#include "sdkconfig.h" | |
#define TICKS_TO_DELAY 100 | |
BLEScan *pBLEScan; | |
static const char* LOG_TAG = "TEST"; | |
#include "esp_heap_trace.h" | |
#define NUM_RECORDS 6 | |
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM | |
bool missOne = false; | |
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); | |
static BLEUUID charUUID1("beb5483e-36e1-4688-b7f5-ea07361b26a8"); | |
void scan1(void*); | |
BLEAdvertisedDevice* device; | |
static void notifyCallback( | |
BLERemoteCharacteristic* pBLERemoteCharacteristic, | |
uint8_t* pData, | |
size_t length, | |
bool isNotify) { | |
ESP_LOGI(LOG_TAG, "Notify callback for characteristic %s of data %s length %d", | |
pBLERemoteCharacteristic->getUUID().toString().c_str(), ((char*) pData), length); | |
} | |
class MyCallbacks : public BLEClientCallbacks { | |
void onConnect(BLEClient* pC){ | |
ESP_LOGW(__func__, "connected"); | |
} | |
void onDisconnect(BLEClient* pC) { | |
// delete pC; | |
ESP_LOGW(__func__, "disconnected"); | |
// xTaskCreate(scan1, "scan", 2548, NULL, 1, NULL); | |
} | |
}; | |
int abc = 0; | |
static struct timeval tv; | |
MyCallbacks* callbacks = new MyCallbacks(); | |
void connect_task(void* dev) | |
{ | |
BLEClient* pClient = BLEDevice::createClient(); | |
pClient->setClientCallbacks(callbacks); | |
// ESP_LOGW(__func__, "connect status: %d", (int)); | |
if(!pClient->connect((BLEAdvertisedDevice*)dev)) | |
goto exit; | |
BLERemoteService* pRemoteService; | |
pRemoteService = pClient->getService(serviceUUID); | |
if (pRemoteService == nullptr) { | |
ESP_LOGE(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str()); | |
goto exit; | |
} | |
BLERemoteCharacteristic* pRemoteCharacteristic; | |
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID1); | |
if (pRemoteCharacteristic == nullptr) { | |
ESP_LOGE(LOG_TAG, "Failed to find our characteristic UUID1: %s", charUUID1.toString().c_str()); | |
goto exit; | |
} | |
if(pClient->isConnected()) | |
pRemoteCharacteristic->registerForNotify(notifyCallback); | |
// TickType_t last_wake_time; | |
// last_wake_time = xTaskGetTickCount(); | |
while(pClient->isConnected() && ++abc%6 != 0) { | |
std::ostringstream stringStream; | |
gettimeofday(&tv, nullptr); | |
stringStream << "very long message to test reported issue with stop advertising after few connect/disconnect in issue #513. Write message sent every exactly 100ms with vTaskDelayUntil. Time sent to uuid: " << pRemoteCharacteristic->getUUID().toString().c_str() << tv.tv_sec << "." << tv.tv_usec; | |
// uint8_t test[255] = {0}; | |
pRemoteCharacteristic->writeValue(stringStream.str()); | |
// vTaskDelayUntil(&last_wake_time, TICKS_TO_DELAY/portTICK_PERIOD_MS); | |
} | |
exit: | |
pClient->disconnect(); | |
vTaskDelay(50); | |
delete pClient; | |
// vTaskDelay(2000); | |
xTaskCreate(scan1, "scan", 2548, NULL, 1, NULL); | |
vTaskDelete(NULL); | |
} | |
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { | |
void onResult(BLEAdvertisedDevice* advertisedDevice) { | |
ESP_LOGI(LOG_TAG, "Advertised Device: %s", advertisedDevice->toString().c_str()); | |
if (advertisedDevice->haveServiceUUID() && advertisedDevice->isAdvertisingService(BLEUUID("1234"))) { | |
pBLEScan->stop(); // <--- it is required to always stop scan before we try to connect to another device, if we wont stop app will stall in esp-idf bt stack | |
device = advertisedDevice; | |
heap_caps_print_heap_info(MALLOC_CAP_INTERNAL); | |
xTaskCreate(connect_task, "conT", 4*1024, advertisedDevice, 5, NULL); | |
} | |
} | |
}; | |
static void my_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) { | |
ESP_LOGI(LOG_TAG, "custom gap event handler, event: %d", (uint8_t)event); | |
} | |
static uint32_t dis16 = 0; | |
static uint32_t dis3e = 0; | |
static uint32_t disall = 0; | |
static void my_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param) { | |
ESP_LOGI(LOG_TAG, "custom gattc event handler, event: %d", (uint8_t)event); | |
if((uint8_t)event == 41) | |
{ | |
disall++; | |
if(param->disconnect.reason == 0x16) | |
dis16++; | |
if(param->disconnect.reason == 0x3e) | |
dis3e++; | |
ESP_LOGW(__func__, "total disconnect count: %d, disconnect 0x16: %d, disconnect 0x3e: %d", disall, dis16, dis3e); | |
} | |
} | |
static void my_gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param) { | |
ESP_LOGI(LOG_TAG, "custom gatts event handler, event: %d", (uint8_t)event); | |
} | |
void Connect_test() | |
{ | |
// trace_record = (heap_trace_record_t*)calloc(100, sizeof(heap_trace_record_t)); | |
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) ); | |
esp_log_level_set("*", ESP_LOG_INFO); | |
esp_log_level_set("BLEUtils", ESP_LOG_NONE); | |
esp_log_level_set("FreeRTOS", ESP_LOG_NONE); | |
BLEDevice::init("esp32"); | |
nvs_flash_erase(); | |
BLEDevice::setCustomGapHandler(my_gap_event_handler); | |
BLEDevice::setCustomGattsHandler(my_gatts_event_handler); | |
BLEDevice::setCustomGattcHandler(my_gattc_event_handler); | |
BLEDevice::setMTU(255); | |
pBLEScan = BLEDevice::getScan(); | |
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); | |
// pBLEScan->setActiveScan(true); | |
pBLEScan->setInterval(1533); | |
pBLEScan->setWindow(97); | |
xTaskCreate(scan1, "scan", 2548, NULL, 1, NULL); | |
} // SampleClient | |
void scan1(void*){ | |
vTaskDelay(250); | |
// ESP_LOGI(LOG_TAG, "start scan"); | |
pBLEScan->start(0); | |
// ESP_LOGI(LOG_TAG, "scan stop success"); | |
vTaskDelete(NULL); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* BLEDevice.cpp | |
* | |
* Created on: Mar 22, 2017 | |
* Author: kolban | |
*/ | |
#include "sdkconfig.h" | |
#if defined(CONFIG_BT_ENABLED) | |
#include <esp_bt.h> | |
#include <esp_bt_main.h> | |
#include <esp_gap_ble_api.h> | |
#include <esp_gattc_api.h> | |
#include "BLEClient.h" | |
#include "BLEUtils.h" | |
#include "BLEService.h" | |
#include "GeneralUtils.h" | |
#include <string> | |
#include <sstream> | |
#include <unordered_set> | |
#include "BLEDevice.h" | |
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) | |
#include "esp32-hal-log.h" | |
#define LOG_TAG "" | |
#else | |
#include "esp_log.h" | |
static const char* LOG_TAG = "BLEClient"; | |
#endif | |
/* | |
* Design | |
* ------ | |
* When we perform a searchService() requests, we are asking the BLE server to return each of the services | |
* that it exposes. For each service, we received an ESP_GATTC_SEARCH_RES_EVT event which contains details | |
* of the exposed service including its UUID. | |
* | |
* The objects we will invent for a BLEClient will be as follows: | |
* * BLERemoteService - A model of a remote service. | |
* * BLERemoteCharacteristic - A model of a remote characteristic | |
* * BLERemoteDescriptor - A model of a remote descriptor. | |
* | |
* Since there is a hierarchical relationship here, we will have the idea that from a BLERemoteService will own | |
* zero or more remote characteristics and a BLERemoteCharacteristic will own zero or more remote BLEDescriptors. | |
* | |
* We will assume that a BLERemoteService contains a map that maps BLEUUIDs to the set of owned characteristics | |
* and that a BLECharacteristic contains a map that maps BLEUUIDs to the set of owned descriptors. | |
* | |
* | |
*/ | |
BLEClient::BLEClient() { | |
m_pClientCallbacks = nullptr; | |
m_conn_id = ESP_GATT_IF_NONE; | |
m_gattc_if = ESP_GATT_IF_NONE; | |
m_haveServices = false; | |
m_isConnected = false; // Initially, we are flagged as not connected. | |
m_appId = BLEDevice::m_appId++; | |
m_appId = m_appId%100; | |
BLEDevice::addPeerDevice(this, true, m_appId); | |
m_semaphoreRegEvt.take("connect"); | |
esp_err_t errRc = ::esp_ble_gattc_app_register(m_appId); | |
if (errRc != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); | |
return; | |
} | |
m_semaphoreRegEvt.wait("connect"); | |
} // BLEClient | |
/** | |
* @brief Destructor. | |
*/ | |
BLEClient::~BLEClient() { | |
// We may have allocated service references associated with this client. Before we are finished | |
// with the client, we must release resources. | |
clearServices(); | |
esp_ble_gattc_app_unregister(m_gattc_if); | |
BLEDevice::removePeerDevice(m_appId, true); | |
} // ~BLEClient | |
/** | |
* @brief Clear any existing services. | |
* | |
*/ | |
void BLEClient::clearServices() { | |
ESP_LOGD(LOG_TAG, ">> clearServices"); | |
// Delete all the services. | |
for (auto &myPair : m_servicesMap) { | |
delete myPair.second; | |
} | |
m_servicesMap.clear(); | |
m_servicesMapByInstID.clear(); | |
m_haveServices = false; | |
ESP_LOGD(LOG_TAG, "<< clearServices"); | |
} // clearServices | |
/** | |
* Add overloaded function to ease connect to peer device with not public address | |
*/ | |
bool BLEClient::connect(BLEAdvertisedDevice* device) { | |
BLEAddress address = device->getAddress(); | |
esp_ble_addr_type_t type = device->getAddressType(); | |
return connect(address, type); | |
} | |
/** | |
* @brief Connect to the partner (BLE Server). | |
* @param [in] address The address of the partner. | |
* @return True on success. | |
*/ | |
bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) { | |
ESP_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str()); | |
m_peerAddress = address; | |
// Perform the open connection request against the target BLE Server. | |
m_semaphoreOpenEvt.take("connect"); | |
esp_err_t errRc = ::esp_ble_gattc_open( | |
m_gattc_if, | |
*getPeerAddress().getNative(), // address | |
type, // Note: This was added on 2018-04-03 when the latest ESP-IDF was detected to have changed the signature. | |
1 // direct connection <-- maybe needs to be changed in case of direct indirect connection??? | |
); | |
if (errRc != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); | |
return false; | |
} | |
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. | |
ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK); | |
return rc == ESP_GATT_OK; | |
} // connect | |
/** | |
* @brief Disconnect from the peer. | |
* @return N/A. | |
*/ | |
void BLEClient::disconnect() { | |
ESP_LOGD(LOG_TAG, ">> disconnect()"); | |
ESP_LOGW(__func__, "gattIf: %d, connId: %d", getGattcIf(), getConnId()); | |
esp_err_t errRc = ::esp_ble_gattc_close(getGattcIf(), getConnId()); | |
if (errRc != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "esp_ble_gattc_close: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); | |
return; | |
} | |
ESP_LOGD(LOG_TAG, "<< disconnect()"); | |
} // disconnect | |
/** | |
* @brief Handle GATT Client events | |
*/ | |
void BLEClient::gattClientEventHandler( | |
esp_gattc_cb_event_t event, | |
esp_gatt_if_t gattc_if, | |
esp_ble_gattc_cb_param_t* evtParam) { | |
ESP_LOGD(LOG_TAG, "gattClientEventHandler [esp_gatt_if: %d] ... %s", | |
gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str()); | |
// Execute handler code based on the type of event received. | |
switch(event) { | |
case ESP_GATTC_SRVC_CHG_EVT: | |
ESP_LOGI(LOG_TAG, "SERVICE CHANGED"); | |
break; | |
case ESP_GATTC_CLOSE_EVT: { | |
// esp_ble_gattc_app_unregister(m_appId); | |
// BLEDevice::removePeerDevice(m_gattc_if, true); | |
break; | |
} | |
// | |
// ESP_GATTC_DISCONNECT_EVT | |
// | |
// disconnect: | |
// - esp_gatt_status_t status | |
// - uint16_t conn_id | |
// - esp_bd_addr_t remote_bda | |
case ESP_GATTC_DISCONNECT_EVT: { | |
if(!m_isConnected) | |
break; | |
// If we receive a disconnect event, set the class flag that indicates that we are | |
// no longer connected. | |
// if(evtParam->disconnect.reason != 0x16){ | |
m_semaphoreOpenEvt.give(evtParam->disconnect.reason); | |
esp_ble_gattc_close(m_gattc_if, m_conn_id); | |
// } | |
m_isConnected = false; | |
if (m_pClientCallbacks != nullptr) { | |
m_pClientCallbacks->onDisconnect(this); | |
} | |
// esp_ble_gattc_app_unregister(m_gattc_if); | |
// BLEDevice::removePeerDevice(m_appId, true); | |
break; | |
} // ESP_GATTC_DISCONNECT_EVT | |
// | |
// ESP_GATTC_OPEN_EVT | |
// | |
// open: | |
// - esp_gatt_status_t status | |
// - uint16_t conn_id | |
// - esp_bd_addr_t remote_bda | |
// | |
case ESP_GATTC_OPEN_EVT: { | |
m_conn_id = evtParam->open.conn_id; | |
if (m_pClientCallbacks != nullptr) { | |
m_pClientCallbacks->onConnect(this); | |
} | |
if (evtParam->open.status == ESP_GATT_OK) { | |
m_isConnected = true; // Flag us as connected. | |
} | |
m_semaphoreOpenEvt.give(evtParam->open.status); | |
break; | |
} // ESP_GATTC_OPEN_EVT | |
// | |
// ESP_GATTC_REG_EVT | |
// | |
// reg: | |
// esp_gatt_status_t status | |
// uint16_t app_id | |
// | |
case ESP_GATTC_REG_EVT: { | |
m_gattc_if = gattc_if; | |
m_semaphoreRegEvt.give(); | |
break; | |
} // ESP_GATTC_REG_EVT | |
case ESP_GATTC_CFG_MTU_EVT: | |
if(evtParam->cfg_mtu.status != ESP_GATT_OK) { | |
ESP_LOGE(LOG_TAG,"Config mtu failed"); | |
} | |
m_mtu = evtParam->cfg_mtu.mtu; | |
break; | |
case ESP_GATTC_CONNECT_EVT: { | |
BLEDevice::updatePeerDevice(this, true, m_gattc_if); | |
esp_err_t errRc = esp_ble_gattc_send_mtu_req(gattc_if, evtParam->connect.conn_id); | |
if (errRc != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "esp_ble_gattc_send_mtu_req: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); | |
} | |
#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig | |
if(BLEDevice::m_securityLevel){ | |
esp_ble_set_encryption(evtParam->connect.remote_bda, BLEDevice::m_securityLevel); | |
} | |
#endif // CONFIG_BLE_SMP_ENABLE | |
break; | |
} // ESP_GATTC_CONNECT_EVT | |
// | |
// ESP_GATTC_SEARCH_CMPL_EVT | |
// | |
// search_cmpl: | |
// - esp_gatt_status_t status | |
// - uint16_t conn_id | |
// | |
case ESP_GATTC_SEARCH_CMPL_EVT: { | |
esp_ble_gattc_cb_param_t* p_data = (esp_ble_gattc_cb_param_t*)evtParam; | |
if (p_data->search_cmpl.status != ESP_GATT_OK){ | |
ESP_LOGE(LOG_TAG, "search service failed, error status = %x", p_data->search_cmpl.status); | |
break; | |
} | |
#ifndef ARDUINO_ARCH_ESP32 | |
// commented out just for now to keep backward compatibility | |
// if(p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) { | |
// ESP_LOGI(LOG_TAG, "Get service information from remote device"); | |
// } else if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_NVS_FLASH) { | |
// ESP_LOGI(LOG_TAG, "Get service information from flash"); | |
// } else { | |
// ESP_LOGI(LOG_TAG, "unknown service source"); | |
// } | |
#endif | |
m_semaphoreSearchCmplEvt.give(0); | |
break; | |
} // ESP_GATTC_SEARCH_CMPL_EVT | |
// | |
// ESP_GATTC_SEARCH_RES_EVT | |
// | |
// search_res: | |
// - uint16_t conn_id | |
// - uint16_t start_handle | |
// - uint16_t end_handle | |
// - esp_gatt_id_t srvc_id | |
// | |
case ESP_GATTC_SEARCH_RES_EVT: { | |
BLEUUID uuid = BLEUUID(evtParam->search_res.srvc_id); | |
BLERemoteService* pRemoteService = new BLERemoteService( | |
evtParam->search_res.srvc_id, | |
this, | |
evtParam->search_res.start_handle, | |
evtParam->search_res.end_handle | |
); | |
m_servicesMap.insert(std::pair<std::string, BLERemoteService*>(uuid.toString(), pRemoteService)); | |
m_servicesMapByInstID.insert(std::pair<BLERemoteService *, uint16_t>(pRemoteService, evtParam->search_res.srvc_id.inst_id)); | |
break; | |
} // ESP_GATTC_SEARCH_RES_EVT | |
default: { | |
break; | |
} | |
} // Switch | |
// Pass the request on to all services. | |
for (auto &myPair : m_servicesMap) { | |
myPair.second->gattClientEventHandler(event, gattc_if, evtParam); | |
} | |
} // gattClientEventHandler | |
uint16_t BLEClient::getConnId() { | |
return m_conn_id; | |
} // getConnId | |
esp_gatt_if_t BLEClient::getGattcIf() { | |
return m_gattc_if; | |
} // getGattcIf | |
/** | |
* @brief Retrieve the address of the peer. | |
* | |
* Returns the Bluetooth device address of the %BLE peer to which this client is connected. | |
*/ | |
BLEAddress BLEClient::getPeerAddress() { | |
return m_peerAddress; | |
} // getAddress | |
/** | |
* @brief Ask the BLE server for the RSSI value. | |
* @return The RSSI value. | |
*/ | |
int BLEClient::getRssi() { | |
ESP_LOGD(LOG_TAG, ">> getRssi()"); | |
if (!isConnected()) { | |
ESP_LOGD(LOG_TAG, "<< getRssi(): Not connected"); | |
return 0; | |
} | |
// We make the API call to read the RSSI value which is an asynchronous operation. We expect to receive | |
// an ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT to indicate completion. | |
// | |
m_semaphoreRssiCmplEvt.take("getRssi"); | |
esp_err_t rc = ::esp_ble_gap_read_rssi(*getPeerAddress().getNative()); | |
if (rc != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "<< getRssi: esp_ble_gap_read_rssi: rc=%d %s", rc, GeneralUtils::errorToString(rc)); | |
return 0; | |
} | |
int rssiValue = m_semaphoreRssiCmplEvt.wait("getRssi"); | |
ESP_LOGD(LOG_TAG, "<< getRssi(): %d", rssiValue); | |
return rssiValue; | |
} // getRssi | |
/** | |
* @brief Get the service BLE Remote Service instance corresponding to the uuid. | |
* @param [in] uuid The UUID of the service being sought. | |
* @return A reference to the Service or nullptr if don't know about it. | |
*/ | |
BLERemoteService* BLEClient::getService(const char* uuid) { | |
return getService(BLEUUID(uuid)); | |
} // getService | |
/** | |
* @brief Get the service object corresponding to the uuid. | |
* @param [in] uuid The UUID of the service being sought. | |
* @return A reference to the Service or nullptr if don't know about it. | |
* @throws BLEUuidNotFound | |
*/ | |
BLERemoteService* BLEClient::getService(BLEUUID uuid) { | |
ESP_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); | |
// Design | |
// ------ | |
// We wish to retrieve the service given its UUID. It is possible that we have not yet asked the | |
// device what services it has in which case we have nothing to match against. If we have not | |
// asked the device about its services, then we do that now. Once we get the results we can then | |
// examine the services map to see if it has the service we are looking for. | |
if (!m_haveServices) { | |
getServices(); | |
} | |
std::string uuidStr = uuid.toString(); | |
for (auto &myPair : m_servicesMap) { | |
if (myPair.first == uuidStr) { | |
ESP_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str()); | |
return myPair.second; | |
} | |
} // End of each of the services. | |
ESP_LOGD(LOG_TAG, "<< getService: not found"); | |
return nullptr; | |
} // getService | |
/** | |
* @brief Ask the remote %BLE server for its services. | |
* A %BLE Server exposes a set of services for its partners. Here we ask the server for its set of | |
* services and wait until we have received them all. | |
* @return N/A | |
*/ | |
std::map<std::string, BLERemoteService*>* BLEClient::getServices() { | |
/* | |
* Design | |
* ------ | |
* We invoke esp_ble_gattc_search_service. This will request a list of the service exposed by the | |
* peer BLE partner to be returned as events. Each event will be an an instance of ESP_GATTC_SEARCH_RES_EVT | |
* and will culminate with an ESP_GATTC_SEARCH_CMPL_EVT when all have been received. | |
*/ | |
ESP_LOGD(LOG_TAG, ">> getServices"); | |
// TODO implement retrieving services from cache | |
clearServices(); // Clear any services that may exist. | |
esp_err_t errRc = esp_ble_gattc_search_service( | |
getGattcIf(), | |
getConnId(), | |
NULL // Filter UUID | |
); | |
m_semaphoreSearchCmplEvt.take("getServices"); | |
if (errRc != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "esp_ble_gattc_search_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); | |
return &m_servicesMap; | |
} | |
// If sucessfull, remember that we now have services. | |
m_haveServices = (m_semaphoreSearchCmplEvt.wait("getServices") == 0); | |
ESP_LOGD(LOG_TAG, "<< getServices"); | |
return &m_servicesMap; | |
} // getServices | |
/** | |
* @brief Get the value of a specific characteristic associated with a specific service. | |
* @param [in] serviceUUID The service that owns the characteristic. | |
* @param [in] characteristicUUID The characteristic whose value we wish to read. | |
* @throws BLEUuidNotFound | |
*/ | |
std::string BLEClient::getValue(BLEUUID serviceUUID, BLEUUID characteristicUUID) { | |
ESP_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); | |
std::string ret = getService(serviceUUID)->getCharacteristic(characteristicUUID)->readValue(); | |
ESP_LOGD(LOG_TAG, "<<getValue"); | |
return ret; | |
} // getValue | |
/** | |
* @brief Handle a received GAP event. | |
* | |
* @param [in] event | |
* @param [in] param | |
*/ | |
void BLEClient::handleGAPEvent( | |
esp_gap_ble_cb_event_t event, | |
esp_ble_gap_cb_param_t* param) { | |
ESP_LOGD(LOG_TAG, "BLEClient ... handling GAP event!"); | |
switch (event) { | |
// | |
// ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT | |
// | |
// read_rssi_cmpl | |
// - esp_bt_status_t status | |
// - int8_t rssi | |
// - esp_bd_addr_t remote_addr | |
// | |
case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: { | |
m_semaphoreRssiCmplEvt.give((uint32_t) param->read_rssi_cmpl.rssi); | |
break; | |
} // ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT | |
default: | |
break; | |
} | |
} // handleGAPEvent | |
/** | |
* @brief Are we connected to a partner? | |
* @return True if we are connected and false if we are not connected. | |
*/ | |
bool BLEClient::isConnected() { | |
return m_isConnected; | |
} // isConnected | |
/** | |
* @brief Set the callbacks that will be invoked. | |
*/ | |
void BLEClient::setClientCallbacks(BLEClientCallbacks* pClientCallbacks) { | |
m_pClientCallbacks = pClientCallbacks; | |
} // setClientCallbacks | |
/** | |
* @brief Set the value of a specific characteristic associated with a specific service. | |
* @param [in] serviceUUID The service that owns the characteristic. | |
* @param [in] characteristicUUID The characteristic whose value we wish to write. | |
* @throws BLEUuidNotFound | |
*/ | |
void BLEClient::setValue(BLEUUID serviceUUID, BLEUUID characteristicUUID, std::string value) { | |
ESP_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); | |
getService(serviceUUID)->getCharacteristic(characteristicUUID)->writeValue(value); | |
ESP_LOGD(LOG_TAG, "<< setValue"); | |
} // setValue | |
uint16_t BLEClient::getMTU() { | |
return m_mtu; | |
} | |
/** | |
* @brief Return a string representation of this client. | |
* @return A string representation of this client. | |
*/ | |
std::string BLEClient::toString() { | |
std::ostringstream ss; | |
ss << "peer address: " << m_peerAddress.toString(); | |
ss << "\nServices:\n"; | |
for (auto &myPair : m_servicesMap) { | |
ss << myPair.second->toString() << "\n"; | |
// myPair.second is the value | |
} | |
return ss.str(); | |
} // toString | |
#endif // CONFIG_BT_ENABLED |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment