1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-14 15:53:48 +01:00

[mdns] Conditionally store services to reduce RAM usage by 200-464 bytes

This commit is contained in:
J. Nick Koston
2025-10-11 12:27:39 -10:00
parent dcf2697a2a
commit 0c8c99dbf8
9 changed files with 51 additions and 17 deletions

View File

@@ -1,6 +1,6 @@
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components.esp32 import add_idf_component from esphome.components.esp32 import add_idf_component
from esphome.config_helpers import filter_source_files_from_platform from esphome.config_helpers import filter_source_files_from_platform, get_logger_level
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_DISABLED, CONF_DISABLED,
@@ -125,6 +125,17 @@ def mdns_service(
) )
def enable_mdns_storage():
"""Enable persistent storage of mDNS services in the MDNSComponent.
Called by external components (like OpenThread) that need access to
services after setup() completes via get_services().
Public API for external components. Do not remove.
"""
cg.add_define("USE_MDNS_STORE_SERVICES")
@coroutine_with_priority(CoroPriority.NETWORK_SERVICES) @coroutine_with_priority(CoroPriority.NETWORK_SERVICES)
async def to_code(config): async def to_code(config):
if config[CONF_DISABLED] is True: if config[CONF_DISABLED] is True:
@@ -150,6 +161,8 @@ async def to_code(config):
if config[CONF_SERVICES]: if config[CONF_SERVICES]:
cg.add_define("USE_MDNS_EXTRA_SERVICES") cg.add_define("USE_MDNS_EXTRA_SERVICES")
# Extra services need to be stored persistently
enable_mdns_storage()
# Ensure at least 1 service (fallback service) # Ensure at least 1 service (fallback service)
cg.add_define("MDNS_SERVICE_COUNT", max(1, service_count)) cg.add_define("MDNS_SERVICE_COUNT", max(1, service_count))
@@ -171,6 +184,10 @@ async def to_code(config):
# Ensure at least 1 to avoid zero-size array # Ensure at least 1 to avoid zero-size array
cg.add_define("MDNS_DYNAMIC_TXT_COUNT", max(1, dynamic_txt_count)) cg.add_define("MDNS_DYNAMIC_TXT_COUNT", max(1, dynamic_txt_count))
# Enable storage if verbose logging is enabled (for dump_config)
if get_logger_level() in ("VERBOSE", "VERY_VERBOSE"):
enable_mdns_storage()
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config) await cg.register_component(var, config)

View File

