mirror of
https://github.com/esphome/esphome.git
synced 2025-08-05 18:07:47 +00:00
Add heap tracing capability to API component
- Add heap tracing configuration options to API component - Implement periodic heap trace dumping (every 30 seconds) - Configure ESP-IDF settings for heap tracing - Add sample YAML configuration - Useful for debugging memory reallocation overhead issues
This commit is contained in:
parent
8e29437900
commit
35238c1437
@ -1,8 +1,10 @@
|
|||||||
import base64
|
import base64
|
||||||
|
import logging
|
||||||
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.automation import Condition
|
from esphome.automation import Condition
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ACTION,
|
CONF_ACTION,
|
||||||
@ -23,12 +25,14 @@ from esphome.const import (
|
|||||||
CONF_TRIGGER_ID,
|
CONF_TRIGGER_ID,
|
||||||
CONF_VARIABLES,
|
CONF_VARIABLES,
|
||||||
)
|
)
|
||||||
from esphome.core import coroutine_with_priority
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
|
|
||||||
DEPENDENCIES = ["network"]
|
DEPENDENCIES = ["network"]
|
||||||
AUTO_LOAD = ["socket"]
|
AUTO_LOAD = ["socket"]
|
||||||
CODEOWNERS = ["@OttoWinter"]
|
CODEOWNERS = ["@OttoWinter"]
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
api_ns = cg.esphome_ns.namespace("api")
|
api_ns = cg.esphome_ns.namespace("api")
|
||||||
APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller)
|
APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller)
|
||||||
HomeAssistantServiceCallAction = api_ns.class_(
|
HomeAssistantServiceCallAction = api_ns.class_(
|
||||||
@ -49,6 +53,9 @@ SERVICE_ARG_NATIVE_TYPES = {
|
|||||||
"string[]": cg.std_vector.template(cg.std_string),
|
"string[]": cg.std_vector.template(cg.std_string),
|
||||||
}
|
}
|
||||||
CONF_ENCRYPTION = "encryption"
|
CONF_ENCRYPTION = "encryption"
|
||||||
|
CONF_HEAP_TRACING = "heap_tracing"
|
||||||
|
CONF_HEAP_TRACING_STANDALONE = "standalone" # vs SYSTEM
|
||||||
|
CONF_HEAP_TRACING_RECORDS = "num_records"
|
||||||
|
|
||||||
|
|
||||||
def validate_encryption_key(value):
|
def validate_encryption_key(value):
|
||||||
@ -95,6 +102,20 @@ def _encryption_schema(config):
|
|||||||
return ENCRYPTION_SCHEMA(config)
|
return ENCRYPTION_SCHEMA(config)
|
||||||
|
|
||||||
|
|
||||||
|
HEAP_TRACING_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_HEAP_TRACING_STANDALONE, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_HEAP_TRACING_RECORDS, default=100): cv.positive_int,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _heap_tracing_schema(config):
|
||||||
|
if config is None:
|
||||||
|
config = {}
|
||||||
|
return HEAP_TRACING_SCHEMA(config)
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
@ -109,6 +130,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
): ACTIONS_SCHEMA,
|
): ACTIONS_SCHEMA,
|
||||||
cv.Exclusive(CONF_ACTIONS, group_of_exclusion=CONF_ACTIONS): ACTIONS_SCHEMA,
|
cv.Exclusive(CONF_ACTIONS, group_of_exclusion=CONF_ACTIONS): ACTIONS_SCHEMA,
|
||||||
cv.Optional(CONF_ENCRYPTION): _encryption_schema,
|
cv.Optional(CONF_ENCRYPTION): _encryption_schema,
|
||||||
|
cv.Optional(CONF_HEAP_TRACING): _heap_tracing_schema,
|
||||||
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
|
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
|
||||||
single=True
|
single=True
|
||||||
),
|
),
|
||||||
@ -176,6 +198,59 @@ async def to_code(config):
|
|||||||
else:
|
else:
|
||||||
cg.add_define("USE_API_PLAINTEXT")
|
cg.add_define("USE_API_PLAINTEXT")
|
||||||
|
|
||||||
|
# Handle heap tracing configuration if ESP32 platform and using ESP-IDF
|
||||||
|
if (heap_tracing_config := config.get(CONF_HEAP_TRACING, None)) is not None:
|
||||||
|
if CORE.using_esp_idf:
|
||||||
|
# Enable heap tracing in sdkconfig
|
||||||
|
add_idf_sdkconfig_option("CONFIG_HEAP_TRACING", True)
|
||||||
|
|
||||||
|
# Set tracing mode (standalone or system)
|
||||||
|
if heap_tracing_config[CONF_HEAP_TRACING_STANDALONE]:
|
||||||
|
add_idf_sdkconfig_option("CONFIG_HEAP_TRACING_STANDALONE", True)
|
||||||
|
else:
|
||||||
|
add_idf_sdkconfig_option("CONFIG_HEAP_TRACING_SYSTEM", True)
|
||||||
|
|
||||||
|
# Generate code to implement heap tracing
|
||||||
|
cg.add_global(cg.RawStatement('#include "esp_heap_trace.h"'))
|
||||||
|
|
||||||
|
# Define the trace record buffer
|
||||||
|
num_records = heap_tracing_config[CONF_HEAP_TRACING_RECORDS]
|
||||||
|
cg.add_global(
|
||||||
|
cg.RawStatement(
|
||||||
|
f"static heap_trace_record_t trace_record[{num_records}];"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add helper functions for heap tracing
|
||||||
|
cg.add_global(
|
||||||
|
cg.RawStatement(
|
||||||
|
"""
|
||||||
|
void start_heap_trace() {
|
||||||
|
heap_trace_init_standalone(trace_record, """
|
||||||
|
+ str(num_records)
|
||||||
|
+ """);
|
||||||
|
heap_trace_start(HEAP_TRACE_LEAKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_and_dump_heap_trace() {
|
||||||
|
heap_trace_stop();
|
||||||
|
heap_trace_dump();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add periodic heap trace dumping to the api_server.cpp file
|
||||||
|
# This will be added in C++ code
|
||||||
|
cg.add_define("USE_API_HEAP_TRACE")
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Not using ESP-IDF, so we can't use heap tracing
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Heap tracing is only available when using ESP-IDF. "
|
||||||
|
"Disabling heap tracing configuration."
|
||||||
|
)
|
||||||
|
|
||||||
cg.add_define("USE_API")
|
cg.add_define("USE_API")
|
||||||
cg.add_global(api_ns.using)
|
cg.add_global(api_ns.using)
|
||||||
|
|
||||||
|
@ -30,6 +30,11 @@ void APIServer::setup() {
|
|||||||
ESP_LOGCONFIG(TAG, "Setting up Home Assistant API server...");
|
ESP_LOGCONFIG(TAG, "Setting up Home Assistant API server...");
|
||||||
this->setup_controller();
|
this->setup_controller();
|
||||||
|
|
||||||
|
#ifdef USE_API_HEAP_TRACE
|
||||||
|
ESP_LOGI(TAG, "Initializing heap tracing");
|
||||||
|
start_heap_trace();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_API_NOISE
|
#ifdef USE_API_NOISE
|
||||||
uint32_t hash = 88491486UL;
|
uint32_t hash = 88491486UL;
|
||||||
|
|
||||||
@ -154,6 +159,21 @@ void APIServer::loop() {
|
|||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_API_HEAP_TRACE
|
||||||
|
// Periodically dump heap trace information (every 30 seconds)
|
||||||
|
static uint32_t last_heap_trace_dump = 0;
|
||||||
|
const uint32_t now = millis();
|
||||||
|
if (now - last_heap_trace_dump > 30000) { // 30 seconds
|
||||||
|
ESP_LOGI(TAG, "Dumping heap trace information");
|
||||||
|
stop_and_dump_heap_trace();
|
||||||
|
|
||||||
|
// Start a new trace for the next period
|
||||||
|
start_heap_trace();
|
||||||
|
|
||||||
|
last_heap_trace_dump = now;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIServer::dump_config() {
|
void APIServer::dump_config() {
|
||||||
@ -466,6 +486,12 @@ void APIServer::on_shutdown() {
|
|||||||
c->send_disconnect_request(DisconnectRequest());
|
c->send_disconnect_request(DisconnectRequest());
|
||||||
}
|
}
|
||||||
delay(10);
|
delay(10);
|
||||||
|
|
||||||
|
#ifdef USE_API_HEAP_TRACE
|
||||||
|
// Make sure to stop tracing on shutdown to get final results
|
||||||
|
ESP_LOGI(TAG, "Final heap trace dump on shutdown");
|
||||||
|
stop_and_dump_heap_trace();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
33
heap_trace_example.yaml
Normal file
33
heap_trace_example.yaml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
esphome:
|
||||||
|
name: esp32-heap-trace
|
||||||
|
platform: ESP32
|
||||||
|
board: esp32dev
|
||||||
|
# Use ESP-IDF framework which is required for heap tracing
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
version: recommended
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
logger:
|
||||||
|
level: INFO
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
# Enable heap tracing with the following configuration
|
||||||
|
heap_tracing:
|
||||||
|
# Use standalone tracing (vs system tracing)
|
||||||
|
standalone: true
|
||||||
|
# Number of trace records to keep (more records = more memory usage)
|
||||||
|
num_records: 100
|
||||||
|
|
||||||
|
# Enable OTA updates
|
||||||
|
ota:
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
|
||||||
|
# Enable fallback hotspot in case wifi connection fails
|
||||||
|
ap:
|
||||||
|
ssid: "Esp32-Heap-Trace"
|
||||||
|
password: "12345678"
|
Loading…
x
Reference in New Issue
Block a user