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