1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-29 22:24:26 +00:00

Webserver utilize Component Iterator to not overload eventstream (#3310)

This commit is contained in:
Jesse Hills
2022-03-23 09:45:05 +13:00
committed by GitHub
parent e621b938e3
commit bfbf88b2ea
13 changed files with 217 additions and 134 deletions

View File

@@ -23,7 +23,7 @@ static const char *const TAG = "api.connection";
static const int ESP32_CAMERA_STOP_STREAM = 5000;
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
: parent_(parent), initial_state_iterator_(parent, this), list_entities_iterator_(parent, this) {
: parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
this->proto_write_buffer_.reserve(64);
#if defined(USE_API_PLAINTEXT)

View File

@@ -7,7 +7,6 @@
#include "esphome/components/socket/socket.h"
#include "api_pb2.h"
#include "api_pb2_service.h"
#include "util.h"
#include "list_entities.h"
#include "subscribe_state.h"
#include "user_services.h"

View File

@@ -40,8 +40,7 @@ bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { return this->client_->s
#endif
bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); }
ListEntitiesIterator::ListEntitiesIterator(APIServer *server, APIConnection *client)
: ComponentIterator(server), client_(client) {}
ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {}
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
auto resp = service->encode_list_service_response();
return this->client_->send_list_entities_services_response(resp);

View File

@@ -1,8 +1,8 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/component_iterator.h"
#include "esphome/core/defines.h"
#include "util.h"
namespace esphome {
namespace api {
@@ -11,7 +11,7 @@ class APIConnection;
class ListEntitiesIterator : public ComponentIterator {
public:
ListEntitiesIterator(APIServer *server, APIConnection *client);
ListEntitiesIterator(APIConnection *client);
#ifdef USE_BINARY_SENSOR
bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) override;
#endif
@@ -60,5 +60,3 @@ class ListEntitiesIterator : public ComponentIterator {
} // namespace api
} // namespace esphome
#include "api_server.h"

View File

@@ -1,5 +1,4 @@
#include "proto.h"
#include "util.h"
#include "esphome/core/log.h"
namespace esphome {

View File

@@ -50,8 +50,7 @@ bool InitialStateIterator::on_select(select::Select *select) {
#ifdef USE_LOCK
bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock, a_lock->state); }
#endif
InitialStateIterator::InitialStateIterator(APIServer *server, APIConnection *client)
: ComponentIterator(server), client_(client) {}
InitialStateIterator::InitialStateIterator(APIConnection *client) : client_(client) {}
} // namespace api
} // namespace esphome

View File

