<commit_before>/*
 * BLEDevice.cpp
 *
 *  Created on: Mar 22, 2017
 *      Author: kolban
 */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_log.h>
#include <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>
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#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.
 *
 *
 */
static const char* LOG_TAG = "BLEClient";

BLEClient::BLEClient() {
	m_pClientCallbacks = nullptr;
	m_conn_id          = 0;
	m_gattc_if         = 0;
	m_haveServices     = false;
	m_isConnected      = false;  // Initially, we are flagged as not connected.
} // 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.
	for (auto &myPair : m_servicesMap) {
	   delete myPair.second;
	}
	m_servicesMap.clear();
} // ~BLEClient


/**
 * @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_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());

// We need the connection handle that we get from registering the application.  We register the app
// and then block on its completion.  When the event has arrived, we will have the handle.
	m_semaphoreRegEvt.take("connect");

	esp_err_t errRc = ::esp_ble_gattc_app_register(0);
	if (errRc != ESP_OK) {
		ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
		return false;
	}

	m_semaphoreRegEvt.wait("connect");

	m_peerAddress = address;

	// Perform the open connection request against the target BLE Server.
	m_semaphoreOpenEvt.take("connect");
	errRc = ::esp_ble_gattc_open(
		getGattcIf(),
		*getPeerAddress().getNative(), // address
		1                              // direct 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");
	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_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_ble_gattc_app_unregister(getGattcIf());
	m_peerAddress = BLEAddress("00:00:00:00:00:00");
	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) {

	// Execute handler code based on the type of event received.
	switch(event) {

		//
		// 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 we receive a disconnect event, set the class flag that indicates that we are
				// no longer connected.
				m_isConnected = false;
				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
		// - uint16_t          mtu
		//
		case ESP_GATTC_OPEN_EVT: {
			m_conn_id = evtParam->open.conn_id;
			if (m_pClientCallbacks != nullptr) {
				m_pClientCallbacks->onConnect(this);
			}
			m_isConnected = true;   // Flag us as connected.
			m_semaphoreOpenEvt.give();
			break;
		} // ESP_GATTC_OPEN_EVT


		//
		// ESP_GATTC_REG_EVT
		//
		// reg:<commit_msg>Fixes for #216<commit_after>/*
 * BLEDevice.cpp
 *
 *  Created on: Mar 22, 2017
 *      Author: kolban
 */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_log.h>
#include <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>
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#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.
 *
 *
 */
static const char* LOG_TAG = "BLEClient";

BLEClient::BLEClient() {
	m_pClientCallbacks = nullptr;
	m_conn_id          = 0;
	m_gattc_if         = 0;
	m_haveServices     = false;
	m_isConnected      = false;  // Initially, we are flagged as not connected.
} // 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.
	for (auto &myPair : m_servicesMap) {
	   delete myPair.second;
	}
	m_servicesMap.clear();
} // ~BLEClient


/**
 * @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_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());

// We need the connection handle that we get from registering the application.  We register the app
// and then block on its completion.  When the event has arrived, we will have the handle.
	m_semaphoreRegEvt.take("connect");

	esp_err_t errRc = ::esp_ble_gattc_app_register(0);
	if (errRc != ESP_OK) {
		ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
		return false;
	}

	m_semaphoreRegEvt.wait("connect");

	m_peerAddress = address;

	// Perform the open connection request against the target BLE Server.
	m_semaphoreOpenEvt.take("connect");
	errRc = ::esp_ble_gattc_open(
		getGattcIf(),
		*getPeerAddress().getNative(), // address
		1                              // direct 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");
	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_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_ble_gattc_app_unregister(getGattcIf());
	m_peerAddress = BLEAddress("00:00:00:00:00:00");
	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) {

	// Execute handler code based on the type of event received.
	switch(event) {

		//
		// 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 we receive a disconnect event, set the class flag that indicates that we are
				// no longer connected.
				m_isConnected = false;
				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
		// - uint16_t          mtu
		//
		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:
{'fraction_non_alphanumeric': 0.11352104268232016, 'fraction_numerical': 0.00706397373395682, 'mean_word_length': 3.577413479052823, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2095829', 'n_tokens_mistral': 3829, 'n_tokens_neox': 3579, 'n_words': 944}