summaryrefslogtreecommitdiff
path: root/src/BLEDevice.cpp
diff options
context:
space:
mode:
authorNeil Kolban <kolban1@kolban.com>2018-01-17 18:16:31 -0600
committerNeil Kolban <kolban1@kolban.com>2018-01-17 18:16:31 -0600
commit3f5005c383540d07dd16ac044c78d7be28d4aa8e (patch)
treec5236ddbe5c8dd99ad7083dd498110152ad0e9be /src/BLEDevice.cpp
parentRemoval of unneeded file (diff)
downloadthermostat-3f5005c383540d07dd16ac044c78d7be28d4aa8e.tar.gz
thermostat-3f5005c383540d07dd16ac044c78d7be28d4aa8e.tar.bz2
thermostat-3f5005c383540d07dd16ac044c78d7be28d4aa8e.zip
0.4.8
Diffstat (limited to 'src/BLEDevice.cpp')
-rw-r--r--src/BLEDevice.cpp269
1 files changed, 250 insertions, 19 deletions
diff --git a/src/BLEDevice.cpp b/src/BLEDevice.cpp
index a701459..b333ed7 100644
--- a/src/BLEDevice.cpp
+++ b/src/BLEDevice.cpp
@@ -11,11 +11,13 @@
#include <freertos/task.h>
#include <esp_err.h>
#include <nvs_flash.h>
-#include <bt.h> // ESP32 BLE
+#include <esp_bt.h> // ESP32 BLE
+#include <esp_bt_device.h> // ESP32 BLE
#include <esp_bt_main.h> // ESP32 BLE
#include <esp_gap_ble_api.h> // ESP32 BLE
#include <esp_gatts_api.h> // ESP32 BLE
#include <esp_gattc_api.h> // ESP32 BLE
+#include <esp_gatt_common_api.h>// ESP32 BLE
#include <esp_err.h> // ESP32 ESP-IDF
#include <esp_log.h> // ESP32 ESP-IDF
#include <map> // Part of C++ Standard library
@@ -32,20 +34,29 @@
static const char* LOG_TAG = "BLEDevice";
-
/**
* Singletons for the BLEDevice.
*/
BLEServer* BLEDevice::m_pServer = nullptr;
BLEScan* BLEDevice::m_pScan = nullptr;
BLEClient* BLEDevice::m_pClient = nullptr;
-bool initialized = false;
+bool initialized = false; // Have we been initialized?
+esp_ble_sec_act_t BLEDevice::m_securityLevel = (esp_ble_sec_act_t)0;
+BLESecurityCallbacks* BLEDevice::m_securityCallbacks = nullptr;
+uint16_t BLEDevice::m_localMTU = 23;
+
/**
* @brief Create a new instance of a client.
* @return A new instance of the client.
*/
-BLEClient* BLEDevice::createClient() {
+/* STATIC */ BLEClient* BLEDevice::createClient() {
+ ESP_LOGD(LOG_TAG, ">> createClient");
+#ifndef CONFIG_GATTC_ENABLE // Check that BLE GATTC is enabled in make menuconfig
+ ESP_LOGE(LOG_TAG, "BLE GATTC is not enabled - CONFIG_GATTC_ENABLE not defined");
+ abort();
+#endif // CONFIG_GATTC_ENABLE
m_pClient = new BLEClient();
+ ESP_LOGD(LOG_TAG, "<< createClient");
return m_pClient;
} // createClient
@@ -54,8 +65,12 @@ BLEClient* BLEDevice::createClient() {
* @brief Create a new instance of a server.
* @return A new instance of the server.
*/
-BLEServer* BLEDevice::createServer() {
+/* STATIC */ BLEServer* BLEDevice::createServer() {
ESP_LOGD(LOG_TAG, ">> createServer");
+#ifndef CONFIG_GATTS_ENABLE // Check that BLE GATTS is enabled in make menuconfig
+ ESP_LOGE(LOG_TAG, "BLE GATTS is not enabled - CONFIG_GATTS_ENABLE not defined");
+ abort();
+#endif // CONFIG_GATTS_ENABLE
m_pServer = new BLEServer();
m_pServer->createApp(0);
ESP_LOGD(LOG_TAG, "<< createServer");
@@ -70,7 +85,7 @@ BLEServer* BLEDevice::createServer() {
* @param [in] gatts_if The connection to the GATT interface.
* @param [in] param Parameters for the event.
*/
-void BLEDevice::gattServerEventHandler(
+/* STATIC */ void BLEDevice::gattServerEventHandler(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t* param
@@ -81,6 +96,26 @@ void BLEDevice::gattServerEventHandler(
BLEUtils::dumpGattServerEvent(event, gatts_if, param);
+ switch(event) {
+ case ESP_GATTS_CONNECT_EVT: {
+ BLEDevice::m_localMTU = 23;
+ if(BLEDevice::m_securityLevel){
+ esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel);
+ }
+ break;
+ } // ESP_GATTS_CONNECT_EVT
+
+ case ESP_GATTS_MTU_EVT: {
+ BLEDevice::m_localMTU = param->mtu.mtu;
+ ESP_LOGI(LOG_TAG, "ESP_GATTS_MTU_EVT, MTU %d", BLEDevice::m_localMTU);
+ break;
+ }
+ default: {
+ break;
+ }
+ } // switch
+
+
if (BLEDevice::m_pServer != nullptr) {
BLEDevice::m_pServer->handleGATTServerEvent(event, gatts_if, param);
}
@@ -96,7 +131,7 @@ void BLEDevice::gattServerEventHandler(
* @param [in] gattc_if
* @param [in] param
*/
-void BLEDevice::gattClientEventHandler(
+/* STATIC */ void BLEDevice::gattClientEventHandler(
esp_gattc_cb_event_t event,
esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t* param) {
@@ -104,13 +139,26 @@ void BLEDevice::gattClientEventHandler(
ESP_LOGD(LOG_TAG, "gattClientEventHandler [esp_gatt_if: %d] ... %s",
gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str());
BLEUtils::dumpGattClientEvent(event, gattc_if, param);
-/*
+
switch(event) {
+ case ESP_GATTC_CONNECT_EVT: {
+ if(BLEDevice::getMTU() != 23){
+ esp_err_t errRc = esp_ble_gattc_send_mtu_req(gattc_if, param->connect.conn_id);
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_send_mtu_req: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ }
+ }
+ if(BLEDevice::m_securityLevel){
+ esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel);
+ }
+ break;
+ } // ESP_GATTC_CONNECT_EVT
+
default: {
break;
}
} // switch
- */
+
// If we have a client registered, call it.
if (BLEDevice::m_pClient != nullptr) {
@@ -123,21 +171,70 @@ void BLEDevice::gattClientEventHandler(
/**
* @brief Handle GAP events.
*/
-void BLEDevice::gapEventHandler(
+/* STATIC */ void BLEDevice::gapEventHandler(
esp_gap_ble_cb_event_t event,
esp_ble_gap_cb_param_t *param) {
BLEUtils::dumpGapEvent(event, param);
switch(event) {
- case ESP_GAP_BLE_SEC_REQ_EVT: {
- esp_err_t errRc = ::esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
- if (errRc != ESP_OK) {
- ESP_LOGE(LOG_TAG, "esp_ble_gap_security_rsp: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+
+ case ESP_GAP_BLE_OOB_REQ_EVT: /* OOB request event */
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_OOB_REQ_EVT");
+ break;
+ case ESP_GAP_BLE_LOCAL_IR_EVT: /* BLE local IR event */
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_LOCAL_IR_EVT");
+ break;
+ case ESP_GAP_BLE_LOCAL_ER_EVT: /* BLE local ER event */
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_LOCAL_ER_EVT");
+ break;
+ case ESP_GAP_BLE_NC_REQ_EVT:
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_NC_REQ_EVT");
+ if(BLEDevice::m_securityCallbacks!=nullptr){
+ esp_ble_confirm_reply(param->ble_security.ble_req.bd_addr, BLEDevice::m_securityCallbacks->onConfirmPIN(param->ble_security.key_notif.passkey));
+ }
+ break;
+ case ESP_GAP_BLE_PASSKEY_REQ_EVT: /* passkey request event */
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_PASSKEY_REQ_EVT: ");
+ // esp_log_buffer_hex(LOG_TAG, m_remote_bda, sizeof(m_remote_bda));
+ if(BLEDevice::m_securityCallbacks!=nullptr){
+ esp_ble_passkey_reply(param->ble_security.ble_req.bd_addr, true, BLEDevice::m_securityCallbacks->onPassKeyRequest());
}
break;
- }
-
+ /*
+ * TODO should we add white/black list comparison?
+ */
+ case ESP_GAP_BLE_SEC_REQ_EVT:
+ /* send the positive(true) security response to the peer device to accept the security request.
+ If not accept the security request, should sent the security response with negative(false) accept value*/
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_SEC_REQ_EVT");
+ if(BLEDevice::m_securityCallbacks!=nullptr){
+ esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, BLEDevice::m_securityCallbacks->onSecurityRequest());
+ }
+ else{
+ esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
+ }
+ break;
+ /*
+ *
+ */
+ case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: ///the app will receive this evt when the IO has Output capability and the peer device IO has Input capability.
+ ///show the passkey number to the user to input it in the peer deivce.
+ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_PASSKEY_NOTIF_EVT");
+ if(BLEDevice::m_securityCallbacks!=nullptr){
+ ESP_LOGI(LOG_TAG, "passKey = %d", param->ble_security.key_notif.passkey);
+ BLEDevice::m_securityCallbacks->onPassKeyNotify(param->ble_security.key_notif.passkey);
+ }
+ break;
+ case ESP_GAP_BLE_KEY_EVT:
+ //shows the ble key type info share with peer device to the user.
+ ESP_LOGI(LOG_TAG, "key type = %s", BLESecurity::esp_key_type_to_str(param->ble_security.ble_key.key_type));
+ break;
+ case ESP_GAP_BLE_AUTH_CMPL_EVT:
+ if(BLEDevice::m_securityCallbacks!=nullptr){
+ BLEDevice::m_securityCallbacks->onAuthenticationComplete(param->ble_security.auth_cmpl);
+ }
+ break;
default: {
break;
}
@@ -154,15 +251,33 @@ void BLEDevice::gapEventHandler(
if (BLEDevice::m_pScan != nullptr) {
BLEDevice::getScan()->handleGAPEvent(event, param);
}
+
+ /*
+ * Security events:
+ */
+
+
} // gapEventHandler
/**
+ * @brief Get the BLE device address.
+ * @return The BLE device address.
+ */
+/* STATIC*/ BLEAddress BLEDevice::getAddress() {
+ const uint8_t* bdAddr = esp_bt_dev_get_address();
+ esp_bd_addr_t addr;
+ memcpy(addr, bdAddr, sizeof(addr));
+ return BLEAddress(addr);
+} // getAddress
+
+
+/**
* @brief Retrieve the Scan object that we use for scanning.
* @return The scanning object reference. This is a singleton object. The caller should not
* try and release/delete it.
*/
-BLEScan* BLEDevice::getScan() {
+/* STATIC */ BLEScan* BLEDevice::getScan() {
//ESP_LOGD(LOG_TAG, ">> getScan");
if (m_pScan == nullptr) {
m_pScan = new BLEScan();
@@ -174,12 +289,30 @@ BLEScan* BLEDevice::getScan() {
/**
+ * @brief Get the value of a characteristic of a service on a remote device.
+ * @param [in] bdAddress
+ * @param [in] serviceUUID
+ * @param [in] characteristicUUID
+ */
+/* STATIC */ std::string BLEDevice::getValue(BLEAddress bdAddress, BLEUUID serviceUUID, BLEUUID characteristicUUID) {
+ ESP_LOGD(LOG_TAG, ">> getValue: bdAddress: %s, serviceUUID: %s, characteristicUUID: %s", bdAddress.toString().c_str(), serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
+ BLEClient *pClient = createClient();
+ pClient->connect(bdAddress);
+ std::string ret = pClient->getValue(serviceUUID, characteristicUUID);
+ pClient->disconnect();
+ ESP_LOGD(LOG_TAG, "<< getValue");
+ return ret;
+} // getValue
+
+
+/**
* @brief Initialize the %BLE environment.
* @param deviceName The device name of the device.
*/
-void BLEDevice::init(std::string deviceName) {
+/* STATIC */ void BLEDevice::init(std::string deviceName) {
if(!initialized){
- initialized = true;
+ initialized = true; // Set the initialization flag to ensure we are only initialized once.
+
esp_err_t errRc = ::nvs_flash_init();
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "nvs_flash_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
@@ -192,6 +325,7 @@ void BLEDevice::init(std::string deviceName) {
ESP_LOGE(LOG_TAG, "esp_bt_controller_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return;
}
+
#ifndef CLASSIC_BT_ENABLED
// esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); //FIXME waiting for response from esp-idf issue
errRc = esp_bt_controller_enable(ESP_BT_MODE_BLE);
@@ -207,6 +341,7 @@ void BLEDevice::init(std::string deviceName) {
return;
}
#endif
+
errRc = esp_bluedroid_init();
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_bluedroid_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
@@ -225,17 +360,21 @@ void BLEDevice::init(std::string deviceName) {
return;
}
+#ifdef CONFIG_GATTC_ENABLE // Check that BLE client is configured in make menuconfig
errRc = esp_ble_gattc_register_callback(BLEDevice::gattClientEventHandler);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return;
}
+#endif // CONFIG_GATTC_ENABLE
+#ifdef CONFIG_GATTS_ENABLE // Check that BLE server is configured in make menuconfig
errRc = esp_ble_gatts_register_callback(BLEDevice::gattServerEventHandler);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gatts_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return;
}
+#endif // CONFIG_GATTS_ENABLE
errRc = ::esp_ble_gap_set_device_name(deviceName.c_str());
if (errRc != ESP_OK) {
@@ -276,4 +415,96 @@ void BLEDevice::init(std::string deviceName) {
ESP_LOGD(LOG_TAG, "<< setPower");
} // setPower
+
+/**
+ * @brief Set the value of a characteristic of a service on a remote device.
+ * @param [in] bdAddress
+ * @param [in] serviceUUID
+ * @param [in] characteristicUUID
+ */
+/* STATIC */ void BLEDevice::setValue(BLEAddress bdAddress, BLEUUID serviceUUID, BLEUUID characteristicUUID, std::string value) {
+ ESP_LOGD(LOG_TAG, ">> setValue: bdAddress: %s, serviceUUID: %s, characteristicUUID: %s", bdAddress.toString().c_str(), serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
+ BLEClient *pClient = createClient();
+ pClient->connect(bdAddress);
+ pClient->setValue(serviceUUID, characteristicUUID, value);
+ pClient->disconnect();
+} // setValue
+
+
+/**
+ * @brief Return a string representation of the nature of this device.
+ * @return A string representation of the nature of this device.
+ */
+/* STATIC */ std::string BLEDevice::toString() {
+ std::ostringstream oss;
+ oss << "BD Address: " << getAddress().toString();
+ return oss.str();
+} // toString
+
+
+/**
+ * @brief Add an entry to the BLE white list.
+ * @param [in] address The address to add to the white list.
+ */
+void BLEDevice::whiteListAdd(BLEAddress address) {
+ ESP_LOGD(LOG_TAG, ">> whiteListAdd: %s", address.toString().c_str());
+ esp_err_t errRc = esp_ble_gap_update_whitelist(true, *address.getNative()); // True to add an entry.
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gap_update_whitelist: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ }
+ ESP_LOGD(LOG_TAG, "<< whiteListAdd");
+} // whiteListAdd
+
+
+/**
+ * @brief Remove an entry from the BLE white list.
+ * @param [in] address The address to remove from the white list.
+ */
+void BLEDevice::whiteListRemove(BLEAddress address) {
+ ESP_LOGD(LOG_TAG, ">> whiteListRemove: %s", address.toString().c_str());
+ esp_err_t errRc = esp_ble_gap_update_whitelist(false, *address.getNative()); // False to remove an entry.
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gap_update_whitelist: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ }
+ ESP_LOGD(LOG_TAG, "<< whiteListRemove");
+} // whiteListRemove
+
+/*
+ * @brief Set encryption level that will be negotiated with peer device durng connection
+ * @param [in] level Requested encryption level
+ */
+void BLEDevice::setEncryptionLevel(esp_ble_sec_act_t level) {
+ BLEDevice::m_securityLevel = level;
+}
+
+/*
+ * @brief Set callbacks that will be used to handle encryption negotiation events and authentication events
+ * @param [in] cllbacks Pointer to BLESecurityCallbacks class callback
+ */
+void BLEDevice::setSecurityCallbacks(BLESecurityCallbacks* callbacks) {
+ BLEDevice::m_securityCallbacks = callbacks;
+}
+
+/*
+ * @brief Setup local mtu that will be used to negotiate mtu during request from client peer
+ * @param [in] mtu Value to set local mtu, should be larger than 23 and lower or equal to 517
+ */
+esp_err_t BLEDevice::setMTU(uint16_t mtu) {
+ ESP_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu);
+ esp_err_t err = esp_ble_gatt_set_local_mtu(mtu);
+ if(err == ESP_OK){
+ m_localMTU = mtu;
+ } else {
+ ESP_LOGE(LOG_TAG, "can't set local mtu value: %d", mtu);
+ }
+ ESP_LOGD(LOG_TAG, "<< setLocalMTU");
+ return err;
+}
+
+/*
+ * @brief Get local MTU value set during mtu request or default value
+ */
+uint16_t BLEDevice::getMTU() {
+ return m_localMTU;
+}
#endif // CONFIG_BT_ENABLED