#pragma once #include #include "api_server.h" #ifdef USE_API #ifdef USE_API_SERVICES #include "user_services.h" #endif namespace esphome::api { #ifdef USE_API_SERVICES template class CustomAPIDeviceService : public UserServiceBase { public: CustomAPIDeviceService(const std::string &name, const std::array &arg_names, T *obj, void (T::*callback)(Ts...)) : UserServiceBase(name, arg_names), obj_(obj), callback_(callback) {} protected: void execute(Ts... x) override { (this->obj_->*this->callback_)(x...); } // NOLINT T *obj_; void (T::*callback_)(Ts...); }; #endif // USE_API_SERVICES class CustomAPIDevice { public: /// Return if a client (such as Home Assistant) is connected to the native API. bool is_connected() const { return global_api_server->is_connected(); } /** Register a custom native API service that will show up in Home Assistant. * * Usage: * * ```cpp * void setup() override { * register_service(&CustomNativeAPI::on_start_washer_cycle, "start_washer_cycle", * {"cycle_length"}); * } * * void on_start_washer_cycle(int cycle_length) { * // Start washer cycle. * } * ``` * * @tparam T The class type creating the service, automatically deduced from the function pointer. * @tparam Ts The argument types for the service, automatically deduced from the function arguments. * @param callback The member function to call when the service is triggered. * @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 void register_service(void (T::*callback)(Ts...), const std::string &name, const std::array &arg_names) { auto *service = new CustomAPIDeviceService(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. * * Usage: * * ```cpp * void setup() override { * register_service(&CustomNativeAPI::on_hello_world, "hello_world"); * } * * void on_hello_world() { * // Hello World service called. * } * ``` * * @tparam T The class type creating the service, automatically deduced from the function pointer. * @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 void register_service(void (T::*callback)(), const std::string &name) { auto *service = new CustomAPIDeviceService(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. * * Usage: * * ```cpp * void setup() override { * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "climate.kitchen", "current_temperature"); * } * * void on_state_changed(std::string state) { * // State of sensor.weather_forecast is `state` * } * ``` * * @tparam T The class type creating the service, automatically deduced from the function pointer. * @param callback The member function to call when the entity state changes. * @param entity_id The entity_id to track. * @param attribute The entity state attribute to track. */ template void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id, const std::string &attribute = "") { auto f = std::bind(callback, (T *) this, std::placeholders::_1); global_api_server->subscribe_home_assistant_state(entity_id, optional(attribute), f); } /** Subscribe to the state (or attribute state) of an entity from Home Assistant. * * Usage: * * ```cpp * void setup() override { * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast"); * } * * void on_state_changed(std::string entity_id, std::string state) { * // State of `entity_id` is `state` * } * ``` * * @tparam T The class type creating the service, automatically deduced from the function pointer. * @param callback The member function to call when the entity state changes. * @param entity_id The entity_id to track. * @param attribute The entity state attribute to track. */ template void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id, const std::string &attribute = "") { auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1); global_api_server->subscribe_home_assistant_state(entity_id, optional(attribute), f); } /** Call a Home Assistant service from ESPHome. * * Usage: * * ```cpp * call_homeassistant_service("homeassistant.restart"); * ``` * * @param service_name The service to call. */ void call_homeassistant_service(const std::string &service_name) { HomeassistantServiceResponse resp; resp.set_service(StringRef(service_name)); global_api_server->send_homeassistant_service_call(resp); } /** Call a Home Assistant service from ESPHome. * * Usage: * * ```cpp * call_homeassistant_service("light.turn_on", { * {"entity_id", "light.my_light"}, * {"brightness", "127"}, * }); * ``` * * @param service_name The service to call. * @param data The data for the service call, mapping from string to string. */ void call_homeassistant_service(const std::string &service_name, const std::map &data) { HomeassistantServiceResponse resp; resp.set_service(StringRef(service_name)); for (auto &it : data) { resp.data.emplace_back(); auto &kv = resp.data.back(); kv.set_key(StringRef(it.first)); kv.set_value(StringRef(it.second)); } global_api_server->send_homeassistant_service_call(resp); } /** Fire an ESPHome event in Home Assistant. * * Usage: * * ```cpp * fire_homeassistant_event("esphome.something_happened"); * ``` * * @param event_name The event to fire. */ void fire_homeassistant_event(const std::string &event_name) { HomeassistantServiceResponse resp; resp.set_service(StringRef(event_name)); resp.is_event = true; global_api_server->send_homeassistant_service_call(resp); } /** Fire an ESPHome event in Home Assistant. * * Usage: * * ```cpp * fire_homeassistant_event("esphome.something_happened", { * {"my_value", "500"}, * }); * ``` * * @param event_name The event to fire. * @param data The data for the event, mapping from string to string. */ void fire_homeassistant_event(const std::string &service_name, const std::map &data) { HomeassistantServiceResponse resp; resp.set_service(StringRef(service_name)); resp.is_event = true; for (auto &it : data) { resp.data.emplace_back(); auto &kv = resp.data.back(); kv.set_key(StringRef(it.first)); kv.set_value(StringRef(it.second)); } global_api_server->send_homeassistant_service_call(resp); } }; } // namespace esphome::api #endif