ESPHome 2026.3.0
Loading...
Searching...
No Matches
api_server.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_API
5#include "api_buffer.h"
6#include "api_noise_context.h"
7#include "api_pb2.h"
8#include "api_pb2_service.h"
13#include "esphome/core/log.h"
15#include "list_entities.h"
16#include "subscribe_state.h"
17#ifdef USE_LOGGER
19#endif
20#ifdef USE_CAMERA
22#endif
23
24#include <vector>
25
26namespace esphome::api {
27
28#ifdef USE_API_USER_DEFINED_ACTIONS
29// Forward declaration - full definition in user_services.h
30class UserServiceDescriptor;
31#endif
32
33#ifdef USE_API_NOISE
36} PACKED; // NOLINT
37#endif
38
39class APIServer : public Component,
40 public Controller
41#ifdef USE_CAMERA
42 ,
44#endif
45{
46 public:
47 APIServer();
48 void setup() override;
49 uint16_t get_port() const;
50 float get_setup_priority() const override;
51 void loop() override;
52 void dump_config() override;
53 void on_shutdown() override;
54 bool teardown() override;
55#ifdef USE_LOGGER
56 void on_log(uint8_t level, const char *tag, const char *message, size_t message_len);
57#endif
58#ifdef USE_CAMERA
59 void on_camera_image(const std::shared_ptr<camera::CameraImage> &image) override;
60#endif
61 void set_port(uint16_t port);
62 void set_reboot_timeout(uint32_t reboot_timeout);
63 void set_batch_delay(uint16_t batch_delay);
64 uint16_t get_batch_delay() const { return batch_delay_; }
65 void set_listen_backlog(uint8_t listen_backlog) { this->listen_backlog_ = listen_backlog; }
66 void set_max_connections(uint8_t max_connections) { this->max_connections_ = max_connections; }
67
68 // Get reference to shared buffer for API connections
70
71#ifdef USE_API_NOISE
72 bool save_noise_psk(psk_t psk, bool make_active = true);
73 bool clear_noise_psk(bool make_active = true);
74 void set_noise_psk(psk_t psk) { this->noise_ctx_.set_psk(psk); }
76#endif // USE_API_NOISE
77
79#ifdef USE_BINARY_SENSOR
81#endif
82#ifdef USE_COVER
83 void on_cover_update(cover::Cover *obj) override;
84#endif
85#ifdef USE_FAN
86 void on_fan_update(fan::Fan *obj) override;
87#endif
88#ifdef USE_LIGHT
90#endif
91#ifdef USE_SENSOR
92 void on_sensor_update(sensor::Sensor *obj) override;
93#endif
94#ifdef USE_SWITCH
95 void on_switch_update(switch_::Switch *obj) override;
96#endif
97#ifdef USE_TEXT_SENSOR
99#endif
100#ifdef USE_CLIMATE
102#endif
103#ifdef USE_NUMBER
104 void on_number_update(number::Number *obj) override;
105#endif
106#ifdef USE_DATETIME_DATE
108#endif
109#ifdef USE_DATETIME_TIME
111#endif
112#ifdef USE_DATETIME_DATETIME
114#endif
115#ifdef USE_TEXT
116 void on_text_update(text::Text *obj) override;
117#endif
118#ifdef USE_SELECT
119 void on_select_update(select::Select *obj) override;
120#endif
121#ifdef USE_LOCK
122 void on_lock_update(lock::Lock *obj) override;
123#endif
124#ifdef USE_VALVE
125 void on_valve_update(valve::Valve *obj) override;
126#endif
127#ifdef USE_MEDIA_PLAYER
129#endif
130#ifdef USE_WATER_HEATER
132#endif
133#ifdef USE_API_HOMEASSISTANT_SERVICES
135
136#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
137 // Action response handling
138 using ActionResponseCallback = std::function<void(const class ActionResponse &)>;
140 void handle_action_response(uint32_t call_id, bool success, StringRef error_message);
141#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
142 void handle_action_response(uint32_t call_id, bool success, StringRef error_message, const uint8_t *response_data,
143 size_t response_data_len);
144#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
145#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
146#endif // USE_API_HOMEASSISTANT_SERVICES
147#ifdef USE_API_USER_DEFINED_ACTIONS
148 void initialize_user_services(std::initializer_list<UserServiceDescriptor *> services) {
149 this->user_services_.assign(services);
150 }
151#ifdef USE_API_CUSTOM_SERVICES
152 // Only compile push_back method when custom_services: true (external components)
153 void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
154#endif
155#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
156 // Action call context management - supports concurrent calls from multiple clients
157 // Returns server-generated action_call_id to avoid collisions when clients use same call_id
159 void unregister_active_action_call(uint32_t action_call_id);
161 // Send response for a specific action call (uses action_call_id, sends client_call_id in response)
162 void send_action_response(uint32_t action_call_id, bool success, StringRef error_message);
163#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
164 void send_action_response(uint32_t action_call_id, bool success, StringRef error_message,
165 const uint8_t *response_data, size_t response_data_len);
166#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
167#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
168#endif
169#ifdef USE_HOMEASSISTANT_TIME
170 void request_time();
171#endif
172
173#ifdef USE_ALARM_CONTROL_PANEL
175#endif
176#ifdef USE_EVENT
177 void on_event(event::Event *obj) override;
178#endif
179#ifdef USE_UPDATE
180 void on_update(update::UpdateEntity *obj) override;
181#endif
182#ifdef USE_ZWAVE_PROXY
184#endif
185#ifdef USE_IR_RF
186 void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);
187#endif
188
189 bool is_connected() const { return !this->clients_.empty(); }
191
192#ifdef USE_API_HOMEASSISTANT_STATES
194 const char *entity_id; // Pointer to flash (internal) or heap (external)
195 const char *attribute; // Pointer to flash or nullptr (nullptr means no attribute)
196 std::function<void(StringRef)> callback;
197 bool once;
198
199 // Dynamic storage for external components using std::string API (custom_api_device.h)
200 // These are only allocated when using the std::string overload (nullptr for const char* overload)
201 std::unique_ptr<std::string> entity_id_dynamic_storage;
202 std::unique_ptr<std::string> attribute_dynamic_storage;
203 };
204
205 // New const char* overload (for internal components - zero allocation)
206 void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f);
207 void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f);
208
209 // std::string overload with StringRef callback (for custom_api_device.h with zero-allocation callback)
210 void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
211 std::function<void(StringRef)> &&f);
212 void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
213 std::function<void(StringRef)> &&f);
214
215 // Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string for callback)
216 void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
217 std::function<void(const std::string &)> &&f);
218 void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
219 std::function<void(const std::string &)> &&f);
220
221 const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
222#endif
223#ifdef USE_API_USER_DEFINED_ACTIONS
224 const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; }
225#endif
226
227#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
229#endif
230#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
232#endif
233
234 protected:
235 // Accept incoming socket connections. Only called when socket has pending connections.
236 void __attribute__((noinline)) accept_new_connections_();
237 // Remove a disconnected client by index. Swaps with last element and pops.
238 void __attribute__((noinline)) remove_client_(size_t client_index);
239
240#ifdef USE_API_NOISE
241 bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg,
242 const psk_t &active_psk, bool make_active);
243#endif // USE_API_NOISE
244#ifdef USE_API_HOMEASSISTANT_STATES
245 // Helper methods to reduce code duplication
246 void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f,
247 bool once);
248 void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
249 std::function<void(StringRef)> &&f, bool once);
250 // Legacy helper: wraps std::string callback and delegates to StringRef version
251 void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
252 std::function<void(const std::string &)> &&f, bool once);
253#endif // USE_API_HOMEASSISTANT_STATES
254 // No explicit close() needed — listen sockets have no active connections on
255 // failure/shutdown. Destructor handles fd cleanup (close or abort per platform).
256 inline void destroy_socket_() {
257 delete this->socket_;
258 this->socket_ = nullptr;
259 }
260 void socket_failed_(const LogString *msg);
261 // Pointers and pointer-like types first (4 bytes each)
263#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
265#endif
266#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
268#endif
269
270 // 4-byte aligned types
273
274 // Vectors and strings (12 bytes each on 32-bit)
275 std::vector<std::unique_ptr<APIConnection>> clients_;
276 // Shared proto write buffer for all connections.
277 // Not pre-allocated: all send paths call prepare_first_message_buffer() which
278 // reserves the exact needed size. Pre-allocating here would cause heap fragmentation
279 // since the buffer would almost always reallocate on first use.
281#ifdef USE_API_HOMEASSISTANT_STATES
282 std::vector<HomeAssistantStateSubscription> state_subs_;
283#endif
284#ifdef USE_API_USER_DEFINED_ACTIONS
285 std::vector<UserServiceDescriptor *> user_services_;
286#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
287 // Active action calls - supports concurrent calls from multiple clients
288 // Uses server-generated action_call_id to avoid collisions when multiple clients use same call_id
290 uint32_t action_call_id; // Server-generated unique ID (passed to actions)
291 uint32_t client_call_id; // Client's original call_id (used in response)
293 };
294 std::vector<ActiveActionCall> active_action_calls_;
295 uint32_t next_action_call_id_{1}; // Counter for generating unique action_call_ids
296#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
297#endif
298#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
303 std::vector<PendingActionResponse> action_response_callbacks_;
304#endif
305
306 // Group smaller types together
307 uint16_t port_{6053};
308 uint16_t batch_delay_{100};
309 // Connection limits - these defaults will be overridden by config values
310 // from cv.SplitDefault in __init__.py which sets platform-specific defaults
311 uint8_t listen_backlog_{4};
313 bool shutting_down_ = false;
314 // 7 bytes used, 1 byte padding
315
316#ifdef USE_API_NOISE
319#endif // USE_API_NOISE
320};
321
322extern APIServer *global_api_server; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
323
324template<typename... Ts> class APIConnectedCondition : public Condition<Ts...> {
325 TEMPLATABLE_VALUE(bool, state_subscription_only)
326 public:
327 bool check(const Ts &...x) override {
328 if (this->state_subscription_only_.value(x...)) {
330 }
332 }
333};
334
335} // namespace esphome::api
336#endif
ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", "2026.2.0") void set_retry(const std uint32_t uint8_t std::function< RetryResult(uint8_t)> && f
Definition component.h:395
Base class for all automation conditions.
Definition automation.h:304
virtual bool check(const Ts &...x)=0
StringRef is a reference to a string owned by something else.
Definition string_ref.h:26
Byte buffer that skips zero-initialization on resize().
Definition api_buffer.h:36
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len)
bool is_connected_with_state_subscription() const
Trigger< std::string, std::string > * get_client_connected_trigger()
Definition api_server.h:228
void on_valve_update(valve::Valve *obj) override
uint16_t get_batch_delay() const
Definition api_server.h:64
void on_switch_update(switch_::Switch *obj) override
void register_action_response_callback(uint32_t call_id, ActionResponseCallback callback)
std::vector< std::unique_ptr< APIConnection > > clients_
Definition api_server.h:275
void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector< int32_t > *timings)
APIBuffer & get_shared_buffer_ref()
Definition api_server.h:69
void on_time_update(datetime::TimeEntity *obj) override
void on_cover_update(cover::Cover *obj) override
void add_state_subscription_(const char *entity_id, const char *attribute, std::function< void(StringRef)> &&f, bool once)
void get_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(StringRef)> &&f)
Trigger< std::string, std::string > * get_client_disconnected_trigger()
Definition api_server.h:231
void on_camera_image(const std::shared_ptr< camera::CameraImage > &image) override
std::vector< UserServiceDescriptor * > user_services_
Definition api_server.h:285
void on_light_update(light::LightState *obj) override
void socket_failed_(const LogString *msg)
void on_media_player_update(media_player::MediaPlayer *obj) override
const std::vector< UserServiceDescriptor * > & get_user_services() const
Definition api_server.h:224
void initialize_user_services(std::initializer_list< UserServiceDescriptor * > services)
Definition api_server.h:148
void on_water_heater_update(water_heater::WaterHeater *obj) override
void set_port(uint16_t port)
void dump_config() override
void unregister_active_action_calls_for_connection(APIConnection *conn)
void handle_disconnect(APIConnection *conn)
void set_batch_delay(uint16_t batch_delay)
void set_reboot_timeout(uint32_t reboot_timeout)
Trigger< std::string, std::string > client_connected_trigger_
Definition api_server.h:264
void set_listen_backlog(uint8_t listen_backlog)
Definition api_server.h:65
void send_action_response(uint32_t action_call_id, bool success, StringRef error_message)
APINoiseContext & get_noise_ctx()
Definition api_server.h:75
void register_user_service(UserServiceDescriptor *descriptor)
Definition api_server.h:153
bool save_noise_psk(psk_t psk, bool make_active=true)
void on_lock_update(lock::Lock *obj) override
void setup() override
void on_date_update(datetime::DateEntity *obj) override
bool teardown() override
bool is_connected() const
Definition api_server.h:189
APINoiseContext noise_ctx_
Definition api_server.h:317
void unregister_active_action_call(uint32_t action_call_id)
void on_number_update(number::Number *obj) override
void send_homeassistant_action(const HomeassistantActionRequest &call)
socket::ListenSocket * socket_
Definition api_server.h:262
void on_event(event::Event *obj) override
void on_update(update::UpdateEntity *obj) override
void __attribute__((noinline)) remove_client_(size_t client_index)
std::vector< PendingActionResponse > action_response_callbacks_
Definition api_server.h:303
const std::vector< HomeAssistantStateSubscription > & get_state_subs() const
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(StringRef)> &&f)
void on_climate_update(climate::Climate *obj) override
void handle_action_response(uint32_t call_id, bool success, StringRef error_message)
std::function< void(const class ActionResponse &)> ActionResponseCallback
Definition api_server.h:138
bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg, const psk_t &active_psk, bool make_active)
void set_max_connections(uint8_t max_connections)
Definition api_server.h:66
void on_binary_sensor_update(binary_sensor::BinarySensor *obj) override
ESPPreferenceObject noise_pref_
Definition api_server.h:318
void on_fan_update(fan::Fan *obj) override
Trigger< std::string, std::string > client_disconnected_trigger_
Definition api_server.h:267
std::vector< HomeAssistantStateSubscription > state_subs_
Definition api_server.h:282
bool clear_noise_psk(bool make_active=true)
void on_select_update(select::Select *obj) override
uint16_t get_port() const
void __attribute__((noinline)) accept_new_connections_()
void on_text_update(text::Text *obj) override
void on_text_sensor_update(text_sensor::TextSensor *obj) override
std::vector< ActiveActionCall > active_action_calls_
Definition api_server.h:294
void set_noise_psk(psk_t psk)
Definition api_server.h:74
void on_datetime_update(datetime::DateTimeEntity *obj) override
APIBuffer shared_write_buffer_
Definition api_server.h:280
void on_sensor_update(sensor::Sensor *obj) override
float get_setup_priority() const override
uint32_t register_active_action_call(uint32_t client_call_id, APIConnection *conn)
void on_shutdown() override
void on_zwave_proxy_request(const ZWaveProxyRequest &msg)
void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override
Base class for all binary_sensor-type classes.
Listener interface for camera events.
Definition camera.h:46
ClimateDevice - This is the base class for all climate integrations.
Definition climate.h:186
Base class for all cover devices.
Definition cover.h:110
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:93
Base class for all locks.
Definition lock.h:110
Base-class for all numbers.
Definition number.h:29
Base-class for all selects.
Definition select.h:29
Base-class for all sensors.
Definition sensor.h:47
Base class for all switches.
Definition switch.h:38
Base-class for all text inputs.
Definition text.h:21
Base class for all valve devices.
Definition valve.h:104
const char * message
Definition component.cpp:38
APIServer * global_api_server
struct esphome::api::SavedNoisePsk PACKED
std::array< uint8_t, 32 > psk_t
const char * tag
Definition log.h:74
static void uint32_t
std::unique_ptr< std::string > entity_id_dynamic_storage
Definition api_server.h:201
std::unique_ptr< std::string > attribute_dynamic_storage
Definition api_server.h:202
uint16_t x
Definition tt21100.cpp:5