Refactor NimBLEAdvertisementData/NimBLEExtAdvertising

* NimBLEUtils added method to get UUID type from size.
* NimBLEUUID added method to get location within payload.
* NimBLEUUID added method as wrapper for NimBLEUtils::getType().
This commit is contained in:
thekurtovic 2024-12-21 18:05:13 -05:00
parent 015217c764
commit 1d504bf6ff
6 changed files with 83 additions and 127 deletions

View file

@ -146,20 +146,10 @@ bool NimBLEAdvertisementData::setPreferredParams(uint16_t minInterval, uint16_t
* @param [in] serviceUUID The UUID of the service to expose. * @param [in] serviceUUID The UUID of the service to expose.
*/ */
bool NimBLEAdvertisementData::addServiceUUID(const NimBLEUUID& serviceUUID) { bool NimBLEAdvertisementData::addServiceUUID(const NimBLEUUID& serviceUUID) {
uint8_t bytes = serviceUUID.bitSize() / 8; uint8_t bytes = serviceUUID.bitSize() >> 3;
int type; uint8_t type = serviceUUID.getType();
switch (bytes) { if (type == 0) {
case 2: return false;
type = BLE_HS_ADV_TYPE_COMP_UUIDS16;
break;
case 4:
type = BLE_HS_ADV_TYPE_COMP_UUIDS32;
break;
case 16:
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
break;
default:
return false;
} }
int dataLoc = getDataLocation(type); int dataLoc = getDataLocation(type);
@ -201,20 +191,10 @@ bool NimBLEAdvertisementData::addServiceUUID(const char* serviceUUID) {
* @return True if successful or uuid not found, false if uuid error or data could not be reset. * @return True if successful or uuid not found, false if uuid error or data could not be reset.
*/ */
bool NimBLEAdvertisementData::removeServiceUUID(const NimBLEUUID& serviceUUID) { bool NimBLEAdvertisementData::removeServiceUUID(const NimBLEUUID& serviceUUID) {
uint8_t bytes = serviceUUID.bitSize() / 8; uint8_t bytes = serviceUUID.bitSize() >> 3;
int type; uint8_t type = serviceUUID.getType();
switch (bytes) { if (type == 0) {
case 2: return false;
type = BLE_HS_ADV_TYPE_COMP_UUIDS16;
break;
case 4:
type = BLE_HS_ADV_TYPE_COMP_UUIDS32;
break;
case 16:
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
break;
default:
return false;
} }
int dataLoc = getDataLocation(type); int dataLoc = getDataLocation(type);
@ -222,14 +202,7 @@ bool NimBLEAdvertisementData::removeServiceUUID(const NimBLEUUID& serviceUUID) {
return true; return true;
} }
int uuidLoc = -1; int uuidLoc = serviceUUID.getLoc(dataLoc, m_payload);
for (size_t i = dataLoc + 2; i < m_payload.size(); i += bytes) {
if (memcmp(&m_payload[i], serviceUUID.getValue(), bytes) == 0) {
uuidLoc = i;
break;
}
}
if (uuidLoc == -1) { if (uuidLoc == -1) {
return true; return true;
} }
@ -409,7 +382,7 @@ bool NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>
* @details The number of services will be truncated if the total length exceeds 31 bytes. * @details The number of services will be truncated if the total length exceeds 31 bytes.
*/ */
bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std::vector<NimBLEUUID>& uuids) { bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std::vector<NimBLEUUID>& uuids) {
uint8_t bytes = size / 8; uint8_t bytes = size >> 3;
uint8_t length = 2; // start with 2 for length + type bytes uint8_t length = 2; // start with 2 for length + type bytes
uint8_t data[31]; uint8_t data[31];
@ -429,19 +402,9 @@ bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std
} }
data[0] = length - 1; // don't count the length byte as part of the AD length data[0] = length - 1; // don't count the length byte as part of the AD length
data[1] = NimBLEUtils::getUUIDType(size, complete);
switch (size) { if (data[1] == 0) {
case 16: return false;
data[1] = (complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
break;
case 32:
data[1] = (complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
break;
case 128:
data[1] = (complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128);
break;
default:
return false;
} }
return addData(data, length); return addData(data, length);
@ -456,26 +419,16 @@ bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std
* @return True if successful, false if data length is too long or could not be set. * @return True if successful, false if data length is too long or could not be set.
*/ */
bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) { bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
uint8_t uuidBytes = uuid.bitSize() / 8; uint8_t uuidBytes = uuid.bitSize() >> 3;
uint8_t sDataLen = 2 + uuidBytes + length; uint8_t sDataLen = 2 + uuidBytes + length;
if (sDataLen > 31) { if (sDataLen > 31) {
NIMBLE_LOGE(LOG_TAG, "Service Data too long"); NIMBLE_LOGE(LOG_TAG, "Service Data too long");
return false; return false;
} }
uint8_t type; uint8_t type = uuid.getType();
switch (uuidBytes) { if (type == 0) {
case 2: return false;
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID16;
break;
case 4:
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID32;
break;
case 16:
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128;
break;
default:
return false;
} }
if (length == 0) { if (length == 0) {

View file

@ -688,20 +688,10 @@ bool NimBLEExtAdvertisement::setName(const std::string& name, bool isComplete) {
* @param [in] serviceUUID The UUID of the service to expose. * @param [in] serviceUUID The UUID of the service to expose.
*/ */
bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) { bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
uint8_t bytes = serviceUUID.bitSize() / 8; uint8_t bytes = serviceUUID.bitSize() >> 3;
int type; uint8_t type = serviceUUID.getType();
switch (bytes) { if (type == 0) {
case 2: return false;
type = BLE_HS_ADV_TYPE_COMP_UUIDS16;
break;
case 4:
type = BLE_HS_ADV_TYPE_COMP_UUIDS32;
break;
case 16:
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
break;
default:
return false;
} }
int dataLoc = getDataLocation(type); int dataLoc = getDataLocation(type);
@ -743,20 +733,10 @@ bool NimBLEExtAdvertisement::addServiceUUID(const char* serviceUUID) {
* @return True if successful or uuid not found, false if uuid error or data could not be reset. * @return True if successful or uuid not found, false if uuid error or data could not be reset.
*/ */
bool NimBLEExtAdvertisement::removeServiceUUID(const NimBLEUUID& serviceUUID) { bool NimBLEExtAdvertisement::removeServiceUUID(const NimBLEUUID& serviceUUID) {
uint8_t bytes = serviceUUID.bitSize() / 8; uint8_t bytes = serviceUUID.bitSize() >> 3;
int type; uint8_t type = serviceUUID.getType();
switch (bytes) { if (type == 0) {
case 2: return false;
type = BLE_HS_ADV_TYPE_COMP_UUIDS16;
break;
case 4:
type = BLE_HS_ADV_TYPE_COMP_UUIDS32;
break;
case 16:
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
break;
default:
return false;
} }
int dataLoc = getDataLocation(type); int dataLoc = getDataLocation(type);
@ -764,14 +744,7 @@ bool NimBLEExtAdvertisement::removeServiceUUID(const NimBLEUUID& serviceUUID) {
return true; return true;
} }
int uuidLoc = -1; int uuidLoc = serviceUUID.getLoc(dataLoc, m_payload);
for (size_t i = dataLoc + 2; i < m_payload.size(); i += bytes) {
if (memcmp(&m_payload[i], serviceUUID.getValue(), bytes) == 0) {
uuidLoc = i;
break;
}
}
if (uuidLoc == -1) { if (uuidLoc == -1) {
return true; return true;
} }
@ -866,19 +839,9 @@ bool NimBLEExtAdvertisement::setServices(bool complete, uint8_t size, const std:
uint8_t header[2]; uint8_t header[2];
uint8_t uuidBytes = size / 8; uint8_t uuidBytes = size / 8;
header[0] = uuidBytes * uuids.size() + 1; header[0] = uuidBytes * uuids.size() + 1;
header[1] = NimBLEUtils::getUUIDType(size, complete);
switch (size) { if (header[1] == 0) {
case 16: return false;
header[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
break;
case 32:
header[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
break;
case 128:
header[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
break;
default:
return false;
} }
if (addData(header, 2)) { if (addData(header, 2)) {
@ -913,26 +876,16 @@ bool NimBLEExtAdvertisement::setServices(bool complete, uint8_t size, const std:
* @return True if successful, false if data length is too long or could not be set. * @return True if successful, false if data length is too long or could not be set.
*/ */
bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) { bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
uint8_t uuidBytes = uuid.bitSize() / 8; uint8_t uuidBytes = uuid.bitSize() >> 3;
uint8_t sDataLen = 2 + uuidBytes + length; uint8_t sDataLen = 2 + uuidBytes + length;
if (m_payload.size() + sDataLen > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) { if (m_payload.size() + sDataLen > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
return false; return false;
} }
uint8_t type; uint8_t type = uuid.getType();
switch (uuidBytes) { if (type == 0) {
case 2: return false;
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID16;
break;
case 4:
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID32;
break;
case 16:
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128;
break;
default:
return false;
} }
if (length == 0) { if (length == 0) {

View file

@ -172,6 +172,32 @@ const ble_uuid_t* NimBLEUUID::getBase() const {
return &this->m_uuid.u; return &this->m_uuid.u;
} // getBase } // getBase
/**
* @brief Get the UUID type based on size in bits.
* @return BLE_HS_ADV_TYPE_COMP_UUIDS16/32/128 or BLE_HS_ADV_TYPE_INCOMP_UUIDS16/32/128
* for valid input size, else 0.
*/
uint8_t NimBLEUUID::getType() const {
return NimBLEUtils::getUUIDType(bitSize(), true);
} // getType
/**
* @brief Get the location of the UUID within a payload.
* @param [in] dataLoc The data location.
* @param [in] payload The payload to search through.
* @return >= 0 if found, else -1.
*/
int NimBLEUUID::getLoc(int dataLoc, const std::vector<uint8_t> payload) const {
uint8_t bytes = bitSize() >> 3;
const size_t size = payload.size();
for (size_t i = dataLoc + 2; i < size; i += bytes) {
if (memcmp(&payload[i], getValue(), bytes) == 0) {
return i;
}
}
return -1;
} // getLoc
/** /**
* @brief Compare a UUID against this UUID. * @brief Compare a UUID against this UUID.
* *

View file

@ -34,6 +34,7 @@
# include <string> # include <string>
# include <cstring> # include <cstring>
# include <vector>
/** /**
* @brief A model of a %BLE UUID. * @brief A model of a %BLE UUID.
@ -55,6 +56,8 @@ class NimBLEUUID {
uint8_t bitSize() const; uint8_t bitSize() const;
const uint8_t* getValue() const; const uint8_t* getValue() const;
const ble_uuid_t* getBase() const; const ble_uuid_t* getBase() const;
uint8_t getType() const;
int getLoc(int dataLoc, const std::vector<uint8_t> payload) const;
bool equals(const NimBLEUUID& uuid) const; bool equals(const NimBLEUUID& uuid) const;
std::string toString() const; std::string toString() const;
static NimBLEUUID fromString(const std::string& uuid); static NimBLEUUID fromString(const std::string& uuid);

View file

@ -572,4 +572,24 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
return NimBLEAddress{addr}; return NimBLEAddress{addr};
} // generateAddr } // generateAddr
/**
* @brief Get the UUID type based on size.
* @param [in] size The size of the UUID in bits.
* @param [in] complete False if the UUID is truncated, else True.
* @return BLE_HS_ADV_TYPE_COMP_UUIDS16/32/128 or BLE_HS_ADV_TYPE_INCOMP_UUIDS16/32/128
* for valid input size, else 0.
*/
uint8_t NimBLEUtils::getUUIDType(uint8_t size, bool complete) {
switch (size) {
case 16:
return complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
case 32:
return complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
case 128:
return complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
default:
return 0;
}
} // getUUIDType
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -53,6 +53,7 @@ class NimBLEUtils {
static NimBLEAddress generateAddr(bool nrpa); static NimBLEAddress generateAddr(bool nrpa);
static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout); static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout);
static void taskRelease(const NimBLETaskData& taskData, int rc = 0); static void taskRelease(const NimBLETaskData& taskData, int rc = 0);
static uint8_t getUUIDType(uint8_t size, bool complete = true);
}; };
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED