ESPHome 2026.10.0-dev
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#ifdef USE_API_NOISE
9// Only present in the build when the noise component is loaded
11#endif
12#include "api_pb2.h"
13#include "api_pb2_service.h"
18#include "esphome/core/log.h"
20#ifdef USE_PROVISIONING
22#endif
23#ifdef USE_LOGGER
25#endif
26#ifdef USE_CAMERA
28#endif
29
30#include <array>
31#include <memory>
32#include <vector>
33
34namespace esphome::api {
35
36#ifdef USE_API_USER_DEFINED_ACTIONS
37// Forward declaration - full definition in user_services.h
38class UserServiceDescriptor;
39#endif
40
41#ifdef USE_API_NOISE
45#endif
46
47class APIServer final : public Component,
48 public Controller
49#ifdef USE_CAMERA
50 ,
52#endif
53{
54 public:
55 APIServer();
56 void setup() override;
57 uint16_t get_port() const { return this->port_; }
58 float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
59 void loop() override;
60 void dump_config() override;
61 void on_shutdown() override;
62 bool teardown() override;
63#ifdef USE_LOGGER
64 void on_log(uint8_t level, const char *tag, const char *message, size_t message_len);
65#endif
66#ifdef USE_CAMERA
67 void on_camera_image(const std::shared_ptr<camera::CameraImage> &image) override;
68#endif
69 void set_port(uint16_t port) { this->port_ = port; }
70 void set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
71 void set_batch_delay(uint16_t batch_delay) { this->batch_delay_ = batch_delay; }
72 uint16_t get_batch_delay() const { return batch_delay_; }
73 void set_listen_backlog(uint8_t listen_backlog) { this->listen_backlog_ = listen_backlog; }
74
75 // Get reference to shared buffer for API connections
77
78#ifdef USE_API_NOISE
79#ifndef USE_API_NOISE_PSK_FROM_YAML
80 // Runtime key changes exist for the provisioning path only (not lambdas);
81 // with a yaml key they compile out
82 bool save_noise_psk(noise::psk_t psk, bool make_active = true);
83 bool clear_noise_psk(bool make_active = true);
84#endif
86 void set_noise_psk(const uint8_t *psk) { this->noise_ctx_.set_psk(psk); }
88#endif // USE_API_NOISE
89
91#ifdef USE_BINARY_SENSOR
93#endif
94#ifdef USE_COVER
95 void on_cover_update(cover::Cover *obj) override;
96#endif
97#ifdef USE_FAN
98 void on_fan_update(fan::Fan *obj) override;
99#endif
100#ifdef USE_LIGHT
102#endif
103#ifdef USE_SENSOR
104 void on_sensor_update(sensor::Sensor *obj) override;
105#endif
106#ifdef USE_SWITCH
108#endif
109#ifdef USE_TEXT_SENSOR
111#endif
112#ifdef USE_CLIMATE
114#endif
115#ifdef USE_NUMBER
116 void on_number_update(number::Number *obj) override;
117#endif
118#ifdef USE_DATETIME_DATE
120#endif
121#ifdef USE_DATETIME_TIME
123#endif
124#ifdef USE_DATETIME_DATETIME
126#endif
127#ifdef USE_TEXT
128 void on_text_update(text::Text *obj) override;
129#endif
130#ifdef USE_SELECT
131 void on_select_update(select::Select *obj) override;
132#endif
133#ifdef USE_LOCK
134 void on_lock_update(lock::Lock *obj) override;
135#endif
136#ifdef USE_VALVE
137 void on_valve_update(valve::Valve *obj) override;
138#endif
139#ifdef USE_MEDIA_PLAYER
141#endif
142#ifdef USE_WATER_HEATER
144#endif
145#ifdef USE_API_HOMEASSISTANT_SERVICES
147
148#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
149 // Action response handling
150 using ActionResponseCallback = std::function<void(const class ActionResponse &)>;
152 void handle_action_response(uint32_t call_id, bool success, StringRef error_message);
153#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
154 void handle_action_response(uint32_t call_id, bool success, StringRef error_message, const uint8_t *response_data,
155 size_t response_data_len);
156#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
157#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
158#endif // USE_API_HOMEASSISTANT_SERVICES
159#ifdef USE_API_USER_DEFINED_ACTIONS
160 void initialize_user_services(std::initializer_list<UserServiceDescriptor *> services) {
161 this->user_services_.assign(services);
162 }
163#ifdef USE_API_CUSTOM_SERVICES
164 // Only compile push_back method when custom_services: true (external components)
165 void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
166#endif
167#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
168 // Action call context management - supports concurrent calls from multiple clients
169 // Returns server-generated action_call_id to avoid collisions when clients use same call_id
171 void unregister_active_action_call(uint32_t action_call_id);
173 // Send response for a specific action call (uses action_call_id, sends client_call_id in response)
174 void send_action_response(uint32_t action_call_id, bool success, StringRef error_message);
175#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
176 void send_action_response(uint32_t action_call_id, bool success, StringRef error_message,
177 const uint8_t *response_data, size_t response_data_len);
178#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
179#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
180#endif
181#ifdef USE_HOMEASSISTANT_TIME
182 void request_time();
183#endif
184
185#ifdef USE_ALARM_CONTROL_PANEL
187#endif
188#ifdef USE_EVENT
189 void on_event(event::Event *obj) override;
190#endif
191#ifdef USE_UPDATE
192 void on_update(update::UpdateEntity *obj) override;
193#endif
194#ifdef USE_ZWAVE_PROXY
196#endif
197#if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY)
198 void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);
199#endif
200
201 bool is_connected() const { return this->api_connection_count_ != 0; }
203
204 // Range-for view over the populated slice [0, api_connection_count_). Read-only with respect
205 // to ownership; callers get `const unique_ptr&` so they can invoke non-const methods on the
206 // APIConnection but cannot reset/move the slot and break the count invariant.
207 using APIConnectionPtr = std::unique_ptr<APIConnection>;
209 const APIConnectionPtr *begin_;
210 const APIConnectionPtr *end_;
211
212 public:
213 ActiveClientsView(const APIConnectionPtr *b, const APIConnectionPtr *e) : begin_(b), end_(e) {}
214 const APIConnectionPtr *begin() const { return this->begin_; }
215 const APIConnectionPtr *end() const { return this->end_; }
216 };
218 return {this->clients_.data(), this->clients_.data() + this->api_connection_count_};
219 }
220
221#ifdef USE_API_HOMEASSISTANT_STATES
223 const char *entity_id; // Pointer to flash (internal) or heap (external)
224 const char *attribute; // Pointer to flash or nullptr (nullptr means no attribute)
225 std::function<void(StringRef)> callback;
226 bool once;
227
228 // Dynamic storage for external components using std::string API (custom_api_device.h)
229 // These are only allocated when using the std::string overload (nullptr for const char* overload)
230 std::unique_ptr<std::string> entity_id_dynamic_storage;
231 std::unique_ptr<std::string> attribute_dynamic_storage;
232 };
233
234 // New const char* overload (for internal components - zero allocation)
235 void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f);
236 void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f);
237
238 // std::string overload with StringRef callback (for custom_api_device.h with zero-allocation callback)
239 void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
240 std::function<void(StringRef)> &&f);
241 void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
242 std::function<void(StringRef)> &&f);
243
244 // Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string for callback)
245 void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
246 std::function<void(const std::string &)> &&f);
247 void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
248 std::function<void(const std::string &)> &&f);
249
250 const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
251#endif
252#ifdef USE_API_USER_DEFINED_ACTIONS
253 const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; }
254#endif
255
256#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
258#endif
259#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
261#endif
262
263 protected:
264 // Accept incoming socket connections. Only called when socket has pending connections.
265 void __attribute__((noinline)) accept_new_connections_();
266 // Remove a disconnected client by index. Swaps with the last populated slot and resets it.
267 void __attribute__((noinline)) remove_client_(uint8_t client_index);
268
269#ifdef USE_PROVISIONING
270 // True while a configured provisioning window is still pending (the device is
271 // unprovisioned). Suppresses the reboot timeout and its warning so the device is
272 // not auto-rebooted while waiting to be provisioned. False when no provisioning
273 // window is configured.
278#else
279 bool provisioning_pending_() const { return false; }
280#endif
281
282#ifdef USE_API_NOISE
283#ifndef USE_API_NOISE_PSK_FROM_YAML
284 bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg,
285 bool make_active);
286 // Load saved PSK from preferences and apply it. Returns true on success.
288#endif // USE_API_NOISE_PSK_FROM_YAML
289#endif // USE_API_NOISE
290#ifdef USE_API_HOMEASSISTANT_STATES
291 // Helper methods to reduce code duplication
292 void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f,
293 bool once);
294 void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
295 std::function<void(StringRef)> &&f, bool once);
296 // Legacy helper: wraps std::string callback and delegates to StringRef version
297 void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
298 std::function<void(const std::string &)> &&f, bool once);
299#endif // USE_API_HOMEASSISTANT_STATES
300 // No explicit close() needed — listen sockets have no active connections on
301 // failure/shutdown. Destructor handles fd cleanup (close or abort per platform).
302 inline void destroy_socket_() {
303 delete this->socket_;
304 this->socket_ = nullptr;
305 }
306 void socket_failed_(const LogString *msg);
307 // Pointers and pointer-like types first (4 bytes each)
309#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
311#endif
312#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
314#endif
315
316 // 4-byte aligned types
319
320 // Slots [0, api_connection_count_) are populated; trailing slots are always nullptr.
321 std::array<APIConnectionPtr, MAX_API_CONNECTIONS> clients_{};
322 // Vectors and strings (12 bytes each on 32-bit)
323 // Shared proto write buffer for all connections.
324 // Not pre-allocated: all send paths call prepare_first_message_buffer() which
325 // reserves the exact needed size. Pre-allocating here would cause heap fragmentation
326 // since the buffer would almost always reallocate on first use.
328#ifdef USE_API_HOMEASSISTANT_STATES
329 std::vector<HomeAssistantStateSubscription> state_subs_;
330#endif
331#ifdef USE_API_USER_DEFINED_ACTIONS
332 std::vector<UserServiceDescriptor *> user_services_;
333#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
334 // Active action calls - supports concurrent calls from multiple clients
335 // Uses server-generated action_call_id to avoid collisions when multiple clients use same call_id
337 uint32_t action_call_id; // Server-generated unique ID (passed to actions)
338 uint32_t client_call_id; // Client's original call_id (used in response)
340 };
341 std::vector<ActiveActionCall> active_action_calls_;
342 uint32_t next_action_call_id_{1}; // Counter for generating unique action_call_ids
343#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
344#endif
345#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
350 std::vector<PendingActionResponse> action_response_callbacks_;
351#endif
352
353 // Group smaller types together
354 uint16_t port_{6053};
355 uint16_t batch_delay_{100};
356 // Connection limits - these defaults will be overridden by config values
357 // from cv.SplitDefault in __init__.py which sets platform-specific defaults.
358 uint8_t listen_backlog_{4};
359 bool shutting_down_ = false;
361#if defined(USE_PROVISIONING) && defined(USE_API_NOISE)
362 // Index assigned by the provisioning manager for reporting this transport's state.
364#endif
365
366#ifdef USE_API_NOISE
368#ifndef USE_API_NOISE_PSK_FROM_YAML
369 SavedNoisePsk saved_psk_{}; // backs noise_ctx_ for a runtime provisioned key
370#endif
372#endif // USE_API_NOISE
373};
374
375extern APIServer *global_api_server; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
376
377template<typename... Ts> class APIConnectedCondition final : public Condition<Ts...> {
378 TEMPLATABLE_VALUE(bool, state_subscription_only)
379 public:
380 bool check(const Ts &...x) override {
381 if (this->state_subscription_only_.value(x...)) {
383 }
385 }
386};
387
388} // namespace esphome::api
389#endif
Base class for all automation conditions.
Definition automation.h:438
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:26
const APIConnectionPtr * end() const
Definition api_server.h:215
ActiveClientsView(const APIConnectionPtr *b, const APIConnectionPtr *e)
Definition api_server.h:213
const APIConnectionPtr * begin() const
Definition api_server.h:214
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:257
std::array< APIConnectionPtr, MAX_API_CONNECTIONS > clients_
Definition api_server.h:321
void on_valve_update(valve::Valve *obj) override
uint16_t get_batch_delay() const
Definition api_server.h:72
std::unique_ptr< APIConnection > APIConnectionPtr
Definition api_server.h:207
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:76
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:260
void on_camera_image(const std::shared_ptr< camera::CameraImage > &image) override
std::vector< UserServiceDescriptor * > user_services_
Definition api_server.h:332
void on_light_update(light::LightState *obj) override
void set_noise_psk(const uint8_t *psk)
psk points at 32 bytes that live in flash for the life of the program
Definition api_server.h:86
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:253
void initialize_user_services(std::initializer_list< UserServiceDescriptor * > services)
Definition api_server.h:160
void on_water_heater_update(water_heater::WaterHeater *obj) override
void set_port(uint16_t port)
Definition api_server.h:69
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)
Definition api_server.h:71
void set_reboot_timeout(uint32_t reboot_timeout)
Definition api_server.h:70
Trigger< std::string, std::string > client_connected_trigger_
Definition api_server.h:310
void set_listen_backlog(uint8_t listen_backlog)
Definition api_server.h:73
void send_action_response(uint32_t action_call_id, bool success, StringRef error_message)
void register_user_service(UserServiceDescriptor *descriptor)
Definition api_server.h:165
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:201
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:308
void on_event(event::Event *obj) override
void on_update(update::UpdateEntity *obj) override
std::vector< PendingActionResponse > action_response_callbacks_
Definition api_server.h:350
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:150
bool provisioning_pending_() const
Definition api_server.h:274
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:371
void on_fan_update(fan::Fan *obj) override
SavedNoisePsk saved_psk_
Definition api_server.h:369
Trigger< std::string, std::string > client_disconnected_trigger_
Definition api_server.h:313
std::vector< HomeAssistantStateSubscription > state_subs_
Definition api_server.h:329
bool clear_noise_psk(bool make_active=true)
ActiveClientsView active_clients() const
Definition api_server.h:217
void on_select_update(select::Select *obj) override
uint16_t get_port() const
Definition api_server.h:57
void __attribute__((noinline)) accept_new_connections_()
void on_text_update(text::Text *obj) override
bool save_noise_psk(noise::psk_t psk, bool make_active=true)
void on_text_sensor_update(text_sensor::TextSensor *obj) override
std::vector< ActiveActionCall > active_action_calls_
Definition api_server.h:341
void on_datetime_update(datetime::DateTimeEntity *obj) override
APIBuffer shared_write_buffer_
Definition api_server.h:327
void on_sensor_update(sensor::Sensor *obj) override
void __attribute__((noinline)) remove_client_(uint8_t client_index)
float get_setup_priority() const override
Definition api_server.h:58
uint32_t register_active_action_call(uint32_t client_call_id, APIConnection *conn)
noise::NoiseContext noise_ctx_
Definition api_server.h:367
void on_shutdown() override
void on_zwave_proxy_request(const ZWaveProxyRequest &msg)
void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override
noise::NoiseContext & get_noise_ctx()
Definition api_server.h:87
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
void set_psk(const uint8_t *psk)
psk points at 32 bytes that outlive the context (PROGMEM or caller owned RAM); nullptr means no key.
Definition noise.h:29
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 LogString * message
Definition component.cpp:35
APIServer * global_api_server
struct esphome::api::SavedNoisePsk PACKED
std::array< uint8_t, 32 > psk_t
Definition noise.h:11
ProvisioningManager * global_provisioning_manager
constexpr float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.h:55
static void uint32_t
std::unique_ptr< std::string > entity_id_dynamic_storage
Definition api_server.h:230
std::unique_ptr< std::string > attribute_dynamic_storage
Definition api_server.h:231
uint16_t x
Definition tt21100.cpp:5