ESPHome 2026.1.4
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 f = std::bind(callback, (T *) this, std::placeholders::_1);
140 global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f));
141 }
142
147 template<typename T>
148 ESPDEPRECATED("Use void callback(StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0")
149 void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
150 const std::string &attribute = "") {
151 auto f = std::bind(callback, (T *) this, std::placeholders::_1);
152 // Explicit type to disambiguate overload resolution
154 std::function<void(const std::string &)>(f));
155 }
156
176 template<typename T>
177 void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
178 const std::string &attribute = "") {
179 auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
180 global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f));
181 }
182
187 template<typename T>
188 ESPDEPRECATED("Use void callback(const std::string &, StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0")
189 void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
190 const std::string &attribute = "") {
191 auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
192 // Explicit type to disambiguate overload resolution
194 std::function<void(const std::string &)>(f));
195 }
196#else
197 template<typename T>
198 void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
199 const std::string &attribute = "") {
200 static_assert(sizeof(T) == 0,
201 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
202 "of your YAML configuration");
203 }
204
205 template<typename T>
206 void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
207 const std::string &attribute = "") {
208 static_assert(sizeof(T) == 0,
209 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
210 "of your YAML configuration");
211 }
212
213 template<typename T>
214 void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
215 const std::string &attribute = "") {
216 static_assert(sizeof(T) == 0,
217 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
218 "of your YAML configuration");
219 }
220
221 template<typename T>
222 void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
223 const std::string &attribute = "") {
224 static_assert(sizeof(T) == 0,
225 "subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
226 "of your YAML configuration");
227 }
228#endif
229
230#ifdef USE_API_HOMEASSISTANT_SERVICES
241 void call_homeassistant_service(const std::string &service_name) {
243 resp.service = StringRef(service_name);
245 }
246
261 void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
263 resp.service = StringRef(service_name);
264 resp.data.init(data.size());
265 for (auto &it : data) {
266 auto &kv = resp.data.emplace_back();
267 kv.key = StringRef(it.first);
268 kv.value = StringRef(it.second); // data map lives until send completes
269 }
271 }
272
283 void fire_homeassistant_event(const std::string &event_name) {
285 resp.service = StringRef(event_name);
286 resp.is_event = true;
288 }
289
303 void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
305 resp.service = StringRef(service_name);
306 resp.is_event = true;
307 resp.data.init(data.size());
308 for (auto &it : data) {
309 auto &kv = resp.data.emplace_back();
310 kv.key = StringRef(it.first);
311 kv.value = StringRef(it.second); // data map lives until send completes
312 }
314 }
315#else
316 template<typename T = void> void call_homeassistant_service(const std::string &service_name) {
317 static_assert(sizeof(T) == 0, "call_homeassistant_service() requires 'homeassistant_services: true' in the 'api:' "
318 "section of your YAML configuration");
319 }
320
321 template<typename T = void>
322 void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
323 static_assert(sizeof(T) == 0, "call_homeassistant_service() requires 'homeassistant_services: true' in the 'api:' "
324 "section of your YAML configuration");
325 }
326
327 template<typename T = void> void fire_homeassistant_event(const std::string &event_name) {
328 static_assert(sizeof(T) == 0, "fire_homeassistant_event() requires 'homeassistant_services: true' in the 'api:' "
329 "section of your YAML configuration");
330 }
331
332 template<typename T = void>
333 void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
334 static_assert(sizeof(T) == 0, "fire_homeassistant_event() requires 'homeassistant_services: true' in the 'api:' "
335 "section of your YAML configuration");
336 }
337#endif
338};
339
340} // namespace esphome::api
341#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:156
void send_homeassistant_action(const HomeassistantActionRequest &call)
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(StringRef)> f)
bool is_connected(bool state_subscription_only=false) const
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:1073
APIServer * global_api_server
uint16_t x
Definition tt21100.cpp:5