mirror of
https://github.com/esphome/esphome.git
synced 2025-08-04 01:17:48 +00:00
Guard custom services
This commit is contained in:
parent
143bf694c7
commit
2384b54ee3
@ -24,8 +24,9 @@ from esphome.const import (
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_VARIABLES,
|
||||
)
|
||||
from esphome.core import coroutine_with_priority
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
|
||||
DOMAIN = "api"
|
||||
DEPENDENCIES = ["network"]
|
||||
AUTO_LOAD = ["socket"]
|
||||
CODEOWNERS = ["@OttoWinter"]
|
||||
@ -51,6 +52,7 @@ SERVICE_ARG_NATIVE_TYPES = {
|
||||
}
|
||||
CONF_ENCRYPTION = "encryption"
|
||||
CONF_BATCH_DELAY = "batch_delay"
|
||||
CONF_CUSTOM_SERVICES = "custom_services"
|
||||
|
||||
|
||||
def validate_encryption_key(value):
|
||||
@ -115,6 +117,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.positive_time_period_milliseconds,
|
||||
cv.Range(max=cv.TimePeriod(milliseconds=65535)),
|
||||
),
|
||||
cv.Optional(CONF_CUSTOM_SERVICES, default=False): cv.boolean,
|
||||
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
|
||||
single=True
|
||||
),
|
||||
@ -139,8 +142,11 @@ async def to_code(config):
|
||||
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||
cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY]))
|
||||
|
||||
# Set USE_API_SERVICES if any services are enabled
|
||||
if config.get(CONF_ACTIONS) or config[CONF_CUSTOM_SERVICES]:
|
||||
cg.add_define("USE_API_SERVICES")
|
||||
|
||||
if actions := config.get(CONF_ACTIONS, []):
|
||||
cg.add_define("USE_API_YAML_SERVICES")
|
||||
for conf in actions:
|
||||
template_args = []
|
||||
func_args = []
|
||||
@ -317,7 +323,10 @@ async def api_connected_to_code(config, condition_id, template_arg, args):
|
||||
|
||||
|
||||
def FILTER_SOURCE_FILES() -> list[str]:
|
||||
"""Filter out api_pb2_dump.cpp when proto message dumping is not enabled."""
|
||||
"""Filter out api_pb2_dump.cpp when proto message dumping is not enabled
|
||||
and user_services.cpp when no services are defined."""
|
||||
files_to_filter = []
|
||||
|
||||
# api_pb2_dump.cpp is only needed when HAS_PROTO_MESSAGE_DUMP is defined
|
||||
# This is a particularly large file that still needs to be opened and read
|
||||
# all the way to the end even when ifdef'd out
|
||||
@ -325,6 +334,11 @@ def FILTER_SOURCE_FILES() -> list[str]:
|
||||
# HAS_PROTO_MESSAGE_DUMP is defined when ESPHOME_LOG_HAS_VERY_VERBOSE is set,
|
||||
# which happens when the logger level is VERY_VERBOSE
|
||||
if get_logger_level() != "VERY_VERBOSE":
|
||||
return ["api_pb2_dump.cpp"]
|
||||
files_to_filter.append("api_pb2_dump.cpp")
|
||||
|
||||
return []
|
||||
# user_services.cpp is only needed when services are defined
|
||||
config = CORE.config.get(DOMAIN, {})
|
||||
if config and not config.get(CONF_ACTIONS) and not config[CONF_CUSTOM_SERVICES]:
|
||||
files_to_filter.append("user_services.cpp")
|
||||
|
||||
return files_to_filter
|
||||
|
@ -807,18 +807,21 @@ enum ServiceArgType {
|
||||
SERVICE_ARG_TYPE_STRING_ARRAY = 7;
|
||||
}
|
||||
message ListEntitiesServicesArgument {
|
||||
option (ifdef) = "USE_API_SERVICES";
|
||||
string name = 1;
|
||||
ServiceArgType type = 2;
|
||||
}
|
||||
message ListEntitiesServicesResponse {
|
||||
option (id) = 41;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_API_SERVICES";
|
||||
|
||||
string name = 1;
|
||||
fixed32 key = 2;
|
||||
repeated ListEntitiesServicesArgument args = 3;
|
||||
}
|
||||
message ExecuteServiceArgument {
|
||||
option (ifdef) = "USE_API_SERVICES";
|
||||
bool bool_ = 1;
|
||||
int32 legacy_int = 2;
|
||||
float float_ = 3;
|
||||
@ -834,6 +837,7 @@ message ExecuteServiceRequest {
|
||||
option (id) = 42;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (no_delay) = true;
|
||||
option (ifdef) = "USE_API_SERVICES";
|
||||
|
||||
fixed32 key = 1;
|
||||
repeated ExecuteServiceArgument args = 2;
|
||||
|
@ -1551,6 +1551,7 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
|
||||
bool found = false;
|
||||
for (auto *service : this->parent_->get_user_services()) {
|
||||
@ -1562,6 +1563,7 @@ void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
|
||||
ESP_LOGV(TAG, "Could not find service");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
NoiseEncryptionSetKeyResponse APIConnection::noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) {
|
||||
psk_t psk{};
|
||||
|
@ -195,7 +195,9 @@ class APIConnection : public APIServerConnection {
|
||||
// TODO
|
||||
return {};
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
void execute_service(const ExecuteServiceRequest &msg) override;
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
NoiseEncryptionSetKeyResponse noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) override;
|
||||
#endif
|
||||
|
@ -2046,6 +2046,7 @@ void GetTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixe
|
||||
void GetTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_fixed_field<4>(total_size, 1, this->epoch_seconds != 0, false);
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
bool ListEntitiesServicesArgument::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
@ -2240,6 +2241,7 @@ void ExecuteServiceRequest::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_fixed_field<4>(total_size, 1, this->key != 0, false);
|
||||
ProtoSize::add_repeated_message(total_size, 1, this->args);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
bool ListEntitiesCameraResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
|
@ -82,6 +82,7 @@ enum LogLevel : uint32_t {
|
||||
LOG_LEVEL_VERBOSE = 6,
|
||||
LOG_LEVEL_VERY_VERBOSE = 7,
|
||||
};
|
||||
#ifdef USE_API_SERVICES
|
||||
enum ServiceArgType : uint32_t {
|
||||
SERVICE_ARG_TYPE_BOOL = 0,
|
||||
SERVICE_ARG_TYPE_INT = 1,
|
||||
@ -92,6 +93,7 @@ enum ServiceArgType : uint32_t {
|
||||
SERVICE_ARG_TYPE_FLOAT_ARRAY = 6,
|
||||
SERVICE_ARG_TYPE_STRING_ARRAY = 7,
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
enum ClimateMode : uint32_t {
|
||||
CLIMATE_MODE_OFF = 0,
|
||||
@ -1203,6 +1205,7 @@ class GetTimeResponse : public ProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
};
|
||||
#ifdef USE_API_SERVICES
|
||||
class ListEntitiesServicesArgument : public ProtoMessage {
|
||||
public:
|
||||
std::string name{};
|
||||
@ -1278,6 +1281,7 @@ class ExecuteServiceRequest : public ProtoMessage {
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
class ListEntitiesCameraResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
|
@ -162,6 +162,7 @@ template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel val
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::ServiceArgType value) {
|
||||
switch (value) {
|
||||
case enums::SERVICE_ARG_TYPE_BOOL:
|
||||
@ -184,6 +185,7 @@ template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::Servic
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
template<> const char *proto_enum_to_string<enums::ClimateMode>(enums::ClimateMode value) {
|
||||
switch (value) {
|
||||
@ -1811,6 +1813,7 @@ void GetTimeResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
void ListEntitiesServicesArgument::dump_to(std::string &out) const {
|
||||
__attribute__((unused)) char buffer[64];
|
||||
out.append("ListEntitiesServicesArgument {\n");
|
||||
@ -1910,6 +1913,7 @@ void ExecuteServiceRequest::dump_to(std::string &out) const {
|
||||
}
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
void ListEntitiesCameraResponse::dump_to(std::string &out) const {
|
||||
__attribute__((unused)) char buffer[64];
|
||||
|
@ -195,6 +195,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
this->on_home_assistant_state_response(msg);
|
||||
break;
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
case 42: {
|
||||
ExecuteServiceRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
@ -204,6 +205,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
this->on_execute_service_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
case 45: {
|
||||
CameraImageRequest msg;
|
||||
@ -660,11 +662,13 @@ void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef USE_API_SERVICES
|
||||
void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) {
|
||||
if (this->check_authenticated_()) {
|
||||
this->execute_service(msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) {
|
||||
if (this->check_authenticated_()) {
|
||||
|
@ -69,7 +69,9 @@ class APIServerConnectionBase : public ProtoService {
|
||||
virtual void on_get_time_request(const GetTimeRequest &value){};
|
||||
virtual void on_get_time_response(const GetTimeResponse &value){};
|
||||
|
||||
#ifdef USE_API_SERVICES
|
||||
virtual void on_execute_service_request(const ExecuteServiceRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_CAMERA
|
||||
virtual void on_camera_image_request(const CameraImageRequest &value){};
|
||||
@ -216,7 +218,9 @@ class APIServerConnection : public APIServerConnectionBase {
|
||||
virtual void subscribe_homeassistant_services(const SubscribeHomeassistantServicesRequest &msg) = 0;
|
||||
virtual void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) = 0;
|
||||
virtual GetTimeResponse get_time(const GetTimeRequest &msg) = 0;
|
||||
#ifdef USE_API_SERVICES
|
||||
virtual void execute_service(const ExecuteServiceRequest &msg) = 0;
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
virtual NoiseEncryptionSetKeyResponse noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) = 0;
|
||||
#endif
|
||||
@ -333,7 +337,9 @@ class APIServerConnection : public APIServerConnectionBase {
|
||||
void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &msg) override;
|
||||
void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) override;
|
||||
void on_get_time_request(const GetTimeRequest &msg) override;
|
||||
#ifdef USE_API_SERVICES
|
||||
void on_execute_service_request(const ExecuteServiceRequest &msg) override;
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) override;
|
||||
#endif
|
||||
|
@ -24,7 +24,7 @@ static const char *const TAG = "api";
|
||||
// APIServer
|
||||
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
#ifndef USE_API_YAML_SERVICES
|
||||
#ifndef USE_API_SERVICES
|
||||
// Global empty vector to avoid guard variables (saves 8 bytes)
|
||||
// This is initialized at program startup before any threads
|
||||
static const std::vector<UserServiceDescriptor *> empty_user_services{};
|
||||
|
@ -12,7 +12,9 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "list_entities.h"
|
||||
#include "subscribe_state.h"
|
||||
#ifdef USE_API_SERVICES
|
||||
#include "user_services.h"
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -25,7 +27,7 @@ struct SavedNoisePsk {
|
||||
} PACKED; // NOLINT
|
||||
#endif
|
||||
|
||||
#ifndef USE_API_YAML_SERVICES
|
||||
#ifndef USE_API_SERVICES
|
||||
// Forward declaration of helper function
|
||||
const std::vector<UserServiceDescriptor *> &get_empty_user_services_instance();
|
||||
#endif
|
||||
@ -112,18 +114,9 @@ class APIServer : public Component, public Controller {
|
||||
void on_media_player_update(media_player::MediaPlayer *obj) override;
|
||||
#endif
|
||||
void send_homeassistant_service_call(const HomeassistantServiceResponse &call);
|
||||
void register_user_service(UserServiceDescriptor *descriptor) {
|
||||
#ifdef USE_API_YAML_SERVICES
|
||||
// Vector is pre-allocated when services are defined in YAML
|
||||
this->user_services_.push_back(descriptor);
|
||||
#else
|
||||
// Lazy allocate vector on first use for CustomAPIDevice
|
||||
if (!this->user_services_) {
|
||||
this->user_services_ = std::make_unique<std::vector<UserServiceDescriptor *>>();
|
||||
}
|
||||
this->user_services_->push_back(descriptor);
|
||||
#ifdef USE_API_SERVICES
|
||||
void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_HOMEASSISTANT_TIME
|
||||
void request_time();
|
||||
#endif
|
||||
@ -153,12 +146,9 @@ class APIServer : public Component, public Controller {
|
||||
std::function<void(std::string)> f);
|
||||
const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
|
||||
const std::vector<UserServiceDescriptor *> &get_user_services() const {
|
||||
#ifdef USE_API_YAML_SERVICES
|
||||
#ifdef USE_API_SERVICES
|
||||
return this->user_services_;
|
||||
#else
|
||||
if (this->user_services_) {
|
||||
return *this->user_services_;
|
||||
}
|
||||
// Return reference to global empty instance (no guard needed)
|
||||
return get_empty_user_services_instance();
|
||||
#endif
|
||||
@ -194,14 +184,8 @@ class APIServer : public Component, public Controller {
|
||||
#endif
|
||||
std::vector<uint8_t> shared_write_buffer_; // Shared proto write buffer for all connections
|
||||
std::vector<HomeAssistantStateSubscription> state_subs_;
|
||||
#ifdef USE_API_YAML_SERVICES
|
||||
// When services are defined in YAML, we know at compile time that services will be registered
|
||||
#ifdef USE_API_SERVICES
|
||||
std::vector<UserServiceDescriptor *> user_services_;
|
||||
#else
|
||||
// Services can still be registered at runtime by CustomAPIDevice components even when not
|
||||
// defined in YAML. Using unique_ptr allows lazy allocation, saving 12 bytes in the common
|
||||
// case where no services (YAML or custom) are used.
|
||||
std::unique_ptr<std::vector<UserServiceDescriptor *>> user_services_;
|
||||
#endif
|
||||
|
||||
// Group smaller types together
|
||||
|
@ -3,10 +3,13 @@
|
||||
#include <map>
|
||||
#include "api_server.h"
|
||||
#ifdef USE_API
|
||||
#ifdef USE_API_SERVICES
|
||||
#include "user_services.h"
|
||||
#endif
|
||||
namespace esphome {
|
||||
namespace api {
|
||||
|
||||
#ifdef USE_API_SERVICES
|
||||
template<typename T, typename... Ts> class CustomAPIDeviceService : public UserServiceBase<Ts...> {
|
||||
public:
|
||||
CustomAPIDeviceService(const std::string &name, const std::array<std::string, sizeof...(Ts)> &arg_names, T *obj,
|
||||
@ -19,6 +22,7 @@ template<typename T, typename... Ts> class CustomAPIDeviceService : public UserS
|
||||
T *obj_;
|
||||
void (T::*callback_)(Ts...);
|
||||
};
|
||||
#endif // USE_API_SERVICES
|
||||
|
||||
class CustomAPIDevice {
|
||||
public:
|
||||
@ -46,12 +50,14 @@ class CustomAPIDevice {
|
||||
* @param name The name of the service to register.
|
||||
* @param arg_names The name of the arguments for the service, must match the arguments of the function.
|
||||
*/
|
||||
#ifdef USE_API_SERVICES
|
||||
template<typename T, typename... Ts>
|
||||
void register_service(void (T::*callback)(Ts...), const std::string &name,
|
||||
const std::array<std::string, sizeof...(Ts)> &arg_names) {
|
||||
auto *service = new CustomAPIDeviceService<T, Ts...>(name, arg_names, (T *) this, callback); // NOLINT
|
||||
global_api_server->register_user_service(service);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Register a custom native API service that will show up in Home Assistant.
|
||||
*
|
||||
@ -71,10 +77,12 @@ class CustomAPIDevice {
|
||||
* @param callback The member function to call when the service is triggered.
|
||||
* @param name The name of the arguments for the service, must match the arguments of the function.
|
||||
*/
|
||||
#ifdef USE_API_SERVICES
|
||||
template<typename T> void register_service(void (T::*callback)(), const std::string &name) {
|
||||
auto *service = new CustomAPIDeviceService<T>(name, {}, (T *) this, callback); // NOLINT
|
||||
global_api_server->register_user_service(service);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Subscribe to the state (or attribute state) of an entity from Home Assistant.
|
||||
*
|
||||
|
@ -83,10 +83,12 @@ bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(
|
||||
|
||||
ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {}
|
||||
|
||||
#ifdef USE_API_SERVICES
|
||||
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
|
||||
auto resp = service->encode_list_service_response();
|
||||
return this->client_->send_message(resp);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace api
|
||||
} // namespace esphome
|
||||
|
@ -44,7 +44,9 @@ class ListEntitiesIterator : public ComponentIterator {
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool on_text_sensor(text_sensor::TextSensor *entity) override;
|
||||
#endif
|
||||
#ifdef USE_API_SERVICES
|
||||
bool on_service(UserServiceDescriptor *service) override;
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
bool on_camera(camera::Camera *entity) override;
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "esphome/core/automation.h"
|
||||
#include "api_pb2.h"
|
||||
|
||||
#ifdef USE_API_SERVICES
|
||||
namespace esphome {
|
||||
namespace api {
|
||||
|
||||
@ -73,3 +74,4 @@ template<typename... Ts> class UserServiceTrigger : public UserServiceBase<Ts...
|
||||
|
||||
} // namespace api
|
||||
} // namespace esphome
|
||||
#endif // USE_API_SERVICES
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#ifdef USE_API
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#endif
|
||||
#ifdef USE_API_SERVICES
|
||||
#include "esphome/components/api/user_services.h"
|
||||
#endif
|
||||
|
||||
@ -148,7 +150,7 @@ void ComponentIterator::advance() {
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_API
|
||||
#ifdef USE_API_SERVICES
|
||||
case IteratorState ::SERVICE:
|
||||
if (this->at_ >= api::global_api_server->get_user_services().size()) {
|
||||
advance_platform = true;
|
||||
@ -383,7 +385,7 @@ void ComponentIterator::advance() {
|
||||
}
|
||||
bool ComponentIterator::on_end() { return true; }
|
||||
bool ComponentIterator::on_begin() { return true; }
|
||||
#ifdef USE_API
|
||||
#ifdef USE_API_SERVICES
|
||||
bool ComponentIterator::on_service(api::UserServiceDescriptor *service) { return true; }
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
namespace esphome {
|
||||
|
||||
#ifdef USE_API
|
||||
#ifdef USE_API_SERVICES
|
||||
namespace api {
|
||||
class UserServiceDescriptor;
|
||||
} // namespace api
|
||||
@ -45,7 +45,7 @@ class ComponentIterator {
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
virtual bool on_text_sensor(text_sensor::TextSensor *text_sensor) = 0;
|
||||
#endif
|
||||
#ifdef USE_API
|
||||
#ifdef USE_API_SERVICES
|
||||
virtual bool on_service(api::UserServiceDescriptor *service);
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
@ -122,7 +122,7 @@ class ComponentIterator {
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
TEXT_SENSOR,
|
||||
#endif
|
||||
#ifdef USE_API
|
||||
#ifdef USE_API_SERVICES
|
||||
SERVICE,
|
||||
#endif
|
||||
#ifdef USE_CAMERA
|
||||
|
@ -108,7 +108,7 @@
|
||||
#define USE_API_CLIENT_DISCONNECTED_TRIGGER
|
||||
#define USE_API_NOISE
|
||||
#define USE_API_PLAINTEXT
|
||||
#define USE_API_YAML_SERVICES
|
||||
#define USE_API_SERVICES
|
||||
#define USE_MD5
|
||||
#define USE_MQTT
|
||||
#define USE_NETWORK
|
||||
|
Loading…
x
Reference in New Issue
Block a user