21static const char *
const TAG =
"api";
36 uint32_t hash = 88491486UL;
40#ifndef USE_API_NOISE_PSK_FROM_YAML
44 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);
100 [
this](
int level,
const char *tag,
const char *message,
size_t message_len) {
108 if (!c->flags_.remove && c->get_log_subscription_level() >= level)
109 c->try_send_log_message(level, tag, message, message_len);
119 if (!c->flags_.remove)
120 c->set_camera_state(image);
131 ESP_LOGE(TAG,
"No clients; rebooting");
142 socklen_t addr_len =
sizeof(source_addr);
143 auto sock = this->
socket_->accept_loop_monitored((
struct sockaddr *) &source_addr, &addr_len);
146 ESP_LOGD(TAG,
"Accept %s", sock->getpeername().c_str());
153 if (this->
clients_.size() == 1 && this->reboot_timeout_ != 0) {
168 for (
auto &client : this->
clients_) {
169 client->on_fatal_error();
170 ESP_LOGW(TAG,
"%s: Network down; disconnect", client->get_client_combined_info().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 ESP_LOGV(TAG,
"Remove connection %s", client->client_info_.name.c_str());
193 if (client_index < this->
clients_.size() - 1) {
199 if (this->
clients_.empty() && this->reboot_timeout_ != 0) {
212 ESP_LOGCONFIG(TAG,
" Noise encryption: %s", YESNO(this->
noise_ctx_->has_psk()));
214 ESP_LOGCONFIG(TAG,
" Supports encryption: YES");
217 ESP_LOGCONFIG(TAG,
" Noise encryption: NO");
221#ifdef USE_API_PASSWORD
225 uint32_t len_a = this->
password_.length();
226 const char *b = password.c_str();
227 uint32_t len_b = password.length();
230 volatile uint32_t
length = len_b;
231 volatile const char *left =
nullptr;
232 volatile const char *right = b;
236 left = *((
volatile const char **) &a);
244 for (
size_t i = 0; i <
length; i++) {
245 result |= *left++ ^ *right++;
255#define API_DISPATCH_UPDATE(entity_type, entity_name) \
256 void APIServer::on_##entity_name##_update(entity_type *obj) { \
257 if (obj->is_internal()) \
259 for (auto &c : this->clients_) \
260 c->send_##entity_name##_state(obj); \
264#define API_DISPATCH_UPDATE_IGNORE_PARAMS(entity_type, entity_name, ...) \
265 void APIServer::on_##entity_name##_update(entity_type *obj, __VA_ARGS__) { \
266 if (obj->is_internal()) \
268 for (auto &c : this->clients_) \
269 c->send_##entity_name##_state(obj); \
272#ifdef USE_BINARY_SENSOR
296#ifdef USE_TEXT_SENSOR
308#ifdef USE_DATETIME_DATE
312#ifdef USE_DATETIME_TIME
316#ifdef USE_DATETIME_DATETIME
321API_DISPATCH_UPDATE_IGNORE_PARAMS(
text::Text, text,
const std::string &
state)
325API_DISPATCH_UPDATE_IGNORE_PARAMS(
select::Select, select,
const std::string &
state,
size_t index)
336#ifdef USE_MEDIA_PLAYER
346 c->send_event(obj, event_type);
356 c->send_update_state(obj);
360#ifdef USE_ALARM_CONTROL_PANEL
368#ifdef USE_API_PASSWORD
374#ifdef USE_API_HOMEASSISTANT_SERVICES
376 for (
auto &client : this->
clients_) {
377 client->send_homeassistant_service_call(
call);
382#ifdef USE_API_HOMEASSISTANT_STATES
384 std::function<
void(std::string)> f) {
386 .entity_id = std::move(entity_id),
387 .attribute = std::move(attribute),
388 .callback = std::move(f),
394 std::function<
void(std::string)> f) {
396 .entity_id = std::move(entity_id),
397 .attribute = std::move(attribute),
398 .callback = std::move(f),
414#ifdef USE_API_NOISE_PSK_FROM_YAML
417 ESP_LOGW(TAG,
"Key set in YAML");
421 if (std::equal(old_psk.begin(), old_psk.end(), psk.begin())) {
422 ESP_LOGW(TAG,
"New PSK matches old");
428 ESP_LOGW(TAG,
"Failed to save Noise PSK");
433 ESP_LOGW(TAG,
"Failed to sync preferences");
436 ESP_LOGD(TAG,
"Noise PSK saved");
439 ESP_LOGW(TAG,
"Disconnecting all clients to reset PSK");
452#ifdef USE_HOMEASSISTANT_TIME
454 for (
auto &client : this->
clients_) {
455 if (!client->flags_.remove && client->is_authenticated())
456 client->send_time_request();
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.
void setup_controller(bool include_internal=false)
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(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)
std::vector< std::unique_ptr< APIConnection > > clients_
void send_homeassistant_service_call(const HomeassistantServiceResponse &call)
void set_password(const std::string &password)
void set_port(uint16_t port)
void dump_config() override
void handle_disconnect(APIConnection *conn)
void schedule_reboot_timeout_()
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)
bool is_connected() const
void on_update(update::UpdateEntity *obj) override
bool check_password(const std::string &password) const
void get_home_assistant_state(std::string entity_id, optional< std::string > attribute, std::function< void(std::string)> f)
const std::vector< HomeAssistantStateSubscription > & get_state_subs() const
std::shared_ptr< APINoiseContext > noise_ctx_
Trigger< std::string, std::string > * client_disconnected_trigger_
std::vector< uint8_t > shared_write_buffer_
void subscribe_home_assistant_state(std::string entity_id, optional< std::string > attribute, std::function< void(std::string)> f)
ESPPreferenceObject noise_pref_
std::vector< HomeAssistantStateSubscription > state_subs_
uint16_t get_port() const
void set_noise_psk(psk_t psk)
void on_event(event::Event *obj, const std::string &event_type) override
float get_setup_priority() const override
std::unique_ptr< socket::Socket > socket_
void on_shutdown() override
static constexpr uint8_t MESSAGE_TYPE
static constexpr uint8_t ESTIMATED_SIZE
Base class for all binary_sensor-type classes.
static Camera * instance()
The singleton instance of the camera implementation.
virtual void add_image_callback(std::function< void(std::shared_ptr< CameraImage >)> &&callback)=0
ClimateDevice - This is the base class for all climate integrations.
Base class for all cover devices.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Base class for all locks.
void add_on_log_callback(std::function< void(uint8_t, const char *, const char *, size_t)> &&callback)
Register a callback that will be called for every log message sent.
Base-class for all numbers.
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
std::string 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
Application App
Global storage of Application pointer - only one Application can exist.