@@ -36,7 +36,7 @@ MDNS_STATIC_CONST_CHAR(SERVICE_TCP, "_tcp");
// Wrap build-time defines into flash storage // Wrap build-time defines into flash storage
MDNS_STATIC_CONST_CHAR(VALUE_VERSION, ESPHOME_VERSION); MDNS_STATIC_CONST_CHAR(VALUE_VERSION, ESPHOME_VERSION);
void MDNSComponent::compile_records_() { void MDNSComponent::compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUNT> &services) {
this->hostname_ = App.get_name(); this->hostname_ = App.get_name();
// IMPORTANT: The #ifdef blocks below must match COMPONENTS_WITH_MDNS_SERVICES // IMPORTANT: The #ifdef blocks below must match COMPONENTS_WITH_MDNS_SERVICES
@@ -53,7 +53,7 @@ void MDNSComponent::compile_records_() {
MDNS_STATIC_CONST_CHAR(VALUE_BOARD, ESPHOME_BOARD); MDNS_STATIC_CONST_CHAR(VALUE_BOARD, ESPHOME_BOARD);
if (api::global_api_server != nullptr) { if (api::global_api_server != nullptr) {
auto &service = this->services_.emplace_next(); auto &service = services.emplace_next();
service.service_type = MDNS_STR(SERVICE_ESPHOMELIB); service.service_type = MDNS_STR(SERVICE_ESPHOMELIB);
service.proto = MDNS_STR(SERVICE_TCP); service.proto = MDNS_STR(SERVICE_TCP);
service.port = api::global_api_server->get_port(); service.port = api::global_api_server->get_port();
@@ -146,7 +146,7 @@ void MDNSComponent::compile_records_() {
#ifdef USE_PROMETHEUS #ifdef USE_PROMETHEUS
MDNS_STATIC_CONST_CHAR(SERVICE_PROMETHEUS, "_prometheus-http"); MDNS_STATIC_CONST_CHAR(SERVICE_PROMETHEUS, "_prometheus-http");
auto &prom_service = this->services_.emplace_next(); auto &prom_service = services.emplace_next();
prom_service.service_type = MDNS_STR(SERVICE_PROMETHEUS); prom_service.service_type = MDNS_STR(SERVICE_PROMETHEUS);
prom_service.proto = MDNS_STR(SERVICE_TCP); prom_service.proto = MDNS_STR(SERVICE_TCP);
prom_service.port = USE_WEBSERVER_PORT; prom_service.port = USE_WEBSERVER_PORT;
@@ -155,7 +155,7 @@ void MDNSComponent::compile_records_() {
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
MDNS_STATIC_CONST_CHAR(SERVICE_HTTP, "_http"); MDNS_STATIC_CONST_CHAR(SERVICE_HTTP, "_http");
auto &web_service = this->services_.emplace_next(); auto &web_service = services.emplace_next();
web_service.service_type = MDNS_STR(SERVICE_HTTP); web_service.service_type = MDNS_STR(SERVICE_HTTP);
web_service.proto = MDNS_STR(SERVICE_TCP); web_service.proto = MDNS_STR(SERVICE_TCP);
web_service.port = USE_WEBSERVER_PORT; web_service.port = USE_WEBSERVER_PORT;
@@ -167,12 +167,17 @@ void MDNSComponent::compile_records_() {
// Publish "http" service if not using native API or any other services // Publish "http" service if not using native API or any other services
// This is just to have *some* mDNS service so that .local resolution works // This is just to have *some* mDNS service so that .local resolution works
auto &fallback_service = this->services_.emplace_next(); auto &fallback_service = services.emplace_next();
fallback_service.service_type = MDNS_STR(SERVICE_HTTP); fallback_service.service_type = MDNS_STR(SERVICE_HTTP);
fallback_service.proto = MDNS_STR(SERVICE_TCP); fallback_service.proto = MDNS_STR(SERVICE_TCP);
fallback_service.port = USE_WEBSERVER_PORT; fallback_service.port = USE_WEBSERVER_PORT;
fallback_service.txt_records.push_back({MDNS_STR(TXT_VERSION), MDNS_STR(VALUE_VERSION)}); fallback_service.txt_records.push_back({MDNS_STR(TXT_VERSION), MDNS_STR(VALUE_VERSION)});
#endif #endif
#ifdef USE_MDNS_STORE_SERVICES
// Copy to member variable if storage is enabled (verbose logging, OpenThread, or extra services)
this->services_ = services;
#endif
} }
void MDNSComponent::dump_config() { void MDNSComponent::dump_config() {
@@ -180,7 +185,7 @@ void MDNSComponent::dump_config() {
"mDNS:\n" "mDNS:\n"
" Hostname: %s", " Hostname: %s",
this->hostname_.c_str()); this->hostname_.c_str());
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE #ifdef USE_MDNS_STORE_SERVICES
ESP_LOGV(TAG, " Services:"); ESP_LOGV(TAG, " Services:");
for (const auto &service : this->services_) { for (const auto &service : this->services_) {
ESP_LOGV(TAG, " - %s, %s, %d", MDNS_STR_ARG(service.service_type), MDNS_STR_ARG(service.proto), ESP_LOGV(TAG, " - %s, %s, %d", MDNS_STR_ARG(service.service_type), MDNS_STR_ARG(service.proto),

View File

@@ -55,7 +55,9 @@ class MDNSComponent : public Component {
void add_extra_service(MDNSService service) { this->services_.emplace_next() = std::move(service); } void add_extra_service(MDNSService service) { this->services_.emplace_next() = std::move(service); }
#endif #endif
#ifdef USE_MDNS_STORE_SERVICES
const StaticVector<MDNSService, MDNS_SERVICE_COUNT> &get_services() const { return this->services_; } const StaticVector<MDNSService, MDNS_SERVICE_COUNT> &get_services() const { return this->services_; }
#endif
void on_shutdown() override; void on_shutdown() override;
@@ -71,9 +73,11 @@ class MDNSComponent : public Component {
StaticVector<std::string, MDNS_DYNAMIC_TXT_COUNT> dynamic_txt_values_; StaticVector<std::string, MDNS_DYNAMIC_TXT_COUNT> dynamic_txt_values_;
protected: protected:
#ifdef USE_MDNS_STORE_SERVICES
StaticVector<MDNSService, MDNS_SERVICE_COUNT> services_{}; StaticVector<MDNSService, MDNS_SERVICE_COUNT> services_{};
#endif
std::string hostname_; std::string hostname_;
void compile_records_(); void compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUNT> &services);
}; };
} // namespace mdns } // namespace mdns

View File

@@ -12,7 +12,8 @@ namespace mdns {
static const char *const TAG = "mdns"; static const char *const TAG = "mdns";
void MDNSComponent::setup() { void MDNSComponent::setup() {
this->compile_records_(); StaticVector<MDNSService, MDNS_SERVICE_COUNT> services;
this->compile_records_(services);
esp_err_t err = mdns_init(); esp_err_t err = mdns_init();
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -24,7 +25,7 @@ void MDNSComponent::setup() {
mdns_hostname_set(this->hostname_.c_str()); mdns_hostname_set(this->hostname_.c_str());
mdns_instance_name_set(this->hostname_.c_str()); mdns_instance_name_set(this->hostname_.c_str());
for (const auto &service : this->services_) { for (const auto &service : services) {
std::vector<mdns_txt_item_t> txt_records; std::vector<mdns_txt_item_t> txt_records;
for (const auto &record : service.txt_records) { for (const auto &record : service.txt_records) {
mdns_txt_item_t it{}; mdns_txt_item_t it{};

View File

@@ -12,11 +12,12 @@ namespace esphome {
namespace mdns { namespace mdns {
void MDNSComponent::setup() { void MDNSComponent::setup() {
this->compile_records_(); StaticVector<MDNSService, MDNS_SERVICE_COUNT> services;
this->compile_records_(services);
MDNS.begin(this->hostname_.c_str()); MDNS.begin(this->hostname_.c_str());
for (const auto &service : this->services_) { for (const auto &service : services) {
// Strip the leading underscore from the proto and service_type. While it is // Strip the leading underscore from the proto and service_type. While it is
// part of the wire protocol to have an underscore, and for example ESP-IDF // part of the wire protocol to have an underscore, and for example ESP-IDF
// expects the underscore to be there, the ESP8266 implementation always adds // expects the underscore to be there, the ESP8266 implementation always adds

View File

@@ -12,11 +12,12 @@ namespace esphome {
namespace mdns { namespace mdns {
void MDNSComponent::setup() { void MDNSComponent::setup() {
this->compile_records_(); StaticVector<MDNSService, MDNS_SERVICE_COUNT> services;
this->compile_records_(services);
MDNS.begin(this->hostname_.c_str()); MDNS.begin(this->hostname_.c_str());
for (const auto &service : this->services_) { for (const auto &service : services) {
// Strip the leading underscore from the proto and service_type. While it is // Strip the leading underscore from the proto and service_type. While it is
// part of the wire protocol to have an underscore, and for example ESP-IDF // part of the wire protocol to have an underscore, and for example ESP-IDF
// expects the underscore to be there, the ESP8266 implementation always adds // expects the underscore to be there, the ESP8266 implementation always adds

View File

@@ -12,11 +12,12 @@ namespace esphome {
namespace mdns { namespace mdns {
void MDNSComponent::setup() { void MDNSComponent::setup() {
this->compile_records_(); StaticVector<MDNSService, MDNS_SERVICE_COUNT> services;
this->compile_records_(services);
MDNS.begin(this->hostname_.c_str()); MDNS.begin(this->hostname_.c_str());
for (const auto &service : this->services_) { for (const auto &service : services) {
// Strip the leading underscore from the proto and service_type. While it is // Strip the leading underscore from the proto and service_type. While it is
// part of the wire protocol to have an underscore, and for example ESP-IDF // part of the wire protocol to have an underscore, and for example ESP-IDF
// expects the underscore to be there, the ESP8266 implementation always adds // expects the underscore to be there, the ESP8266 implementation always adds

View File

@@ -5,7 +5,7 @@ from esphome.components.esp32 import (
add_idf_sdkconfig_option, add_idf_sdkconfig_option,
only_on_variant, only_on_variant,
) )
from esphome.components.mdns import MDNSComponent from esphome.components.mdns import MDNSComponent, enable_mdns_storage
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID
import esphome.final_validate as fv import esphome.final_validate as fv
@@ -141,6 +141,9 @@ FINAL_VALIDATE_SCHEMA = _final_validate
async def to_code(config): async def to_code(config):
cg.add_define("USE_OPENTHREAD") cg.add_define("USE_OPENTHREAD")
# OpenThread SRP needs access to mDNS services after setup
enable_mdns_storage()
ot = cg.new_Pvariable(config[CONF_ID]) ot = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(ot, config) await cg.register_component(ot, config)

View File

@@ -83,6 +83,7 @@
#define USE_LVGL_TILEVIEW #define USE_LVGL_TILEVIEW
#define USE_LVGL_TOUCHSCREEN #define USE_LVGL_TOUCHSCREEN
#define USE_MDNS #define USE_MDNS
#define USE_MDNS_STORE_SERVICES
#define MDNS_SERVICE_COUNT 3 #define MDNS_SERVICE_COUNT 3
#define MDNS_DYNAMIC_TXT_COUNT 3 #define MDNS_DYNAMIC_TXT_COUNT 3
#define USE_MEDIA_PLAYER #define USE_MEDIA_PLAYER