diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h
index 6a840661097..8c22d757b67 100644
--- a/esphome/components/web_server/list_entities.h
+++ b/esphome/components/web_server/list_entities.h
@@ -75,6 +75,9 @@ class ListEntitiesIterator final : public ComponentIterator {
#ifdef USE_VALVE
bool on_valve(valve::Valve *obj) override;
#endif
+#ifdef USE_MEDIA_PLAYER
+ bool on_media_player(media_player::MediaPlayer *obj) override { return true; }
+#endif
#ifdef USE_ALARM_CONTROL_PANEL
bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *obj) override;
#endif
diff --git a/esphome/core/application.h b/esphome/core/application.h
index 60087d527d2..b4bb8a1eec9 100644
--- a/esphome/core/application.h
+++ b/esphome/core/application.h
@@ -39,78 +39,7 @@
#include "esphome/components/runtime_stats/runtime_stats.h"
#endif
#include "esphome/core/wake.h"
-#ifdef USE_BINARY_SENSOR
-#include "esphome/components/binary_sensor/binary_sensor.h"
-#endif
-#ifdef USE_SENSOR
-#include "esphome/components/sensor/sensor.h"
-#endif
-#ifdef USE_SWITCH
-#include "esphome/components/switch/switch.h"
-#endif
-#ifdef USE_BUTTON
-#include "esphome/components/button/button.h"
-#endif
-#ifdef USE_TEXT_SENSOR
-#include "esphome/components/text_sensor/text_sensor.h"
-#endif
-#ifdef USE_FAN
-#include "esphome/components/fan/fan.h"
-#endif
-#ifdef USE_CLIMATE
-#include "esphome/components/climate/climate.h"
-#endif
-#ifdef USE_LIGHT
-#include "esphome/components/light/light_state.h"
-#endif
-#ifdef USE_COVER
-#include "esphome/components/cover/cover.h"
-#endif
-#ifdef USE_NUMBER
-#include "esphome/components/number/number.h"
-#endif
-#ifdef USE_DATETIME_DATE
-#include "esphome/components/datetime/date_entity.h"
-#endif
-#ifdef USE_DATETIME_TIME
-#include "esphome/components/datetime/time_entity.h"
-#endif
-#ifdef USE_DATETIME_DATETIME
-#include "esphome/components/datetime/datetime_entity.h"
-#endif
-#ifdef USE_TEXT
-#include "esphome/components/text/text.h"
-#endif
-#ifdef USE_SELECT
-#include "esphome/components/select/select.h"
-#endif
-#ifdef USE_LOCK
-#include "esphome/components/lock/lock.h"
-#endif
-#ifdef USE_VALVE
-#include "esphome/components/valve/valve.h"
-#endif
-#ifdef USE_MEDIA_PLAYER
-#include "esphome/components/media_player/media_player.h"
-#endif
-#ifdef USE_ALARM_CONTROL_PANEL
-#include "esphome/components/alarm_control_panel/alarm_control_panel.h"
-#endif
-#ifdef USE_WATER_HEATER
-#include "esphome/components/water_heater/water_heater.h"
-#endif
-#ifdef USE_INFRARED
-#include "esphome/components/infrared/infrared.h"
-#endif
-#ifdef USE_SERIAL_PROXY
-#include "esphome/components/serial_proxy/serial_proxy.h"
-#endif
-#ifdef USE_EVENT
-#include "esphome/components/event/event.h"
-#endif
-#ifdef USE_UPDATE
-#include "esphome/components/update/update_entity.h"
-#endif
+#include "esphome/core/entity_includes.h"
namespace esphome::socket {
#ifdef USE_HOST
@@ -190,93 +119,16 @@ class Application {
void set_current_component(Component *component) { this->current_component_ = component; }
Component *get_current_component() { return this->current_component_; }
-#ifdef USE_BINARY_SENSOR
- void register_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
- this->binary_sensors_.push_back(binary_sensor);
- }
-#endif
-
-#ifdef USE_SENSOR
- void register_sensor(sensor::Sensor *sensor) { this->sensors_.push_back(sensor); }
-#endif
-
-#ifdef USE_SWITCH
- void register_switch(switch_::Switch *a_switch) { this->switches_.push_back(a_switch); }
-#endif
-
-#ifdef USE_BUTTON
- void register_button(button::Button *button) { this->buttons_.push_back(button); }
-#endif
-
-#ifdef USE_TEXT_SENSOR
- void register_text_sensor(text_sensor::TextSensor *sensor) { this->text_sensors_.push_back(sensor); }
-#endif
-
-#ifdef USE_FAN
- void register_fan(fan::Fan *state) { this->fans_.push_back(state); }
-#endif
-
-#ifdef USE_COVER
- void register_cover(cover::Cover *cover) { this->covers_.push_back(cover); }
-#endif
-
-#ifdef USE_CLIMATE
- void register_climate(climate::Climate *climate) { this->climates_.push_back(climate); }
-#endif
-
-#ifdef USE_LIGHT
- void register_light(light::LightState *light) { this->lights_.push_back(light); }
-#endif
-
-#ifdef USE_NUMBER
- void register_number(number::Number *number) { this->numbers_.push_back(number); }
-#endif
-
-#ifdef USE_DATETIME_DATE
- void register_date(datetime::DateEntity *date) { this->dates_.push_back(date); }
-#endif
-
-#ifdef USE_DATETIME_TIME
- void register_time(datetime::TimeEntity *time) { this->times_.push_back(time); }
-#endif
-
-#ifdef USE_DATETIME_DATETIME
- void register_datetime(datetime::DateTimeEntity *datetime) { this->datetimes_.push_back(datetime); }
-#endif
-
-#ifdef USE_TEXT
- void register_text(text::Text *text) { this->texts_.push_back(text); }
-#endif
-
-#ifdef USE_SELECT
- void register_select(select::Select *select) { this->selects_.push_back(select); }
-#endif
-
-#ifdef USE_LOCK
- void register_lock(lock::Lock *a_lock) { this->locks_.push_back(a_lock); }
-#endif
-
-#ifdef USE_VALVE
- void register_valve(valve::Valve *valve) { this->valves_.push_back(valve); }
-#endif
-
-#ifdef USE_MEDIA_PLAYER
- void register_media_player(media_player::MediaPlayer *media_player) { this->media_players_.push_back(media_player); }
-#endif
-
-#ifdef USE_ALARM_CONTROL_PANEL
- void register_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
- this->alarm_control_panels_.push_back(a_alarm_control_panel);
- }
-#endif
-
-#ifdef USE_WATER_HEATER
- void register_water_heater(water_heater::WaterHeater *water_heater) { this->water_heaters_.push_back(water_heater); }
-#endif
-
-#ifdef USE_INFRARED
- void register_infrared(infrared::Infrared *infrared) { this->infrareds_.push_back(infrared); }
-#endif
+// Entity register methods (generated from entity_types.h)
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define ENTITY_TYPE_(type, singular, plural, count, upper) \
+ void register_##singular(type *obj) { this->plural##_.push_back(obj); }
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
+ ENTITY_TYPE_(type, singular, plural, count, upper)
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+ // NOLINTEND(bugprone-macro-parentheses)
#ifdef USE_SERIAL_PROXY
void register_serial_proxy(serial_proxy::SerialProxy *proxy) {
@@ -285,14 +137,6 @@ class Application {
}
#endif
-#ifdef USE_EVENT
- void register_event(event::Event *event) { this->events_.push_back(event); }
-#endif
-
-#ifdef USE_UPDATE
- void register_update(update::UpdateEntity *update) { this->updates_.push_back(update); }
-#endif
-
/// Reserve space for components to avoid memory fragmentation
/// Set up all the registered components. Call this at the end of your setup() function.
@@ -456,108 +300,22 @@ class Application {
#ifdef USE_AREAS
const auto &get_areas() { return this->areas_; }
#endif
-#ifdef USE_BINARY_SENSOR
- auto &get_binary_sensors() const { return this->binary_sensors_; }
- GET_ENTITY_METHOD(binary_sensor::BinarySensor, binary_sensor, binary_sensors)
-#endif
-#ifdef USE_SWITCH
- auto &get_switches() const { return this->switches_; }
- GET_ENTITY_METHOD(switch_::Switch, switch, switches)
-#endif
-#ifdef USE_BUTTON
- auto &get_buttons() const { return this->buttons_; }
- GET_ENTITY_METHOD(button::Button, button, buttons)
-#endif
-#ifdef USE_SENSOR
- auto &get_sensors() const { return this->sensors_; }
- GET_ENTITY_METHOD(sensor::Sensor, sensor, sensors)
-#endif
-#ifdef USE_TEXT_SENSOR
- auto &get_text_sensors() const { return this->text_sensors_; }
- GET_ENTITY_METHOD(text_sensor::TextSensor, text_sensor, text_sensors)
-#endif
-#ifdef USE_FAN
- auto &get_fans() const { return this->fans_; }
- GET_ENTITY_METHOD(fan::Fan, fan, fans)
-#endif
-#ifdef USE_COVER
- auto &get_covers() const { return this->covers_; }
- GET_ENTITY_METHOD(cover::Cover, cover, covers)
-#endif
-#ifdef USE_LIGHT
- auto &get_lights() const { return this->lights_; }
- GET_ENTITY_METHOD(light::LightState, light, lights)
-#endif
-#ifdef USE_CLIMATE
- auto &get_climates() const { return this->climates_; }
- GET_ENTITY_METHOD(climate::Climate, climate, climates)
-#endif
-#ifdef USE_NUMBER
- auto &get_numbers() const { return this->numbers_; }
- GET_ENTITY_METHOD(number::Number, number, numbers)
-#endif
-#ifdef USE_DATETIME_DATE
- auto &get_dates() const { return this->dates_; }
- GET_ENTITY_METHOD(datetime::DateEntity, date, dates)
-#endif
-#ifdef USE_DATETIME_TIME
- auto &get_times() const { return this->times_; }
- GET_ENTITY_METHOD(datetime::TimeEntity, time, times)
-#endif
-#ifdef USE_DATETIME_DATETIME
- auto &get_datetimes() const { return this->datetimes_; }
- GET_ENTITY_METHOD(datetime::DateTimeEntity, datetime, datetimes)
-#endif
-#ifdef USE_TEXT
- auto &get_texts() const { return this->texts_; }
- GET_ENTITY_METHOD(text::Text, text, texts)
-#endif
-#ifdef USE_SELECT
- auto &get_selects() const { return this->selects_; }
- GET_ENTITY_METHOD(select::Select, select, selects)
-#endif
-#ifdef USE_LOCK
- auto &get_locks() const { return this->locks_; }
- GET_ENTITY_METHOD(lock::Lock, lock, locks)
-#endif
-#ifdef USE_VALVE
- auto &get_valves() const { return this->valves_; }
- GET_ENTITY_METHOD(valve::Valve, valve, valves)
-#endif
-#ifdef USE_MEDIA_PLAYER
- auto &get_media_players() const { return this->media_players_; }
- GET_ENTITY_METHOD(media_player::MediaPlayer, media_player, media_players)
-#endif
-
-#ifdef USE_ALARM_CONTROL_PANEL
- auto &get_alarm_control_panels() const { return this->alarm_control_panels_; }
- GET_ENTITY_METHOD(alarm_control_panel::AlarmControlPanel, alarm_control_panel, alarm_control_panels)
-#endif
-
-#ifdef USE_WATER_HEATER
- auto &get_water_heaters() const { return this->water_heaters_; }
- GET_ENTITY_METHOD(water_heater::WaterHeater, water_heater, water_heaters)
-#endif
-
-#ifdef USE_INFRARED
- auto &get_infrareds() const { return this->infrareds_; }
- GET_ENTITY_METHOD(infrared::Infrared, infrared, infrareds)
-#endif
+// Entity getter methods (generated from entity_types.h)
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define ENTITY_TYPE_(type, singular, plural, count, upper) \
+ auto &get_##plural() const { return this->plural##_; } \
+ GET_ENTITY_METHOD(type, singular, plural)
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
+ ENTITY_TYPE_(type, singular, plural, count, upper)
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+ // NOLINTEND(bugprone-macro-parentheses)
#ifdef USE_SERIAL_PROXY
auto &get_serial_proxies() const { return this->serial_proxies_; }
#endif
-#ifdef USE_EVENT
- auto &get_events() const { return this->events_; }
- GET_ENTITY_METHOD(event::Event, event, events)
-#endif
-
-#ifdef USE_UPDATE
- auto &get_updates() const { return this->updates_; }
- GET_ENTITY_METHOD(update::UpdateEntity, update, updates)
-#endif
-
Scheduler scheduler;
/// Register/unregister a socket to be monitored for read events.
@@ -743,79 +501,19 @@ class Application {
#ifdef USE_AREAS
StaticVector areas_{};
#endif
-#ifdef USE_BINARY_SENSOR
- StaticVector binary_sensors_{};
-#endif
-#ifdef USE_SWITCH
- StaticVector switches_{};
-#endif
-#ifdef USE_BUTTON
- StaticVector buttons_{};
-#endif
-#ifdef USE_EVENT
- StaticVector events_{};
-#endif
-#ifdef USE_SENSOR
- StaticVector sensors_{};
-#endif
-#ifdef USE_TEXT_SENSOR
- StaticVector text_sensors_{};
-#endif
-#ifdef USE_FAN
- StaticVector fans_{};
-#endif
-#ifdef USE_COVER
- StaticVector covers_{};
-#endif
-#ifdef USE_CLIMATE
- StaticVector climates_{};
-#endif
-#ifdef USE_LIGHT
- StaticVector lights_{};
-#endif
-#ifdef USE_NUMBER
- StaticVector numbers_{};
-#endif
-#ifdef USE_DATETIME_DATE
- StaticVector dates_{};
-#endif
-#ifdef USE_DATETIME_TIME
- StaticVector times_{};
-#endif
-#ifdef USE_DATETIME_DATETIME
- StaticVector datetimes_{};
-#endif
-#ifdef USE_SELECT
- StaticVector selects_{};
-#endif
-#ifdef USE_TEXT
- StaticVector texts_{};
-#endif
-#ifdef USE_LOCK
- StaticVector locks_{};
-#endif
-#ifdef USE_VALVE
- StaticVector valves_{};
-#endif
-#ifdef USE_MEDIA_PLAYER
- StaticVector media_players_{};
-#endif
-#ifdef USE_ALARM_CONTROL_PANEL
- StaticVector
- alarm_control_panels_{};
-#endif
-#ifdef USE_WATER_HEATER
- StaticVector water_heaters_{};
-#endif
-#ifdef USE_INFRARED
- StaticVector infrareds_{};
-#endif
+// Entity StaticVector fields (generated from entity_types.h)
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define ENTITY_TYPE_(type, singular, plural, count, upper) StaticVector plural##_{};
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
+ ENTITY_TYPE_(type, singular, plural, count, upper)
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+ // NOLINTEND(bugprone-macro-parentheses)
+
#ifdef USE_SERIAL_PROXY
StaticVector serial_proxies_{};
#endif
-#ifdef USE_UPDATE
- StaticVector updates_{};
-#endif
};
/// Global storage of Application pointer - only one Application can exist.
diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp
index ff76b2b81bf..f4d3c05e190 100644
--- a/esphome/core/component_iterator.cpp
+++ b/esphome/core/component_iterator.cpp
@@ -33,53 +33,18 @@ void ComponentIterator::advance() {
}
break;
-#ifdef USE_BINARY_SENSOR
- case IteratorState::BINARY_SENSOR:
- this->process_platform_item_(App.get_binary_sensors(), &ComponentIterator::on_binary_sensor);
- break;
-#endif
-
-#ifdef USE_COVER
- case IteratorState::COVER:
- this->process_platform_item_(App.get_covers(), &ComponentIterator::on_cover);
- break;
-#endif
-
-#ifdef USE_FAN
- case IteratorState::FAN:
- this->process_platform_item_(App.get_fans(), &ComponentIterator::on_fan);
- break;
-#endif
-
-#ifdef USE_LIGHT
- case IteratorState::LIGHT:
- this->process_platform_item_(App.get_lights(), &ComponentIterator::on_light);
- break;
-#endif
-
-#ifdef USE_SENSOR
- case IteratorState::SENSOR:
- this->process_platform_item_(App.get_sensors(), &ComponentIterator::on_sensor);
- break;
-#endif
-
-#ifdef USE_SWITCH
- case IteratorState::SWITCH:
- this->process_platform_item_(App.get_switches(), &ComponentIterator::on_switch);
- break;
-#endif
-
-#ifdef USE_BUTTON
- case IteratorState::BUTTON:
- this->process_platform_item_(App.get_buttons(), &ComponentIterator::on_button);
- break;
-#endif
-
-#ifdef USE_TEXT_SENSOR
- case IteratorState::TEXT_SENSOR:
- this->process_platform_item_(App.get_text_sensors(), &ComponentIterator::on_text_sensor);
- break;
-#endif
+// Entity iterator cases (generated from entity_types.h)
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define ENTITY_TYPE_(type, singular, plural, count, upper) \
+ case IteratorState::upper: \
+ this->process_platform_item_(App.get_##plural(), &ComponentIterator::on_##singular); \
+ break;
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
+ ENTITY_TYPE_(type, singular, plural, count, upper)
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+ // NOLINTEND(bugprone-macro-parentheses)
#ifdef USE_API_USER_DEFINED_ACTIONS
case IteratorState::SERVICE:
@@ -97,96 +62,6 @@ void ComponentIterator::advance() {
} break;
#endif
-#ifdef USE_CLIMATE
- case IteratorState::CLIMATE:
- this->process_platform_item_(App.get_climates(), &ComponentIterator::on_climate);
- break;
-#endif
-
-#ifdef USE_NUMBER
- case IteratorState::NUMBER:
- this->process_platform_item_(App.get_numbers(), &ComponentIterator::on_number);
- break;
-#endif
-
-#ifdef USE_DATETIME_DATE
- case IteratorState::DATETIME_DATE:
- this->process_platform_item_(App.get_dates(), &ComponentIterator::on_date);
- break;
-#endif
-
-#ifdef USE_DATETIME_TIME
- case IteratorState::DATETIME_TIME:
- this->process_platform_item_(App.get_times(), &ComponentIterator::on_time);
- break;
-#endif
-
-#ifdef USE_DATETIME_DATETIME
- case IteratorState::DATETIME_DATETIME:
- this->process_platform_item_(App.get_datetimes(), &ComponentIterator::on_datetime);
- break;
-#endif
-
-#ifdef USE_TEXT
- case IteratorState::TEXT:
- this->process_platform_item_(App.get_texts(), &ComponentIterator::on_text);
- break;
-#endif
-
-#ifdef USE_SELECT
- case IteratorState::SELECT:
- this->process_platform_item_(App.get_selects(), &ComponentIterator::on_select);
- break;
-#endif
-
-#ifdef USE_LOCK
- case IteratorState::LOCK:
- this->process_platform_item_(App.get_locks(), &ComponentIterator::on_lock);
- break;
-#endif
-
-#ifdef USE_VALVE
- case IteratorState::VALVE:
- this->process_platform_item_(App.get_valves(), &ComponentIterator::on_valve);
- break;
-#endif
-
-#ifdef USE_MEDIA_PLAYER
- case IteratorState::MEDIA_PLAYER:
- this->process_platform_item_(App.get_media_players(), &ComponentIterator::on_media_player);
- break;
-#endif
-
-#ifdef USE_ALARM_CONTROL_PANEL
- case IteratorState::ALARM_CONTROL_PANEL:
- this->process_platform_item_(App.get_alarm_control_panels(), &ComponentIterator::on_alarm_control_panel);
- break;
-#endif
-
-#ifdef USE_WATER_HEATER
- case IteratorState::WATER_HEATER:
- this->process_platform_item_(App.get_water_heaters(), &ComponentIterator::on_water_heater);
- break;
-#endif
-
-#ifdef USE_INFRARED
- case IteratorState::INFRARED:
- this->process_platform_item_(App.get_infrareds(), &ComponentIterator::on_infrared);
- break;
-#endif
-
-#ifdef USE_EVENT
- case IteratorState::EVENT:
- this->process_platform_item_(App.get_events(), &ComponentIterator::on_event);
- break;
-#endif
-
-#ifdef USE_UPDATE
- case IteratorState::UPDATE:
- this->process_platform_item_(App.get_updates(), &ComponentIterator::on_update);
- break;
-#endif
-
case IteratorState::MAX:
if (this->on_end()) {
this->state_ = IteratorState::NONE;
@@ -203,7 +78,4 @@ bool ComponentIterator::on_service(api::UserServiceDescriptor *service) { return
#ifdef USE_CAMERA
bool ComponentIterator::on_camera(camera::Camera *camera) { return true; }
#endif
-#ifdef USE_MEDIA_PLAYER
-bool ComponentIterator::on_media_player(media_player::MediaPlayer *media_player) { return true; }
-#endif
} // namespace esphome
diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h
index 6c03b74a17c..9a1e5da3518 100644
--- a/esphome/core/component_iterator.h
+++ b/esphome/core/component_iterator.h
@@ -28,80 +28,21 @@ class ComponentIterator {
void advance();
bool completed() const { return this->state_ == IteratorState::NONE; }
virtual bool on_begin();
-#ifdef USE_BINARY_SENSOR
- virtual bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) = 0;
-#endif
-#ifdef USE_COVER
- virtual bool on_cover(cover::Cover *cover) = 0;
-#endif
-#ifdef USE_FAN
- virtual bool on_fan(fan::Fan *fan) = 0;
-#endif
-#ifdef USE_LIGHT
- virtual bool on_light(light::LightState *light) = 0;
-#endif
-#ifdef USE_SENSOR
- virtual bool on_sensor(sensor::Sensor *sensor) = 0;
-#endif
-#ifdef USE_SWITCH
- virtual bool on_switch(switch_::Switch *a_switch) = 0;
-#endif
-#ifdef USE_BUTTON
- virtual bool on_button(button::Button *button) = 0;
-#endif
-#ifdef USE_TEXT_SENSOR
- virtual bool on_text_sensor(text_sensor::TextSensor *text_sensor) = 0;
-#endif
+// Pure virtual entity callbacks (generated from entity_types.h)
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define ENTITY_TYPE_(type, singular, plural, count, upper) virtual bool on_##singular(type *obj) = 0;
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
+ ENTITY_TYPE_(type, singular, plural, count, upper)
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+// NOLINTEND(bugprone-macro-parentheses)
+// Non-entity and non-pure-virtual callbacks (have default implementations)
#ifdef USE_API_USER_DEFINED_ACTIONS
virtual bool on_service(api::UserServiceDescriptor *service);
#endif
#ifdef USE_CAMERA
virtual bool on_camera(camera::Camera *camera);
-#endif
-#ifdef USE_CLIMATE
- virtual bool on_climate(climate::Climate *climate) = 0;
-#endif
-#ifdef USE_NUMBER
- virtual bool on_number(number::Number *number) = 0;
-#endif
-#ifdef USE_DATETIME_DATE
- virtual bool on_date(datetime::DateEntity *date) = 0;
-#endif
-#ifdef USE_DATETIME_TIME
- virtual bool on_time(datetime::TimeEntity *time) = 0;
-#endif
-#ifdef USE_DATETIME_DATETIME
- virtual bool on_datetime(datetime::DateTimeEntity *datetime) = 0;
-#endif
-#ifdef USE_TEXT
- virtual bool on_text(text::Text *text) = 0;
-#endif
-#ifdef USE_SELECT
- virtual bool on_select(select::Select *select) = 0;
-#endif
-#ifdef USE_LOCK
- virtual bool on_lock(lock::Lock *a_lock) = 0;
-#endif
-#ifdef USE_VALVE
- virtual bool on_valve(valve::Valve *valve) = 0;
-#endif
-#ifdef USE_MEDIA_PLAYER
- virtual bool on_media_player(media_player::MediaPlayer *media_player);
-#endif
-#ifdef USE_ALARM_CONTROL_PANEL
- virtual bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) = 0;
-#endif
-#ifdef USE_WATER_HEATER
- virtual bool on_water_heater(water_heater::WaterHeater *water_heater) = 0;
-#endif
-#ifdef USE_INFRARED
- virtual bool on_infrared(infrared::Infrared *infrared) = 0;
-#endif
-#ifdef USE_EVENT
- virtual bool on_event(event::Event *event) = 0;
-#endif
-#ifdef USE_UPDATE
- virtual bool on_update(update::UpdateEntity *update) = 0;
#endif
virtual bool on_end();
@@ -111,80 +52,19 @@ class ComponentIterator {
enum class IteratorState : uint8_t {
NONE = 0,
BEGIN,
-#ifdef USE_BINARY_SENSOR
- BINARY_SENSOR,
-#endif
-#ifdef USE_COVER
- COVER,
-#endif
-#ifdef USE_FAN
- FAN,
-#endif
-#ifdef USE_LIGHT
- LIGHT,
-#endif
-#ifdef USE_SENSOR
- SENSOR,
-#endif
-#ifdef USE_SWITCH
- SWITCH,
-#endif
-#ifdef USE_BUTTON
- BUTTON,
-#endif
-#ifdef USE_TEXT_SENSOR
- TEXT_SENSOR,
-#endif
+// Entity iterator states (generated from entity_types.h)
+// NOLINTBEGIN(bugprone-macro-parentheses)
+#define ENTITY_TYPE_(type, singular, plural, count, upper) upper,
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) upper,
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+// NOLINTEND(bugprone-macro-parentheses)
#ifdef USE_API_USER_DEFINED_ACTIONS
SERVICE,
#endif
#ifdef USE_CAMERA
CAMERA,
-#endif
-#ifdef USE_CLIMATE
- CLIMATE,
-#endif
-#ifdef USE_NUMBER
- NUMBER,
-#endif
-#ifdef USE_DATETIME_DATE
- DATETIME_DATE,
-#endif
-#ifdef USE_DATETIME_TIME
- DATETIME_TIME,
-#endif
-#ifdef USE_DATETIME_DATETIME
- DATETIME_DATETIME,
-#endif
-#ifdef USE_TEXT
- TEXT,
-#endif
-#ifdef USE_SELECT
- SELECT,
-#endif
-#ifdef USE_LOCK
- LOCK,
-#endif
-#ifdef USE_VALVE
- VALVE,
-#endif
-#ifdef USE_MEDIA_PLAYER
- MEDIA_PLAYER,
-#endif
-#ifdef USE_ALARM_CONTROL_PANEL
- ALARM_CONTROL_PANEL,
-#endif
-#ifdef USE_WATER_HEATER
- WATER_HEATER,
-#endif
-#ifdef USE_INFRARED
- INFRARED,
-#endif
-#ifdef USE_EVENT
- EVENT,
-#endif
-#ifdef USE_UPDATE
- UPDATE,
#endif
MAX,
};
diff --git a/esphome/core/controller.h b/esphome/core/controller.h
index 632b46c8937..09975b465f8 100644
--- a/esphome/core/controller.h
+++ b/esphome/core/controller.h
@@ -1,140 +1,19 @@
#pragma once
-#include "esphome/core/defines.h"
-#ifdef USE_BINARY_SENSOR
-#include "esphome/components/binary_sensor/binary_sensor.h"
-#endif
-#ifdef USE_FAN
-#include "esphome/components/fan/fan.h"
-#endif
-#ifdef USE_LIGHT
-#include "esphome/components/light/light_state.h"
-#endif
-#ifdef USE_COVER
-#include "esphome/components/cover/cover.h"
-#endif
-#ifdef USE_SENSOR
-#include "esphome/components/sensor/sensor.h"
-#endif
-#ifdef USE_TEXT_SENSOR
-#include "esphome/components/text_sensor/text_sensor.h"
-#endif
-#ifdef USE_SWITCH
-#include "esphome/components/switch/switch.h"
-#endif
-#ifdef USE_BUTTON
-#include "esphome/components/button/button.h"
-#endif
-#ifdef USE_CLIMATE
-#include "esphome/components/climate/climate.h"
-#endif
-#ifdef USE_NUMBER
-#include "esphome/components/number/number.h"
-#endif
-#ifdef USE_DATETIME_DATE
-#include "esphome/components/datetime/date_entity.h"
-#endif
-#ifdef USE_DATETIME_TIME
-#include "esphome/components/datetime/time_entity.h"
-#endif
-#ifdef USE_DATETIME_DATETIME
-#include "esphome/components/datetime/datetime_entity.h"
-#endif
-#ifdef USE_TEXT
-#include "esphome/components/text/text.h"
-#endif
-#ifdef USE_SELECT
-#include "esphome/components/select/select.h"
-#endif
-#ifdef USE_LOCK
-#include "esphome/components/lock/lock.h"
-#endif
-#ifdef USE_VALVE
-#include "esphome/components/valve/valve.h"
-#endif
-#ifdef USE_MEDIA_PLAYER
-#include "esphome/components/media_player/media_player.h"
-#endif
-#ifdef USE_ALARM_CONTROL_PANEL
-#include "esphome/components/alarm_control_panel/alarm_control_panel.h"
-#endif
-#ifdef USE_WATER_HEATER
-#include "esphome/components/water_heater/water_heater.h"
-#endif
-#ifdef USE_EVENT
-#include "esphome/components/event/event.h"
-#endif
-#ifdef USE_UPDATE
-#include "esphome/components/update/update_entity.h"
-#endif
+#include "esphome/core/entity_includes.h"
namespace esphome {
class Controller {
public:
-#ifdef USE_BINARY_SENSOR
- virtual void on_binary_sensor_update(binary_sensor::BinarySensor *obj){};
-#endif
-#ifdef USE_FAN
- virtual void on_fan_update(fan::Fan *obj){};
-#endif
-#ifdef USE_LIGHT
- virtual void on_light_update(light::LightState *obj){};
-#endif
-#ifdef USE_SENSOR
- virtual void on_sensor_update(sensor::Sensor *obj){};
-#endif
-#ifdef USE_SWITCH
- virtual void on_switch_update(switch_::Switch *obj){};
-#endif
-#ifdef USE_COVER
- virtual void on_cover_update(cover::Cover *obj){};
-#endif
-#ifdef USE_TEXT_SENSOR
- virtual void on_text_sensor_update(text_sensor::TextSensor *obj){};
-#endif
-#ifdef USE_CLIMATE
- virtual void on_climate_update(climate::Climate *obj){};
-#endif
-#ifdef USE_NUMBER
- virtual void on_number_update(number::Number *obj){};
-#endif
-#ifdef USE_DATETIME_DATE
- virtual void on_date_update(datetime::DateEntity *obj){};
-#endif
-#ifdef USE_DATETIME_TIME
- virtual void on_time_update(datetime::TimeEntity *obj){};
-#endif
-#ifdef USE_DATETIME_DATETIME
- virtual void on_datetime_update(datetime::DateTimeEntity *obj){};
-#endif
-#ifdef USE_TEXT
- virtual void on_text_update(text::Text *obj){};
-#endif
-#ifdef USE_SELECT
- virtual void on_select_update(select::Select *obj){};
-#endif
-#ifdef USE_LOCK
- virtual void on_lock_update(lock::Lock *obj){};
-#endif
-#ifdef USE_VALVE
- virtual void on_valve_update(valve::Valve *obj){};
-#endif
-#ifdef USE_MEDIA_PLAYER
- virtual void on_media_player_update(media_player::MediaPlayer *obj){};
-#endif
-#ifdef USE_ALARM_CONTROL_PANEL
- virtual void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj){};
-#endif
-#ifdef USE_WATER_HEATER
- virtual void on_water_heater_update(water_heater::WaterHeater *obj){};
-#endif
-#ifdef USE_EVENT
- virtual void on_event(event::Event *obj){};
-#endif
-#ifdef USE_UPDATE
- virtual void on_update(update::UpdateEntity *obj){};
-#endif
+// Controller virtual methods (generated from entity_types.h)
+// 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) virtual void on_##callback(type *obj){};
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+ // NOLINTEND(bugprone-macro-parentheses)
};
} // namespace esphome
diff --git a/esphome/core/controller_registry.cpp b/esphome/core/controller_registry.cpp
index 92f23f56427..907e0f923d6 100644
--- a/esphome/core/controller_registry.cpp
+++ b/esphome/core/controller_registry.cpp
@@ -6,8 +6,6 @@ namespace esphome {
StaticVector ControllerRegistry::controllers;
-void ControllerRegistry::register_controller(Controller *controller) { controllers.push_back(controller); }
-
} // namespace esphome
#endif // USE_CONTROLLER_REGISTRY
diff --git a/esphome/core/controller_registry.h b/esphome/core/controller_registry.h
index 846642da292..c6113116ffd 100644
--- a/esphome/core/controller_registry.h
+++ b/esphome/core/controller_registry.h
@@ -4,139 +4,13 @@
#ifdef USE_CONTROLLER_REGISTRY
+#include "esphome/core/entity_includes.h"
#include "esphome/core/helpers.h"
-// Forward declarations
namespace esphome {
class Controller;
-#ifdef USE_BINARY_SENSOR
-namespace binary_sensor {
-class BinarySensor;
-}
-#endif
-
-#ifdef USE_FAN
-namespace fan {
-class Fan;
-}
-#endif
-
-#ifdef USE_LIGHT
-namespace light {
-class LightState;
-}
-#endif
-
-#ifdef USE_SENSOR
-namespace sensor {
-class Sensor;
-}
-#endif
-
-#ifdef USE_SWITCH
-namespace switch_ {
-class Switch;
-}
-#endif
-
-#ifdef USE_COVER
-namespace cover {
-class Cover;
-}
-#endif
-
-#ifdef USE_TEXT_SENSOR
-namespace text_sensor {
-class TextSensor;
-}
-#endif
-
-#ifdef USE_CLIMATE
-namespace climate {
-class Climate;
-}
-#endif
-
-#ifdef USE_NUMBER
-namespace number {
-class Number;
-}
-#endif
-
-#ifdef USE_DATETIME_DATE
-namespace datetime {
-class DateEntity;
-}
-#endif
-
-#ifdef USE_DATETIME_TIME
-namespace datetime {
-class TimeEntity;
-}
-#endif
-
-#ifdef USE_DATETIME_DATETIME
-namespace datetime {
-class DateTimeEntity;
-}
-#endif
-
-#ifdef USE_TEXT
-namespace text {
-class Text;
-}
-#endif
-
-#ifdef USE_SELECT
-namespace select {
-class Select;
-}
-#endif
-
-#ifdef USE_LOCK
-namespace lock {
-class Lock;
-}
-#endif
-
-#ifdef USE_VALVE
-namespace valve {
-class Valve;
-}
-#endif
-
-#ifdef USE_MEDIA_PLAYER
-namespace media_player {
-class MediaPlayer;
-}
-#endif
-
-#ifdef USE_ALARM_CONTROL_PANEL
-namespace alarm_control_panel {
-class AlarmControlPanel;
-}
-#endif
-
-#ifdef USE_WATER_HEATER
-namespace water_heater {
-class WaterHeater;
-}
-#endif
-
-#ifdef USE_EVENT
-namespace event {
-class Event;
-}
-#endif
-
-#ifdef USE_UPDATE
-namespace update {
-class UpdateEntity;
-}
-#endif
-
/** Global registry for Controllers to receive entity state updates.
*
* This singleton registry allows Controllers (APIServer, WebServer) to receive
@@ -160,91 +34,17 @@ class ControllerRegistry {
* Controllers should call this in their setup() method.
* Typically only APIServer and WebServer register.
*/
- static void register_controller(Controller *controller);
+ static void register_controller(Controller *controller) { controllers.push_back(controller); }
-#ifdef USE_BINARY_SENSOR
- static void notify_binary_sensor_update(binary_sensor::BinarySensor *obj);
-#endif
-
-#ifdef USE_FAN
- static void notify_fan_update(fan::Fan *obj);
-#endif
-
-#ifdef USE_LIGHT
- static void notify_light_update(light::LightState *obj);
-#endif
-
-#ifdef USE_SENSOR
- static void notify_sensor_update(sensor::Sensor *obj);
-#endif
-
-#ifdef USE_SWITCH
- static void notify_switch_update(switch_::Switch *obj);
-#endif
-
-#ifdef USE_COVER
- static void notify_cover_update(cover::Cover *obj);
-#endif
-
-#ifdef USE_TEXT_SENSOR
- static void notify_text_sensor_update(text_sensor::TextSensor *obj);
-#endif
-
-#ifdef USE_CLIMATE
- static void notify_climate_update(climate::Climate *obj);
-#endif
-
-#ifdef USE_NUMBER
- static void notify_number_update(number::Number *obj);
-#endif
-
-#ifdef USE_DATETIME_DATE
- static void notify_date_update(datetime::DateEntity *obj);
-#endif
-
-#ifdef USE_DATETIME_TIME
- static void notify_time_update(datetime::TimeEntity *obj);
-#endif
-
-#ifdef USE_DATETIME_DATETIME
- static void notify_datetime_update(datetime::DateTimeEntity *obj);
-#endif
-
-#ifdef USE_TEXT
- static void notify_text_update(text::Text *obj);
-#endif
-
-#ifdef USE_SELECT
- static void notify_select_update(select::Select *obj);
-#endif
-
-#ifdef USE_LOCK
- static void notify_lock_update(lock::Lock *obj);
-#endif
-
-#ifdef USE_VALVE
- static void notify_valve_update(valve::Valve *obj);
-#endif
-
-#ifdef USE_MEDIA_PLAYER
- static void notify_media_player_update(media_player::MediaPlayer *obj);
-#endif
-
-#ifdef USE_ALARM_CONTROL_PANEL
- static void notify_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj);
-#endif
-
-#ifdef USE_WATER_HEATER
- static void notify_water_heater_update(water_heater::WaterHeater *obj);
-#endif
-
-#ifdef USE_EVENT
- static void notify_event(event::Event *obj);
-#endif
-
-#ifdef USE_UPDATE
- static void notify_update(update::UpdateEntity *obj);
-#endif
+// Notify method declarations (generated from entity_types.h)
+// 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) \
+ static void notify_##callback(type *obj);
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
+ // NOLINTEND(bugprone-macro-parentheses)
protected:
static StaticVector controllers;
@@ -265,108 +65,18 @@ namespace esphome {
// notify_frontend_(), eliminating an unnecessary function-call frame.
// NOLINTBEGIN(bugprone-macro-parentheses)
-#define CONTROLLER_REGISTRY_NOTIFY(entity_type, entity_name) \
- inline void ControllerRegistry::notify_##entity_name##_update(entity_type *obj) { \
+#define ENTITY_TYPE_(type, singular, plural, count, upper) // no controller callback
+#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
+ inline void ControllerRegistry::notify_##callback(type *obj) { \
for (auto *controller : controllers) { \
- controller->on_##entity_name##_update(obj); \
- } \
- }
-
-#define CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(entity_type, entity_name) \
- inline void ControllerRegistry::notify_##entity_name(entity_type *obj) { \
- for (auto *controller : controllers) { \
- controller->on_##entity_name(obj); \
+ controller->on_##callback(obj); \
} \
}
+#include "esphome/core/entity_types.h"
+#undef ENTITY_TYPE_
+#undef ENTITY_CONTROLLER_TYPE_
// NOLINTEND(bugprone-macro-parentheses)
-#ifdef USE_BINARY_SENSOR
-CONTROLLER_REGISTRY_NOTIFY(binary_sensor::BinarySensor, binary_sensor)
-#endif
-
-#ifdef USE_FAN
-CONTROLLER_REGISTRY_NOTIFY(fan::Fan, fan)
-#endif
-
-#ifdef USE_LIGHT
-CONTROLLER_REGISTRY_NOTIFY(light::LightState, light)
-#endif
-
-#ifdef USE_SENSOR
-CONTROLLER_REGISTRY_NOTIFY(sensor::Sensor, sensor)
-#endif
-
-#ifdef USE_SWITCH
-CONTROLLER_REGISTRY_NOTIFY(switch_::Switch, switch)
-#endif
-
-#ifdef USE_COVER
-CONTROLLER_REGISTRY_NOTIFY(cover::Cover, cover)
-#endif
-
-#ifdef USE_TEXT_SENSOR
-CONTROLLER_REGISTRY_NOTIFY(text_sensor::TextSensor, text_sensor)
-#endif
-
-#ifdef USE_CLIMATE
-CONTROLLER_REGISTRY_NOTIFY(climate::Climate, climate)
-#endif
-
-#ifdef USE_NUMBER
-CONTROLLER_REGISTRY_NOTIFY(number::Number, number)
-#endif
-
-#ifdef USE_DATETIME_DATE
-CONTROLLER_REGISTRY_NOTIFY(datetime::DateEntity, date)
-#endif
-
-#ifdef USE_DATETIME_TIME
-CONTROLLER_REGISTRY_NOTIFY(datetime::TimeEntity, time)
-#endif
-
-#ifdef USE_DATETIME_DATETIME
-CONTROLLER_REGISTRY_NOTIFY(datetime::DateTimeEntity, datetime)
-#endif
-
-#ifdef USE_TEXT
-CONTROLLER_REGISTRY_NOTIFY(text::Text, text)
-#endif
-
-#ifdef USE_SELECT
-CONTROLLER_REGISTRY_NOTIFY(select::Select, select)
-#endif
-
-#ifdef USE_LOCK
-CONTROLLER_REGISTRY_NOTIFY(lock::Lock, lock)
-#endif
-
-#ifdef USE_VALVE
-CONTROLLER_REGISTRY_NOTIFY(valve::Valve, valve)
-#endif
-
-#ifdef USE_MEDIA_PLAYER
-CONTROLLER_REGISTRY_NOTIFY(media_player::MediaPlayer, media_player)
-#endif
-
-#ifdef USE_ALARM_CONTROL_PANEL
-CONTROLLER_REGISTRY_NOTIFY(alarm_control_panel::AlarmControlPanel, alarm_control_panel)
-#endif
-
-#ifdef USE_WATER_HEATER
-CONTROLLER_REGISTRY_NOTIFY(water_heater::WaterHeater, water_heater)
-#endif
-
-#ifdef USE_EVENT
-CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(event::Event, event)
-#endif
-
-#ifdef USE_UPDATE
-CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(update::UpdateEntity, update)
-#endif
-
-#undef CONTROLLER_REGISTRY_NOTIFY
-#undef CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX
-
} // namespace esphome
#endif // USE_CONTROLLER_REGISTRY
diff --git a/esphome/core/entity_includes.h b/esphome/core/entity_includes.h
new file mode 100644
index 00000000000..f67887b30be
--- /dev/null
+++ b/esphome/core/entity_includes.h
@@ -0,0 +1,79 @@
+#pragma once
+
+// Shared entity component includes.
+// Conditionally includes headers for all entity types based on USE_* defines.
+
+#include "esphome/core/defines.h"
+
+#ifdef USE_BINARY_SENSOR
+#include "esphome/components/binary_sensor/binary_sensor.h"
+#endif
+#ifdef USE_COVER
+#include "esphome/components/cover/cover.h"
+#endif
+#ifdef USE_FAN
+#include "esphome/components/fan/fan.h"
+#endif
+#ifdef USE_LIGHT
+#include "esphome/components/light/light_state.h"
+#endif
+#ifdef USE_SENSOR
+#include "esphome/components/sensor/sensor.h"
+#endif
+#ifdef USE_SWITCH
+#include "esphome/components/switch/switch.h"
+#endif
+#ifdef USE_BUTTON
+#include "esphome/components/button/button.h"
+#endif
+#ifdef USE_TEXT_SENSOR
+#include "esphome/components/text_sensor/text_sensor.h"
+#endif
+#ifdef USE_CLIMATE
+#include "esphome/components/climate/climate.h"
+#endif
+#ifdef USE_NUMBER
+#include "esphome/components/number/number.h"
+#endif
+#ifdef USE_DATETIME_DATE
+#include "esphome/components/datetime/date_entity.h"
+#endif
+#ifdef USE_DATETIME_TIME
+#include "esphome/components/datetime/time_entity.h"
+#endif
+#ifdef USE_DATETIME_DATETIME
+#include "esphome/components/datetime/datetime_entity.h"
+#endif
+#ifdef USE_TEXT
+#include "esphome/components/text/text.h"
+#endif
+#ifdef USE_SELECT
+#include "esphome/components/select/select.h"
+#endif
+#ifdef USE_LOCK
+#include "esphome/components/lock/lock.h"
+#endif
+#ifdef USE_VALVE
+#include "esphome/components/valve/valve.h"
+#endif
+#ifdef USE_MEDIA_PLAYER
+#include "esphome/components/media_player/media_player.h"
+#endif
+#ifdef USE_ALARM_CONTROL_PANEL
+#include "esphome/components/alarm_control_panel/alarm_control_panel.h"
+#endif
+#ifdef USE_WATER_HEATER
+#include "esphome/components/water_heater/water_heater.h"
+#endif
+#ifdef USE_INFRARED
+#include "esphome/components/infrared/infrared.h"
+#endif
+#ifdef USE_SERIAL_PROXY
+#include "esphome/components/serial_proxy/serial_proxy.h"
+#endif
+#ifdef USE_EVENT
+#include "esphome/components/event/event.h"
+#endif
+#ifdef USE_UPDATE
+#include "esphome/components/update/update_entity.h"
+#endif
diff --git a/esphome/core/entity_types.h b/esphome/core/entity_types.h
new file mode 100644
index 00000000000..04b490e10ea
--- /dev/null
+++ b/esphome/core/entity_types.h
@@ -0,0 +1,98 @@
+// X-macro include file for entity type declarations.
+// This file is included multiple times with different macro definitions.
+//
+// Both macros must be defined before including this file:
+//
+// ENTITY_TYPE_(type, singular, plural, count, upper)
+// — entities without controller callbacks (button, infrared)
+//
+// ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback)
+// — entities with controller callbacks
+//
+// Excluded from this list (handled manually):
+// - devices/areas: not entities
+// - serial_proxy: custom register logic, no by-key lookup
+
+#ifndef ENTITY_TYPE_
+#error "ENTITY_TYPE_(type, singular, plural, count, upper) must be defined before including entity_types.h"
+#endif
+#ifndef ENTITY_CONTROLLER_TYPE_
+#error \
+ "ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) must be defined before including entity_types.h"
+#endif
+
+#ifdef USE_BINARY_SENSOR
+ENTITY_CONTROLLER_TYPE_(binary_sensor::BinarySensor, binary_sensor, binary_sensors, ESPHOME_ENTITY_BINARY_SENSOR_COUNT,
+ BINARY_SENSOR, binary_sensor_update)
+#endif
+#ifdef USE_COVER
+ENTITY_CONTROLLER_TYPE_(cover::Cover, cover, covers, ESPHOME_ENTITY_COVER_COUNT, COVER, cover_update)
+#endif
+#ifdef USE_FAN
+ENTITY_CONTROLLER_TYPE_(fan::Fan, fan, fans, ESPHOME_ENTITY_FAN_COUNT, FAN, fan_update)
+#endif
+#ifdef USE_LIGHT
+ENTITY_CONTROLLER_TYPE_(light::LightState, light, lights, ESPHOME_ENTITY_LIGHT_COUNT, LIGHT, light_update)
+#endif
+#ifdef USE_SENSOR
+ENTITY_CONTROLLER_TYPE_(sensor::Sensor, sensor, sensors, ESPHOME_ENTITY_SENSOR_COUNT, SENSOR, sensor_update)
+#endif
+#ifdef USE_SWITCH
+ENTITY_CONTROLLER_TYPE_(switch_::Switch, switch, switches, ESPHOME_ENTITY_SWITCH_COUNT, SWITCH, switch_update)
+#endif
+#ifdef USE_BUTTON
+ENTITY_TYPE_(button::Button, button, buttons, ESPHOME_ENTITY_BUTTON_COUNT, BUTTON)
+#endif
+#ifdef USE_TEXT_SENSOR
+ENTITY_CONTROLLER_TYPE_(text_sensor::TextSensor, text_sensor, text_sensors, ESPHOME_ENTITY_TEXT_SENSOR_COUNT,
+ TEXT_SENSOR, text_sensor_update)
+#endif
+#ifdef USE_CLIMATE
+ENTITY_CONTROLLER_TYPE_(climate::Climate, climate, climates, ESPHOME_ENTITY_CLIMATE_COUNT, CLIMATE, climate_update)
+#endif
+#ifdef USE_NUMBER
+ENTITY_CONTROLLER_TYPE_(number::Number, number, numbers, ESPHOME_ENTITY_NUMBER_COUNT, NUMBER, number_update)
+#endif
+#ifdef USE_DATETIME_DATE
+ENTITY_CONTROLLER_TYPE_(datetime::DateEntity, date, dates, ESPHOME_ENTITY_DATE_COUNT, DATETIME_DATE, date_update)
+#endif
+#ifdef USE_DATETIME_TIME
+ENTITY_CONTROLLER_TYPE_(datetime::TimeEntity, time, times, ESPHOME_ENTITY_TIME_COUNT, DATETIME_TIME, time_update)
+#endif
+#ifdef USE_DATETIME_DATETIME
+ENTITY_CONTROLLER_TYPE_(datetime::DateTimeEntity, datetime, datetimes, ESPHOME_ENTITY_DATETIME_COUNT, DATETIME_DATETIME,
+ datetime_update)
+#endif
+#ifdef USE_TEXT
+ENTITY_CONTROLLER_TYPE_(text::Text, text, texts, ESPHOME_ENTITY_TEXT_COUNT, TEXT, text_update)
+#endif
+#ifdef USE_SELECT
+ENTITY_CONTROLLER_TYPE_(select::Select, select, selects, ESPHOME_ENTITY_SELECT_COUNT, SELECT, select_update)
+#endif
+#ifdef USE_LOCK
+ENTITY_CONTROLLER_TYPE_(lock::Lock, lock, locks, ESPHOME_ENTITY_LOCK_COUNT, LOCK, lock_update)
+#endif
+#ifdef USE_VALVE
+ENTITY_CONTROLLER_TYPE_(valve::Valve, valve, valves, ESPHOME_ENTITY_VALVE_COUNT, VALVE, valve_update)
+#endif
+#ifdef USE_MEDIA_PLAYER
+ENTITY_CONTROLLER_TYPE_(media_player::MediaPlayer, media_player, media_players, ESPHOME_ENTITY_MEDIA_PLAYER_COUNT,
+ MEDIA_PLAYER, media_player_update)
+#endif
+#ifdef USE_ALARM_CONTROL_PANEL
+ENTITY_CONTROLLER_TYPE_(alarm_control_panel::AlarmControlPanel, alarm_control_panel, alarm_control_panels,
+ ESPHOME_ENTITY_ALARM_CONTROL_PANEL_COUNT, ALARM_CONTROL_PANEL, alarm_control_panel_update)
+#endif
+#ifdef USE_WATER_HEATER
+ENTITY_CONTROLLER_TYPE_(water_heater::WaterHeater, water_heater, water_heaters, ESPHOME_ENTITY_WATER_HEATER_COUNT,
+ WATER_HEATER, water_heater_update)
+#endif
+#ifdef USE_INFRARED
+ENTITY_TYPE_(infrared::Infrared, infrared, infrareds, ESPHOME_ENTITY_INFRARED_COUNT, INFRARED)
+#endif
+#ifdef USE_EVENT
+ENTITY_CONTROLLER_TYPE_(event::Event, event, events, ESPHOME_ENTITY_EVENT_COUNT, EVENT, event)
+#endif
+#ifdef USE_UPDATE
+ENTITY_CONTROLLER_TYPE_(update::UpdateEntity, update, updates, ESPHOME_ENTITY_UPDATE_COUNT, UPDATE, update)
+#endif
diff --git a/esphome/writer.py b/esphome/writer.py
index 06a22301184..787ecac6f6e 100644
--- a/esphome/writer.py
+++ b/esphome/writer.py
@@ -171,6 +171,7 @@ VERSION_H_FORMAT = """\
DEFINES_H_TARGET = "esphome/core/defines.h"
VERSION_H_TARGET = "esphome/core/version.h"
BUILD_INFO_DATA_H_TARGET = "esphome/core/build_info_data.h"
+ENTITY_TYPES_H_TARGET = "esphome/core/entity_types.h"
ESPHOME_README_TXT = """
THIS DIRECTORY IS AUTO-GENERATED, DO NOT MODIFY
@@ -196,9 +197,12 @@ def copy_src_tree():
source_files_l.sort()
# Build #include list for esphome.h
+ # X-macro files are included multiple times with different macro definitions
+ # and must not be included bare in esphome.h
+ esphome_h_exclude = {Path(ENTITY_TYPES_H_TARGET)}
include_l = []
for target, _ in source_files_l:
- if target.suffix in HEADER_FILE_EXTENSIONS:
+ if target.suffix in HEADER_FILE_EXTENSIONS and target not in esphome_h_exclude:
include_l.append(f'#include "{target}"')
include_l.append("")
include_s = "\n".join(include_l)
diff --git a/script/ci-custom.py b/script/ci-custom.py
index 1ec3eab3a94..6dce86924e0 100755
--- a/script/ci-custom.py
+++ b/script/ci-custom.py
@@ -672,7 +672,7 @@ def lint_using_esp_idf_deprecated(fname, line, col, content):
)
-@lint_content_check(include=["*.h"])
+@lint_content_check(include=["*.h"], exclude=["esphome/core/entity_types.h"])
def lint_pragma_once(fname, content):
if "#pragma once" not in content:
return (
diff --git a/script/helpers.py b/script/helpers.py
index c9c550d8893..9f5ea7894cd 100644
--- a/script/helpers.py
+++ b/script/helpers.py
@@ -174,7 +174,12 @@ def build_all_include(header_files: list[str] | None = None) -> None:
if line
]
- headers = [f'#include "{h}"' for h in header_files]
+ from esphome.writer import ENTITY_TYPES_H_TARGET
+
+ # X-macro files are included multiple times with different macro definitions
+ # and must not be included bare in the all-include header
+ exclude = {ENTITY_TYPES_H_TARGET}
+ headers = [f'#include "{h}"' for h in header_files if h not in exclude]
headers.sort()
headers.append("")
content = "\n".join(headers)