mirror of https://github.com/esphome/esphome.git
246 lines
7.6 KiB
C++
246 lines
7.6 KiB
C++
#pragma once
|
|
|
|
#include "esphome/core/component.h"
|
|
#include "esphome/core/controller.h"
|
|
#include "esphome/core/defines.h"
|
|
#include "esphome/core/log.h"
|
|
#include "util.h"
|
|
#include "api_message.h"
|
|
#include "basic_messages.h"
|
|
#include "list_entities.h"
|
|
#include "subscribe_state.h"
|
|
#include "subscribe_logs.h"
|
|
#include "command_messages.h"
|
|
#include "service_call_message.h"
|
|
#include "user_services.h"
|
|
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
#include <AsyncTCP.h>
|
|
#endif
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
#include <ESPAsyncTCP.h>
|
|
#endif
|
|
|
|
namespace esphome {
|
|
namespace api {
|
|
|
|
class APIServer;
|
|
|
|
class APIConnection {
|
|
public:
|
|
APIConnection(AsyncClient *client, APIServer *parent);
|
|
~APIConnection();
|
|
|
|
void disconnect_client();
|
|
APIBuffer get_buffer();
|
|
bool send_buffer(APIMessageType type);
|
|
bool send_message(APIMessage &msg);
|
|
bool send_empty_message(APIMessageType type);
|
|
void loop();
|
|
|
|
#ifdef USE_BINARY_SENSOR
|
|
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state);
|
|
#endif
|
|
#ifdef USE_COVER
|
|
bool send_cover_state(cover::Cover *cover);
|
|
#endif
|
|
#ifdef USE_FAN
|
|
bool send_fan_state(fan::FanState *fan);
|
|
#endif
|
|
#ifdef USE_LIGHT
|
|
bool send_light_state(light::LightState *light);
|
|
#endif
|
|
#ifdef USE_SENSOR
|
|
bool send_sensor_state(sensor::Sensor *sensor, float state);
|
|
#endif
|
|
#ifdef USE_SWITCH
|
|
bool send_switch_state(switch_::Switch *a_switch, bool state);
|
|
#endif
|
|
#ifdef USE_TEXT_SENSOR
|
|
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state);
|
|
#endif
|
|
#ifdef USE_ESP32_CAMERA
|
|
void send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image);
|
|
#endif
|
|
#ifdef USE_CLIMATE
|
|
bool send_climate_state(climate::Climate *climate);
|
|
#endif
|
|
bool send_log_message(int level, const char *tag, const char *line);
|
|
bool send_disconnect_request();
|
|
bool send_ping_request();
|
|
void send_service_call(ServiceCallResponse &call);
|
|
#ifdef USE_HOMEASSISTANT_TIME
|
|
void send_time_request();
|
|
#endif
|
|
|
|
protected:
|
|
friend APIServer;
|
|
|
|
void on_error_(int8_t error);
|
|
void on_disconnect_();
|
|
void on_timeout_(uint32_t time);
|
|
void on_data_(uint8_t *buf, size_t len);
|
|
void fatal_error_();
|
|
bool valid_rx_message_type_(uint32_t msg_type);
|
|
void read_message_(uint32_t size, uint32_t type, uint8_t *msg);
|
|
void parse_recv_buffer_();
|
|
|
|
// request types
|
|
void on_hello_request_(const HelloRequest &req);
|
|
void on_connect_request_(const ConnectRequest &req);
|
|
void on_disconnect_request_(const DisconnectRequest &req);
|
|
void on_disconnect_response_(const DisconnectResponse &req);
|
|
void on_ping_request_(const PingRequest &req);
|
|
void on_ping_response_(const PingResponse &req);
|
|
void on_device_info_request_(const DeviceInfoRequest &req);
|
|
void on_list_entities_request_(const ListEntitiesRequest &req);
|
|
void on_subscribe_states_request_(const SubscribeStatesRequest &req);
|
|
void on_subscribe_logs_request_(const SubscribeLogsRequest &req);
|
|
#ifdef USE_COVER
|
|
void on_cover_command_request_(const CoverCommandRequest &req);
|
|
#endif
|
|
#ifdef USE_FAN
|
|
void on_fan_command_request_(const FanCommandRequest &req);
|
|
#endif
|
|
#ifdef USE_LIGHT
|
|
void on_light_command_request_(const LightCommandRequest &req);
|
|
#endif
|
|
#ifdef USE_SWITCH
|
|
void on_switch_command_request_(const SwitchCommandRequest &req);
|
|
#endif
|
|
#ifdef USE_CLIMATE
|
|
void on_climate_command_request_(const ClimateCommandRequest &req);
|
|
#endif
|
|
void on_subscribe_service_calls_request_(const SubscribeServiceCallsRequest &req);
|
|
void on_subscribe_home_assistant_states_request_(const SubscribeHomeAssistantStatesRequest &req);
|
|
void on_home_assistant_state_response_(const HomeAssistantStateResponse &req);
|
|
void on_execute_service_(const ExecuteServiceRequest &req);
|
|
#ifdef USE_ESP32_CAMERA
|
|
void on_camera_image_request_(const CameraImageRequest &req);
|
|
#endif
|
|
|
|
enum class ConnectionState {
|
|
WAITING_FOR_HELLO,
|
|
WAITING_FOR_CONNECT,
|
|
CONNECTED,
|
|
} connection_state_{ConnectionState::WAITING_FOR_HELLO};
|
|
|
|
bool remove_{false};
|
|
|
|
std::vector<uint8_t> send_buffer_;
|
|
std::vector<uint8_t> recv_buffer_;
|
|
|
|
std::string client_info_;
|
|
#ifdef USE_ESP32_CAMERA
|
|
esp32_camera::CameraImageReader image_reader_;
|
|
#endif
|
|
|
|
bool state_subscription_{false};
|
|
int log_subscription_{ESPHOME_LOG_LEVEL_NONE};
|
|
uint32_t last_traffic_;
|
|
bool sent_ping_{false};
|
|
bool service_call_subscription_{false};
|
|
AsyncClient *client_;
|
|
APIServer *parent_;
|
|
InitialStateIterator initial_state_iterator_;
|
|
ListEntitiesIterator list_entities_iterator_;
|
|
};
|
|
|
|
template<typename... Ts> class HomeAssistantServiceCallAction;
|
|
|
|
class APIServer : public Component, public Controller {
|
|
public:
|
|
APIServer();
|
|
void setup() override;
|
|
uint16_t get_port() const;
|
|
float get_setup_priority() const override;
|
|
void loop() override;
|
|
void dump_config() override;
|
|
void on_shutdown() override;
|
|
bool check_password(const std::string &password) const;
|
|
bool uses_password() const;
|
|
void set_port(uint16_t port);
|
|
void set_password(const std::string &password);
|
|
void set_reboot_timeout(uint32_t reboot_timeout);
|
|
void handle_disconnect(APIConnection *conn);
|
|
#ifdef USE_BINARY_SENSOR
|
|
void on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool state) override;
|
|
#endif
|
|
#ifdef USE_COVER
|
|
void on_cover_update(cover::Cover *obj) override;
|
|
#endif
|
|
#ifdef USE_FAN
|
|
void on_fan_update(fan::FanState *obj) override;
|
|
#endif
|
|
#ifdef USE_LIGHT
|
|
void on_light_update(light::LightState *obj) override;
|
|
#endif
|
|
#ifdef USE_SENSOR
|
|
void on_sensor_update(sensor::Sensor *obj, float state) override;
|
|
#endif
|
|
#ifdef USE_SWITCH
|
|
void on_switch_update(switch_::Switch *obj, bool state) override;
|
|
#endif
|
|
#ifdef USE_TEXT_SENSOR
|
|
void on_text_sensor_update(text_sensor::TextSensor *obj, std::string state) override;
|
|
#endif
|
|
#ifdef USE_CLIMATE
|
|
void on_climate_update(climate::Climate *obj) override;
|
|
#endif
|
|
void send_service_call(ServiceCallResponse &call);
|
|
void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
|
|
#ifdef USE_HOMEASSISTANT_TIME
|
|
void request_time();
|
|
#endif
|
|
|
|
bool is_connected() const;
|
|
|
|
struct HomeAssistantStateSubscription {
|
|
std::string entity_id;
|
|
std::function<void(std::string)> callback;
|
|
};
|
|
|
|
void subscribe_home_assistant_state(std::string entity_id, std::function<void(std::string)> f);
|
|
const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
|
|
const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; }
|
|
|
|
protected:
|
|
AsyncServer server_{0};
|
|
uint16_t port_{6053};
|
|
uint32_t reboot_timeout_{300000};
|
|
uint32_t last_connected_{0};
|
|
std::vector<APIConnection *> clients_;
|
|
std::string password_;
|
|
std::vector<HomeAssistantStateSubscription> state_subs_;
|
|
std::vector<UserServiceDescriptor *> user_services_;
|
|
};
|
|
|
|
extern APIServer *global_api_server;
|
|
|
|
template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts...> {
|
|
public:
|
|
explicit HomeAssistantServiceCallAction(APIServer *parent) : parent_(parent) {}
|
|
void set_service(const std::string &service) { this->resp_.set_service(service); }
|
|
void set_data(const std::vector<KeyValuePair> &data) { this->resp_.set_data(data); }
|
|
void set_data_template(const std::vector<KeyValuePair> &data_template) {
|
|
this->resp_.set_data_template(data_template);
|
|
}
|
|
void set_variables(const std::vector<TemplatableKeyValuePair> &variables) { this->resp_.set_variables(variables); }
|
|
void play(Ts... x) override {
|
|
this->parent_->send_service_call(this->resp_);
|
|
this->play_next(x...);
|
|
}
|
|
|
|
protected:
|
|
APIServer *parent_;
|
|
ServiceCallResponse resp_;
|
|
};
|
|
|
|
template<typename... Ts> class APIConnectedCondition : public Condition<Ts...> {
|
|
public:
|
|
bool check(Ts... x) override { return global_api_server->is_connected(); }
|
|
};
|
|
|
|
} // namespace api
|
|
} // namespace esphome
|