This commit is contained in:
J. Nick Koston 2025-06-28 22:45:00 -05:00
parent 562d024623
commit 128bd76f20
No known key found for this signature in database
3 changed files with 105 additions and 152 deletions

View File

@ -0,0 +1,27 @@
#pragma once
#include "esphome/core/defines.h"
#ifdef USE_API
// Macro-based approach to eliminate duplication without runtime overhead
// This generates the entity handler methods at compile time
// For ListEntitiesIterator - calls schedule_message_ with try_send_*_info
#define LIST_ENTITIES_HANDLER(entity_type, EntityClass, ResponseType) \
bool ListEntitiesIterator::on_##entity_type(EntityClass *entity) { \
return this->client_->schedule_message_(entity, &APIConnection::try_send_##entity_type##_info, \
ResponseType::MESSAGE_TYPE); \
}
// For InitialStateIterator - calls send_*_state
#define INITIAL_STATE_HANDLER(entity_type, EntityClass) \
bool InitialStateIterator::on_##entity_type(EntityClass *entity) { \
return this->client_->send_##entity_type##_state(entity); \
}
// Combined macro that generates both handlers
#define ENTITY_HANDLERS(entity_type, EntityClass, ResponseType) \
LIST_ENTITIES_HANDLER(entity_type, EntityClass, ResponseType) \
INITIAL_STATE_HANDLER(entity_type, EntityClass)
#endif // USE_API

View File