@@ -1,9 +1,9 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/component_iterator.h"
#include "esphome/core/controller.h"
#include "esphome/core/defines.h"
#include "util.h"
namespace esphome {
namespace api {
@@ -12,7 +12,7 @@ class APIConnection;
class InitialStateIterator : public ComponentIterator {
public:
InitialStateIterator(APIServer *server, APIConnection *client);
InitialStateIterator(APIConnection *client);
#ifdef USE_BINARY_SENSOR
bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) override;
#endif
@@ -55,5 +55,3 @@ class InitialStateIterator : public ComponentIterator {
} // namespace api
} // namespace esphome
#include "api_server.h"

View File

@@ -1,253 +0,0 @@
#include "util.h"
#include "api_server.h"
#include "user_services.h"
#include "esphome/core/log.h"
#include "esphome/core/application.h"
namespace esphome {
namespace api {
ComponentIterator::ComponentIterator(APIServer *server) : server_(server) {}
void ComponentIterator::begin() {
this->state_ = IteratorState::BEGIN;
this->at_ = 0;
}
void ComponentIterator::advance() {
bool advance_platform = false;
bool success = true;
switch (this->state_) {
case IteratorState::NONE:
// not started
return;
case IteratorState::BEGIN:
if (this->on_begin()) {
advance_platform = true;
} else {
return;
}
break;
#ifdef USE_BINARY_SENSOR
case IteratorState::BINARY_SENSOR:
if (this->at_ >= App.get_binary_sensors().size()) {
advance_platform = true;
} else {
auto *binary_sensor = App.get_binary_sensors()[this->at_];
if (binary_sensor->is_internal()) {
success = true;
break;
} else {
success = this->on_binary_sensor(binary_sensor);
}
}
break;
#endif
#ifdef USE_COVER
case IteratorState::COVER:
if (this->at_ >= App.get_covers().size()) {
advance_platform = true;
} else {
auto *cover = App.get_covers()[this->at_];
if (cover->is_internal()) {
success = true;
break;
} else {
success = this->on_cover(cover);
}
}
break;
#endif
#ifdef USE_FAN
case IteratorState::FAN:
if (this->at_ >= App.get_fans().size()) {
advance_platform = true;
} else {
auto *fan = App.get_fans()[this->at_];
if (fan->is_internal()) {
success = true;
break;
} else {
success = this->on_fan(fan);
}
}
break;
#endif
#ifdef USE_LIGHT
case IteratorState::LIGHT:
if (this->at_ >= App.get_lights().size()) {
advance_platform = true;
} else {
auto *light = App.get_lights()[this->at_];
if (light->is_internal()) {
success = true;
break;
} else {
success = this->on_light(light);
}
}
break;
#endif
#ifdef USE_SENSOR
case IteratorState::SENSOR:
if (this->at_ >= App.get_sensors().size()) {
advance_platform = true;
} else {
auto *sensor = App.get_sensors()[this->at_];
if (sensor->is_internal()) {
success = true;
break;
} else {
success = this->on_sensor(sensor);
}
}
break;
#endif
#ifdef USE_SWITCH
case IteratorState::SWITCH:
if (this->at_ >= App.get_switches().size()) {
advance_platform = true;
} else {
auto *a_switch = App.get_switches()[this->at_];
if (a_switch->is_internal()) {
success = true;
break;
} else {
success = this->on_switch(a_switch);
}
}
break;
#endif
#ifdef USE_BUTTON
case IteratorState::BUTTON:
if (this->at_ >= App.get_buttons().size()) {
advance_platform = true;
} else {
auto *button = App.get_buttons()[this->at_];
if (button->is_internal()) {
success = true;
break;
} else {
success = this->on_button(button);
}
}
break;
#endif
#ifdef USE_TEXT_SENSOR
case IteratorState::TEXT_SENSOR:
if (this->at_ >= App.get_text_sensors().size()) {
advance_platform = true;
} else {
auto *text_sensor = App.get_text_sensors()[this->at_];
if (text_sensor->is_internal()) {
success = true;
break;
} else {
success = this->on_text_sensor(text_sensor);
}
}
break;
#endif
case IteratorState ::SERVICE:
if (this->at_ >= this->server_->get_user_services().size()) {
advance_platform = true;
} else {
auto *service = this->server_->get_user_services()[this->at_];
success = this->on_service(service);
}
break;
#ifdef USE_ESP32_CAMERA
case IteratorState::CAMERA:
if (esp32_camera::global_esp32_camera == nullptr) {
advance_platform = true;
} else {
if (esp32_camera::global_esp32_camera->is_internal()) {
advance_platform = success = true;
break;
} else {
advance_platform = success = this->on_camera(esp32_camera::global_esp32_camera);
}
}
break;
#endif
#ifdef USE_CLIMATE
case IteratorState::CLIMATE:
if (this->at_ >= App.get_climates().size()) {
advance_platform = true;
} else {
auto *climate = App.get_climates()[this->at_];
if (climate->is_internal()) {
success = true;
break;
} else {
success = this->on_climate(climate);
}
}
break;
#endif
#ifdef USE_NUMBER
case IteratorState::NUMBER:
if (this->at_ >= App.get_numbers().size()) {
advance_platform = true;
} else {
auto *number = App.get_numbers()[this->at_];
if (number->is_internal()) {
success = true;
break;
} else {
success = this->on_number(number);
}
}
break;
#endif
#ifdef USE_SELECT
case IteratorState::SELECT:
if (this->at_ >= App.get_selects().size()) {
advance_platform = true;
} else {
auto *select = App.get_selects()[this->at_];
if (select->is_internal()) {
success = true;
break;
} else {
success = this->on_select(select);
}
}
break;
#endif
#ifdef USE_LOCK
case IteratorState::LOCK:
if (this->at_ >= App.get_locks().size()) {
advance_platform = true;
} else {
auto *a_lock = App.get_locks()[this->at_];
if (a_lock->is_internal()) {
success = true;
break;
} else {
success = this->on_lock(a_lock);
}
}
break;
#endif
case IteratorState::MAX:
if (this->on_end()) {
this->state_ = IteratorState::NONE;
}
return;
}
if (advance_platform) {
this->state_ = static_cast<IteratorState>(static_cast<uint32_t>(this->state_) + 1);
this->at_ = 0;
} else if (success) {
this->at_++;
}
}
bool ComponentIterator::on_end() { return true; }
bool ComponentIterator::on_begin() { return true; }
bool ComponentIterator::on_service(UserServiceDescriptor *service) { return true; }
#ifdef USE_ESP32_CAMERA
bool ComponentIterator::on_camera(esp32_camera::ESP32Camera *camera) { return true; }
#endif
} // namespace api
} // namespace esphome

View File

@@ -1,117 +0,0 @@
#pragma once
#include "esphome/core/helpers.h"
#include "esphome/core/component.h"
#include "esphome/core/controller.h"
#ifdef USE_ESP32_CAMERA
#include "esphome/components/esp32_camera/esp32_camera.h"
#endif
namespace esphome {
namespace api {
class APIServer;
class UserServiceDescriptor;
class ComponentIterator {
public:
ComponentIterator(APIServer *server);
void begin();
void advance();
virtual bool on_begin();
#ifdef USE_BINARY_SENSOR
virtual bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) = 0;
#endif
#ifdef USE_COVER
virtual bool on_cover(cover::Cover *cover) = 0;
#endif
#ifdef USE_FAN
virtual bool on_fan(fan::Fan *fan) = 0;
#endif
#ifdef USE_LIGHT
virtual bool on_light(light::LightState *light) = 0;
#endif
#ifdef USE_SENSOR
virtual bool on_sensor(sensor::Sensor *sensor) = 0;
#endif
#ifdef USE_SWITCH
virtual bool on_switch(switch_::Switch *a_switch) = 0;
#endif
#ifdef USE_BUTTON
virtual bool on_button(button::Button *button) = 0;
#endif
#ifdef USE_TEXT_SENSOR
virtual bool on_text_sensor(text_sensor::TextSensor *text_sensor) = 0;
#endif
virtual bool on_service(UserServiceDescriptor *service);
#ifdef USE_ESP32_CAMERA
virtual bool on_camera(esp32_camera::ESP32Camera *camera);
#endif
#ifdef USE_CLIMATE
virtual bool on_climate(climate::Climate *climate) = 0;
#endif
#ifdef USE_NUMBER
virtual bool on_number(number::Number *number) = 0;
#endif
#ifdef USE_SELECT
virtual bool on_select(select::Select *select) = 0;
#endif
#ifdef USE_LOCK
virtual bool on_lock(lock::Lock *a_lock) = 0;
#endif
virtual bool on_end();
protected:
enum class IteratorState {
NONE = 0,
BEGIN,
#ifdef USE_BINARY_SENSOR
BINARY_SENSOR,
#endif
#ifdef USE_COVER
COVER,
#endif
#ifdef USE_FAN
FAN,
#endif
#ifdef USE_LIGHT
LIGHT,
#endif
#ifdef USE_SENSOR
SENSOR,
#endif
#ifdef USE_SWITCH
SWITCH,
#endif
#ifdef USE_BUTTON
BUTTON,
#endif
#ifdef USE_TEXT_SENSOR
TEXT_SENSOR,
#endif
SERVICE,
#ifdef USE_ESP32_CAMERA
CAMERA,
#endif
#ifdef USE_CLIMATE
CLIMATE,
#endif
#ifdef USE_NUMBER
NUMBER,
#endif
#ifdef USE_SELECT
SELECT,
#endif
#ifdef USE_LOCK
LOCK,
#endif
MAX,
} state_{IteratorState::NONE};
size_t at_{0};
APIServer *server_;
};
} // namespace api
} // namespace esphome