From d107b37d3b6534b5aa3dc5b16d9bd3587c1c7fef Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 4 Jan 2026 17:51:02 -1000 Subject: [PATCH 1/4] [st7735] Combine log statements to reduce loop blocking (#12977) --- esphome/components/st7735/st7735.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/esphome/components/st7735/st7735.cpp b/esphome/components/st7735/st7735.cpp index 160ba151f7..1a74b5ce1e 100644 --- a/esphome/components/st7735/st7735.cpp +++ b/esphome/components/st7735/st7735.cpp @@ -373,15 +373,18 @@ void ST7735::display_init_(const uint8_t *addr) { void ST7735::dump_config() { LOG_DISPLAY("", "ST7735", this); - ESP_LOGCONFIG(TAG, " Model: %s", this->model_str_()); LOG_PIN(" CS Pin: ", this->cs_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Reset Pin: ", this->reset_pin_); - ESP_LOGD(TAG, " Buffer Size: %zu", this->get_buffer_length()); - ESP_LOGD(TAG, " Height: %d", this->height_); - ESP_LOGD(TAG, " Width: %d", this->width_); - ESP_LOGD(TAG, " ColStart: %d", this->colstart_); - ESP_LOGD(TAG, " RowStart: %d", this->rowstart_); + ESP_LOGCONFIG(TAG, + " Model: %s\n" + " Buffer Size: %zu\n" + " Height: %d\n" + " Width: %d\n" + " ColStart: %d\n" + " RowStart: %d", + this->model_str_(), this->get_buffer_length(), this->height_, this->width_, this->colstart_, + this->rowstart_); LOG_UPDATE_INTERVAL(this); } From bd8f9d5984e70d1cf77c1180689ee4fa5cf02771 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 4 Jan 2026 18:14:55 -1000 Subject: [PATCH 2/4] [esp32_ble] Avoid heap allocation in ESPBTUUID::from_raw for string literals --- esphome/components/esp32_ble/ble_uuid.cpp | 28 +++++++++++------------ esphome/components/esp32_ble/ble_uuid.h | 6 ++++- 2 files changed, 19 insertions(+), 15 deletions(-) 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..ef1537c016 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,10 @@ 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(data.begin(), data.size()); } static ESPBTUUID from_uuid(esp_bt_uuid_t uuid); From 5ed2043037d06c388a467304320b3761952cd094 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 4 Jan 2026 18:21:06 -1000 Subject: [PATCH 3/4] constexpr --- esphome/components/esp32_ble/ble_uuid.cpp | 73 -------------------- esphome/components/esp32_ble/ble_uuid.h | 84 ++++++++++++++++++++--- 2 files changed, 76 insertions(+), 81 deletions(-) diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index 7bad8d1866..dd9df1f898 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -4,83 +4,10 @@ #ifdef USE_ESP32_BLE_UUID #include -#include -#include -#include "esphome/core/log.h" #include "esphome/core/helpers.h" namespace esphome::esp32_ble { -static const char *const TAG = "esp32_ble"; - -ESPBTUUID::ESPBTUUID() : uuid_() {} -ESPBTUUID ESPBTUUID::from_uint16(uint16_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_16; - ret.uuid_.uuid.uuid16 = uuid; - return ret; -} -ESPBTUUID ESPBTUUID::from_uint32(uint32_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_32; - ret.uuid_.uuid.uuid32 = uuid; - return ret; -} -ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_128; - memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128); - return ret; -} -ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_128; - for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; - return ret; -} -ESPBTUUID ESPBTUUID::from_raw(const char *data, size_t length) { - ESPBTUUID ret; - if (length == 4) { - // 16-bit UUID as 4-character hex string - 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 (length == 8) { - // 32-bit UUID as 8-character hex string - 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 (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, 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 (size_t i = 0; i < length; i += 2) { - if (data[i] == '-') - i++; - uint8_t msb = data[i]; - uint8_t lsb = data[i + 1]; - - if (msb > '9') - msb -= 7; - if (lsb > '9') - lsb -= 7; - 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); - } - return ret; -} ESPBTUUID ESPBTUUID::from_uuid(esp_bt_uuid_t uuid) { ESPBTUUID ret; ret.uuid_.len = uuid.len; diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index ef1537c016..6746f096cc 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -19,19 +19,70 @@ static constexpr size_t UUID_STR_LEN = 37; class ESPBTUUID { public: - ESPBTUUID(); + constexpr ESPBTUUID() : uuid_{} {} - static ESPBTUUID from_uint16(uint16_t uuid); + static constexpr ESPBTUUID from_uint16(uint16_t uuid) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_16; + ret.uuid_.uuid.uuid16 = uuid; + return ret; + } - static ESPBTUUID from_uint32(uint32_t uuid); + static constexpr ESPBTUUID from_uint32(uint32_t uuid) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_32; + ret.uuid_.uuid.uuid32 = uuid; + return ret; + } - static ESPBTUUID from_raw(const uint8_t *data); - static ESPBTUUID from_raw_reversed(const uint8_t *data); + static constexpr ESPBTUUID from_raw(const uint8_t *data) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_128; + for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) + ret.uuid_.uuid.uuid128[i] = data[i]; + return ret; + } - static ESPBTUUID from_raw(const char *data, size_t length); - static ESPBTUUID from_raw(const char *data) { return from_raw(data, strlen(data)); } + static constexpr ESPBTUUID from_raw_reversed(const uint8_t *data) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_128; + for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) + ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; + return ret; + } + + static constexpr ESPBTUUID from_raw(const char *data, size_t length) { + ESPBTUUID ret; + if (length == 4) { + // 16-bit UUID as 4-character hex string + ret.uuid_.len = ESP_UUID_LEN_16; + ret.uuid_.uuid.uuid16 = parse_hex_16_(data); + } else if (length == 8) { + // 32-bit UUID as 8-character hex string + ret.uuid_.len = ESP_UUID_LEN_32; + ret.uuid_.uuid.uuid32 = parse_hex_32_(data); + } else if (length == 16) { + // 16 raw bytes + ret.uuid_.len = ESP_UUID_LEN_128; + for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) + ret.uuid_.uuid.uuid128[i] = static_cast(data[i]); + } else if (length == 36) { + // UUID format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + ret.uuid_.len = ESP_UUID_LEN_128; + int n = 0; + for (size_t i = 0; i < 36; i += 2) { + if (data[i] == '-') + i++; + ret.uuid_.uuid.uuid128[15 - n++] = (parse_hex_char(data[i]) << 4) | parse_hex_char(data[i + 1]); + } + } + // Invalid length returns empty UUID (len=0) + return ret; + } + + static constexpr ESPBTUUID from_raw(const char *data) { return from_raw(data, c_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(data.begin(), data.size()); } + static constexpr ESPBTUUID from_raw(std::initializer_list data) { return from_raw(data.begin(), data.size()); } static ESPBTUUID from_uuid(esp_bt_uuid_t uuid); @@ -49,6 +100,23 @@ class ESPBTUUID { protected: esp_bt_uuid_t uuid_; + + private: + static constexpr uint16_t parse_hex_16_(const char *s) { + return (parse_hex_char(s[0]) << 12) | (parse_hex_char(s[1]) << 8) | (parse_hex_char(s[2]) << 4) | + parse_hex_char(s[3]); + } + + static constexpr uint32_t parse_hex_32_(const char *s) { + return (static_cast(parse_hex_16_(s)) << 16) | parse_hex_16_(s + 4); + } + + static constexpr size_t c_strlen_(const char *s) { + size_t len = 0; + while (s[len] != '\0') + len++; + return len; + } }; } // namespace esphome::esp32_ble From 6dc8e8ce64b48e3ba9daabb19660a466f1639da5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 4 Jan 2026 18:27:53 -1000 Subject: [PATCH 4/4] Revert "constexpr" This reverts commit 5ed2043037d06c388a467304320b3761952cd094. --- esphome/components/esp32_ble/ble_uuid.cpp | 73 ++++++++++++++++++++ esphome/components/esp32_ble/ble_uuid.h | 84 +++-------------------- 2 files changed, 81 insertions(+), 76 deletions(-) diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index dd9df1f898..7bad8d1866 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -4,10 +4,83 @@ #ifdef USE_ESP32_BLE_UUID #include +#include +#include +#include "esphome/core/log.h" #include "esphome/core/helpers.h" namespace esphome::esp32_ble { +static const char *const TAG = "esp32_ble"; + +ESPBTUUID::ESPBTUUID() : uuid_() {} +ESPBTUUID ESPBTUUID::from_uint16(uint16_t uuid) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_16; + ret.uuid_.uuid.uuid16 = uuid; + return ret; +} +ESPBTUUID ESPBTUUID::from_uint32(uint32_t uuid) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_32; + ret.uuid_.uuid.uuid32 = uuid; + return ret; +} +ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_128; + memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128); + return ret; +} +ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { + ESPBTUUID ret; + ret.uuid_.len = ESP_UUID_LEN_128; + for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) + ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; + return ret; +} +ESPBTUUID ESPBTUUID::from_raw(const char *data, size_t length) { + ESPBTUUID ret; + if (length == 4) { + // 16-bit UUID as 4-character hex string + 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 (length == 8) { + // 32-bit UUID as 8-character hex string + 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 (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, 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 (size_t i = 0; i < length; i += 2) { + if (data[i] == '-') + i++; + uint8_t msb = data[i]; + uint8_t lsb = data[i + 1]; + + if (msb > '9') + msb -= 7; + if (lsb > '9') + lsb -= 7; + 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); + } + return ret; +} ESPBTUUID ESPBTUUID::from_uuid(esp_bt_uuid_t uuid) { ESPBTUUID ret; ret.uuid_.len = uuid.len; diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index 6746f096cc..ef1537c016 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -19,70 +19,19 @@ static constexpr size_t UUID_STR_LEN = 37; class ESPBTUUID { public: - constexpr ESPBTUUID() : uuid_{} {} + ESPBTUUID(); - static constexpr ESPBTUUID from_uint16(uint16_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_16; - ret.uuid_.uuid.uuid16 = uuid; - return ret; - } + static ESPBTUUID from_uint16(uint16_t uuid); - static constexpr ESPBTUUID from_uint32(uint32_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_32; - ret.uuid_.uuid.uuid32 = uuid; - return ret; - } + static ESPBTUUID from_uint32(uint32_t uuid); - static constexpr ESPBTUUID from_raw(const uint8_t *data) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_128; - for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[i] = data[i]; - return ret; - } + static ESPBTUUID from_raw(const uint8_t *data); + static ESPBTUUID from_raw_reversed(const uint8_t *data); - static constexpr ESPBTUUID from_raw_reversed(const uint8_t *data) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_128; - for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; - return ret; - } - - static constexpr ESPBTUUID from_raw(const char *data, size_t length) { - ESPBTUUID ret; - if (length == 4) { - // 16-bit UUID as 4-character hex string - ret.uuid_.len = ESP_UUID_LEN_16; - ret.uuid_.uuid.uuid16 = parse_hex_16_(data); - } else if (length == 8) { - // 32-bit UUID as 8-character hex string - ret.uuid_.len = ESP_UUID_LEN_32; - ret.uuid_.uuid.uuid32 = parse_hex_32_(data); - } else if (length == 16) { - // 16 raw bytes - ret.uuid_.len = ESP_UUID_LEN_128; - for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[i] = static_cast(data[i]); - } else if (length == 36) { - // UUID format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - ret.uuid_.len = ESP_UUID_LEN_128; - int n = 0; - for (size_t i = 0; i < 36; i += 2) { - if (data[i] == '-') - i++; - ret.uuid_.uuid.uuid128[15 - n++] = (parse_hex_char(data[i]) << 4) | parse_hex_char(data[i + 1]); - } - } - // Invalid length returns empty UUID (len=0) - return ret; - } - - static constexpr ESPBTUUID from_raw(const char *data) { return from_raw(data, c_strlen_(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 constexpr ESPBTUUID from_raw(std::initializer_list data) { return from_raw(data.begin(), data.size()); } + static ESPBTUUID from_raw(std::initializer_list data) { return from_raw(data.begin(), data.size()); } static ESPBTUUID from_uuid(esp_bt_uuid_t uuid); @@ -100,23 +49,6 @@ class ESPBTUUID { protected: esp_bt_uuid_t uuid_; - - private: - static constexpr uint16_t parse_hex_16_(const char *s) { - return (parse_hex_char(s[0]) << 12) | (parse_hex_char(s[1]) << 8) | (parse_hex_char(s[2]) << 4) | - parse_hex_char(s[3]); - } - - static constexpr uint32_t parse_hex_32_(const char *s) { - return (static_cast(parse_hex_16_(s)) << 16) | parse_hex_16_(s + 4); - } - - static constexpr size_t c_strlen_(const char *s) { - size_t len = 0; - while (s[len] != '\0') - len++; - return len; - } }; } // namespace esphome::esp32_ble