ESPHome 2026.5.1
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// Must precede clients_ so APIConnection is complete for default_delete (libc++).
7#include "api_connection.h"
8#include "api_noise_context.h"
9#include "api_pb2.h"
10#include "api_pb2_service.h"
15#include "esphome/core/log.h"
17#ifdef USE_LOGGER
19#endif
20#ifdef USE_CAMERA
22#endif
23
24#include <array>
25#include <memory>
26#include <vector>
27
28namespace esphome::api {
29
30#ifdef USE_API_USER_DEFINED_ACTIONS
31// Forward declaration - full definition in user_services.h
32class UserServiceDescriptor;
33#endif
34
35#ifdef USE_API_NOISE
38} PACKED; // NOLINT
39#endif
40
41class APIServer final : public Component,
42 public Controller
43#ifdef USE_CAMERA
44 ,
46#endif
47{
48 public:
49 APIServer();
50 void setup() override;
51 uint16_t get_port() const;
52 float get_setup_priority() const override;
53 void loop() override;
54 void dump_config() override;
55 void on_shutdown() override;
56 bool teardown() override;
57#ifdef USE_LOGGER
58 void on_log(uint8_t level, const char *tag, const char *message, size_t message_len);
59#endif
60#ifdef USE_CAMERA
61 void on_camera_image(const std::shared_ptr<camera::CameraImage> &image) override;
62#endif
63 void set_port(uint16_t port);
64 void set_reboot_timeout(uint32_t reboot_timeout);
65 void set_batch_delay(uint16_t batch_delay);
66 uint16_t get_batch_delay() const { return batch_delay_; }
67 void set_listen_backlog(uint8_t listen_backlog) { this->listen_backlog_ = listen_backlog; }
68
69 // Get reference to shared buffer for API connections
71
72#ifdef USE_API_NOISE
73 bool save_noise_psk(psk_t psk, bool make_active = true);
74 bool clear_noise_psk(bool make_active = true);
75 void set_noise_psk(psk_t psk) { this->noise_ctx_.set_psk(psk); }
77#endif // USE_API_NOISE
78
80#ifdef USE_BINARY_SENSOR
82#endif
83#ifdef USE_COVER
84 void on_cover_update(cover::Cover *obj) override;
85#endif
86#ifdef USE_FAN
87 void on_fan_update(fan::Fan *obj) override;
88#endif
89#ifdef USE_LIGHT
91#endif
92#ifdef USE_SENSOR
93 void on_sensor_update(sensor::Sensor *obj) override;
94#endif
95#ifdef USE_SWITCH
96 void on_switch_update(switch_::Switch *obj) override;
97#endif
98#ifdef USE_TEXT_SENSOR
100#endif
101#ifdef USE_CLIMATE
103#endif
104#ifdef USE_NUMBER
105 void on_number_update(number::Number *obj) override;
106#endif
107#ifdef USE_DATETIME_DATE
109#endif
110#ifdef USE_DATETIME_TIME
112#endif
113#ifdef USE_DATETIME_DATETIME
115#endif
116#ifdef USE_TEXT
117 void on_text_update(text::Text *obj) override;
118#endif
119#ifdef USE_SELECT
120 void on_select_update(select::Select *obj) override;
121#endif
122#ifdef USE_LOCK
123 void on_lock_update(lock::Lock *obj) override;
124#endif
125#ifdef USE_VALVE
126 void on_valve_update(valve::Valve *obj) override;
127#endif
128#ifdef USE_MEDIA_PLAYER
130#endif
131#ifdef USE_WATER_HEATER
133#endif
134#ifdef USE_API_HOMEASSISTANT_SERVICES
136
137#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
138 // Action response handling
139 using ActionResponseCallback = std::function<void(const class ActionResponse &)>;
141 void handle_action_response(uint32_t call_id, bool success, StringRef error_message);
142#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
143 void handle_action_response(uint32_t call_id, bool success, StringRef error_message, const uint8_t *response_data,
144 size_t response_data_len);
145#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
146#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
147#endif // USE_API_HOMEASSISTANT_SERVICES
148#ifdef USE_API_USER_DEFINED_ACTIONS
149 void initialize_user_services(std::initializer_list<UserServiceDescriptor *> services) {
150 this->user_services_.assign(services);
151 }
152#ifdef USE_API_CUSTOM_SERVICES
153 // Only compile push_back method when custom_services: true (external components)
154 void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
155#endif
156#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
157 // Action call context management - supports concurrent calls from multiple clients
158 // Returns server-generated action_call_id to avoid collisions when clients use same call_id
160 void unregister_active_action_call(uint32_t action_call_id);
162 // Send response for a specific action call (uses action_call_id, sends client_call_id in response)
163 void send_action_response(uint32_t action_call_id, bool success, StringRef error_message);
164#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
165 void send_action_response(uint32_t action_call_id, bool success, StringRef error_message,
166 const uint8_t *response_data, size_t response_data_len);
167#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
168#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
169#endif
170#ifdef USE_HOMEASSISTANT_TIME
171 void request_time();
172#endif
173
174#ifdef USE_ALARM_CONTROL_PANEL
176#endif
177#ifdef USE_EVENT
178 void on_event(event::Event *obj) override;
179#endif
180#ifdef USE_UPDATE
181 void on_update(update::UpdateEntity *obj) override;
182#endif
183#ifdef USE_ZWAVE_PROXY
185#endif
186#if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY)
187 void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);
188#endif
189
190 bool is_connected() const { return this->api_connection_count_ != 0; }
192
193 // Range-for view over the populated slice [0, api_connection_count_). Read-only with respect
194 // to ownership; callers get `const unique_ptr&` so they can invoke non-const methods on the
195 // APIConnection but cannot reset/move the slot and break the count invariant.
196 using APIConnectionPtr = std::unique_ptr<APIConnection>;
198 const APIConnectionPtr *begin_;
199 const APIConnectionPtr *end_;
200
201 public:
202 ActiveClientsView(const APIConnectionPtr *b, const APIConnectionPtr *e) : begin_(b), end_(e) {}
203 const APIConnectionPtr *begin() const { return this->begin_; }
204 const APIConnectionPtr *end() const { return this->end_; }
205 };
207 return {this->clients_.data(), this->clients_.data() + this->api_connection_count_};
208 }
209
210#ifdef USE_API_HOMEASSISTANT_STATES
212 const char *entity_id; // Pointer to flash (internal) or heap (external)
213 const char *attribute; // Pointer to flash or nullptr (nullptr means no attribute)
214 std::function<void(StringRef)> callback;
215 bool once;
216
217 // Dynamic storage for external components using std::string API (custom_api_device.h)
218 // These are only allocated when using the std::string overload (nullptr for const char* overload)
219 std::unique_ptr<std::string> entity_id_dynamic_storage;
220 std::unique_ptr<std::string> attribute_dynamic_storage;
221 };
222
223 // New const char* overload (for internal components - zero allocation)
224 void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f);
225 void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f);
226
227 // std::string overload with StringRef callback (for custom_api_device.h with zero-allocation callback)
228 void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
229 std::function<void(StringRef)> &&f);
230 void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
231 std::function<void(StringRef)> &&f);
232
233 // Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string for callback)
234 void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
235 std::function<void(const std::string &)> &&f);
236 void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
237 std::function<void(const std::string &)> &&f);
238
239 const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
240#endif
241#ifdef USE_API_USER_DEFINED_ACTIONS
242 const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; }
243#endif
244
245#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
247#endif
248#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
250#endif
251
252 protected:
253 // Accept incoming socket connections. Only called when socket has pending connections.
254 void __attribute__((noinline)) accept_new_connections_();
255 // Remove a disconnected client by index. Swaps with the last populated slot and resets it.
256 void __attribute__((noinline)) remove_client_(uint8_t client_index);
257
258#ifdef USE_API_NOISE
259 bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg,
260 bool make_active);
261 // Load saved PSK from preferences and apply it. Returns true on success.
263#endif // USE_API_NOISE
264#ifdef USE_API_HOMEASSISTANT_STATES
265 // Helper methods to reduce code duplication
266 void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f,
267 bool once);
268 void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
269 std::function<void(StringRef)> &&f, bool once);
270 // Legacy helper: wraps std::string callback and delegates to StringRef version
271 void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
272 std::function<void(const std::string &)> &&f, bool once);
273#endif // USE_API_HOMEASSISTANT_STATES
274 // No explicit close() needed — listen sockets have no active connections on
275 // failure/shutdown. Destructor handles fd cleanup (close or abort per platform).
276 inline void destroy_socket_() {
277 delete this->socket_;
278 this->socket_ = nullptr;
279 }
280 void socket_failed_(const LogString *msg);
281 // Pointers and pointer-like types first (4 bytes each)
283#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
285#endif
286#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
288#endif
289
290 // 4-byte aligned types
293
294 // Slots [0, api_connection_count_) are populated; trailing slots are always nullptr.
295 std::array<APIConnectionPtr, MAX_API_CONNECTIONS> clients_{};
296 // Vectors and strings (12 bytes each on 32-bit)
297 // Shared proto write buffer for all connections.
298 // Not pre-allocated: all send paths call prepare_first_message_buffer() which
299 // reserves the exact needed size. Pre-allocating here would cause heap fragmentation
300 // since the buffer would almost always reallocate on first use.
302#ifdef USE_API_HOMEASSISTANT_STATES
303 std::vector<HomeAssistantStateSubscription> state_subs_;
304#endif
305#ifdef USE_API_USER_DEFINED_ACTIONS
306 std::vector<UserServiceDescriptor *> user_services_;
307#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
308 // Active action calls - supports concurrent calls from multiple clients
309 // Uses server-generated action_call_id to avoid collisions when multiple clients use same call_id
311 uint32_t action_call_id; // Server-generated unique ID (passed to actions)
312 uint32_t client_call_id; // Client's original call_id (used in response)
314 };
315 std::vector<ActiveActionCall> active_action_calls_;
316 uint32_t next_action_call_id_{1}; // Counter for generating unique action_call_ids
317#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
318#endif
319#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
324 std::vector<PendingActionResponse> action_response_callbacks_;
325#endif
326
327 // Group smaller types together
328 uint16_t port_{6053};
329 uint16_t batch_delay_{100};
330 // Connection limits - these defaults will be overridden by config values
331 // from cv.SplitDefault in __init__.py which sets platform-specific defaults.
332 uint8_t listen_backlog_{4};
333 bool shutting_down_ = false;
335 // 7 bytes used, 1 byte padding
336
337#ifdef USE_API_NOISE
340#endif // USE_API_NOISE
341};
342
343extern APIServer *global_api_server; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
344
345template<typename... Ts> class APIConnectedCondition : public Condition<Ts...> {
346 TEMPLATABLE_VALUE(bool, state_subscription_only)
347 public:
348 bool check(const Ts &...x) override {
349 if (this->state_subscription_only_.value(x...)) {
351 }
353 }
354};
355
356} // namespace esphome::api
357#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:454
Base class for all automation conditions.
Definition automation.h:459
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
const APIConnectionPtr * end() const
Definition api_server.h:204
ActiveClientsView(const APIConnectionPtr *b, const APIConnectionPtr *e)
Definition api_server.h:202
const APIConnectionPtr * begin() const
Definition api_server.h:203
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:246
std::array< APIConnectionPtr, MAX_API_CONNECTIONS > clients_
Definition api_server.h:295
void on_valve_update(valve::Valve *obj) override
uint16_t get_batch_delay() const
Definition api_server.h:66
std::unique_ptr< APIConnection > APIConnectionPtr
Definition api_server.h:196
void on_switch_update(switch_::Switch *obj) override
void register_action_response_callback(uint32_t call_id, ActionResponseCallback callback)
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:70
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:249
void on_camera_image(const std::shared_ptr< camera::CameraImage > &image) override
std::vector< UserServiceDescriptor * > user_services_
Definition api_server.h:306
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:242
void initialize_user_services(std::initializer_list< UserServiceDescriptor * > services)
Definition api_server.h:149
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:284
void set_listen_backlog(uint8_t listen_backlog)
Definition api_server.h:67
void send_action_response(uint32_t action_call_id, bool success, StringRef error_message)
APINoiseContext & get_noise_ctx()
Definition api_server.h:76
void register_user_service(UserServiceDescriptor *descriptor)
Definition api_server.h:154
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:190
APINoiseContext noise_ctx_
Definition api_server.h:338
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:282
void on_event(event::Event *obj) override
void on_update(update::UpdateEntity *obj) override
std::vector< PendingActionResponse > action_response_callbacks_
Definition api_server.h:324
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:139
void on_binary_sensor_update(binary_sensor::BinarySensor *obj) override
bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg, bool make_active)
ESPPreferenceObject noise_pref_
Definition api_server.h:339
void on_fan_update(fan::Fan *obj) override
Trigger< std::string, std::string > client_disconnected_trigger_
Definition api_server.h:287
std::vector< HomeAssistantStateSubscription > state_subs_
Definition api_server.h:303
bool clear_noise_psk(bool make_active=true)
ActiveClientsView active_clients() const
Definition api_server.h:206
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:315
void set_noise_psk(psk_t psk)
Definition api_server.h:75
void on_datetime_update(datetime::DateTimeEntity *obj) override
APIBuffer shared_write_buffer_
Definition api_server.h:301
void on_sensor_update(sensor::Sensor *obj) override
void __attribute__((noinline)) remove_client_(uint8_t client_index)
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:45
ClimateDevice - This is the base class for all climate integrations.
Definition climate.h:187
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:112
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:103
const char * message
Definition component.cpp:35
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:219
std::unique_ptr< std::string > attribute_dynamic_storage
Definition api_server.h:220
uint16_t x
Definition tt21100.cpp:5