mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2026-01-27 01:22:19 +01:00
[Breaking] Refactor NimBLEUUID.
* msbFirst parameter has been removed from constructor as it was unnecessary, caller should reverse the data first or call the new `reverseByteOrder` method after. * `getNative` method replaced with `getBase` which returns a read-only pointer to the UUID size underlying. * Added `reverseByteOrder` method, this will reverse the bytes of the UUID, which can be useful for advertising/logging. * Added `getValue` method, which returns a read-only `uint8_t` pointer to the UUID value. * Removed `m_valueSet` member variable, `bitSize()` can be used as a replacement. * General code cleanup.
This commit is contained in:
@@ -15,21 +15,22 @@
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "NimBLELog.h"
|
||||
# include "NimBLEUtils.h"
|
||||
# include "NimBLEUUID.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
static const char* LOG_TAG = "NimBLEUUID";
|
||||
# include <algorithm>
|
||||
|
||||
static const char* LOG_TAG = "NimBLEUUID";
|
||||
static const uint8_t ble_base_uuid[] = {
|
||||
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from a string.
|
||||
*
|
||||
* Create a UUID from a string. There will be two possible stories here. Either the string represents
|
||||
* a binary data field or the string represents a hex encoding of a UUID.
|
||||
* For the hex encoding, here is an example:
|
||||
* Create a UUID from a string. There will be two possible stories here. Either
|
||||
* the string represents a binary data field or the string represents a hex
|
||||
* encoding of a UUID. For the hex encoding, here is an example:
|
||||
*
|
||||
* ```
|
||||
* "beb5483e-36e1-4688-b7f5-ea07361b26a8"
|
||||
@@ -41,104 +42,68 @@ static const char* LOG_TAG = "NimBLEUUID";
|
||||
*
|
||||
* @param [in] value The string to build a UUID from.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const std::string &value) {
|
||||
m_valueSet = true;
|
||||
NimBLEUUID::NimBLEUUID(const std::string& value) {
|
||||
if (value.length() == 4) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
m_uuid.u16.value = strtoul(value.c_str(), NULL, 16);
|
||||
}
|
||||
else if (value.length() == 8) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
m_uuid.u32.value = strtoul(value.c_str(), NULL, 16);
|
||||
}
|
||||
else if (value.length() == 16) {
|
||||
*this = NimBLEUUID((uint8_t*)value.data(), 16, true);
|
||||
}
|
||||
else if (value.length() == 36) {
|
||||
// If the length of the string is 36 bytes then we will assume it is a long hex string in
|
||||
// UUID format.
|
||||
char * position = const_cast<char *>(value.c_str());
|
||||
uint32_t first = strtoul(position, &position, 16);
|
||||
uint16_t second = strtoul(position + 1, &position, 16);
|
||||
uint16_t third = strtoul(position + 1, &position, 16);
|
||||
uint16_t fourth = strtoul(position + 1, &position, 16);
|
||||
uint64_t fifth = strtoull(position + 1, NULL, 16);
|
||||
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||
}
|
||||
else {
|
||||
m_valueSet = false;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
m_uuid.u16.value = strtoul(value.c_str(), nullptr, 16);
|
||||
} else if (value.length() == 8) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
m_uuid.u32.value = strtoul(value.c_str(), nullptr, 16);
|
||||
} else if (value.length() == 16) {
|
||||
memcpy(m_uuid.u128.value, &value[0], 16);
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
} else if (value.length() == 36) {
|
||||
char* position;
|
||||
uint64_t first_half = (strtoull(&value[0], &position, 16) << 32) +
|
||||
(strtoull(position + 1, &position, 16) << 16) + strtoull(position + 1, &position, 16);
|
||||
uint64_t second_half = (strtoull(position + 1, &position, 16) << 48) + strtoull(position + 1, nullptr, 16);
|
||||
memcpy(m_uuid.u128.value + 8, &first_half, 8);
|
||||
memcpy(m_uuid.u128.value, &second_half, 8);
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
} else {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid UUID length");
|
||||
m_uuid.u.type = 0;
|
||||
}
|
||||
} // NimBLEUUID(std::string)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from 2, 4, 16 bytes of memory.
|
||||
* @param [in] pData The pointer to the start of the UUID.
|
||||
* @param [in] size The size of the data.
|
||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||
uint8_t *uuidValue = nullptr;
|
||||
|
||||
switch(size) {
|
||||
case 2:
|
||||
uuidValue = (uint8_t*)&m_uuid.u16.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
break;
|
||||
case 4:
|
||||
uuidValue = (uint8_t*)&m_uuid.u32.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
break;
|
||||
case 16:
|
||||
uuidValue = m_uuid.u128.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
break;
|
||||
default:
|
||||
m_valueSet = false;
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid UUID size");
|
||||
return;
|
||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size) {
|
||||
if (ble_uuid_init_from_buf(&m_uuid, pData, size)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid UUID size");
|
||||
m_uuid.u.type = 0;
|
||||
}
|
||||
if (msbFirst) {
|
||||
std::reverse_copy(pData, pData + size, uuidValue);
|
||||
} else {
|
||||
memcpy(uuidValue, pData, size);
|
||||
}
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
|
||||
} // NimBLEUUID(const uint8_t* pData, size_t size)
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from the 16bit value.
|
||||
* @param [in] uuid The 16bit short form UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint16_t uuid) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
m_uuid.u16.value = uuid;
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
m_uuid.u16.value = uuid;
|
||||
} // NimBLEUUID(uint16_t uuid)
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from the 32bit value.
|
||||
* @param [in] uuid The 32bit short form UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint32_t uuid) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
m_uuid.u32.value = uuid;
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
m_uuid.u32.value = uuid;
|
||||
} // NimBLEUUID(uint32_t uuid)
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from the native UUID.
|
||||
* @param [in] uuid The native UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(m_uuid.u128.value, uuid->value, 16);
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
|
||||
} // NimBLEUUID(const ble_uuid128_t* uuid)
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from the 128bit value using hex parts instead of string,
|
||||
@@ -151,32 +116,47 @@ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
|
||||
* @param [in] fourth The last 64bit of the UUID, combining the last 2 parts of the string equivalent
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(m_uuid.u128.value + 12, &first, 4);
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(m_uuid.u128.value + 12, &first, 4);
|
||||
memcpy(m_uuid.u128.value + 10, &second, 2);
|
||||
memcpy(m_uuid.u128.value + 8, &third, 2);
|
||||
memcpy(m_uuid.u128.value, &fourth, 8);
|
||||
m_valueSet = true;
|
||||
}
|
||||
|
||||
memcpy(m_uuid.u128.value + 8, &third, 2);
|
||||
memcpy(m_uuid.u128.value, &fourth, 8);
|
||||
} // NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth)
|
||||
|
||||
/**
|
||||
* @brief Creates an empty UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID() {
|
||||
m_valueSet = false;
|
||||
} // NimBLEUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the number of bits in this uuid.
|
||||
* @return The number of bits in the UUID. One of 16, 32 or 128.
|
||||
* @brief Get the bit size of the UUID, 16, 32 or 128.
|
||||
* @return The bit size of the UUID or 0 if not initialized.
|
||||
*/
|
||||
uint8_t NimBLEUUID::bitSize() const {
|
||||
if (!m_valueSet) return 0;
|
||||
return m_uuid.u.type;
|
||||
return this->m_uuid.u.type;
|
||||
} // bitSize
|
||||
|
||||
/**
|
||||
* @brief Get the uuid value.
|
||||
* @return A pointer to the UUID value or nullptr if not initialized.
|
||||
* @note This should be checked with `bitSize()` before accessing.
|
||||
*/
|
||||
const uint8_t* NimBLEUUID::getValue() const {
|
||||
switch (bitSize()) {
|
||||
case BLE_UUID_TYPE_16:
|
||||
return reinterpret_cast<const uint8_t*>(&m_uuid.u16.value);
|
||||
case BLE_UUID_TYPE_32:
|
||||
return reinterpret_cast<const uint8_t*>(&m_uuid.u32.value);
|
||||
case BLE_UUID_TYPE_128:
|
||||
return m_uuid.u128.value;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
} // getValue
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the NimBLE UUID base structure.
|
||||
* @return A Read-only pointer to the NimBLE UUID base structure.
|
||||
* @note The type value should be checked, if no 16, 32 or 128 then the UUID is not initialized.
|
||||
*/
|
||||
const ble_uuid_t* NimBLEUUID::getBase() const {
|
||||
return &this->m_uuid.u;
|
||||
} // getBase
|
||||
|
||||
/**
|
||||
* @brief Compare a UUID against this UUID.
|
||||
@@ -184,10 +164,9 @@ uint8_t NimBLEUUID::bitSize() const {
|
||||
* @param [in] uuid The UUID to compare against.
|
||||
* @return True if the UUIDs are equal and false otherwise.
|
||||
*/
|
||||
bool NimBLEUUID::equals(const NimBLEUUID &uuid) const {
|
||||
bool NimBLEUUID::equals(const NimBLEUUID& uuid) const {
|
||||
return *this == uuid;
|
||||
}
|
||||
|
||||
} // equals
|
||||
|
||||
/**
|
||||
* Create a NimBLEUUID from a string of the form:
|
||||
@@ -200,14 +179,14 @@ bool NimBLEUUID::equals(const NimBLEUUID &uuid) const {
|
||||
*
|
||||
* @param [in] uuid The string to create the UUID from.
|
||||
*/
|
||||
NimBLEUUID NimBLEUUID::fromString(const std::string &uuid) {
|
||||
NimBLEUUID NimBLEUUID::fromString(const std::string& uuid) {
|
||||
uint8_t start = 0;
|
||||
if (strstr(uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters.
|
||||
start = 2;
|
||||
}
|
||||
uint8_t len = uuid.length() - start; // Calculate the length of the string we are going to use.
|
||||
|
||||
if(len == 4) {
|
||||
uint8_t len = uuid.length() - start; // Calculate the length of the string we are going to use.
|
||||
if (len == 4) {
|
||||
uint16_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16);
|
||||
return NimBLEUUID(x);
|
||||
} else if (len == 8) {
|
||||
@@ -216,47 +195,29 @@ NimBLEUUID NimBLEUUID::fromString(const std::string &uuid) {
|
||||
} else if (len == 36) {
|
||||
return NimBLEUUID(uuid);
|
||||
}
|
||||
|
||||
return NimBLEUUID();
|
||||
} // fromString
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the native UUID value.
|
||||
* @return The native UUID value or nullptr if not set.
|
||||
*/
|
||||
const ble_uuid_any_t* NimBLEUUID::getNative() const {
|
||||
if (m_valueSet == false) {
|
||||
NIMBLE_LOGD(LOG_TAG,"<< Return of un-initialized UUID!");
|
||||
return nullptr;
|
||||
}
|
||||
return &m_uuid;
|
||||
} // getNative
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert a UUID to its 128 bit representation.
|
||||
* @details A UUID can be internally represented as 16bit, 32bit or the full 128bit.
|
||||
* This method will convert 16 or 32bit representations to the full 128bit.
|
||||
* @return The NimBLEUUID converted to 128bit.
|
||||
*/
|
||||
const NimBLEUUID &NimBLEUUID::to128() {
|
||||
const NimBLEUUID& NimBLEUUID::to128() {
|
||||
// If we either don't have a value or are already a 128 bit UUID, nothing further to do.
|
||||
if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_128) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If we are 16 bit or 32 bit, then set the other bytes of the UUID.
|
||||
if (m_uuid.u.type == BLE_UUID_TYPE_16) {
|
||||
*this = NimBLEUUID(m_uuid.u16.value, 0x0000, 0x1000, 0x800000805f9b34fb);
|
||||
}
|
||||
else if (m_uuid.u.type == BLE_UUID_TYPE_32) {
|
||||
*this = NimBLEUUID(m_uuid.u32.value, 0x0000, 0x1000, 0x800000805f9b34fb);
|
||||
if (bitSize() != BLE_UUID_TYPE_128) {
|
||||
uint32_t val = bitSize() == BLE_UUID_TYPE_16 ? *reinterpret_cast<const uint16_t*>(getValue())
|
||||
: *reinterpret_cast<const uint32_t*>(getValue());
|
||||
memcpy(m_uuid.u128.value, &ble_base_uuid, sizeof(ble_base_uuid) - 4);
|
||||
memcpy(m_uuid.u128.value + 12, &val, 4);
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
}
|
||||
|
||||
return *this;
|
||||
} // to128
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert 128 bit UUID to its 16 bit representation.
|
||||
* @details A UUID can be internally represented as 16bit, 32bit or the full 128bit.
|
||||
@@ -264,21 +225,16 @@ const NimBLEUUID &NimBLEUUID::to128() {
|
||||
* @return The NimBLEUUID converted to 16bit if successful, otherwise the original uuid.
|
||||
*/
|
||||
const NimBLEUUID& NimBLEUUID::to16() {
|
||||
if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_16) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (m_uuid.u.type == BLE_UUID_TYPE_128) {
|
||||
uint8_t base128[] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00,
|
||||
0x00, 0x80, 0x00, 0x10, 0x00, 0x00};
|
||||
if (memcmp(m_uuid.u128.value, base128, sizeof(base128)) == 0 ) {
|
||||
*this = NimBLEUUID(*(uint16_t*)(m_uuid.u128.value + 12));
|
||||
if (bitSize() == BLE_UUID_TYPE_128) {
|
||||
const uint8_t* val = getValue();
|
||||
if (memcmp(val, ble_base_uuid, sizeof(ble_base_uuid) - 4) == 0) {
|
||||
m_uuid.u16.value = *reinterpret_cast<const uint16_t*>(val + 12);
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // to16
|
||||
|
||||
/**
|
||||
* @brief Get a string representation of the UUID.
|
||||
@@ -295,53 +251,55 @@ std::string NimBLEUUID::toString() const {
|
||||
return std::string(*this);
|
||||
} // toString
|
||||
|
||||
/**
|
||||
* @brief Reverse the byte order of the UUID.
|
||||
* @return The NimBLEUUID with the byte order reversed.
|
||||
* @details This is useful when comparing UUIDs or when the advertisement data is reversed.
|
||||
*/
|
||||
const NimBLEUUID& NimBLEUUID::reverseByteOrder() {
|
||||
if (bitSize() == BLE_UUID_TYPE_128) {
|
||||
std::reverse(m_uuid.u128.value, m_uuid.u128.value + 16);
|
||||
} else if (bitSize() == BLE_UUID_TYPE_32) {
|
||||
m_uuid.u32.value = __builtin_bswap32(m_uuid.u32.value);
|
||||
} else if (bitSize() == BLE_UUID_TYPE_16) {
|
||||
m_uuid.u16.value = __builtin_bswap16(m_uuid.u16.value);
|
||||
}
|
||||
|
||||
return *this;
|
||||
} // reverseByteOrder
|
||||
|
||||
/**
|
||||
* @brief Convenience operator to check if this UUID is equal to another.
|
||||
*/
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
if(m_uuid.u.type != rhs.m_uuid.u.type) {
|
||||
uint8_t uuidBase[16] = {
|
||||
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
bool NimBLEUUID::operator==(const NimBLEUUID& rhs) const {
|
||||
if (this->bitSize() != rhs.bitSize()) {
|
||||
uint8_t uuid128[sizeof(ble_base_uuid)];
|
||||
memcpy(uuid128, &ble_base_uuid, sizeof(ble_base_uuid));
|
||||
if (this->bitSize() == BLE_UUID_TYPE_128) {
|
||||
memcpy(uuid128 + 12, rhs.getValue(), rhs.bitSize() == BLE_UUID_TYPE_16 ? 2 : 4);
|
||||
return memcmp(this->getValue(), uuid128, sizeof(ble_base_uuid)) == 0;
|
||||
|
||||
if(m_uuid.u.type == BLE_UUID_TYPE_128){
|
||||
if(rhs.m_uuid.u.type == BLE_UUID_TYPE_16){
|
||||
memcpy(uuidBase+12, &rhs.m_uuid.u16.value, 2);
|
||||
} else if (rhs.m_uuid.u.type == BLE_UUID_TYPE_32){
|
||||
memcpy(uuidBase+12, &rhs.m_uuid.u32.value, 4);
|
||||
}
|
||||
return memcmp(m_uuid.u128.value,uuidBase,16) == 0;
|
||||
|
||||
} else if(rhs.m_uuid.u.type == BLE_UUID_TYPE_128) {
|
||||
if(m_uuid.u.type == BLE_UUID_TYPE_16){
|
||||
memcpy(uuidBase+12, &m_uuid.u16.value, 2);
|
||||
} else if (m_uuid.u.type == BLE_UUID_TYPE_32){
|
||||
memcpy(uuidBase+12, &m_uuid.u32.value, 4);
|
||||
}
|
||||
return memcmp(rhs.m_uuid.u128.value,uuidBase,16) == 0;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (rhs.bitSize() == BLE_UUID_TYPE_128) {
|
||||
memcpy(uuid128 + 12, getValue(), this->bitSize() == BLE_UUID_TYPE_16 ? 2 : 4);
|
||||
return memcmp(rhs.getValue(), uuid128, sizeof(ble_base_uuid)) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0;
|
||||
}
|
||||
|
||||
return m_valueSet == rhs.m_valueSet;
|
||||
}
|
||||
if (this->bitSize() != BLE_UUID_TYPE_128) {
|
||||
return this->getValue() == rhs.getValue();
|
||||
}
|
||||
|
||||
return memcmp(this->getValue(), rhs.getValue(), 16);
|
||||
} // operator==
|
||||
|
||||
/**
|
||||
* @brief Convenience operator to check if this UUID is not equal to another.
|
||||
*/
|
||||
bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||
bool NimBLEUUID::operator!=(const NimBLEUUID& rhs) const {
|
||||
return !this->operator==(rhs);
|
||||
}
|
||||
|
||||
} // operator!=
|
||||
|
||||
/**
|
||||
* @brief Convenience operator to convert this UUID to string representation.
|
||||
@@ -349,12 +307,8 @@ bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||
* that accept std::string and/or or it's methods as a parameter.
|
||||
*/
|
||||
NimBLEUUID::operator std::string() const {
|
||||
if (!m_valueSet) return std::string(); // If we have no value, nothing to format.
|
||||
|
||||
char buf[BLE_UUID_STR_LEN];
|
||||
|
||||
return ble_uuid_to_str(&m_uuid.u, buf);
|
||||
}
|
||||
|
||||
} // operator std::string
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
||||
Reference in New Issue
Block a user