13#ifdef USE_API_HOMEASSISTANT_SERVICES
26static const char *
const TAG =
"api";
41 uint32_t hash = 88491486UL;
45#ifndef USE_API_NOISE_PSK_FROM_YAML
49 ESP_LOGD(TAG,
"Loaded saved Noise PSK");
57 ESP_LOGW(TAG,
"Could not create socket");
62 int err = this->
socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(
int));
64 ESP_LOGW(TAG,
"Socket unable to set reuseaddr: errno %d", err);
67 err = this->
socket_->setblocking(
false);
69 ESP_LOGW(TAG,
"Socket unable to set nonblocking mode: errno %d", err);
78 ESP_LOGW(TAG,
"Socket unable to set sockaddr: errno %d", errno);
85 ESP_LOGW(TAG,
"Socket unable to bind: errno %d", errno);
92 ESP_LOGW(TAG,
"Socket unable to listen: errno %d", errno);
129 if (this->
clients_.size() >= this->max_connections_) {
130 ESP_LOGW(TAG,
"Max connections (%d), rejecting %s", this->
max_connections_, sock->getpeername().c_str());
136 ESP_LOGD(TAG,
"Accept %s", sock->getpeername().c_str());
143 if (this->
clients_.size() == 1 && this->reboot_timeout_ != 0) {
156 ESP_LOGE(TAG,
"No clients; rebooting");
167 for (
auto &client : this->
clients_) {
168 client->on_fatal_error();
169 ESP_LOGW(TAG,
"%s (%s): Network down; disconnect", client->client_info_.name.c_str(),
170 client->client_info_.peername.c_str());
175 size_t client_index = 0;
176 while (client_index < this->
clients_.size()) {
177 auto &client = this->
clients_[client_index];
179 if (!client->flags_.remove) {
187#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
190#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
193 ESP_LOGV(TAG,
"Remove connection %s", client->client_info_.name.c_str());
196 if (client_index < this->
clients_.size() - 1) {
202 if (this->
clients_.empty() && this->reboot_timeout_ != 0) {
214 " Listen backlog: %u\n"
215 " Max connections: %u",
220 ESP_LOGCONFIG(TAG,
" Supports encryption: YES");
223 ESP_LOGCONFIG(TAG,
" Noise encryption: NO");
227#ifdef USE_API_PASSWORD
231 uint32_t len_a = this->
password_.length();
232 const char *b =
reinterpret_cast<const char *
>(password_data);
233 uint32_t len_b = password_len;
236 volatile uint32_t
length = len_b;
237 volatile const char *left =
nullptr;
238 volatile const char *right = b;
242 left = *((
volatile const char **) &a);
250 for (
size_t i = 0; i <
length; i++) {
251 result |= *left++ ^ *right++;
262#define API_DISPATCH_UPDATE(entity_type, entity_name) \
263 void APIServer::on_##entity_name##_update(entity_type *obj) { \
264 if (obj->is_internal()) \
266 for (auto &c : this->clients_) \
267 c->send_##entity_name##_state(obj); \
270#ifdef USE_BINARY_SENSOR
294#ifdef USE_TEXT_SENSOR
306#ifdef USE_DATETIME_DATE
310#ifdef USE_DATETIME_TIME
314#ifdef USE_DATETIME_DATETIME
334#ifdef USE_MEDIA_PLAYER
355 c->send_update_state(obj);
359#ifdef USE_ZWAVE_PROXY
368#ifdef USE_ALARM_CONTROL_PANEL
376#ifdef USE_API_PASSWORD
382#ifdef USE_API_HOMEASSISTANT_SERVICES
384 for (
auto &client : this->
clients_) {
385 client->send_homeassistant_action(
call);
388#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
395 if (it->call_id == call_id) {
396 auto callback = std::move(it->callback);
404#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
406 const uint8_t *response_data,
size_t response_data_len) {
408 if (it->call_id == call_id) {
409 auto callback = std::move(it->callback);
411 ActionResponse response(success, error_message, response_data, response_data_len);
421#ifdef USE_API_HOMEASSISTANT_STATES
424 std::function<
void(std::string)> f,
bool once) {
426 .entity_id = entity_id, .attribute = attribute, .callback = std::move(f), .once = once,
433 std::function<
void(std::string)> f,
bool once) {
453 std::function<
void(std::string)> f) {
458 std::function<
void(std::string)> f) {
464 std::function<
void(std::string)> f) {
469 std::function<
void(std::string)> f) {
484 const LogString *fail_log_msg,
const psk_t &active_psk,
bool make_active) {
486 ESP_LOGW(TAG,
"%s", LOG_STR_ARG(fail_log_msg));
491 ESP_LOGW(TAG,
"Failed to sync preferences");
494 ESP_LOGD(TAG,
"%s", LOG_STR_ARG(save_log_msg));
497 ESP_LOGW(TAG,
"Disconnecting all clients to reset PSK");
509#ifdef USE_API_NOISE_PSK_FROM_YAML
512 ESP_LOGW(TAG,
"Key set in YAML");
516 if (std::equal(old_psk.begin(), old_psk.end(), psk.begin())) {
517 ESP_LOGW(TAG,
"New PSK matches old");
522 return this->
update_noise_psk_(new_saved_psk, LOG_STR(
"Noise PSK saved"), LOG_STR(
"Failed to save Noise PSK"), psk,
527#ifdef USE_API_NOISE_PSK_FROM_YAML
530 ESP_LOGW(TAG,
"Key set in YAML");
535 return this->
update_noise_psk_(empty_psk, LOG_STR(
"Noise PSK cleared"), LOG_STR(
"Failed to clear Noise PSK"), empty,
541#ifdef USE_HOMEASSISTANT_TIME
543 for (
auto &client : this->
clients_) {
544 if (!client->flags_.remove && client->is_authenticated())
545 client->send_time_request();
551 if (!state_subscription_only) {
555 for (
const auto &client : this->
clients_) {
556 if (client->flags_.state_subscription) {
572 if (!c->flags_.remove && c->get_log_subscription_level() >= level)
573 c->try_send_log_message(level, tag,
message, message_len);
581 if (!c->flags_.remove)
582 c->set_camera_state(image);
622#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
625#ifndef USE_API_ACTION_CALL_TIMEOUT_MS
626#define USE_API_ACTION_CALL_TIMEOUT_MS 30000
639 [
this, action_call_id]() {
640 ESP_LOGD(TAG,
"Action call %u timed out", action_call_id);
644 return action_call_id;
679 if (
call.action_call_id == action_call_id) {
680 call.connection->send_execute_service_response(
call.client_call_id, success, error_message);
684 ESP_LOGW(TAG,
"Cannot send response: no active call found for action_call_id %u", action_call_id);
686#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
688 const uint8_t *response_data,
size_t response_data_len) {
690 if (
call.action_call_id == action_call_id) {
691 call.connection->send_execute_service_response(
call.client_call_id, success, error_message, response_data,
696 ESP_LOGW(TAG,
"Cannot send response: no active call found for action_call_id %u", action_call_id);
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
virtual void mark_failed()
Mark this component as failed.
void status_set_warning(const char *message=nullptr)
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
void status_clear_warning()
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
static void register_controller(Controller *controller)
Register a controller to receive entity state updates.
virtual bool sync()=0
Commit pending writes to flash.
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
void trigger(const Ts &...x)
Inform the parent automation that the event has triggered.
static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single)
const psk_t & get_psk() const
void get_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(std::string)> f)
void register_action_response_callback(uint32_t call_id, ActionResponseCallback callback)
std::vector< std::unique_ptr< APIConnection > > clients_
void set_password(const std::string &password)
void on_camera_image(const std::shared_ptr< camera::CameraImage > &image) 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)
bool save_noise_psk(psk_t psk, bool make_active=true)
void handle_action_response(uint32_t call_id, bool success, const std::string &error_message)
APINoiseContext noise_ctx_
void unregister_active_action_call(uint32_t action_call_id)
void send_homeassistant_action(const HomeassistantActionRequest &call)
void on_event(event::Event *obj) override
void on_update(update::UpdateEntity *obj) override
uint32_t next_action_call_id_
bool check_password(const uint8_t *password_data, size_t password_len) const
std::vector< PendingActionResponse > action_response_callbacks_
const std::vector< HomeAssistantStateSubscription > & get_state_subs() const
Trigger< std::string, std::string > * client_disconnected_trigger_
std::vector< uint8_t > shared_write_buffer_
std::function< void(const class ActionResponse &)> ActionResponseCallback
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)
bool is_connected(bool state_subscription_only=false) const
ESPPreferenceObject noise_pref_
std::vector< HomeAssistantStateSubscription > state_subs_
void on_zwave_proxy_request(const esphome::api::ProtoMessage &msg)
bool clear_noise_psk(bool make_active=true)
uint16_t get_port() const
std::vector< ActiveActionCall > active_action_calls_
void set_noise_psk(psk_t psk)
void send_action_response(uint32_t action_call_id, bool success, const std::string &error_message)
void add_state_subscription_(const char *entity_id, const char *attribute, std::function< void(std::string)> f, bool once)
float get_setup_priority() const override
std::unique_ptr< socket::Socket > socket_
uint32_t register_active_action_call(uint32_t client_call_id, APIConnection *conn)
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(std::string)> f)
void on_shutdown() override
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override
static constexpr uint8_t MESSAGE_TYPE
static constexpr uint8_t ESTIMATED_SIZE
static constexpr uint8_t MESSAGE_TYPE
Base class for all binary_sensor-type classes.
virtual void add_listener(CameraListener *listener)=0
Add a listener to receive camera events.
static Camera * instance()
The singleton instance of the camera implementation.
ClimateDevice - This is the base class for all climate integrations.
Base class for all cover devices.
const char * get_last_event_type() const
Return the last triggered event type (pointer to string in types_), or nullptr if no event triggered ...
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Base class for all locks.
void add_log_listener(LogListener *listener)
Register a log listener to receive log messages.
Base-class for all numbers.
value_type const & value() const
Base-class for all selects.
Base-class for all sensors.
Base class for all switches.
Base-class for all text inputs.
Base class for all valve devices.
APIServer * global_api_server
API_DISPATCH_UPDATE(binary_sensor::BinarySensor, binary_sensor) API_DISPATCH_UPDATE(cover
std::array< uint8_t, 32 > psk_t
const char * get_use_address()
Get the active network hostname.
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
const float AFTER_WIFI
For components that should be initialized after WiFi is connected.
std::unique_ptr< Socket > socket_ip_loop_monitored(int type, int protocol)
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port)
Set a sockaddr to the any address and specified port for the IP version used by socket_ip().
ESPPreferences * global_preferences
std::string str_sprintf(const char *fmt,...)
Application App
Global storage of Application pointer - only one Application can exist.
std::function< void(std::string)> callback
std::unique_ptr< std::string > entity_id_dynamic_storage
std::unique_ptr< std::string > attribute_dynamic_storage