From 7b116be48be0ed54654333154e16e8a5fed569ce Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 18:54:23 -0500 Subject: [PATCH 01/10] [bluetooth_proxy] Optimize UUID conversion and reduce flash usage by 296 bytes --- .../bluetooth_proxy/bluetooth_connection.cpp | 29 +++++++++++++------ esphome/components/esp32_ble/ble_uuid.cpp | 4 ++- esphome/components/esp32_ble/ble_uuid.h | 4 ++- .../esp32_ble_tracker/esp32_ble_tracker.h | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index b16b894188..37447e1ed9 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -1,5 +1,6 @@ #include "bluetooth_connection.h" +#include #include "esphome/components/api/api_pb2.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -12,16 +13,26 @@ namespace esphome::bluetooth_proxy { static const char *const TAG = "bluetooth_proxy.connection"; +// This function allocates nothing and directly packs UUIDs into the output array +// The base UUID is stored in flash memory as constexpr static void fill_128bit_uuid_array(std::array &out, esp_bt_uuid_t uuid_source) { - esp_bt_uuid_t uuid = espbt::ESPBTUUID::from_uuid(uuid_source).as_128bit().get_uuid(); - out[0] = ((uint64_t) uuid.uuid.uuid128[15] << 56) | ((uint64_t) uuid.uuid.uuid128[14] << 48) | - ((uint64_t) uuid.uuid.uuid128[13] << 40) | ((uint64_t) uuid.uuid.uuid128[12] << 32) | - ((uint64_t) uuid.uuid.uuid128[11] << 24) | ((uint64_t) uuid.uuid.uuid128[10] << 16) | - ((uint64_t) uuid.uuid.uuid128[9] << 8) | ((uint64_t) uuid.uuid.uuid128[8]); - out[1] = ((uint64_t) uuid.uuid.uuid128[7] << 56) | ((uint64_t) uuid.uuid.uuid128[6] << 48) | - ((uint64_t) uuid.uuid.uuid128[5] << 40) | ((uint64_t) uuid.uuid.uuid128[4] << 32) | - ((uint64_t) uuid.uuid.uuid128[3] << 24) | ((uint64_t) uuid.uuid.uuid128[2] << 16) | - ((uint64_t) uuid.uuid.uuid128[1] << 8) | ((uint64_t) uuid.uuid.uuid128[0]); + // Bluetooth base UUID: 00000000-0000-1000-8000-00805F9B34FB + // Pack 32/16-bit UUID directly into out[0] with bytes 12-15 + out[0] = uuid_source.len == ESP_UUID_LEN_128 + ? (((uint64_t) uuid_source.uuid.uuid128[15] << 56) | ((uint64_t) uuid_source.uuid.uuid128[14] << 48) | + ((uint64_t) uuid_source.uuid.uuid128[13] << 40) | ((uint64_t) uuid_source.uuid.uuid128[12] << 32) | + ((uint64_t) uuid_source.uuid.uuid128[11] << 24) | ((uint64_t) uuid_source.uuid.uuid128[10] << 16) | + ((uint64_t) uuid_source.uuid.uuid128[9] << 8) | ((uint64_t) uuid_source.uuid.uuid128[8])) + : (((uint64_t) (uuid_source.len == ESP_UUID_LEN_16 ? uuid_source.uuid.uuid16 : uuid_source.uuid.uuid32) + << 32) | + 0x00001000ULL); + // Pack bytes 0-7 into out[1] - this part is always the same for the base UUID + out[1] = uuid_source.len == ESP_UUID_LEN_128 + ? ((uint64_t) uuid_source.uuid.uuid128[7] << 56) | ((uint64_t) uuid_source.uuid.uuid128[6] << 48) | + ((uint64_t) uuid_source.uuid.uuid128[5] << 40) | ((uint64_t) uuid_source.uuid.uuid128[4] << 32) | + ((uint64_t) uuid_source.uuid.uuid128[3] << 24) | ((uint64_t) uuid_source.uuid.uuid128[2] << 16) | + ((uint64_t) uuid_source.uuid.uuid128[1] << 8) | ((uint64_t) uuid_source.uuid.uuid128[0]) + : 0x800000805F9B34FBULL; // Precalculated base UUID bytes 0-7 } // Helper to fill UUID in the appropriate format based on client support and UUID type diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index fc6981acd3..7b5ccdf5e2 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -1,6 +1,7 @@ #include "ble_uuid.h" #ifdef USE_ESP32 +#ifdef USE_ESP32_BLE_DEVICE #include #include @@ -190,4 +191,5 @@ std::string ESPBTUUID::to_string() const { } // namespace esphome::esp32_ble -#endif +#endif // USE_ESP32_BLE_DEVICE +#endif // USE_ESP32 diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index 150ca359d3..314d59379b 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -4,6 +4,7 @@ #include "esphome/core/helpers.h" #ifdef USE_ESP32 +#ifdef USE_ESP32_BLE_DEVICE #include #include @@ -42,4 +43,5 @@ class ESPBTUUID { } // namespace esphome::esp32_ble -#endif +#endif // USE_ESP32_BLE_DEVICE +#endif // USE_ESP32 diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index bf99026810..5d95bcb995 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -33,12 +33,12 @@ enum AdvertisementParserType { RAW_ADVERTISEMENTS, }; +#ifdef USE_ESP32_BLE_DEVICE struct ServiceData { ESPBTUUID uuid; adv_data_t data; }; -#ifdef USE_ESP32_BLE_DEVICE class ESPBLEiBeacon { public: ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); } From c2ebfe8f2774c32891602b6b7a6841f854efb150 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 18:56:20 -0500 Subject: [PATCH 02/10] [bluetooth_proxy] Optimize UUID conversion and reduce flash usage by 296 bytes --- .../bluetooth_proxy/bluetooth_connection.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 37447e1ed9..4826b1dd38 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -17,7 +17,9 @@ static const char *const TAG = "bluetooth_proxy.connection"; // The base UUID is stored in flash memory as constexpr static void fill_128bit_uuid_array(std::array &out, esp_bt_uuid_t uuid_source) { // Bluetooth base UUID: 00000000-0000-1000-8000-00805F9B34FB - // Pack 32/16-bit UUID directly into out[0] with bytes 12-15 + // out[0] = bytes 8-15 (big-endian) + // - For 128-bit UUIDs: use bytes 8-15 as-is + // - For 16/32-bit UUIDs: insert into bytes 12-15, use 0x00001000 for bytes 8-11 out[0] = uuid_source.len == ESP_UUID_LEN_128 ? (((uint64_t) uuid_source.uuid.uuid128[15] << 56) | ((uint64_t) uuid_source.uuid.uuid128[14] << 48) | ((uint64_t) uuid_source.uuid.uuid128[13] << 40) | ((uint64_t) uuid_source.uuid.uuid128[12] << 32) | @@ -25,14 +27,16 @@ static void fill_128bit_uuid_array(std::array &out, esp_bt_uuid_t u ((uint64_t) uuid_source.uuid.uuid128[9] << 8) | ((uint64_t) uuid_source.uuid.uuid128[8])) : (((uint64_t) (uuid_source.len == ESP_UUID_LEN_16 ? uuid_source.uuid.uuid16 : uuid_source.uuid.uuid32) << 32) | - 0x00001000ULL); - // Pack bytes 0-7 into out[1] - this part is always the same for the base UUID + 0x00001000ULL); // Base UUID bytes 8-11 + // out[1] = bytes 0-7 (big-endian) + // - For 128-bit UUIDs: use bytes 0-7 as-is + // - For 16/32-bit UUIDs: use precalculated base UUID constant out[1] = uuid_source.len == ESP_UUID_LEN_128 ? ((uint64_t) uuid_source.uuid.uuid128[7] << 56) | ((uint64_t) uuid_source.uuid.uuid128[6] << 48) | ((uint64_t) uuid_source.uuid.uuid128[5] << 40) | ((uint64_t) uuid_source.uuid.uuid128[4] << 32) | ((uint64_t) uuid_source.uuid.uuid128[3] << 24) | ((uint64_t) uuid_source.uuid.uuid128[2] << 16) | ((uint64_t) uuid_source.uuid.uuid128[1] << 8) | ((uint64_t) uuid_source.uuid.uuid128[0]) - : 0x800000805F9B34FBULL; // Precalculated base UUID bytes 0-7 + : 0x800000805F9B34FBULL; // Base UUID bytes 0-7: 80-00-00-80-5F-9B-34-FB } // Helper to fill UUID in the appropriate format based on client support and UUID type From 841deff578a8d8460344753d16d3f4c2658d6dcc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 18:57:17 -0500 Subject: [PATCH 03/10] [bluetooth_proxy] Optimize UUID conversion and reduce flash usage by 296 bytes --- esphome/components/bluetooth_proxy/bluetooth_connection.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 4826b1dd38..6d41b083d0 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -1,6 +1,5 @@ #include "bluetooth_connection.h" -#include #include "esphome/components/api/api_pb2.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" From 5b279f5f92f9a32381fcd7c795a3111c6f544694 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:14:37 -0500 Subject: [PATCH 04/10] tweak --- esphome/components/esp32_ble/ble_uuid.cpp | 4 ++-- esphome/components/esp32_ble/ble_uuid.h | 4 ++-- esphome/components/esp32_ble_server/__init__.py | 1 + esphome/components/esp32_ble_tracker/__init__.py | 1 + esphome/components/esp32_ble_tracker/esp32_ble_tracker.h | 4 +++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index 7b5ccdf5e2..be9c6945d7 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -1,7 +1,7 @@ #include "ble_uuid.h" #ifdef USE_ESP32 -#ifdef USE_ESP32_BLE_DEVICE +#ifdef USE_ESP32_BLE_UUID #include #include @@ -191,5 +191,5 @@ std::string ESPBTUUID::to_string() const { } // namespace esphome::esp32_ble -#endif // USE_ESP32_BLE_DEVICE +#endif // USE_ESP32_BLE_UUID #endif // USE_ESP32 diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index 314d59379b..b3bdd46e06 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -4,7 +4,7 @@ #include "esphome/core/helpers.h" #ifdef USE_ESP32 -#ifdef USE_ESP32_BLE_DEVICE +#ifdef USE_ESP32_BLE_UUID #include #include @@ -43,5 +43,5 @@ class ESPBTUUID { } // namespace esphome::esp32_ble -#endif // USE_ESP32_BLE_DEVICE +#endif // USE_ESP32_BLE_UUID #endif // USE_ESP32 diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index feeb055600..aea6de599e 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -447,6 +447,7 @@ def parse_properties(char_conf): def parse_uuid(uuid): # If the UUID is a int, use from_uint32 + cg.add_define("USE_ESP32_BLE_UUID") if isinstance(uuid, int): return ESPBTUUID_ns.from_uint32(uuid) # Otherwise, use ESPBTUUID_ns.from_raw diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index d03e968e2d..9ad2f3b25f 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -373,6 +373,7 @@ async def _add_ble_features(): # Add feature-specific defines based on what's needed if BLEFeatures.ESP_BT_DEVICE in _required_features: cg.add_define("USE_ESP32_BLE_DEVICE") + cg.add_define("USE_ESP32_BLE_UUID") ESP32_BLE_START_SCAN_ACTION_SCHEMA = cv.Schema( diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 5d95bcb995..3022eb25d2 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -33,12 +33,14 @@ enum AdvertisementParserType { RAW_ADVERTISEMENTS, }; -#ifdef USE_ESP32_BLE_DEVICE +#ifdef USE_ESP32_BLE_UUID struct ServiceData { ESPBTUUID uuid; adv_data_t data; }; +#endif +#ifdef USE_ESP32_BLE_DEVICE class ESPBLEiBeacon { public: ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); } From 803d665a948bcbdff39d88d313edcdcffcd895c1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:16:02 -0500 Subject: [PATCH 05/10] tweak --- esphome/core/defines.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 01f6811e05..5df3bcf475 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -154,6 +154,7 @@ #define USE_ESP32_BLE_CLIENT #define USE_ESP32_BLE_DEVICE #define USE_ESP32_BLE_SERVER +#define USE_ESP32_BLE_UUID #define USE_ESP32_BLE_ADVERTISING #define USE_I2C #define USE_IMPROV From 36613507be8e3b03f047e72579d253d3f4e6010e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:19:21 -0500 Subject: [PATCH 06/10] fix --- esphome/components/ble_client/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 0f3869c23b..014170ea42 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -285,6 +285,7 @@ async def remove_bond_to_code(config, action_id, template_arg, args): async def to_code(config): # Register the loggers this component needs + cg.add_define("USE_ESP32_BLE_UUID") esp32_ble.register_bt_logger(BTLoggers.GATT, BTLoggers.SMP) var = cg.new_Pvariable(config[CONF_ID]) From 5c12f638bd80b727c3289d5560622542489a5bc8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:22:27 -0500 Subject: [PATCH 07/10] fix --- esphome/components/ble_client/__init__.py | 1 - esphome/components/esp32_ble/ble_uuid.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 014170ea42..0f3869c23b 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -285,7 +285,6 @@ async def remove_bond_to_code(config, action_id, template_arg, args): async def to_code(config): # Register the loggers this component needs - cg.add_define("USE_ESP32_BLE_UUID") esp32_ble.register_bt_logger(BTLoggers.GATT, BTLoggers.SMP) var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index b3bdd46e06..4cf2d10abd 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/defines.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" From b5c381982cb58131165e9fd8dc700778fd8a428a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:23:44 -0500 Subject: [PATCH 08/10] fix --- esphome/components/bluetooth_proxy/bluetooth_connection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 6d41b083d0..5d81f680d9 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -12,8 +12,8 @@ namespace esphome::bluetooth_proxy { static const char *const TAG = "bluetooth_proxy.connection"; -// This function allocates nothing and directly packs UUIDs into the output array -// The base UUID is stored in flash memory as constexpr +// This function is designed to be allocation-free and only called in the event loop (not thread-safe) +// It directly packs UUIDs into the output array with precalculated constants for the base UUID static void fill_128bit_uuid_array(std::array &out, esp_bt_uuid_t uuid_source) { // Bluetooth base UUID: 00000000-0000-1000-8000-00805F9B34FB // out[0] = bytes 8-15 (big-endian) From 235050fe58a339da05387bfcaad5fdadfb5976b3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:25:20 -0500 Subject: [PATCH 09/10] fix --- esphome/components/bluetooth_proxy/bluetooth_connection.cpp | 4 ++-- esphome/components/esp32_ble_server/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 5d81f680d9..347f60c28f 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -12,8 +12,8 @@ namespace esphome::bluetooth_proxy { static const char *const TAG = "bluetooth_proxy.connection"; -// This function is designed to be allocation-free and only called in the event loop (not thread-safe) -// It directly packs UUIDs into the output array with precalculated constants for the base UUID +// This function is allocation-free and directly packs UUIDs into the output array +// using precalculated constants for the Bluetooth base UUID static void fill_128bit_uuid_array(std::array &out, esp_bt_uuid_t uuid_source) { // Bluetooth base UUID: 00000000-0000-1000-8000-00805F9B34FB // out[0] = bytes 8-15 (big-endian) diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index aea6de599e..8ddb15a7f8 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -447,7 +447,6 @@ def parse_properties(char_conf): def parse_uuid(uuid): # If the UUID is a int, use from_uint32 - cg.add_define("USE_ESP32_BLE_UUID") if isinstance(uuid, int): return ESPBTUUID_ns.from_uint32(uuid) # Otherwise, use ESPBTUUID_ns.from_raw @@ -530,6 +529,7 @@ async def to_code_characteristic(service_var, char_conf): async def to_code(config): # Register the loggers this component needs esp32_ble.register_bt_logger(BTLoggers.GATT, BTLoggers.SMP) + cg.add_define("USE_ESP32_BLE_UUID") var = cg.new_Pvariable(config[CONF_ID]) From dec9810177506a248ad4cf4cf7c20c18ca464571 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Aug 2025 19:26:41 -0500 Subject: [PATCH 10/10] fix --- esphome/components/ble_client/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 0f3869c23b..5f4ea8afd1 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -286,6 +286,7 @@ async def remove_bond_to_code(config, action_id, template_arg, args): async def to_code(config): # Register the loggers this component needs esp32_ble.register_bt_logger(BTLoggers.GATT, BTLoggers.SMP) + cg.add_define("USE_ESP32_BLE_UUID") var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config)