@ -2,6 +2,7 @@
#ifdef USE_API
#include "api_connection.h"
#include "api_pb2.h"
#include "entity_iterator_macros.h"
#include "esphome/core/application.h"
#include "esphome/core/log.h"
#include "esphome/core/util.h"
@ -9,155 +10,85 @@
namespace esphome {
namespace api {
// Generate entity handler implementations using macros
#ifdef USE_BINARY_SENSOR
bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
return this->client_->schedule_message_(binary_sensor, &APIConnection::try_send_binary_sensor_info,
ListEntitiesBinarySensorResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(binary_sensor, binary_sensor::BinarySensor, ListEntitiesBinarySensorResponse)
#endif
#ifdef USE_COVER
bool ListEntitiesIterator::on_cover(cover::Cover *cover) {
return this->client_->schedule_message_(cover, &APIConnection::try_send_cover_info,
ListEntitiesCoverResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(cover, cover::Cover, ListEntitiesCoverResponse)
#endif
#ifdef USE_FAN
bool ListEntitiesIterator::on_fan(fan::Fan *fan) {
return this->client_->schedule_message_(fan, &APIConnection::try_send_fan_info,
ListEntitiesFanResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(fan, fan::Fan, ListEntitiesFanResponse)
#endif
#ifdef USE_LIGHT
bool ListEntitiesIterator::on_light(light::LightState *light) {
return this->client_->schedule_message_(light, &APIConnection::try_send_light_info,
ListEntitiesLightResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(light, light::LightState, ListEntitiesLightResponse)
#endif
#ifdef USE_SENSOR
bool ListEntitiesIterator::on_sensor(sensor::Sensor *sensor) {
return this->client_->schedule_message_(sensor, &APIConnection::try_send_sensor_info,
ListEntitiesSensorResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(sensor, sensor::Sensor, ListEntitiesSensorResponse)
#endif
#ifdef USE_SWITCH
bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) {
return this->client_->schedule_message_(a_switch, &APIConnection::try_send_switch_info,
ListEntitiesSwitchResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(switch, switch_::Switch, ListEntitiesSwitchResponse)
#endif
#ifdef USE_BUTTON
bool ListEntitiesIterator::on_button(button::Button *button) {
return this->client_->schedule_message_(button, &APIConnection::try_send_button_info,
ListEntitiesButtonResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(button, button::Button, ListEntitiesButtonResponse)
#endif
#ifdef USE_TEXT_SENSOR
bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
return this->client_->schedule_message_(text_sensor, &APIConnection::try_send_text_sensor_info,
ListEntitiesTextSensorResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(text_sensor, text_sensor::TextSensor, ListEntitiesTextSensorResponse)
#endif
#ifdef USE_LOCK
bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) {
return this->client_->schedule_message_(a_lock, &APIConnection::try_send_lock_info,
ListEntitiesLockResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(lock, lock::Lock, ListEntitiesLockResponse)
#endif
#ifdef USE_VALVE
bool ListEntitiesIterator::on_valve(valve::Valve *valve) {
return this->client_->schedule_message_(valve, &APIConnection::try_send_valve_info,
ListEntitiesValveResponse::MESSAGE_TYPE);
}
LIST_ENTITIES_HANDLER(valve, valve::Valve, ListEntitiesValveResponse)
#endif
#ifdef USE_ESP32_CAMERA
LIST_ENTITIES_HANDLER(camera, esp32_camera::ESP32Camera, ListEntitiesCameraResponse)
#endif
#ifdef USE_CLIMATE
LIST_ENTITIES_HANDLER(climate, climate::Climate, ListEntitiesClimateResponse)
#endif
#ifdef USE_NUMBER
LIST_ENTITIES_HANDLER(number, number::Number, ListEntitiesNumberResponse)
#endif
#ifdef USE_DATETIME_DATE
LIST_ENTITIES_HANDLER(date, datetime::DateEntity, ListEntitiesDateResponse)
#endif
#ifdef USE_DATETIME_TIME
LIST_ENTITIES_HANDLER(time, datetime::TimeEntity, ListEntitiesTimeResponse)
#endif
#ifdef USE_DATETIME_DATETIME
LIST_ENTITIES_HANDLER(datetime, datetime::DateTimeEntity, ListEntitiesDateTimeResponse)
#endif
#ifdef USE_TEXT
LIST_ENTITIES_HANDLER(text, text::Text, ListEntitiesTextResponse)
#endif
#ifdef USE_SELECT
LIST_ENTITIES_HANDLER(select, select::Select, ListEntitiesSelectResponse)
#endif
#ifdef USE_MEDIA_PLAYER
LIST_ENTITIES_HANDLER(media_player, media_player::MediaPlayer, ListEntitiesMediaPlayerResponse)
#endif
#ifdef USE_ALARM_CONTROL_PANEL
LIST_ENTITIES_HANDLER(alarm_control_panel, alarm_control_panel::AlarmControlPanel,
ListEntitiesAlarmControlPanelResponse)
#endif
#ifdef USE_EVENT
LIST_ENTITIES_HANDLER(event, event::Event, ListEntitiesEventResponse)
#endif
#ifdef USE_UPDATE
LIST_ENTITIES_HANDLER(update, update::UpdateEntity, ListEntitiesUpdateResponse)
#endif
// Special cases that don't follow the pattern
bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); }
ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {}
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
auto resp = service->encode_list_service_response();
return this->client_->send_message(resp);
}
#ifdef USE_ESP32_CAMERA
bool ListEntitiesIterator::on_camera(esp32_camera::ESP32Camera *camera) {
return this->client_->schedule_message_(camera, &APIConnection::try_send_camera_info,
ListEntitiesCameraResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_CLIMATE
bool ListEntitiesIterator::on_climate(climate::Climate *climate) {
return this->client_->schedule_message_(climate, &APIConnection::try_send_climate_info,
ListEntitiesClimateResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_NUMBER
bool ListEntitiesIterator::on_number(number::Number *number) {
return this->client_->schedule_message_(number, &APIConnection::try_send_number_info,
ListEntitiesNumberResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_DATETIME_DATE
bool ListEntitiesIterator::on_date(datetime::DateEntity *date) {
return this->client_->schedule_message_(date, &APIConnection::try_send_date_info,
ListEntitiesDateResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_DATETIME_TIME
bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) {
return this->client_->schedule_message_(time, &APIConnection::try_send_time_info,
ListEntitiesTimeResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_DATETIME_DATETIME
bool ListEntitiesIterator::on_datetime(datetime::DateTimeEntity *datetime) {
return this->client_->schedule_message_(datetime, &APIConnection::try_send_datetime_info,
ListEntitiesDateTimeResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_TEXT
bool ListEntitiesIterator::on_text(text::Text *text) {
return this->client_->schedule_message_(text, &APIConnection::try_send_text_info,
ListEntitiesTextResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_SELECT
bool ListEntitiesIterator::on_select(select::Select *select) {
return this->client_->schedule_message_(select, &APIConnection::try_send_select_info,
ListEntitiesSelectResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_MEDIA_PLAYER
bool ListEntitiesIterator::on_media_player(media_player::MediaPlayer *media_player) {
return this->client_->schedule_message_(media_player, &APIConnection::try_send_media_player_info,
ListEntitiesMediaPlayerResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_ALARM_CONTROL_PANEL
bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
return this->client_->schedule_message_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_info,
ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_EVENT
bool ListEntitiesIterator::on_event(event::Event *event) {
return this->client_->schedule_message_(event, &APIConnection::try_send_event_info,
ListEntitiesEventResponse::MESSAGE_TYPE);
}
#endif
#ifdef USE_UPDATE
bool ListEntitiesIterator::on_update(update::UpdateEntity *update) {
return this->client_->schedule_message_(update, &APIConnection::try_send_update_info,
ListEntitiesUpdateResponse::MESSAGE_TYPE);
}
#endif
} // namespace api
} // namespace esphome
#endif
#endif

View File

@ -1,80 +1,75 @@
#include "subscribe_state.h"
#ifdef USE_API
#include "api_connection.h"
#include "entity_iterator_macros.h"
#include "esphome/core/log.h"
namespace esphome {
namespace api {
// Generate entity handler implementations using macros
#ifdef USE_BINARY_SENSOR
bool InitialStateIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
return this->client_->send_binary_sensor_state(binary_sensor);
}
INITIAL_STATE_HANDLER(binary_sensor, binary_sensor::BinarySensor)
#endif
#ifdef USE_COVER
bool InitialStateIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_state(cover); }
INITIAL_STATE_HANDLER(cover, cover::Cover)
#endif
#ifdef USE_FAN
bool InitialStateIterator::on_fan(fan::Fan *fan) { return this->client_->send_fan_state(fan); }
INITIAL_STATE_HANDLER(fan, fan::Fan)
#endif
#ifdef USE_LIGHT
bool InitialStateIterator::on_light(light::LightState *light) { return this->client_->send_light_state(light); }
INITIAL_STATE_HANDLER(light, light::LightState)
#endif
#ifdef USE_SENSOR
bool InitialStateIterator::on_sensor(sensor::Sensor *sensor) { return this->client_->send_sensor_state(sensor); }
INITIAL_STATE_HANDLER(sensor, sensor::Sensor)
#endif
#ifdef USE_SWITCH
bool InitialStateIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_state(a_switch); }
INITIAL_STATE_HANDLER(switch, switch_::Switch)
#endif
#ifdef USE_TEXT_SENSOR
bool InitialStateIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
return this->client_->send_text_sensor_state(text_sensor);
}
INITIAL_STATE_HANDLER(text_sensor, text_sensor::TextSensor)
#endif
#ifdef USE_CLIMATE
bool InitialStateIterator::on_climate(climate::Climate *climate) { return this->client_->send_climate_state(climate); }
INITIAL_STATE_HANDLER(climate, climate::Climate)
#endif
#ifdef USE_NUMBER
bool InitialStateIterator::on_number(number::Number *number) { return this->client_->send_number_state(number); }
INITIAL_STATE_HANDLER(number, number::Number)
#endif
#ifdef USE_DATETIME_DATE
bool InitialStateIterator::on_date(datetime::DateEntity *date) { return this->client_->send_date_state(date); }
INITIAL_STATE_HANDLER(date, datetime::DateEntity)
#endif
#ifdef USE_DATETIME_TIME
bool InitialStateIterator::on_time(datetime::TimeEntity *time) { return this->client_->send_time_state(time); }
INITIAL_STATE_HANDLER(time, datetime::TimeEntity)
#endif
#ifdef USE_DATETIME_DATETIME
bool InitialStateIterator::on_datetime(datetime::DateTimeEntity *datetime) {
return this->client_->send_datetime_state(datetime);
}
INITIAL_STATE_HANDLER(datetime, datetime::DateTimeEntity)
#endif
#ifdef USE_TEXT
bool InitialStateIterator::on_text(text::Text *text) { return this->client_->send_text_state(text); }
INITIAL_STATE_HANDLER(text, text::Text)
#endif
#ifdef USE_SELECT
bool InitialStateIterator::on_select(select::Select *select) { return this->client_->send_select_state(select); }
INITIAL_STATE_HANDLER(select, select::Select)
#endif
#ifdef USE_LOCK
bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock); }
INITIAL_STATE_HANDLER(lock, lock::Lock)
#endif
#ifdef USE_VALVE
bool InitialStateIterator::on_valve(valve::Valve *valve) { return this->client_->send_valve_state(valve); }
INITIAL_STATE_HANDLER(valve, valve::Valve)
#endif
#ifdef USE_MEDIA_PLAYER
bool InitialStateIterator::on_media_player(media_player::MediaPlayer *media_player) {
return this->client_->send_media_player_state(media_player);
}
INITIAL_STATE_HANDLER(media_player, media_player::MediaPlayer)
#endif
#ifdef USE_ALARM_CONTROL_PANEL
bool InitialStateIterator::on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
return this->client_->send_alarm_control_panel_state(a_alarm_control_panel);
}
INITIAL_STATE_HANDLER(alarm_control_panel, alarm_control_panel::AlarmControlPanel)
#endif
#ifdef USE_UPDATE
bool InitialStateIterator::on_update(update::UpdateEntity *update) { return this->client_->send_update_state(update); }
INITIAL_STATE_HANDLER(update, update::UpdateEntity)
#endif
// Special cases (button and event) are already defined inline in subscribe_state.h
InitialStateIterator::InitialStateIterator(APIConnection *client) : client_(client) {}
} // namespace api
} // namespace esphome
#endif
#endif