ESPHome 2026.4.0
Loading...
Searching...
No Matches
custom_api_device.h
Go to the documentation of this file.
1#pragma once
2
3#include <map>
4#include "api_server.h"
5#ifdef USE_API
6#ifdef USE_API_USER_DEFINED_ACTIONS
7#include "user_services.h"
8#endif
9namespace esphome::api {
10
11#ifdef USE_API_USER_DEFINED_ACTIONS
12template<typename T, typename... Ts> class CustomAPIDeviceService : public UserServiceDynamic<Ts...> {
13 public:
14 CustomAPIDeviceService(const std::string &name, const std::array<std::string, sizeof...(Ts)> &arg_names, T *obj,
15 void (T::*callback)(Ts...))
16 : UserServiceDynamic<Ts...>(name, arg_names), obj_(obj), callback_(callback) {}
17
18 protected:
19 // CustomAPIDevice services don't support action responses - ignore call_id and return_response
20 void execute(uint32_t /*call_id*/, bool /*return_response*/, Ts... x) override {
21 (this->obj_->*this->callback_)(x...); // NOLINT
22 }
23
24 T *obj_;
25 void (T::*callback_)(Ts...);
26};
27#endif // USE_API_USER_DEFINED_ACTIONS
28
30 public:
32 bool is_connected() const { return global_api_server->is_connected(); }
33
55#ifdef USE_API_USER_DEFINED_ACTIONS
56 template<typename T, typename... Ts>
57 void register_service(void (T::*callback)(Ts...), const std::string &name,
58 const std::array<std::string, sizeof...(Ts)> &arg_names) {
59#ifdef USE_API_CUSTOM_SERVICES
60 auto *service = new CustomAPIDeviceService<T, Ts...>(name, arg_names, (T *) this, callback); // NOLINT
62#else
63 static_assert(
64 sizeof(T) == 0,
65 "register_service() requires 'custom_services: true' in the 'api:' section of your YAML configuration");
66#endif
67 }
68#else
69 template<typename T, typename... Ts>
70 void register_service(void (T::*callback)(Ts...), const std::string &name,
71 const std::array<std::string, sizeof...(Ts)> &arg_names) {
72 static_assert(
73 sizeof(T) == 0,
74 "register_service() requires 'custom_services: true' in the 'api:' section of your YAML configuration");
75 }
76#endif
77
96#ifdef USE_API_USER_DEFINED_ACTIONS
97 template<typename T> void register_service(void (T::*callback)(), const std::string &name) {
98#ifdef USE_API_CUSTOM_SERVICES
99 auto *service = new CustomAPIDeviceService<T>(name, {}, (T *) this, callback); // NOLINT
101#else
102 static_assert(
103 sizeof(T) == 0,
104 "register_service() requires 'custom_services: true' in the 'api:' section of your YAML configuration");
105#endif
106 }
107#else
108 template<typename T> void register_service(void (T::*callback)(), const std::string &name) {
109 static_assert(
110 sizeof(T) == 0,
111 "register_service() requires 'custom_services: true' in the 'api:' section of your YAML configuration");
112 }
113#endif
114
115#ifdef USE_API_HOMEASSISTANT_STATES
136 template<typename T>
137 void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
138 const std::string &attribute = "") {
139 auto *obj = static_cast<T *>(this);
140 global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute),
141 [obj, callback](StringRef state) { (obj->*callback)(state); });
142 }
143
148 template<typename T>
149 ESPDEPRECATED("Use void callback(StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0")
150 void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
151 const std::string &attribute = "") {
152 auto *obj = static_cast<T *>(this);
153 // Explicit type to disambiguate overload resolution
155 entity_id, optional<std::string>(attribute),
156 std::function<void(const std::string &)>(
157 [obj, callback](const std::string &state) { (obj->*callback)(state); }));
158 }
159
179 template<typename T>
180 void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
181 const std::string &attribute = "") {
182 auto *obj = static_cast<T *>(this);
184 entity_id, optional<std::string>(attribute),
185 [obj, callback, entity_id](StringRef state) { (obj->*callback)(entity_id, state); });
186 }
187
192 template<typename T>
193 ESPDEPRECATED("Use void callback(const std::string &, StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0")
194 void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
195 const std::string &attribute = "") {
196 auto *obj = static_cast<T *>(this);
197 // Explicit type to disambiguate overload resolution
199 entity_id, optional<std::string>(attribute),
200 std::function<void(const std::string &)>(
201 [obj, callback, entity_id](const std::string &state) { (obj->*callback)(entity_id, state); }));
202 }
203#else
204 template<typename T>
205 void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
206 const std::string &attribute = "") {
207 static_assert(sizeof(T) == 0,
208 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
209 "of your YAML configuration");
210 }
211
212 template<typename T>
213 void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
214 const std::string &attribute = "") {
215 static_assert(sizeof(T) == 0,
216 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
217 "of your YAML configuration");
218 }
219
220 template<typename T>
221 void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
222 const std::string &attribute = "") {
223 static_assert(sizeof(T) == 0,
224 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
225 "of your YAML configuration");
226 }
227
228 template<typename T>
229 void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
230 const std::string &attribute = "") {
231 static_assert(sizeof(T) == 0,
232 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
233 "of your YAML configuration");
234 }
235#endif
236
237#ifdef USE_API_HOMEASSISTANT_SERVICES
248 void call_homeassistant_service(const std::string &service_name) {
250 resp.service = StringRef(service_name);
252 }
253
268 void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
270 resp.service = StringRef(service_name);
271 resp.data.init(data.size());
272 for (auto &it : data) {
273 auto &kv = resp.data.emplace_back();
274 kv.key = StringRef(it.first);
275 kv.value = StringRef(it.second); // data map lives until send completes
276 }
278 }
279
290 void fire_homeassistant_event(const std::string &event_name) {
292 resp.service = StringRef(event_name);
293 resp.is_event = true;
295 }
296
310 void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
312 resp.service = StringRef(service_name);
313 resp.is_event = true;
314 resp.data.init(data.size());
315 for (auto &it : data) {
316 auto &kv = resp.data.emplace_back();
317 kv.key = StringRef(it.first);
318 kv.value = StringRef(it.second); // data map lives until send completes
319 }
321 }
322#else
323 template<typename T = void> void call_homeassistant_service(const std::string &service_name) {
324 static_assert(sizeof(T) == 0, "call_homeassistant_service() requires 'homeassistant_services: true' in the 'api:' "
325 "section of your YAML configuration");
326 }
327
328 template<typename T = void>
329 void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
330 static_assert(sizeof(T) == 0, "call_homeassistant_service() requires 'homeassistant_services: true' in the 'api:' "
331 "section of your YAML configuration");
332 }
333
334 template<typename T = void> void fire_homeassistant_event(const std::string &event_name) {
335 static_assert(sizeof(T) == 0, "fire_homeassistant_event() requires 'homeassistant_services: true' in the 'api:' "
336 "section of your YAML configuration");
337 }
338
339 template<typename T = void>
340 void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
341 static_assert(sizeof(T) == 0, "fire_homeassistant_event() requires 'homeassistant_services: true' in the 'api:' "
342 "section of your YAML configuration");
343 }
344#endif
345};
346
347} // namespace esphome::api
348#endif
StringRef is a reference to a string owned by something else.
Definition string_ref.h:26
void register_user_service(UserServiceDescriptor *descriptor)
Definition api_server.h:153
bool is_connected() const
Definition api_server.h:189
void send_homeassistant_action(const HomeassistantActionRequest &call)
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(StringRef)> &&f)
void subscribe_homeassistant_state(void(T::*callback)(std::string), const std::string &entity_id, const std::string &attribute="")
void fire_homeassistant_event(const std::string &service_name, const std::map< std::string, std::string > &data)
void register_service(void(T::*callback)(Ts...), const std::string &name, const std::array< std::string, sizeof...(Ts)> &arg_names)
Register a custom native API service that will show up in Home Assistant.
ESPDEPRECATED("Use void callback(StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0") void subscribe_homeassistant_state(void(T
Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string vers...
void fire_homeassistant_event(const std::string &event_name)
void subscribe_homeassistant_state(void(T::*callback)(const std::string &, StringRef), const std::string &entity_id, const std::string &attribute="")
Subscribe to the state (or attribute state) of an entity from Home Assistant.
void call_homeassistant_service(const std::string &service_name)
Call a Home Assistant service from ESPHome.
void register_service(void(T::*callback)(), const std::string &name)
Register a custom native API service that will show up in Home Assistant.
void fire_homeassistant_event(const std::string &event_name)
Fire an ESPHome event in Home Assistant.
bool is_connected() const
Return if a client (such as Home Assistant) is connected to the native API.
ESPDEPRECATED("Use void callback(const std::string &, StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0") void subscribe_homeassistant_state(void(T
Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string vers...
void subscribe_homeassistant_state(void(T::*callback)(StringRef), const std::string &entity_id, const std::string &attribute="")
Subscribe to the state (or attribute state) of an entity from Home Assistant.
void fire_homeassistant_event(const std::string &service_name, const std::map< std::string, std::string > &data)
Fire an ESPHome event in Home Assistant.
void call_homeassistant_service(const std::string &service_name)
void subscribe_homeassistant_state(void(T::*callback)(std::string, std::string), const std::string &entity_id, const std::string &attribute="")
void call_homeassistant_service(const std::string &service_name, const std::map< std::string, std::string > &data)
Call a Home Assistant service from ESPHome.
void call_homeassistant_service(const std::string &service_name, const std::map< std::string, std::string > &data)
void execute(uint32_t, bool, Ts... x) override
CustomAPIDeviceService(const std::string &name, const std::array< std::string, sizeof...(Ts)> &arg_names, T *obj, void(T::*callback)(Ts...))
FixedVector< HomeassistantServiceMap > data
Definition api_pb2.h:1070
bool state
Definition fan.h:2
APIServer * global_api_server
static void uint32_t
uint16_t x
Definition tt21100.cpp:5