forked from h2zero/esp-nimble-cpp
Compare commits
23 Commits
1.2.0
...
remove-ard
Author | SHA1 | Date | |
---|---|---|---|
c218a27dd8 | |||
8883f44d9f | |||
9c7b690771 | |||
641f297120 | |||
7f853fa04b | |||
df4eb9f7d8 | |||
d3a0f95aaf | |||
d9d794ae40 | |||
30d6c399b8 | |||
7815d89dbf | |||
9fa9531e50 | |||
946b971750 | |||
b62358a520 | |||
e45fb8616a | |||
d38865e022 | |||
62d1f67d8b | |||
4f8342e275 | |||
05080abad4 | |||
f5eab87a87 | |||
3c33129600 | |||
3227681476 | |||
cf3227503b | |||
ef049ddf19 |
@ -2,9 +2,33 @@
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(SUPPORTED_TARGETS esp32)
|
||||
idf_build_get_property(__hack_component_targets __COMPONENT_TARGETS)
|
||||
|
||||
set(COMPONENT_SRCS
|
||||
if("esp-nimble-component" IN_LIST BUILD_COMPONENTS OR "__esp-nimble-component" IN_LIST __hack_component_targets)
|
||||
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
esp-nimble-component
|
||||
)
|
||||
elseif("nimble" IN_LIST BUILD_COMPONENTS OR "__nimble" IN_LIST __hack_component_targets)
|
||||
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
endif()
|
||||
|
||||
# Dont use arduino bullshit
|
||||
#if("arduino" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "__idf_arduino")
|
||||
# list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
# arduino
|
||||
# )
|
||||
#endif()
|
||||
|
||||
idf_component_register(
|
||||
REQUIRED_IDF_TARGETS
|
||||
"esp32"
|
||||
"esp32s3"
|
||||
"esp32c3"
|
||||
INCLUDE_DIRS
|
||||
"src"
|
||||
SRCS
|
||||
"src/FreeRTOS.cpp"
|
||||
"src/NimBLE2904.cpp"
|
||||
"src/NimBLEAddress.cpp"
|
||||
@ -27,31 +51,15 @@ set(COMPONENT_SRCS
|
||||
"src/NimBLEService.cpp"
|
||||
"src/NimBLEUtils.cpp"
|
||||
"src/NimBLEUUID.cpp"
|
||||
)
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
src
|
||||
)
|
||||
|
||||
set(COMPONENT_PRIV_REQUIRES
|
||||
nvs_flash
|
||||
REQUIRES
|
||||
bt
|
||||
nvs_flash
|
||||
esp_ringbuf
|
||||
PRIV_REQUIRES
|
||||
${ESP_NIMBLE_PRIV_REQUIRES}
|
||||
)
|
||||
|
||||
if(COMPONENTS MATCHES "esp-nimble-component")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
esp-nimble-component
|
||||
)
|
||||
elseif(COMPONENTS MATCHES "nimble")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
endif()
|
||||
|
||||
if(COMPONENTS MATCHES "arduino")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
arduino
|
||||
)
|
||||
endif()
|
||||
|
||||
register_component()
|
||||
target_compile_options(${COMPONENT_TARGET}
|
||||
PUBLIC
|
||||
-DDONT_USE_ARDUINO_BULLSHIT
|
||||
)
|
||||
|
57
CMakeLists.txt_idf3
Normal file
57
CMakeLists.txt_idf3
Normal file
@ -0,0 +1,57 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(SUPPORTED_TARGETS esp32)
|
||||
|
||||
set(COMPONENT_SRCS
|
||||
"src/FreeRTOS.cpp"
|
||||
"src/NimBLE2904.cpp"
|
||||
"src/NimBLEAddress.cpp"
|
||||
"src/NimBLEAdvertisedDevice.cpp"
|
||||
"src/NimBLEAdvertising.cpp"
|
||||
"src/NimBLEBeacon.cpp"
|
||||
"src/NimBLECharacteristic.cpp"
|
||||
"src/NimBLEClient.cpp"
|
||||
"src/NimBLEDescriptor.cpp"
|
||||
"src/NimBLEDevice.cpp"
|
||||
"src/NimBLEEddystoneTLM.cpp"
|
||||
"src/NimBLEEddystoneURL.cpp"
|
||||
"src/NimBLEHIDDevice.cpp"
|
||||
"src/NimBLERemoteCharacteristic.cpp"
|
||||
"src/NimBLERemoteDescriptor.cpp"
|
||||
"src/NimBLERemoteService.cpp"
|
||||
"src/NimBLEScan.cpp"
|
||||
"src/NimBLESecurity.cpp"
|
||||
"src/NimBLEServer.cpp"
|
||||
"src/NimBLEService.cpp"
|
||||
"src/NimBLEUtils.cpp"
|
||||
"src/NimBLEUUID.cpp"
|
||||
)
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
src
|
||||
)
|
||||
|
||||
set(COMPONENT_PRIV_REQUIRES
|
||||
nvs_flash
|
||||
bt
|
||||
)
|
||||
|
||||
if(COMPONENTS MATCHES "esp-nimble-component")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
esp-nimble-component
|
||||
)
|
||||
elseif(COMPONENTS MATCHES "nimble")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
endif()
|
||||
|
||||
if(COMPONENTS MATCHES "arduino")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
arduino
|
||||
)
|
||||
endif()
|
||||
|
||||
register_component()
|
@ -1,27 +0,0 @@
|
||||
menu "ESP-NimBLE-CPP configuration"
|
||||
|
||||
config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
bool "Show NimBLE return codes as text in debug log."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will display return code values as text
|
||||
messages in the debug log. This will use approximately 8kB
|
||||
of flash memory.
|
||||
|
||||
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
bool "Show NimBLE gap events as text in debug log."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will display gap event codes as text
|
||||
messages in the debug log. This will use approximately 1kB
|
||||
of flash memory.
|
||||
|
||||
config NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
bool "Show advertisment types as text in debug log."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will display advertisment types recieved
|
||||
while scanning as text messages in the debug log.
|
||||
This will use approximately 250 bytes of flash memory.
|
||||
|
||||
endmenu
|
@ -155,7 +155,7 @@ void FreeRTOS::Semaphore::give() {
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
// #ifdef ARDUINO_ARCH_ESP32
|
||||
// #if defined(ARDUINO_ARCH_ESP32) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
// FreeRTOS::sleep(10);
|
||||
// #endif
|
||||
|
||||
@ -243,7 +243,7 @@ bool FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
|
||||
std::string FreeRTOS::Semaphore::toString() {
|
||||
char hex[9];
|
||||
std::string res = "name: " + m_name + " (0x";
|
||||
snprintf(hex, sizeof(hex), "%08x", (uint32_t)m_semaphore);
|
||||
snprintf(hex, sizeof(hex), "%08lx", (uint32_t)m_semaphore);
|
||||
res += hex;
|
||||
res += "), owner: " + m_owner;
|
||||
return res;
|
||||
|
@ -45,7 +45,7 @@
|
||||
/* of data as per HID Class standard */
|
||||
|
||||
/* Main items */
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
#define HIDINPUT(size) (0x80 | size)
|
||||
#define HIDOUTPUT(size) (0x90 | size)
|
||||
#else
|
||||
|
@ -42,6 +42,7 @@ struct BLE2904_Data {
|
||||
*/
|
||||
class NimBLE2904: public NimBLEDescriptor {
|
||||
public:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic = nullptr);
|
||||
static const uint8_t FORMAT_BOOLEAN = 1;
|
||||
static const uint8_t FORMAT_UINT2 = 2;
|
||||
static const uint8_t FORMAT_UINT4 = 3;
|
||||
@ -77,7 +78,6 @@ public:
|
||||
void setUnit(uint16_t unit);
|
||||
|
||||
private:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic);
|
||||
friend class NimBLECharacteristic;
|
||||
BLE2904_Data m_data;
|
||||
}; // BLE2904
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef COMPONENTS_NIMBLEADDRESS_H_
|
||||
#define COMPONENTS_NIMBLEADDRESS_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "nimble/ble.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
|
@ -734,7 +734,7 @@ uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
||||
* @param [in] length The length of the payload in bytes.
|
||||
* @param [in] append Indicates if the the data should be appended (scan response).
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setPayload(uint8_t *payload, uint8_t length, bool append) {
|
||||
void NimBLEAdvertisedDevice::setPayload(const uint8_t *payload, uint8_t length, bool append) {
|
||||
if(!append) {
|
||||
m_advLength = length;
|
||||
m_payload.assign(payload, payload + length);
|
||||
|
@ -137,7 +137,7 @@ private:
|
||||
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setPayload(uint8_t *payload, uint8_t length, bool append);
|
||||
void setPayload(const uint8_t *payload, uint8_t length, bool append);
|
||||
void setRSSI(int rssi);
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
|
@ -471,16 +471,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16,
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc((void*)m_advData.uuids16,
|
||||
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids16[m_advData.num_uuids16].value,
|
||||
&it.getNative()->u16.value, 2);
|
||||
|
||||
m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16;
|
||||
memcpy((void*)&m_advData.uuids16[m_advData.num_uuids16],
|
||||
&it.getNative()->u16, sizeof(ble_uuid16_t));
|
||||
m_advData.uuids16_is_complete = 1;
|
||||
m_advData.num_uuids16++;
|
||||
}
|
||||
@ -492,16 +490,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc(m_advData.uuids32,
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc((void*)m_advData.uuids32,
|
||||
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids32[m_advData.num_uuids32].value,
|
||||
&it.getNative()->u32.value, 4);
|
||||
|
||||
m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32;
|
||||
memcpy((void*)&m_advData.uuids32[m_advData.num_uuids32],
|
||||
&it.getNative()->u32, sizeof(ble_uuid32_t));
|
||||
m_advData.uuids32_is_complete = 1;
|
||||
m_advData.num_uuids32++;
|
||||
}
|
||||
@ -513,16 +509,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128,
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc((void*)m_advData.uuids128,
|
||||
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids128[m_advData.num_uuids128].value,
|
||||
&it.getNative()->u128.value, 16);
|
||||
|
||||
m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128;
|
||||
memcpy((void*)&m_advData.uuids128[m_advData.num_uuids128],
|
||||
&it.getNative()->u128, sizeof(ble_uuid128_t));
|
||||
m_advData.uuids128_is_complete = 1;
|
||||
m_advData.num_uuids128++;
|
||||
}
|
||||
@ -599,19 +593,19 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids128 > 0) {
|
||||
free(m_advData.uuids128);
|
||||
free((void*)m_advData.uuids128);
|
||||
m_advData.uuids128 = nullptr;
|
||||
m_advData.num_uuids128 = 0;
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids32 > 0) {
|
||||
free(m_advData.uuids32);
|
||||
free((void*)m_advData.uuids32);
|
||||
m_advData.uuids32 = nullptr;
|
||||
m_advData.num_uuids32 = 0;
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids16 > 0) {
|
||||
free(m_advData.uuids16);
|
||||
free((void*)m_advData.uuids16);
|
||||
m_advData.uuids16 = nullptr;
|
||||
m_advData.num_uuids16 = 0;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef MAIN_NIMBLEBEACON_H_
|
||||
#define MAIN_NIMBLEBEACON_H_
|
||||
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
#include "NimBLEUUID.h"
|
||||
/**
|
||||
* @brief Representation of a beacon.
|
||||
@ -48,4 +49,5 @@ public:
|
||||
void setSignalPower(int8_t signalPower);
|
||||
}; // NimBLEBeacon
|
||||
|
||||
#endif
|
||||
#endif /* MAIN_NIMBLEBEACON_H_ */
|
||||
|
@ -52,7 +52,6 @@ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t prop
|
||||
m_pService = pService;
|
||||
m_value = "";
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
m_pTaskData = nullptr;
|
||||
m_timestamp = 0;
|
||||
} // NimBLECharacteristic
|
||||
|
||||
@ -95,9 +94,20 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
|
||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||
}
|
||||
|
||||
m_dscVec.push_back(pDescriptor);
|
||||
addDescriptor(pDescriptor);
|
||||
|
||||
return pDescriptor;
|
||||
} // createCharacteristic
|
||||
} // createDescriptor
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a descriptor to the characteristic.
|
||||
* @param [in] A pointer to the descriptor to add.
|
||||
*/
|
||||
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) {
|
||||
pDescriptor->setCharacteristic(this);
|
||||
m_dscVec.push_back(pDescriptor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -165,6 +175,11 @@ NimBLEService* NimBLECharacteristic::getService() {
|
||||
} // getService
|
||||
|
||||
|
||||
void NimBLECharacteristic::setService(NimBLEService *pService) {
|
||||
m_pService = pService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID of the characteristic.
|
||||
* @return The UUID of the characteristic.
|
||||
@ -301,16 +316,13 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||
subVal |= NIMBLE_SUB_INDICATE;
|
||||
}
|
||||
|
||||
if(m_pTaskData != nullptr) {
|
||||
m_pTaskData->rc = (subVal & NIMBLE_SUB_INDICATE) ? 0 :
|
||||
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED;
|
||||
xTaskNotifyGive(m_pTaskData->task);
|
||||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
||||
event->subscribe.conn_handle, subVal);
|
||||
|
||||
if(!event->subscribe.cur_indicate && event->subscribe.prev_indicate) {
|
||||
NimBLEDevice::getServer()->clearIndicateWait(event->subscribe.conn_handle);
|
||||
}
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
||||
event->subscribe.conn_handle, subVal);
|
||||
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
|
||||
auto it = m_subscribedVec.begin();
|
||||
for(;it != m_subscribedVec.end(); ++it) {
|
||||
@ -322,16 +334,14 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||
if(subVal > 0) {
|
||||
if(it == m_subscribedVec.end()) {
|
||||
m_subscribedVec.push_back({event->subscribe.conn_handle, subVal});
|
||||
return;
|
||||
} else {
|
||||
(*it).second = subVal;
|
||||
}
|
||||
|
||||
(*it).second = subVal;
|
||||
|
||||
} else if(it != m_subscribedVec.end()) {
|
||||
m_subscribedVec.erase(it);
|
||||
m_subscribedVec.shrink_to_fit();
|
||||
}
|
||||
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
}
|
||||
|
||||
|
||||
@ -416,40 +426,20 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
||||
// We also must create it in each loop iteration because it is consumed with each host call.
|
||||
os_mbuf *om = ble_hs_mbuf_from_flat((uint8_t*)value.data(), length);
|
||||
|
||||
NimBLECharacteristicCallbacks::Status statusRC;
|
||||
|
||||
if(!is_notification && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
|
||||
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
||||
m_pTaskData = &taskData;
|
||||
if(!NimBLEDevice::getServer()->setIndicateWait(it.first)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "prior Indication in progress");
|
||||
os_mbuf_free_chain(om);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = ble_gattc_indicate_custom(it.first, m_handle, om);
|
||||
if(rc != 0){
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
} else {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
rc = m_pTaskData->rc;
|
||||
}
|
||||
|
||||
m_pTaskData = nullptr;
|
||||
|
||||
if(rc == BLE_HS_EDONE) {
|
||||
rc = 0;
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE;
|
||||
} else if(rc == BLE_HS_ETIMEOUT) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
NimBLEDevice::getServer()->clearIndicateWait(it.first);
|
||||
}
|
||||
} else {
|
||||
rc = ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
if(rc == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
}
|
||||
ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
}
|
||||
|
||||
m_pCallbacks->onStatus(this, statusRC, rc);
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify");
|
||||
@ -469,6 +459,13 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
/**
|
||||
* @brief Get the callback handlers for this characteristic.
|
||||
*/
|
||||
NimBLECharacteristicCallbacks* NimBLECharacteristic::getCallbacks() {
|
||||
return m_pCallbacks;
|
||||
} //getCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the value of the characteristic.
|
||||
@ -476,7 +473,7 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
|
||||
* @param [in] length The length of the data in bytes.
|
||||
*/
|
||||
void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && !defined(DONT_USE_ARDUINO_BULLSHIT) && CORE_DEBUG_LEVEL >= 4)
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
|
||||
free(pHex);
|
||||
|
@ -59,12 +59,26 @@ class NimBLECharacteristicCallbacks;
|
||||
*/
|
||||
class NimBLECharacteristic {
|
||||
public:
|
||||
NimBLECharacteristic(const char* uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
|
||||
~NimBLECharacteristic();
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
NimBLECharacteristicCallbacks*
|
||||
getCallbacks();
|
||||
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
@ -81,6 +95,7 @@ public:
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
|
||||
void addDescriptor(NimBLEDescriptor *pDescriptor);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
||||
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
|
||||
@ -115,30 +130,15 @@ public:
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NimBLEService* getService();
|
||||
uint16_t getProperties();
|
||||
|
||||
private:
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
|
||||
NimBLECharacteristic(const char* uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
|
||||
~NimBLECharacteristic();
|
||||
|
||||
NimBLEService* getService();
|
||||
uint16_t getProperties();
|
||||
void setService(NimBLEService *pService);
|
||||
void setSubscribe(struct ble_gap_event *event);
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
@ -150,7 +150,6 @@ private:
|
||||
NimBLEService* m_pService;
|
||||
std::string m_value;
|
||||
std::vector<NimBLEDescriptor*> m_dscVec;
|
||||
ble_task_data_t *m_pTaskData;
|
||||
portMUX_TYPE m_valMux;
|
||||
time_t m_timestamp;
|
||||
|
||||
|
@ -436,6 +436,24 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
} // updateConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get detailed information about the current peer connection.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEClient::getConnInfo() {
|
||||
NimBLEConnInfo connInfo;
|
||||
if (!isConnected()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Not connected");
|
||||
} else {
|
||||
int rc = ble_gap_conn_find(m_conn_id, &connInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||
}
|
||||
}
|
||||
|
||||
return connInfo;
|
||||
} // getConnInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the timeout to wait for connection attempt to complete.
|
||||
* @param [in] time The number of seconds before timeout.
|
||||
@ -1016,7 +1034,7 @@ uint16_t NimBLEClient::getMTU() {
|
||||
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
|
||||
|
||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp);
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %lu", event->passkey.params.numcmp);
|
||||
pkey.action = event->passkey.params.action;
|
||||
// Compatibility only - Do not use, should be removed the in future
|
||||
if(NimBLEDevice::m_securityCallbacks != nullptr) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "NimBLERemoteService.h"
|
||||
|
||||
@ -71,6 +72,7 @@ public:
|
||||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
void discoverAttributes();
|
||||
NimBLEConnInfo getConnInfo();
|
||||
|
||||
private:
|
||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||
|
55
src/NimBLEConnInfo.h
Normal file
55
src/NimBLEConnInfo.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef NIMBLECONNINFO_H_
|
||||
#define NIMBLECONNINFO_H_
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
|
||||
/**
|
||||
* @brief Connection information.
|
||||
*/
|
||||
class NimBLEConnInfo {
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEClient;
|
||||
ble_gap_conn_desc m_desc;
|
||||
NimBLEConnInfo() { m_desc = {}; }
|
||||
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
|
||||
public:
|
||||
/** @brief Gets the over-the-air address of the connected peer */
|
||||
NimBLEAddress getAddress() { return NimBLEAddress(m_desc.peer_ota_addr); }
|
||||
|
||||
/** @brief Gets the ID address of the connected peer */
|
||||
NimBLEAddress getIdAddress() { return NimBLEAddress(m_desc.peer_id_addr); }
|
||||
|
||||
/** @brief Gets the connection handle of the connected peer */
|
||||
uint16_t getConnHandle() { return m_desc.conn_handle; }
|
||||
|
||||
/** @brief Gets the connection interval for this connection (in 1.25ms units) */
|
||||
uint16_t getConnInterval() { return m_desc.conn_itvl; }
|
||||
|
||||
/** @brief Gets the supervision timeout for this connection (in 10ms units) */
|
||||
uint16_t getConnTimeout() { return m_desc.supervision_timeout; }
|
||||
|
||||
/** @brief Gets the allowable latency for this connection (unit = number of intervals) */
|
||||
uint16_t getConnLatency() { return m_desc.conn_latency; }
|
||||
|
||||
/** @brief Gets the maximum transmission unit size for this connection (in bytes) */
|
||||
uint16_t getMTU() { return ble_att_mtu(m_desc.conn_handle); }
|
||||
|
||||
/** @brief Check if we are in the master role in this connection */
|
||||
bool isMaster() { return (m_desc.role == BLE_GAP_ROLE_MASTER); }
|
||||
|
||||
/** @brief Check if we are in the slave role in this connection */
|
||||
bool isSlave() { return (m_desc.role == BLE_GAP_ROLE_SLAVE); }
|
||||
|
||||
/** @brief Check if we are connected to a bonded peer */
|
||||
bool isBonded() { return (m_desc.sec_state.bonded == 1); }
|
||||
|
||||
/** @brief Check if the connection in encrypted */
|
||||
bool isEncrypted() { return (m_desc.sec_state.encrypted == 1); }
|
||||
|
||||
/** @brief Check if the the connection has been authenticated */
|
||||
bool isAuthenticated() { return (m_desc.sec_state.authenticated == 1); }
|
||||
|
||||
/** @brief Gets the key size used to encrypt the connection */
|
||||
uint8_t getSecKeySize() { return m_desc.sec_state.key_size; }
|
||||
};
|
||||
#endif
|
@ -37,6 +37,7 @@ NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16
|
||||
: NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief NimBLEDescriptor constructor.
|
||||
*/
|
||||
@ -47,7 +48,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
|
||||
m_value.attr_len = 0; // Initial length is 0.
|
||||
m_value.attr_max_len = max_len; // Maximum length of the data.
|
||||
m_handle = NULL_HANDLE; // Handle is initially unknown.
|
||||
m_pCharacteristic = nullptr; // No initial characteristic.
|
||||
m_pCharacteristic = pCharacteristic;
|
||||
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
||||
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
@ -122,6 +123,7 @@ uint8_t* NimBLEDescriptor::getValue() {
|
||||
return m_value.attr_value;
|
||||
} // getValue
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the value of this descriptor as a string.
|
||||
* @return A std::string instance containing a copy of the descriptor's value.
|
||||
@ -130,9 +132,18 @@ std::string NimBLEDescriptor::getStringValue() {
|
||||
return std::string((char *) m_value.attr_value, m_value.attr_len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the characteristic this descriptor belongs to.
|
||||
* @return A pointer to the characteristic this descriptor belongs to.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() {
|
||||
return m_pCharacteristic;
|
||||
} // getCharacteristic
|
||||
|
||||
|
||||
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg) {
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
@ -169,7 +180,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
if((len + next->om_len) > pDescriptor->m_value.attr_max_len) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
memcpy(&buf[len-1], next->om_data, next->om_len);
|
||||
memcpy(&buf[len], next->om_data, next->om_len);
|
||||
len += next->om_len;
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
@ -237,6 +248,14 @@ void NimBLEDescriptor::setValue(const std::string &value) {
|
||||
setValue((uint8_t*) value.data(), value.length());
|
||||
} // setValue
|
||||
|
||||
/**
|
||||
* @brief Set the characteristic this descriptor belongs to.
|
||||
* @param [in] pChar A pointer to the characteristic this descriptior belongs to.
|
||||
*/
|
||||
void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) {
|
||||
m_pCharacteristic = pChar;
|
||||
} // setCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of the descriptor.
|
||||
|
@ -43,46 +43,48 @@ class NimBLEDescriptorCallbacks;
|
||||
*/
|
||||
class NimBLEDescriptor {
|
||||
public:
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||
|
||||
size_t getLength();
|
||||
uint8_t* getValue();
|
||||
std::string getStringValue();
|
||||
~NimBLEDescriptor();
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
|
||||
size_t getLength();
|
||||
uint8_t* getValue();
|
||||
std::string getStringValue();
|
||||
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
NimBLECharacteristic* getCharacteristic();
|
||||
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
/**
|
||||
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLE2902;
|
||||
friend class NimBLE2904;
|
||||
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
~NimBLEDescriptor();
|
||||
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
void setHandle(uint16_t handle);
|
||||
void setCharacteristic(NimBLECharacteristic* pChar);
|
||||
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_handle;
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#include "NimBLEDevice.h"
|
||||
@ -30,7 +30,7 @@
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
#include "esp32-hal-bt.h"
|
||||
#endif
|
||||
|
||||
@ -60,6 +60,7 @@ ble_gap_event_listener NimBLEDevice::m_listener;
|
||||
std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
||||
#endif
|
||||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||
std::vector<NimBLEAddress> NimBLEDevice::m_whiteList;
|
||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
||||
uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE;
|
||||
@ -448,6 +449,211 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
m_scanFilterMode = mode;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
/**
|
||||
* @brief Gets the number of bonded peers stored
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEDevice::getNumBonds() {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc !=0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return num_peers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes all bonding information.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::deleteAllBonds() {
|
||||
ble_store_clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes a peer bond.
|
||||
* @param [in] address The address of the peer with which to delete bond info.
|
||||
* @returns true on success.
|
||||
*/
|
||||
/*STATIC*/
|
||||
bool NimBLEDevice::deleteBond(const NimBLEAddress &address) {
|
||||
ble_addr_t delAddr;
|
||||
memcpy(&delAddr.val, address.getNative(),6);
|
||||
delAddr.type = address.getType();
|
||||
|
||||
int rc = ble_gap_unpair(&delAddr);
|
||||
if (rc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a peer device is bonded.
|
||||
* @param [in] address The address to check for bonding.
|
||||
* @returns true if bonded.
|
||||
*/
|
||||
/*STATIC*/
|
||||
bool NimBLEDevice::isBonded(const NimBLEAddress &address) {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_peers; i++) {
|
||||
NimBLEAddress storedAddr(peer_id_addrs[i]);
|
||||
if(storedAddr == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the address of a bonded peer device by index.
|
||||
* @param [in] index The index to retrieve the peer address of.
|
||||
* @returns NimBLEAddress of the found bonded peer or nullptr if not found.
|
||||
*/
|
||||
/*STATIC*/
|
||||
NimBLEAddress NimBLEDevice::getBondedAddress(int index) {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (index > num_peers || index < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return NimBLEAddress(peer_id_addrs[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks if a peer device is whitelisted.
|
||||
* @param [in] address The address to check for in the whitelist.
|
||||
* @returns true if the address is in the whitelist.
|
||||
*/
|
||||
bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) {
|
||||
for (auto &it : m_whiteList) {
|
||||
if (it == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a peer address to the whitelist.
|
||||
* @param [in] address The address to add to the whitelist.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) {
|
||||
if (NimBLEDevice::onWhiteList(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_whiteList.push_back(address);
|
||||
std::vector<ble_addr_t> wlVec;
|
||||
wlVec.reserve(m_whiteList.size());
|
||||
|
||||
for (auto &it : m_whiteList) {
|
||||
ble_addr_t wlAddr;
|
||||
memcpy(&wlAddr.val, it.getNative(), 6);
|
||||
wlAddr.type = it.getType();
|
||||
wlVec.push_back(wlAddr);
|
||||
}
|
||||
|
||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a peer address from the whitelist.
|
||||
* @param [in] address The address to remove from the whitelist.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) {
|
||||
if (!NimBLEDevice::onWhiteList(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<ble_addr_t> wlVec;
|
||||
wlVec.reserve(m_whiteList.size());
|
||||
|
||||
for (auto &it : m_whiteList) {
|
||||
if (it != address) {
|
||||
ble_addr_t wlAddr;
|
||||
memcpy(&wlAddr.val, it.getNative(), 6);
|
||||
wlAddr.type = it.getType();
|
||||
wlVec.push_back(wlAddr);
|
||||
}
|
||||
}
|
||||
|
||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't remove from the list unless NimBLE returned success
|
||||
for (auto it = m_whiteList.begin(); it < m_whiteList.end(); ++it) {
|
||||
if ((*it) == address) {
|
||||
m_whiteList.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the count of addresses in the whitelist.
|
||||
* @returns The number of addresses in the whitelist.
|
||||
*/
|
||||
size_t NimBLEDevice::getWhiteListCount() {
|
||||
return m_whiteList.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the address at the vector index.
|
||||
* @param [in] index The vector index to retrieve the address from.
|
||||
* @returns the NimBLEAddress at the whitelist index or nullptr if not found.
|
||||
*/
|
||||
NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
|
||||
if (index > m_whiteList.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index);
|
||||
return nullptr;
|
||||
}
|
||||
return m_whiteList[index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Host reset, we pass the message so we don't make calls until resynced.
|
||||
@ -534,7 +740,7 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
int rc=0;
|
||||
esp_err_t errRc = ESP_OK;
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
// make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
|
||||
btStarted();
|
||||
#endif
|
||||
@ -577,6 +783,8 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
|
||||
// Set the device name.
|
||||
rc = ble_svc_gap_device_name_set(deviceName.c_str());
|
||||
if (rc != 0)
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_svc_gap_device_name_set() failed %i name_size=%zd", rc, deviceName.size());
|
||||
assert(rc == 0);
|
||||
|
||||
ble_store_config_init();
|
||||
@ -602,10 +810,12 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
if (ret == 0) {
|
||||
nimble_port_deinit();
|
||||
|
||||
#if 0
|
||||
ret = esp_nimble_hci_and_controller_deinit();
|
||||
if (ret != ESP_OK) {
|
||||
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
initialized = false;
|
||||
m_synced = false;
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef MAIN_NIMBLEDEVICE_H_
|
||||
#define MAIN_NIMBLEDEVICE_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
|
||||
@ -95,6 +95,11 @@ public:
|
||||
static bool getInitialized();
|
||||
static NimBLEAddress getAddress();
|
||||
static std::string toString();
|
||||
static bool whiteListAdd(const NimBLEAddress & address);
|
||||
static bool whiteListRemove(const NimBLEAddress & address);
|
||||
static bool onWhiteList(const NimBLEAddress & address);
|
||||
static size_t getWhiteListCount();
|
||||
static NimBLEAddress getWhiteListAddress(size_t index);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
static NimBLEScan* getScan();
|
||||
@ -142,6 +147,14 @@ public:
|
||||
static std::list<NimBLEClient*>* getClientList();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
static bool deleteBond(const NimBLEAddress &address);
|
||||
static int getNumBonds();
|
||||
static bool isBonded(const NimBLEAddress &address);
|
||||
static void deleteAllBonds();
|
||||
static NimBLEAddress getBondedAddress(int index);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
friend class NimBLEClient;
|
||||
@ -188,6 +201,7 @@ private:
|
||||
static uint8_t m_own_addr_type;
|
||||
static uint16_t m_scanDuplicateSize;
|
||||
static uint8_t m_scanFilterMode;
|
||||
static std::vector<NimBLEAddress> m_whiteList;
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: pcbreflux
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEEddystoneTLM.h"
|
||||
#include "NimBLELog.h"
|
||||
@ -124,30 +124,30 @@ std::string NimBLEEddystoneTLM::toString() {
|
||||
out += " C\n";
|
||||
|
||||
out += "Adv. Count ";
|
||||
snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
|
||||
snprintf(val, sizeof(val), "%lu", ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
out += "Time in seconds ";
|
||||
snprintf(val, sizeof(val), "%d", rawsec/10);
|
||||
snprintf(val, sizeof(val), "%lu", rawsec/10);
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
out += "Time ";
|
||||
|
||||
snprintf(val, sizeof(val), "%04d", rawsec / 864000);
|
||||
snprintf(val, sizeof(val), "%04lu", rawsec / 864000);
|
||||
out += val;
|
||||
out += ".";
|
||||
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 36000) % 24);
|
||||
snprintf(val, sizeof(val), "%02lu", (rawsec / 36000) % 24);
|
||||
out += val;
|
||||
out += ":";
|
||||
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 600) % 60);
|
||||
snprintf(val, sizeof(val), "%02lu", (rawsec / 600) % 60);
|
||||
out += val;
|
||||
out += ":";
|
||||
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 10) % 60);
|
||||
snprintf(val, sizeof(val), "%02lu", (rawsec / 10) % 60);
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#ifndef _NimBLEEddystoneTLM_H_
|
||||
#define _NimBLEEddystoneTLM_H_
|
||||
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
#include "NimBLEUUID.h"
|
||||
|
||||
#include <string>
|
||||
@ -57,4 +59,5 @@ private:
|
||||
|
||||
}; // NimBLEEddystoneTLM
|
||||
|
||||
#endif
|
||||
#endif /* _NimBLEEddystoneTLM_H_ */
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: pcbreflux
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEEddystoneURL.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#ifndef _NIMBLEEddystoneURL_H_
|
||||
#define _NIMBLEEddystoneURL_H_
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
#include "NimBLEUUID.h"
|
||||
|
||||
#include <string>
|
||||
@ -49,4 +50,5 @@ private:
|
||||
|
||||
}; // NIMBLEEddystoneURL
|
||||
|
||||
#endif
|
||||
#endif /* _NIMBLEEddystoneURL_H_ */
|
||||
|
@ -7,17 +7,17 @@
|
||||
*/
|
||||
#ifndef MAIN_NIMBLELOG_H_
|
||||
#define MAIN_NIMBLELOG_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "modlog/modlog.h"
|
||||
|
||||
|
||||
// If Arduino is being used, strip out the colors and ignore log printing below ui setting.
|
||||
// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR
|
||||
// otherwise no messages will be printed above that level.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#ifndef CORE_DEBUG_LEVEL
|
||||
#define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
||||
#endif
|
||||
@ -49,12 +49,15 @@
|
||||
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "\033[0;31mE %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(WARN, "\033[0;33mW %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(INFO, "\033[0;32mI %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(DEBUG, "D %s: "#format"\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "\033[1;31mCRIT %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#define NIMBLE_LOGE(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGW(tag, format, ...) ESP_LOGW(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGI(tag, format, ...) ESP_LOGI(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGC(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
|
||||
#endif /*ARDUINO_ARCH_ESP32*/
|
||||
|
||||
#endif /*CONFIG_BT_ENABLED*/
|
||||
#endif /*MAIN_NIMBLELOG_H_*/
|
@ -55,6 +55,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||
|
||||
m_handle = chr->val_handle;
|
||||
m_defHandle = chr->def_handle;
|
||||
m_endHandle = 0;
|
||||
m_charProp = chr->properties;
|
||||
m_pRemoteService = pRemoteService;
|
||||
m_notifyCallback = nullptr;
|
||||
@ -146,31 +147,25 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_dsc *dsc,
|
||||
void *arg)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
||||
error->status, (error->status == 0) ? dsc->handle : -1);
|
||||
int rc = error->status;
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovered >> status: %d handle: %d",
|
||||
rc, (rc == 0) ? dsc->handle : -1);
|
||||
|
||||
desc_filter_t *filter = (desc_filter_t*)arg;
|
||||
const NimBLEUUID *uuid_filter = filter->uuid;
|
||||
ble_task_data_t *pTaskData = (ble_task_data_t*)filter->task_data;
|
||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||
int rc=0;
|
||||
|
||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
if (characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (error->status) {
|
||||
switch (rc) {
|
||||
case 0: {
|
||||
if(dsc->uuid.u.type == BLE_UUID_TYPE_16 && dsc->uuid.u16.value == uint16_t(0x2803)) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor NOT found - end of Characteristic definintion");
|
||||
rc = BLE_HS_EDONE;
|
||||
break;
|
||||
}
|
||||
if(uuid_filter != nullptr) {
|
||||
if(ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
if (uuid_filter != nullptr) {
|
||||
if (ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Found");
|
||||
rc = BLE_HS_EDONE;
|
||||
}
|
||||
}
|
||||
@ -180,11 +175,10 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
/** If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||
/* If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||
* Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE.
|
||||
* If we get any other error code tell the application to abort by returning non-zero in the rc.
|
||||
*/
|
||||
@ -202,6 +196,38 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief callback from NimBLE when the next characteristic of the service is discovered.
|
||||
*/
|
||||
int NimBLERemoteCharacteristic::nextCharCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg)
|
||||
{
|
||||
int rc = error->status;
|
||||
NIMBLE_LOGD(LOG_TAG, "Next Characteristic >> status: %d handle: %d",
|
||||
rc, (rc == 0) ? chr->val_handle : -1);
|
||||
|
||||
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||
NimBLERemoteCharacteristic *pChar = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||
|
||||
if (pChar->getRemoteService()->getClient()->getConnId() != conn_handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
pChar->m_endHandle = chr->def_handle - 1;
|
||||
rc = BLE_HS_EDONE;
|
||||
} else if (rc == BLE_HS_EDONE) {
|
||||
pChar->m_endHandle = pChar->getRemoteService()->getEndHandle();
|
||||
} else {
|
||||
pTaskData->rc = rc;
|
||||
}
|
||||
|
||||
xTaskNotifyGive(pTaskData->task);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Populate the descriptors (if any) for this characteristic.
|
||||
* @param [in] the end handle of the characteristic, or the service, whichever comes first.
|
||||
@ -209,35 +235,57 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filter) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
||||
|
||||
uint16_t endHandle = getRemoteService()->getEndHandle(this);
|
||||
if(m_handle >= endHandle) {
|
||||
return false;
|
||||
// If this is the last handle then there are no descriptors
|
||||
if (m_handle == getRemoteService()->getEndHandle()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||
|
||||
// If we don't know the end handle of this characteristic retrieve the next one in the service
|
||||
// The end handle is the next characteristic definition handle -1.
|
||||
if (m_endHandle == 0) {
|
||||
rc = ble_gattc_disc_all_chrs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
getRemoteService()->getEndHandle(),
|
||||
NimBLERemoteCharacteristic::nextCharCB,
|
||||
&taskData);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error getting end handle rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if (taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Could not retrieve end handle rc=%d", taskData.rc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc_filter_t filter = {uuid_filter, &taskData};
|
||||
|
||||
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
endHandle,
|
||||
m_endHandle,
|
||||
NimBLERemoteCharacteristic::descriptorDiscCB,
|
||||
&filter);
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if(taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: startHandle:%d endHandle:%d taskData.rc=%d %s", m_handle, endHandle, taskData.rc, NimBLEUtils::returnCodeToString(0x0100+taskData.rc));
|
||||
return false;
|
||||
if (taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to retrieve descriptors; startHandle:%d endHandle:%d taskData.rc=%d",
|
||||
m_handle, m_endHandle, taskData.rc);
|
||||
}
|
||||
|
||||
return true;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size());
|
||||
return (taskData.rc == 0);
|
||||
} // retrieveDescriptors
|
||||
|
||||
|
||||
@ -664,7 +712,7 @@ std::string NimBLERemoteCharacteristic::toString() {
|
||||
* @return false if not connected or cant perform write for some reason.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) {
|
||||
return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
|
||||
return writeValue((uint8_t*)newValue.c_str(), newValue.length(), response);
|
||||
} // writeValue
|
||||
|
||||
|
||||
|
@ -148,12 +148,15 @@ private:
|
||||
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
||||
void *arg);
|
||||
static int nextCharCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg);
|
||||
|
||||
// Private properties
|
||||
NimBLEUUID m_uuid;
|
||||
uint8_t m_charProp;
|
||||
uint16_t m_handle;
|
||||
uint16_t m_defHandle;
|
||||
uint16_t m_endHandle;
|
||||
NimBLERemoteService* m_pRemoteService;
|
||||
std::string m_value;
|
||||
notify_callback m_notifyCallback;
|
||||
|
@ -223,6 +223,20 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if(taskData.rc == 0){
|
||||
if (uuid_filter == nullptr) {
|
||||
if (m_characteristicVector.size() > 1) {
|
||||
for (auto it = m_characteristicVector.begin(); it != m_characteristicVector.end(); ++it ) {
|
||||
auto nx = std::next(it, 1);
|
||||
if (nx == m_characteristicVector.end()) {
|
||||
break;
|
||||
}
|
||||
(*it)->m_endHandle = (*nx)->m_defHandle - 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||
return true;
|
||||
}
|
||||
@ -249,23 +263,6 @@ uint16_t NimBLERemoteService::getEndHandle() {
|
||||
return m_endHandle;
|
||||
} // getEndHandle
|
||||
|
||||
/**
|
||||
* @brief Get the end handle of specified NimBLERemoteCharacteristic.
|
||||
*/
|
||||
|
||||
uint16_t NimBLERemoteService::getEndHandle(NimBLERemoteCharacteristic *pCharacteristic) {
|
||||
uint16_t endHandle = m_endHandle;
|
||||
|
||||
for(auto &it: m_characteristicVector) {
|
||||
uint16_t defHandle = it->getDefHandle() - 1;
|
||||
if(defHandle > pCharacteristic->getDefHandle() && endHandle > defHandle) {
|
||||
endHandle = defHandle;
|
||||
}
|
||||
}
|
||||
|
||||
return endHandle;
|
||||
} // getEndHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service start handle.
|
||||
|
@ -70,7 +70,6 @@ private:
|
||||
|
||||
uint16_t getStartHandle();
|
||||
uint16_t getEndHandle();
|
||||
uint16_t getEndHandle(NimBLERemoteCharacteristic *pCharacteristic);
|
||||
void releaseSemaphores();
|
||||
|
||||
// Properties
|
||||
|
@ -284,7 +284,7 @@ bool NimBLEScan::isScanning() {
|
||||
* @return True if scan started or false if there was an error.
|
||||
*/
|
||||
bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(duration=%d)", duration);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(duration=%lu)", duration);
|
||||
|
||||
// Save the callback to be invoked when the scan completes.
|
||||
m_scanCompleteCB = scanCompleteCB;
|
||||
@ -316,6 +316,8 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
// Clear the cache if already scanning in case an advertiser was missed.
|
||||
clearDuplicateCache();
|
||||
break;
|
||||
|
||||
case BLE_HS_EBUSY:
|
||||
@ -398,6 +400,14 @@ bool NimBLEScan::stop() {
|
||||
} // stop
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clears the duplicate scan filter cache.
|
||||
*/
|
||||
void NimBLEScan::clearDuplicateCache() {
|
||||
esp_ble_scan_dupilcate_list_flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Delete peer device from the scan results vector.
|
||||
* @param [in] address The address of the device to delete from the results.
|
||||
@ -453,6 +463,7 @@ void NimBLEScan::clearResults() {
|
||||
delete it;
|
||||
}
|
||||
m_scanResults.m_advertisedDevicesVector.clear();
|
||||
clearDuplicateCache();
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
void setDuplicateFilter(bool enabled);
|
||||
void setLimitedOnly(bool enabled);
|
||||
void setFilterPolicy(uint8_t filter);
|
||||
void clearDuplicateCache();
|
||||
bool stop();
|
||||
void clearResults();
|
||||
NimBLEScanResults getResults();
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef COMPONENTS_NIMBLESECURITY_H_
|
||||
#define COMPONENTS_NIMBLESECURITY_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
|
@ -37,6 +37,7 @@ static NimBLEServerCallbacks defaultCallbacks;
|
||||
* the NimBLEDevice class.
|
||||
*/
|
||||
NimBLEServer::NimBLEServer() {
|
||||
memset(m_indWait, BLE_HS_CONN_HANDLE_NONE, sizeof(m_indWait));
|
||||
// m_svcChgChrHdl = 0xffff; // Future Use
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
@ -173,7 +174,7 @@ void NimBLEServer::start() {
|
||||
abort();
|
||||
}
|
||||
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && !defined(DONT_USE_ARDUINO_BULLSHIT) && CORE_DEBUG_LEVEL >= 4)
|
||||
ble_gatts_show_local();
|
||||
#endif
|
||||
/*** Future use ***
|
||||
@ -253,6 +254,63 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
} // getConnectedCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the vector of the connected client ID's.
|
||||
*/
|
||||
std::vector<uint16_t> NimBLEServer::getPeerDevices() {
|
||||
return m_connectedPeersVec;
|
||||
} // getPeerDevices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by vector index.
|
||||
* @param [in] index The vector index of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(size_t index) {
|
||||
if (index >= m_connectedPeersVec.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "No peer at index %u", index);
|
||||
return NimBLEConnInfo();
|
||||
}
|
||||
|
||||
return getPeerIDInfo(m_connectedPeersVec[index]);
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by address.
|
||||
* @param [in] address The address of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) {
|
||||
ble_addr_t peerAddr;
|
||||
memcpy(&peerAddr.val, address.getNative(),6);
|
||||
peerAddr.type = address.getType();
|
||||
|
||||
NimBLEConnInfo peerInfo;
|
||||
int rc = ble_gap_conn_find_by_addr(&peerAddr, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by connection ID.
|
||||
* @param [in] id The connection id of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
NimBLEConnInfo peerInfo;
|
||||
|
||||
int rc = ble_gap_conn_find(id, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerIDInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle a GATT Server Event.
|
||||
*
|
||||
@ -280,7 +338,9 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->m_pServerCallbacks->onConnect(server);
|
||||
server->m_pServerCallbacks->onConnect(server, &desc);
|
||||
@ -335,7 +395,9 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
(it->getProperties() & BLE_GATT_CHR_F_READ_ENC))
|
||||
{
|
||||
rc = ble_gap_conn_find(event->subscribe.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!desc.sec_state.encrypted) {
|
||||
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
|
||||
@ -358,18 +420,44 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
} // BLE_GAP_EVENT_MTU
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_TX: {
|
||||
if(event->notify_tx.indication && event->notify_tx.status != 0) {
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
if(it->m_pTaskData != nullptr) {
|
||||
it->m_pTaskData->rc = event->notify_tx.status;
|
||||
xTaskNotifyGive(it->m_pTaskData->task);
|
||||
}
|
||||
break;
|
||||
}
|
||||
NimBLECharacteristic *pChar = nullptr;
|
||||
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
pChar = it;
|
||||
}
|
||||
}
|
||||
|
||||
if(pChar == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLECharacteristicCallbacks::Status statusRC;
|
||||
|
||||
if(event->notify_tx.indication) {
|
||||
if(event->notify_tx.status != 0) {
|
||||
if(event->notify_tx.status == BLE_HS_EDONE) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE;
|
||||
} else if(rc == BLE_HS_ETIMEOUT) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->clearIndicateWait(event->notify_tx.conn_handle);
|
||||
} else {
|
||||
if(event->notify_tx.status == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
}
|
||||
}
|
||||
|
||||
pChar->m_pCallbacks->onStatus(pChar, statusRC, event->notify_tx.status);
|
||||
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
@ -392,7 +480,10 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
|
||||
/* Delete the old bond. */
|
||||
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0){
|
||||
return BLE_GAP_REPEAT_PAIRING_IGNORE;
|
||||
}
|
||||
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
|
||||
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
|
||||
@ -433,7 +524,7 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
|
||||
|
||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp);
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %lu", event->passkey.params.numcmp);
|
||||
pkey.action = event->passkey.params.action;
|
||||
// Compatibility only - Do not use, should be removed the in future
|
||||
if(NimBLEDevice::m_securityCallbacks != nullptr) {
|
||||
@ -559,14 +650,23 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds a service which was already created, but removed from availability.
|
||||
* @brief Adds a service which was either already created but removed from availability,\n
|
||||
* or created and later added to services list.
|
||||
* @param [in] service The service object to add.
|
||||
* @note If it is desired to advertise the service it must be added by
|
||||
* calling NimBLEAdvertising::addServiceUUID.
|
||||
*/
|
||||
void NimBLEServer::addService(NimBLEService* service) {
|
||||
// If adding a service that was not removed just return.
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if(getServiceByUUID(service->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s",
|
||||
std::string(service->getUUID()).c_str());
|
||||
}
|
||||
|
||||
// If adding a service that was not removed add it and return.
|
||||
// Else reset GATT and send service changed notification.
|
||||
if(service->m_removed == 0) {
|
||||
m_svcVec.push_back(service);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -668,6 +768,27 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
||||
}// updateConnParams
|
||||
|
||||
|
||||
bool NimBLEServer::setIndicateWait(uint16_t conn_handle) {
|
||||
for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void NimBLEServer::clearIndicateWait(uint16_t conn_handle) {
|
||||
for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
m_indWait[i] = BLE_HS_CONN_HANDLE_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Default callback handlers */
|
||||
|
||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "NimBLEAdvertising.h"
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
|
||||
|
||||
class NimBLEService;
|
||||
@ -58,7 +59,10 @@ public:
|
||||
uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
uint16_t getPeerMTU(uint16_t conn_id);
|
||||
// std::vector<uint16_t> getPeerDevices();
|
||||
std::vector<uint16_t> getPeerDevices();
|
||||
NimBLEConnInfo getPeerInfo(size_t index);
|
||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||
void advertiseOnDisconnect(bool);
|
||||
|
||||
private:
|
||||
@ -73,6 +77,7 @@ private:
|
||||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
bool m_deleteCallbacks;
|
||||
uint16_t m_indWait[CONFIG_BT_NIMBLE_MAX_CONNECTIONS];
|
||||
std::vector<uint16_t> m_connectedPeersVec;
|
||||
|
||||
// uint16_t m_svcChgChrHdl; // Future use
|
||||
@ -82,6 +87,8 @@ private:
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
void resetGATT();
|
||||
bool setIndicateWait(uint16_t conn_handle);
|
||||
void clearIndicateWait(uint16_t conn_handle);
|
||||
}; // NimBLEServer
|
||||
|
||||
|
||||
|
@ -246,6 +246,11 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
|
||||
} // createCharacteristic
|
||||
|
||||
|
||||
void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
|
||||
pCharacteristic->setService(this);
|
||||
m_chrVec.push_back(pCharacteristic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
|
@ -36,6 +36,10 @@ class NimBLECharacteristic;
|
||||
class NimBLEService {
|
||||
public:
|
||||
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
NimBLEServer* getServer();
|
||||
|
||||
NimBLEUUID getUUID();
|
||||
@ -55,6 +59,7 @@ public:
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
|
||||
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
|
||||
@ -65,9 +70,6 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEDevice;
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEUUID.h"
|
||||
@ -277,10 +277,6 @@ std::string NimBLEUUID::toString() const {
|
||||
*/
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Comparing UUIDs; type %u to %u; UUID %s to %s",
|
||||
m_uuid.u.type, rhs.m_uuid.u.type,
|
||||
this->toString().c_str(), rhs.toString().c_str());
|
||||
|
||||
if(m_uuid.u.type != rhs.m_uuid.u.type) {
|
||||
uint8_t uuidBase[16] = {
|
||||
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef COMPONENTS_NIMBLEUUID_H_
|
||||
#define COMPONENTS_NIMBLEUUID_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "host/ble_uuid.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef COMPONENTS_NIMBLEUTILS_H_
|
||||
#define COMPONENTS_NIMBLEUTILS_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
|
||||
|
Reference in New Issue
Block a user