mirror of
https://github.com/esphome/esphome.git
synced 2026-09-29 16:00:23 +00:00
[core] Move the controller dispatch into controller_dispatch.h
Code generation now emits one function returning the registered controllers as a tuple plus an include; the header defines the ControllerRegistry notify functions with a fold expression and checks ControllerContract for every tuple element.
This commit is contained in:
+5
-20
@@ -675,34 +675,19 @@ async def _add_platform_defines() -> None:
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _add_controller_registry_dispatch() -> None:
|
||||
# Define ControllerRegistry::notify_*() in main.cpp as direct calls on each
|
||||
# registered controller. entity_types.h expands one definition per entity
|
||||
# type that is compiled in, so only the callbacks in use are emitted.
|
||||
# controller_dispatch.h defines ControllerRegistry::notify_*() as direct
|
||||
# calls on the controllers returned by esphome_controllers().
|
||||
controllers = CORE.data.get(KEY_CONTROLLER_REGISTRY_CONTROLLERS)
|
||||
if not controllers:
|
||||
return
|
||||
cg.add_define("USE_CONTROLLER_REGISTRY")
|
||||
for var in controllers:
|
||||
cg.add_global(
|
||||
cg.RawStatement(
|
||||
f"static_assert(ControllerContract<std::remove_pointer_t<decltype({var})>>, "
|
||||
f'"{var} is missing an on_*_update() callback for an entity type in this build '
|
||||
'(esphome/core/controller_registry.h)");'
|
||||
)
|
||||
)
|
||||
calls = " \\\n".join(f" {var}->on_##callback(obj);" for var in controllers)
|
||||
entries = ", ".join(str(var) for var in controllers)
|
||||
cg.add_global(
|
||||
cg.RawStatement(
|
||||
"#define ENTITY_TYPE_(type, singular, plural, count, upper)\n"
|
||||
"#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \\\n"
|
||||
" void ControllerRegistry::notify_##callback(type *obj) { \\\n"
|
||||
f"{calls} \\\n"
|
||||
" }\n"
|
||||
'#include "esphome/core/entity_types.h"\n'
|
||||
"#undef ENTITY_TYPE_\n"
|
||||
"#undef ENTITY_CONTROLLER_TYPE_"
|
||||
f"static auto esphome_controllers() {{ return std::tuple{{{entries}}}; }}"
|
||||
)
|
||||
)
|
||||
cg.add_global(cg.RawStatement('#include "esphome/core/controller_dispatch.h"'))
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
// Included once by the generated main.cpp, after it returns the registered controllers as a tuple:
|
||||
//
|
||||
// static auto esphome_controllers() { return std::tuple{api_apiserver_id, web_server_webserver_id}; }
|
||||
// #include "esphome/core/controller_dispatch.h"
|
||||
//
|
||||
// Defines ControllerRegistry::notify_*() as direct calls on those controllers. Excluded from
|
||||
// esphome.h so nothing else includes it.
|
||||
|
||||
#include "esphome/core/controller_registry.h"
|
||||
|
||||
#ifdef USE_CONTROLLER_REGISTRY
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace esphome {
|
||||
|
||||
template<typename... Controllers> constexpr bool controllers_satisfy_contract(std::tuple<Controllers...> *) {
|
||||
static_assert((ControllerContract<std::remove_pointer_t<Controllers>> && ...),
|
||||
"A registered controller is missing an on_*_update() callback for an entity type in this build "
|
||||
"(esphome/core/controller_registry.h)");
|
||||
return true;
|
||||
}
|
||||
static_assert(controllers_satisfy_contract(static_cast<decltype(esphome_controllers()) *>(nullptr)));
|
||||
|
||||
// NOLINTBEGIN(bugprone-macro-parentheses)
|
||||
#define ENTITY_TYPE_(type, singular, plural, count, upper) // no controller callback
|
||||
#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
|
||||
void ControllerRegistry::notify_##callback(type *obj) { \
|
||||
std::apply([obj](auto *...controller) { (controller->on_##callback(obj), ...); }, esphome_controllers()); \
|
||||
}
|
||||
#include "esphome/core/entity_types.h"
|
||||
#undef ENTITY_TYPE_
|
||||
#undef ENTITY_CONTROLLER_TYPE_
|
||||
// NOLINTEND(bugprone-macro-parentheses)
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_CONTROLLER_REGISTRY
|
||||
@@ -211,6 +211,7 @@ VERSION_H_TARGET = "esphome/core/version.h"
|
||||
BUILD_INFO_DATA_H_TARGET = "esphome/core/build_info_data.h"
|
||||
BUILD_INFO_DATA_CPP_TARGET = "esphome/core/build_info_data.cpp"
|
||||
ENTITY_TYPES_H_TARGET = "esphome/core/entity_types.h"
|
||||
CONTROLLER_DISPATCH_H_TARGET = "esphome/core/controller_dispatch.h"
|
||||
ESPHOME_README_TXT = """
|
||||
THIS DIRECTORY IS AUTO-GENERATED, DO NOT MODIFY
|
||||
|
||||
@@ -243,6 +244,9 @@ def copy_src_tree():
|
||||
# new component is loaded by a consumer.
|
||||
esphome_h_exclude = {
|
||||
Path(ENTITY_TYPES_H_TARGET),
|
||||
Path(
|
||||
CONTROLLER_DISPATCH_H_TARGET
|
||||
), # included by main.cpp once ESPHOME_CONTROLLERS is defined
|
||||
Path(
|
||||
"esphome/core/ring_buffer.h"
|
||||
), # moved to components/ring_buffer/, removed in 2026.11.0
|
||||
|
||||
Reference in New Issue
Block a user