[core] Combine entity register + configure_entity_ into one call (#16030)
CI / Create common environment (push) Has been cancelled
CI / Check pylint (push) Has been cancelled
CI / Run script/ci-custom (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.11) (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.14) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.11) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.13) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.14) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.11) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.14) (push) Has been cancelled
CI / Determine which jobs to run (push) Has been cancelled
CI / Run integration tests (push) Has been cancelled
CI / Run C++ unit tests (push) Has been cancelled
CI / Run CodSpeed benchmarks (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 IDF (push) Has been cancelled
CI / Run script/clang-tidy for ESP8266 (push) Has been cancelled
CI / Run script/clang-tidy for ZEPHYR (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 1/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 2/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 3/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 4/4 (push) Has been cancelled
CI / Test components batch (${{ matrix.components }}) (push) Has been cancelled
CI / pre-commit.ci lite (push) Has been cancelled
CI / Build target branch for memory impact (push) Has been cancelled
CI / Build PR branch for memory impact (push) Has been cancelled
CI / Comment memory impact (push) Has been cancelled
CI / CI Status (push) Has been cancelled

This commit is contained in:
J. Nick Koston
2026-04-26 22:03:39 -05:00
committed by GitHub
parent 112646a9c4
commit 79b741b8dc
30 changed files with 145 additions and 48 deletions
@@ -13,7 +13,11 @@ from esphome.const import (
CONF_WEB_SERVER, CONF_WEB_SERVER,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@grahambrown11", "@hwstar"] CODEOWNERS = ["@grahambrown11", "@hwstar"]
@@ -181,7 +185,7 @@ async def setup_alarm_control_panel_core_(var, config):
async def register_alarm_control_panel(var, config): async def register_alarm_control_panel(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_alarm_control_panel(var)) queue_entity_register("alarm_control_panel", config)
CORE.register_platform_component("alarm_control_panel", var) CORE.register_platform_component("alarm_control_panel", var)
await setup_alarm_control_panel_core_(var, config) await setup_alarm_control_panel_core_(var, config)
+2 -1
View File
@@ -62,6 +62,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -624,7 +625,7 @@ async def setup_binary_sensor_core_(var, config):
async def register_binary_sensor(var, config): async def register_binary_sensor(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_binary_sensor(var)) queue_entity_register("binary_sensor", config)
CORE.register_platform_component("binary_sensor", var) CORE.register_platform_component("binary_sensor", var)
await setup_binary_sensor_core_(var, config) await setup_binary_sensor_core_(var, config)
+2 -1
View File
@@ -19,6 +19,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -101,7 +102,7 @@ async def setup_button_core_(var, config):
async def register_button(var, config): async def register_button(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_button(var)) queue_entity_register("button", config)
CORE.register_platform_component("button", var) CORE.register_platform_component("button", var)
await setup_button_core_(var, config) await setup_button_core_(var, config)
+6 -2
View File
@@ -49,7 +49,11 @@ from esphome.const import (
CONF_WEB_SERVER, CONF_WEB_SERVER,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
IS_PLATFORM_COMPONENT = True IS_PLATFORM_COMPONENT = True
@@ -442,7 +446,7 @@ async def setup_climate_core_(var, config):
async def register_climate(var, config): async def register_climate(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_climate(var)) queue_entity_register("climate", config)
CORE.register_platform_component("climate", var) CORE.register_platform_component("climate", var)
await setup_climate_core_(var, config) await setup_climate_core_(var, config)
+2 -1
View File
@@ -39,6 +39,7 @@ from esphome.const import (
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -232,7 +233,7 @@ async def setup_cover_core_(var, config):
async def register_cover(var, config): async def register_cover(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_cover(var)) queue_entity_register("cover", config)
CORE.register_platform_component("cover", var) CORE.register_platform_component("cover", var)
await setup_cover_core_(var, config) await setup_cover_core_(var, config)
+6 -2
View File
@@ -22,7 +22,11 @@ from esphome.const import (
CONF_YEAR, CONF_YEAR,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@rfdarter", "@jesserockz"] CODEOWNERS = ["@rfdarter", "@jesserockz"]
@@ -160,7 +164,7 @@ async def register_datetime(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
entity_type = config[CONF_TYPE].lower() entity_type = config[CONF_TYPE].lower()
cg.add(getattr(cg.App, f"register_{entity_type}")(var)) queue_entity_register(entity_type, config)
CORE.register_platform_component(entity_type, var) CORE.register_platform_component(entity_type, var)
await setup_datetime_core_(var, config) await setup_datetime_core_(var, config)
+2 -1
View File
@@ -19,6 +19,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -108,7 +109,7 @@ async def setup_event_core_(var, config, *, event_types: list[str]):
async def register_event(var, config, *, event_types: list[str]): async def register_event(var, config, *, event_types: list[str]):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_event(var)) queue_entity_register("event", config)
CORE.register_platform_component("event", var) CORE.register_platform_component("event", var)
await setup_event_core_(var, config, event_types=event_types) await setup_event_core_(var, config, event_types=event_types)
+6 -2
View File
@@ -32,7 +32,11 @@ from esphome.const import (
CONF_WEB_SERVER, CONF_WEB_SERVER,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
IS_PLATFORM_COMPONENT = True IS_PLATFORM_COMPONENT = True
@@ -292,7 +296,7 @@ async def setup_fan_core_(var, config):
async def register_fan(var, config): async def register_fan(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_fan(var)) queue_entity_register("fan", config)
CORE.register_platform_component("fan", var) CORE.register_platform_component("fan", var)
await setup_fan_core_(var, config) await setup_fan_core_(var, config)
+2 -2
View File
@@ -12,7 +12,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID from esphome.const import CONF_ID
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
from esphome.core.entity_helpers import setup_entity from esphome.core.entity_helpers import queue_entity_register, setup_entity
from esphome.coroutine import CoroPriority from esphome.coroutine import CoroPriority
from esphome.types import ConfigType from esphome.types import ConfigType
@@ -54,8 +54,8 @@ async def register_infrared(var: cg.Pvariable, config: ConfigType) -> None:
"""Register an infrared device with the core.""" """Register an infrared device with the core."""
cg.add_define("USE_IR_RF") cg.add_define("USE_IR_RF")
await cg.register_component(var, config) await cg.register_component(var, config)
queue_entity_register("infrared", config)
await setup_infrared_core_(var, config) await setup_infrared_core_(var, config)
cg.add(cg.App.register_infrared(var))
CORE.register_platform_component("infrared", var) CORE.register_platform_component("infrared", var)
+6 -2
View File
@@ -40,7 +40,11 @@ from esphome.const import (
CONF_WHITE, CONF_WHITE,
) )
from esphome.core import CORE, ID, CoroPriority, HexInt, Lambda, coroutine_with_priority from esphome.core import CORE, ID, CoroPriority, HexInt, Lambda, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
import esphome.final_validate as fv import esphome.final_validate as fv
from esphome.types import ConfigType from esphome.types import ConfigType
@@ -405,7 +409,7 @@ async def setup_light_core_(light_var, config, output_var):
async def register_light(output_var, config): async def register_light(output_var, config):
light_var = cg.new_Pvariable(config[CONF_ID], output_var) light_var = cg.new_Pvariable(config[CONF_ID], output_var)
cg.add(cg.App.register_light(light_var)) queue_entity_register("light", config)
CORE.register_platform_component("light", light_var) CORE.register_platform_component("light", light_var)
await cg.register_component(light_var, config) await cg.register_component(light_var, config)
await setup_light_core_(light_var, config, output_var) await setup_light_core_(light_var, config, output_var)
+6 -2
View File
@@ -13,7 +13,11 @@ from esphome.const import (
CONF_WEB_SERVER, CONF_WEB_SERVER,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
@@ -112,7 +116,7 @@ async def _setup_lock_core(var, config):
async def register_lock(var, config): async def register_lock(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_lock(var)) queue_entity_register("lock", config)
CORE.register_platform_component("lock", var) CORE.register_platform_component("lock", var)
await _setup_lock_core(var, config) await _setup_lock_core(var, config)
+2 -1
View File
@@ -21,6 +21,7 @@ from esphome.core import CORE
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
inherit_property_from, inherit_property_from,
queue_entity_register,
setup_entity, setup_entity,
) )
from esphome.coroutine import CoroPriority, coroutine_with_priority from esphome.coroutine import CoroPriority, coroutine_with_priority
@@ -262,7 +263,7 @@ async def setup_media_player_core_(var, config):
async def register_media_player(var, config): async def register_media_player(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_media_player(var)) queue_entity_register("media_player", config)
CORE.register_platform_component("media_player", var) CORE.register_platform_component("media_player", var)
await setup_media_player_core_(var, config) await setup_media_player_core_(var, config)
+2 -1
View File
@@ -82,6 +82,7 @@ from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
setup_unit_of_measurement, setup_unit_of_measurement,
@@ -301,7 +302,7 @@ async def register_number(
): ):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_number(var)) queue_entity_register("number", config)
CORE.register_platform_component("number", var) CORE.register_platform_component("number", var)
await setup_number_core_( await setup_number_core_(
var, config, min_value=min_value, max_value=max_value, step=step var, config, min_value=min_value, max_value=max_value, step=step
@@ -12,7 +12,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID from esphome.const import CONF_ID
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
from esphome.core.entity_helpers import setup_entity from esphome.core.entity_helpers import queue_entity_register, setup_entity
from esphome.coroutine import CoroPriority from esphome.coroutine import CoroPriority
from esphome.types import ConfigType from esphome.types import ConfigType
@@ -55,8 +55,8 @@ async def register_radio_frequency(var: cg.Pvariable, config: ConfigType) -> Non
"""Register a radio frequency device with the core.""" """Register a radio frequency device with the core."""
cg.add_define("USE_RADIO_FREQUENCY") cg.add_define("USE_RADIO_FREQUENCY")
await cg.register_component(var, config) await cg.register_component(var, config)
queue_entity_register("radio_frequency", config)
await setup_radio_frequency_core_(var, config) await setup_radio_frequency_core_(var, config)
cg.add(cg.App.register_radio_frequency(var))
CORE.register_platform_component("radio_frequency", var) CORE.register_platform_component("radio_frequency", var)
+6 -2
View File
@@ -19,7 +19,11 @@ from esphome.const import (
CONF_WEB_SERVER, CONF_WEB_SERVER,
) )
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass, TemplateArguments from esphome.cpp_generator import MockObjClass, TemplateArguments
from esphome.cpp_types import global_ns from esphome.cpp_types import global_ns
@@ -113,7 +117,7 @@ async def setup_select_core_(var, config, *, options: list[str]):
async def register_select(var, config, *, options: list[str]): async def register_select(var, config, *, options: list[str]):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_select(var)) queue_entity_register("select", config)
CORE.register_platform_component("select", var) CORE.register_platform_component("select", var)
await setup_select_core_(var, config, options=options) await setup_select_core_(var, config, options=options)
+2 -1
View File
@@ -109,6 +109,7 @@ from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
setup_unit_of_measurement, setup_unit_of_measurement,
@@ -982,7 +983,7 @@ async def setup_sensor_core_(var, config):
async def register_sensor(var, config): async def register_sensor(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_sensor(var)) queue_entity_register("sensor", config)
CORE.register_platform_component("sensor", var) CORE.register_platform_component("sensor", var)
await setup_sensor_core_(var, config) await setup_sensor_core_(var, config)
+2 -1
View File
@@ -23,6 +23,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -166,7 +167,7 @@ async def setup_switch_core_(var, config):
async def register_switch(var, config): async def register_switch(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_switch(var)) queue_entity_register("switch", config)
CORE.register_platform_component("switch", var) CORE.register_platform_component("switch", var)
await setup_switch_core_(var, config) await setup_switch_core_(var, config)
+6 -2
View File
@@ -14,7 +14,11 @@ from esphome.const import (
CONF_WEB_SERVER, CONF_WEB_SERVER,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@mauritskorse"] CODEOWNERS = ["@mauritskorse"]
@@ -122,7 +126,7 @@ async def register_text(
): ):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_text(var)) queue_entity_register("text", config)
CORE.register_platform_component("text", var) CORE.register_platform_component("text", var)
await setup_text_core_( await setup_text_core_(
var, config, min_length=min_length, max_length=max_length, pattern=pattern var, config, min_length=min_length, max_length=max_length, pattern=pattern
+2 -1
View File
@@ -22,6 +22,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -221,7 +222,7 @@ async def setup_text_sensor_core_(var, config):
async def register_text_sensor(var, config): async def register_text_sensor(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_text_sensor(var)) queue_entity_register("text_sensor", config)
CORE.register_platform_component("text_sensor", var) CORE.register_platform_component("text_sensor", var)
await setup_text_sensor_core_(var, config) await setup_text_sensor_core_(var, config)
+2 -1
View File
@@ -17,6 +17,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -113,7 +114,7 @@ async def setup_update_core_(var, config):
async def register_update(var, config): async def register_update(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_update(var)) queue_entity_register("update", config)
CORE.register_platform_component("update", var) CORE.register_platform_component("update", var)
await setup_update_core_(var, config) await setup_update_core_(var, config)
+2 -1
View File
@@ -24,6 +24,7 @@ from esphome.const import (
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import ( from esphome.core.entity_helpers import (
entity_duplicate_validator, entity_duplicate_validator,
queue_entity_register,
setup_device_class, setup_device_class,
setup_entity, setup_entity,
) )
@@ -162,7 +163,7 @@ async def _setup_valve_core(var, config):
async def register_valve(var, config): async def register_valve(var, config):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var) var = cg.Pvariable(config[CONF_ID], var)
cg.add(cg.App.register_valve(var)) queue_entity_register("valve", config)
CORE.register_platform_component("valve", var) CORE.register_platform_component("valve", var)
await _setup_valve_core(var, config) await _setup_valve_core(var, config)
+6 -2
View File
@@ -9,7 +9,11 @@ from esphome.const import (
CONF_VISUAL, CONF_VISUAL,
) )
from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.core.entity_helpers import (
entity_duplicate_validator,
queue_entity_register,
setup_entity,
)
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
from esphome.types import ConfigType from esphome.types import ConfigType
@@ -90,7 +94,7 @@ async def register_water_heater(var: cg.Pvariable, config: ConfigType) -> cg.Pva
cg.add_define("USE_WATER_HEATER") cg.add_define("USE_WATER_HEATER")
cg.add(cg.App.register_water_heater(var)) queue_entity_register("water_heater", config)
CORE.register_platform_component("water_heater", var) CORE.register_platform_component("water_heater", var)
await setup_water_heater_core_(var, config) await setup_water_heater_core_(var, config)
+11 -2
View File
@@ -103,10 +103,19 @@ class Application {
void set_current_component(Component *component) { this->current_component_ = component; } void set_current_component(Component *component) { this->current_component_ = component; }
Component *get_current_component() { return this->current_component_; } Component *get_current_component() { return this->current_component_; }
// Entity register methods (generated from entity_types.h) // Entity register methods (generated from entity_types.h).
// Each entity type gets two overloads:
// - register_<entity>(obj) — bare push_back
// - register_<entity>(obj, name, hash, fields) — configure_entity_ + push_back
// The 4-arg form lets codegen collapse `App.register_<entity>(obj); obj->configure_entity_(...);`
// into a single call site, saving flash and a `main.cpp` line per entity.
// NOLINTBEGIN(bugprone-macro-parentheses) // NOLINTBEGIN(bugprone-macro-parentheses)
#define ENTITY_TYPE_(type, singular, plural, count, upper) \ #define ENTITY_TYPE_(type, singular, plural, count, upper) \
void register_##singular(type *obj) { this->plural##_.push_back(obj); } void register_##singular(type *obj) { this->plural##_.push_back(obj); } \
void register_##singular(type *obj, const char *name, uint32_t object_id_hash, uint32_t entity_fields) { \
obj->configure_entity_(name, object_id_hash, entity_fields); \
this->plural##_.push_back(obj); \
}
#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \ #define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
ENTITY_TYPE_(type, singular, plural, count, upper) ENTITY_TYPE_(type, singular, plural, count, upper)
#include "esphome/core/entity_types.h" #include "esphome/core/entity_types.h"
+3
View File
@@ -238,6 +238,9 @@ class EntityBase {
protected: protected:
friend void ::setup(); friend void ::setup();
friend void ::original_setup(); friend void ::original_setup();
// Application's register_<entity>(obj, name, hash, fields) overloads call configure_entity_
// before push_back, so codegen can emit a single combined call per entity.
friend class Application;
/// Combined entity setup from codegen: set name, object_id hash, entity string indices, and flags. /// Combined entity setup from codegen: set name, object_id hash, entity string indices, and flags.
/// Bit layout of entity_fields is defined by the ENTITY_FIELD_*_SHIFT constants above. /// Bit layout of entity_fields is defined by the ENTITY_FIELD_*_SHIFT constants above.
+30 -2
View File
@@ -23,6 +23,7 @@ from esphome.core.config import (
UNIT_OF_MEASUREMENT_MAX_LENGTH, UNIT_OF_MEASUREMENT_MAX_LENGTH,
) )
from esphome.cpp_generator import MockObj, RawStatement, add, get_variable from esphome.cpp_generator import MockObj, RawStatement, add, get_variable
from esphome.cpp_types import App
import esphome.final_validate as fv import esphome.final_validate as fv
from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case
from esphome.types import ConfigType, EntityMetadata from esphome.types import ConfigType, EntityMetadata
@@ -52,6 +53,12 @@ _KEY_INTERNAL = "_entity_internal"
_KEY_DISABLED_BY_DEFAULT = "_entity_disabled_by_default" _KEY_DISABLED_BY_DEFAULT = "_entity_disabled_by_default"
_KEY_ENTITY_CATEGORY = "_entity_category" _KEY_ENTITY_CATEGORY = "_entity_category"
# Private config key for the App.register_<method> entry point.
# When set, finalize_entity_strings() emits a single combined call
# `App.register_<method>(var, name, hash, packed)` instead of separate
# `App.register_<method>(var)` and `var->configure_entity_(...)` calls.
_KEY_REGISTER_METHOD = "_entity_register_method"
# Maximum unique strings per category (8-bit index, 0 = not set) # Maximum unique strings per category (8-bit index, 0 = not set)
_MAX_DEVICE_CLASSES = 0xFF # 255 _MAX_DEVICE_CLASSES = 0xFF # 255
_MAX_UNITS = 0xFF # 255 _MAX_UNITS = 0xFF # 255
@@ -271,11 +278,26 @@ def _describe_packed_flags(config: ConfigType, entity_category: int) -> str:
return ", ".join(parts) return ", ".join(parts)
def queue_entity_register(method_name: str, config: ConfigType) -> None:
"""Defer ``App.register_<method_name>(var)`` emission to ``finalize_entity_strings``.
When the deferred call is emitted, it is folded with ``configure_entity_`` into
a single ``App.register_<method_name>(var, name, hash, packed)`` call site,
which removes one statement and one method dispatch per entity from the
generated ``main.cpp``.
"""
config[_KEY_REGISTER_METHOD] = method_name
def finalize_entity_strings(var: MockObj, config: ConfigType) -> None: def finalize_entity_strings(var: MockObj, config: ConfigType) -> None:
"""Emit a single configure_entity_() call with name, hash, packed string indices, and flags. """Emit the entity-registration / configure_entity_ tail.
Call this at the end of each component's setup function, after Call this at the end of each component's setup function, after
setup_entity() and any register_device_class/register_unit_of_measurement calls. setup_entity() and any register_device_class/register_unit_of_measurement calls.
If queue_entity_register() was called for this entity, emits one combined call
``App.register_<method>(var, name, hash, packed)``. Otherwise falls back to a
standalone ``var->configure_entity_(name, hash, packed)``.
""" """
entity_name = config[_KEY_ENTITY_NAME] entity_name = config[_KEY_ENTITY_NAME]
object_id_hash = config[_KEY_OBJECT_ID_HASH] object_id_hash = config[_KEY_OBJECT_ID_HASH]
@@ -295,7 +317,13 @@ def finalize_entity_strings(var: MockObj, config: ConfigType) -> None:
) )
# Build inline comment describing the packed flags for readability # Build inline comment describing the packed flags for readability
comment = _describe_packed_flags(config, entity_category) comment = _describe_packed_flags(config, entity_category)
expr = var.configure_entity_(entity_name, object_id_hash, packed) register_method = config.get(_KEY_REGISTER_METHOD)
if register_method is not None:
expr = getattr(App, f"register_{register_method}")(
var, entity_name, object_id_hash, packed
)
else:
expr = var.configure_entity_(entity_name, object_id_hash, packed)
if comment: if comment:
add(RawStatement(f"{expr}; // {comment}")) add(RawStatement(f"{expr}; // {comment}"))
else: else:
@@ -31,7 +31,7 @@ def test_binary_sensor_sets_mandatory_fields(generate_main):
) )
# Then # Then
assert 'bs_1->configure_entity_("test bs1",' in main_cpp assert 'App.register_binary_sensor(bs_1, "test bs1",' in main_cpp
assert "bs_1->set_pin(" in main_cpp assert "bs_1->set_pin(" in main_cpp
+1 -1
View File
@@ -29,7 +29,7 @@ def test_button_sets_mandatory_fields(generate_main):
main_cpp = generate_main("tests/component_tests/button/test_button.yaml") main_cpp = generate_main("tests/component_tests/button/test_button.yaml")
# Then # Then
assert 'wol_1->configure_entity_("wol_test_1",' in main_cpp assert 'App.register_button(wol_1, "wol_test_1",' in main_cpp
assert "wol_2->set_macaddr(18, 52, 86, 120, 144, 171);" in main_cpp assert "wol_2->set_macaddr(18, 52, 86, 120, 144, 171);" in main_cpp
+15 -5
View File
@@ -8,12 +8,22 @@ INTERNAL_BIT = 1 << 24
def extract_packed_value(main_cpp: str, var_name: str) -> int: def extract_packed_value(main_cpp: str, var_name: str) -> int:
"""Extract the third (packed) argument from a configure_entity_ call.""" """Extract the packed-fields argument from the entity's configure call.
pattern = (
rf"{re.escape(var_name)}->configure_entity_\(" Matches both legacy form ``var->configure_entity_(name, hash, packed)`` and the
combined form ``App.register_<entity>(var, name, hash, packed)``.
"""
escaped_var = re.escape(var_name)
legacy_pattern = (
rf"{escaped_var}->configure_entity_\("
r'"(?:\\.|[^"\\])*"' r'"(?:\\.|[^"\\])*"'
r",\s*\w+,\s*(\d+)\)" r",\s*\w+,\s*(\d+)\)"
) )
match = re.search(pattern, main_cpp) combined_pattern = (
assert match, f"configure_entity_ call not found for {var_name}" rf"App\.register_\w+\(\s*{escaped_var}\s*,\s*"
r'"(?:\\.|[^"\\])*"'
r",\s*\w+,\s*(\d+)\)"
)
match = re.search(combined_pattern, main_cpp) or re.search(legacy_pattern, main_cpp)
assert match, f"configure call not found for {var_name}"
return int(match.group(1)) return int(match.group(1))
+1 -1
View File
@@ -28,7 +28,7 @@ def test_text_sets_mandatory_fields(generate_main):
main_cpp = generate_main("tests/component_tests/text/test_text.yaml") main_cpp = generate_main("tests/component_tests/text/test_text.yaml")
# Then # Then
assert 'it_1->configure_entity_("test 1 text",' in main_cpp assert 'App.register_text(it_1, "test 1 text",' in main_cpp
def test_text_config_value_internal_set(generate_main): def test_text_config_value_internal_set(generate_main):
@@ -28,9 +28,9 @@ def test_text_sensor_sets_mandatory_fields(generate_main):
main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml") main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml")
# Then # Then
assert 'ts_1->configure_entity_("Template Text Sensor 1",' in main_cpp assert 'App.register_text_sensor(ts_1, "Template Text Sensor 1",' in main_cpp
assert 'ts_2->configure_entity_("Template Text Sensor 2",' in main_cpp assert 'App.register_text_sensor(ts_2, "Template Text Sensor 2",' in main_cpp
assert 'ts_3->configure_entity_("Template Text Sensor 3",' in main_cpp assert 'App.register_text_sensor(ts_3, "Template Text Sensor 3",' in main_cpp
def test_text_sensor_config_value_internal_set(generate_main): def test_text_sensor_config_value_internal_set(generate_main):