From 0990a9c2b0515ce46f7fb477d64615409309885e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 5 Jan 2026 07:39:24 -1000 Subject: [PATCH] [esp32_ble] Avoid heap allocation in ESPBTUUID::from_raw for string literals (#12980) --- esphome/components/alpha3/alpha3.h | 6 ++--- esphome/components/esp32_ble/ble_uuid.cpp | 28 +++++++++++------------ esphome/components/esp32_ble/ble_uuid.h | 8 ++++++- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/esphome/components/alpha3/alpha3.h b/esphome/components/alpha3/alpha3.h index 7189ecbc33..19d8e99331 100644 --- a/esphome/components/alpha3/alpha3.h +++ b/esphome/components/alpha3/alpha3.h @@ -15,10 +15,8 @@ namespace alpha3 { namespace espbt = esphome::esp32_ble_tracker; static const espbt::ESPBTUUID ALPHA3_GENI_SERVICE_UUID = espbt::ESPBTUUID::from_uint16(0xfe5d); -static const espbt::ESPBTUUID ALPHA3_GENI_CHARACTERISTIC_UUID = - espbt::ESPBTUUID::from_raw({static_cast(0xa9), 0x7b, static_cast(0xb8), static_cast(0x85), 0x0, - 0x1a, 0x28, static_cast(0xaa), 0x2a, 0x43, 0x6e, 0x3, static_cast(0xd1), - static_cast(0xff), static_cast(0x9c), static_cast(0x85)}); +static const espbt::ESPBTUUID ALPHA3_GENI_CHARACTERISTIC_UUID = espbt::ESPBTUUID::from_raw( + {0xa9, 0x7b, 0xb8, 0x85, 0x00, 0x1a, 0x28, 0xaa, 0x2a, 0x43, 0x6e, 0x03, 0xd1, 0xff, 0x9c, 0x85}); static const int16_t GENI_RESPONSE_HEADER_LENGTH = 13; static const size_t GENI_RESPONSE_TYPE_LENGTH = 8; diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index c6b27f3bb9..7bad8d1866 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -39,36 +39,36 @@ ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; return ret; } -ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { +ESPBTUUID ESPBTUUID::from_raw(const char *data, size_t length) { ESPBTUUID ret; - if (data.length() == 4) { + if (length == 4) { // 16-bit UUID as 4-character hex string - auto parsed = parse_hex(data); + auto parsed = parse_hex(data, length); if (parsed.has_value()) { ret.uuid_.len = ESP_UUID_LEN_16; ret.uuid_.uuid.uuid16 = parsed.value(); } - } else if (data.length() == 8) { + } else if (length == 8) { // 32-bit UUID as 8-character hex string - auto parsed = parse_hex(data); + auto parsed = parse_hex(data, length); if (parsed.has_value()) { ret.uuid_.len = ESP_UUID_LEN_32; ret.uuid_.uuid.uuid32 = parsed.value(); } - } else if (data.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be - // investigated (lack of time) + } else if (length == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be + // investigated (lack of time) ret.uuid_.len = ESP_UUID_LEN_128; - memcpy(ret.uuid_.uuid.uuid128, (uint8_t *) data.data(), 16); - } else if (data.length() == 36) { + memcpy(ret.uuid_.uuid.uuid128, reinterpret_cast(data), 16); + } else if (length == 36) { // If the length of the string is 36 bytes then we will assume it is a long hex string in // UUID format. ret.uuid_.len = ESP_UUID_LEN_128; int n = 0; - for (uint i = 0; i < data.length(); i += 2) { - if (data.c_str()[i] == '-') + for (size_t i = 0; i < length; i += 2) { + if (data[i] == '-') i++; - uint8_t msb = data.c_str()[i]; - uint8_t lsb = data.c_str()[i + 1]; + uint8_t msb = data[i]; + uint8_t lsb = data[i + 1]; if (msb > '9') msb -= 7; @@ -77,7 +77,7 @@ ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { ret.uuid_.uuid.uuid128[15 - n++] = ((msb & 0x0F) << 4) | (lsb & 0x0F); } } else { - ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data.c_str()); + ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data); } return ret; } diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index ed561d70e4..2d8c69e44e 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -7,6 +7,7 @@ #ifdef USE_ESP32 #ifdef USE_ESP32_BLE_UUID +#include #include #include #include @@ -27,7 +28,12 @@ class ESPBTUUID { static ESPBTUUID from_raw(const uint8_t *data); static ESPBTUUID from_raw_reversed(const uint8_t *data); - static ESPBTUUID from_raw(const std::string &data); + static ESPBTUUID from_raw(const char *data, size_t length); + static ESPBTUUID from_raw(const char *data) { return from_raw(data, strlen(data)); } + static ESPBTUUID from_raw(const std::string &data) { return from_raw(data.c_str(), data.length()); } + static ESPBTUUID from_raw(std::initializer_list data) { + return from_raw(reinterpret_cast(data.begin()), data.size()); + } static ESPBTUUID from_uuid(esp_bt_uuid_t uuid);