ESPHome 2025.12.0-dev
Loading...
Searching...
No Matches
user_services.h
Go to the documentation of this file.
1#pragma once
2
3#include <utility>
4#include <vector>
5
8#include "api_pb2.h"
9
10#ifdef USE_API_SERVICES
11namespace esphome::api {
12
14 public:
16
17 virtual bool execute_service(const ExecuteServiceRequest &req) = 0;
18
19 bool is_internal() { return false; }
20};
21
22template<typename T> T get_execute_arg_value(const ExecuteServiceArgument &arg);
23
25
26// Base class for YAML-defined services (most common case)
27// Stores only pointers to string literals in flash - no heap allocation
28template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
29 public:
30 UserServiceBase(const char *name, const std::array<const char *, sizeof...(Ts)> &arg_names)
31 : name_(name), arg_names_(arg_names) {
32 this->key_ = fnv1_hash(name);
33 }
34
37 msg.set_name(StringRef(this->name_));
38 msg.key = this->key_;
39 std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
40 msg.args.init(sizeof...(Ts));
41 for (size_t i = 0; i < sizeof...(Ts); i++) {
42 auto &arg = msg.args.emplace_back();
43 arg.type = arg_types[i];
44 arg.set_name(StringRef(this->arg_names_[i]));
45 }
46 return msg;
47 }
48
49 bool execute_service(const ExecuteServiceRequest &req) override {
50 if (req.key != this->key_)
51 return false;
52 if (req.args.size() != sizeof...(Ts))
53 return false;
54 this->execute_(req.args, typename gens<sizeof...(Ts)>::type());
55 return true;
56 }
57
58 protected:
59 virtual void execute(Ts... x) = 0;
60 template<typename ArgsContainer, int... S> void execute_(const ArgsContainer &args, seq<S...> type) {
61 this->execute((get_execute_arg_value<Ts>(args[S]))...);
62 }
63
64 // Pointers to string literals in flash - no heap allocation
65 const char *name_;
66 std::array<const char *, sizeof...(Ts)> arg_names_;
67 uint32_t key_{0};
68};
69
70// Separate class for custom_api_device services (rare case)
71// Stores copies of runtime-generated names
72template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor {
73 public:
74 UserServiceDynamic(std::string name, const std::array<std::string, sizeof...(Ts)> &arg_names)
75 : name_(std::move(name)), arg_names_(arg_names) {
76 this->key_ = fnv1_hash(this->name_.c_str());
77 }
78
81 msg.set_name(StringRef(this->name_));
82 msg.key = this->key_;
83 std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
84 msg.args.init(sizeof...(Ts));
85 for (size_t i = 0; i < sizeof...(Ts); i++) {
86 auto &arg = msg.args.emplace_back();
87 arg.type = arg_types[i];
88 arg.set_name(StringRef(this->arg_names_[i]));
89 }
90 return msg;
91 }
92
93 bool execute_service(const ExecuteServiceRequest &req) override {
94 if (req.key != this->key_)
95 return false;
96 if (req.args.size() != sizeof...(Ts))
97 return false;
98 this->execute_(req.args, typename gens<sizeof...(Ts)>::type());
99 return true;
100 }
101
102 protected:
103 virtual void execute(Ts... x) = 0;
104 template<typename ArgsContainer, int... S> void execute_(const ArgsContainer &args, seq<S...> type) {
105 this->execute((get_execute_arg_value<Ts>(args[S]))...);
106 }
107
108 // Heap-allocated strings for runtime-generated names
109 std::string name_;
110 std::array<std::string, sizeof...(Ts)> arg_names_;
111 uint32_t key_{0};
112};
113
114template<typename... Ts> class UserServiceTrigger : public UserServiceBase<Ts...>, public Trigger<Ts...> {
115 public:
116 // Constructor for static names (YAML-defined services - used by code generator)
117 UserServiceTrigger(const char *name, const std::array<const char *, sizeof...(Ts)> &arg_names)
118 : UserServiceBase<Ts...>(name, arg_names) {}
119
120 protected:
121 void execute(Ts... x) override { this->trigger(x...); } // NOLINT
122};
123
124} // namespace esphome::api
125#endif // USE_API_SERVICES
StringRef is a reference to a string owned by something else.
Definition string_ref.h:22
void trigger(const Ts &...x)
Definition automation.h:169
FixedVector< ExecuteServiceArgument > args
Definition api_pb2.h:1304
FixedVector< ListEntitiesServicesArgument > args
Definition api_pb2.h:1266
void set_name(const StringRef &ref)
Definition api_pb2.h:1264
virtual void execute(Ts... x)=0
void execute_(const ArgsContainer &args, seq< S... > type)
UserServiceBase(const char *name, const std::array< const char *, sizeof...(Ts)> &arg_names)
std::array< const char *, sizeof...(Ts)> arg_names_
ListEntitiesServicesResponse encode_list_service_response() override
bool execute_service(const ExecuteServiceRequest &req) override
virtual ListEntitiesServicesResponse encode_list_service_response()=0
virtual bool execute_service(const ExecuteServiceRequest &req)=0
UserServiceDynamic(std::string name, const std::array< std::string, sizeof...(Ts)> &arg_names)
bool execute_service(const ExecuteServiceRequest &req) override
virtual void execute(Ts... x)=0
ListEntitiesServicesResponse encode_list_service_response() override
std::array< std::string, sizeof...(Ts)> arg_names_
void execute_(const ArgsContainer &args, seq< S... > type)
void execute(Ts... x) override
UserServiceTrigger(const char *name, const std::array< const char *, sizeof...(Ts)> &arg_names)
uint16_t type
enums::ServiceArgType to_service_arg_type()
T get_execute_arg_value(const ExecuteServiceArgument &arg)
uint32_t fnv1_hash(const char *str)
Calculate a FNV-1 hash of str.
Definition helpers.cpp:146
uint16_t x
Definition tt21100.cpp:5