1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-18 15:55:46 +00:00

[bthome] Use StaticVector with compile-time sizes

Switch from FixedVector (runtime-sized, heap allocated) to StaticVector
(compile-time sized, stack allocated) for better memory efficiency:

**Changes:**
- Replace FixedVector with StaticVector in bthome.h
- Use cg.add_define to set sizes at compile time before creating component
- Remove runtime init() calls (StaticVector doesn't need them)
- Add default defines to esphome/core/defines.h for static analysis

**Benefits:**
- All memory allocated on stack at compile time
- Zero runtime allocation overhead
- Better for embedded systems with limited heap
- StaticVector allocates all N slots upfront (no dynamic growth)

**Defines added:**
- BTHOME_MAX_MEASUREMENTS: Max number of sensor measurements
- BTHOME_MAX_BINARY_MEASUREMENTS: Max number of binary sensor measurements
- BTHOME_MAX_ADV_PACKETS: Max advertisement packets for cycling

Sizes are calculated from YAML config and set via cg.add_define before
component instantiation, ensuring compile-time type safety.
This commit is contained in:
Claude
2025-11-17 22:45:08 +00:00
parent f81a3a8c64
commit bc35d616dd
3 changed files with 17 additions and 15 deletions

View File

@@ -172,6 +172,16 @@ FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant
async def to_code(config): async def to_code(config):
# Calculate sizes for StaticVector compile-time allocation
num_sensors = max(1, len(config.get(CONF_SENSORS, [])))
num_binary_sensors = max(1, len(config.get(CONF_BINARY_SENSORS, [])))
max_packets = max(1, num_sensors + num_binary_sensors)
# Add defines for compile-time sizes (must be before new_Pvariable)
cg.add_define("BTHOME_MAX_MEASUREMENTS", num_sensors)
cg.add_define("BTHOME_MAX_BINARY_MEASUREMENTS", num_binary_sensors)
cg.add_define("BTHOME_MAX_ADV_PACKETS", max_packets)
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID]) parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID])
@@ -182,17 +192,6 @@ async def to_code(config):
cg.add(var.set_max_interval(config[CONF_MAX_INTERVAL])) cg.add(var.set_max_interval(config[CONF_MAX_INTERVAL]))
cg.add(var.set_tx_power(config[CONF_TX_POWER])) cg.add(var.set_tx_power(config[CONF_TX_POWER]))
# Initialize FixedVectors with proper sizes
num_sensors = len(config.get(CONF_SENSORS, []))
num_binary_sensors = len(config.get(CONF_BINARY_SENSORS, []))
max_packets = max(1, num_sensors + num_binary_sensors)
# Initialize the measurements and binary_measurements FixedVectors
cg.add(cg.RawExpression(f"{var}->measurements_.init({num_sensors})"))
cg.add(cg.RawExpression(f"{var}->binary_measurements_.init({num_binary_sensors})"))
cg.add(cg.RawExpression(f"{var}->adv_packets_.init({max_packets})"))
cg.add(cg.RawExpression(f"{var}->adv_packet_sizes_.init({max_packets})"))
if CONF_ENCRYPTION_KEY in config: if CONF_ENCRYPTION_KEY in config:
key = config[CONF_ENCRYPTION_KEY] key = config[CONF_ENCRYPTION_KEY]
key_bytes = [cg.RawExpression(f"0x{key[i:i+2]}") for i in range(0, len(key), 2)] key_bytes = [cg.RawExpression(f"0x{key[i:i+2]}") for i in range(0, len(key), 2)]

View File

@@ -57,8 +57,8 @@ class BTHome : public Component, public GAPEventHandler, public Parented<ESP32BL
bool encrypt_payload_(const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len); bool encrypt_payload_(const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len);
void trigger_immediate_advertising_(uint8_t measurement_index, bool is_binary); void trigger_immediate_advertising_(uint8_t measurement_index, bool is_binary);
FixedVector<SensorMeasurement> measurements_; StaticVector<SensorMeasurement, BTHOME_MAX_MEASUREMENTS> measurements_;
FixedVector<BinarySensorMeasurement> binary_measurements_; StaticVector<BinarySensorMeasurement, BTHOME_MAX_BINARY_MEASUREMENTS> binary_measurements_;
uint16_t min_interval_{}; uint16_t min_interval_{};
uint16_t max_interval_{}; uint16_t max_interval_{};
@@ -72,8 +72,8 @@ class BTHome : public Component, public GAPEventHandler, public Parented<ESP32BL
uint32_t counter_{0}; uint32_t counter_{0};
// Advertisement cycling support // Advertisement cycling support
FixedVector<std::unique_ptr<uint8_t[]>> adv_packets_; // Multiple advertisement packets StaticVector<std::unique_ptr<uint8_t[]>, BTHOME_MAX_ADV_PACKETS> adv_packets_; // Multiple advertisement packets
FixedVector<uint16_t> adv_packet_sizes_; // Size of each packet StaticVector<uint16_t, BTHOME_MAX_ADV_PACKETS> adv_packet_sizes_; // Size of each packet
uint8_t current_packet_index_{0}; uint8_t current_packet_index_{0};
bool data_changed_{true}; bool data_changed_{true};
bool immediate_advertising_pending_{false}; bool immediate_advertising_pending_{false};

View File

@@ -176,6 +176,9 @@
#define USE_ESP32_BLE_SERVER #define USE_ESP32_BLE_SERVER
#define USE_ESP32_BLE_UUID #define USE_ESP32_BLE_UUID
#define USE_ESP32_BLE_ADVERTISING #define USE_ESP32_BLE_ADVERTISING
#define BTHOME_MAX_MEASUREMENTS 8
#define BTHOME_MAX_BINARY_MEASUREMENTS 8
#define BTHOME_MAX_ADV_PACKETS 16
#define USE_ESP32_BLE_SERVER_SET_VALUE_ACTION #define USE_ESP32_BLE_SERVER_SET_VALUE_ACTION
#define USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION #define USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION
#define USE_ESP32_BLE_SERVER_NOTIFY_ACTION #define USE_ESP32_BLE_SERVER_NOTIFY_ACTION