5#ifdef USE_API_HOMEASSISTANT_SERVICES
10#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
23 static_assert(std::is_constructible_v<
TemplatableValue<std::string, X...>,
const char *>,
24 "Base class must have const char* constructor for STATIC_STRING optimization");
28 template<
typename T>
static std::string value_to_string(T &&
val) {
return to_string(std::forward<T>(
val)); }
31 static std::string value_to_string(
char *
val) {
32 return val ? std::string(
val) : std::string();
34 static std::string value_to_string(
const char *
val) {
return std::string(
val); }
35 static std::string value_to_string(
const std::string &
val) {
return val; }
36 static std::string value_to_string(std::string &&
val) {
return std::move(
val); }
41 template<
typename F, enable_if_t<!is_invocable<F, X...>
::value,
int> = 0>
44 template<
typename F, enable_if_t<is_invocable<F, X...>
::value,
int> = 0>
46 :
TemplatableValue<std::string, X...>([f](X...
x) -> std::string { return value_to_string(f(
x...)); }) {}
59 const char *key{
nullptr};
63#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
72#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
74 : success_(success), error_message_(error_message) {
75 if (data ==
nullptr || data_len == 0)
77 this->json_document_ = json::parse_json(data, data_len);
85#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
87 JsonObjectConst
get_json()
const {
return this->json_document_.as<JsonObjectConst>(); }
93#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
105 this->flags_.is_event = is_event;
108 template<
typename T>
void set_service(T service) { this->service_ = service; }
112 void init_data(
size_t count) { this->data_.init(count); }
119 template<
typename V>
void add_data(
const char *key, V &&value) {
120 this->add_kv_(this->data_, key, std::forward<V>(value));
123 this->add_kv_(this->data_template_, key, std::forward<V>(value));
126 this->add_kv_(this->variables_, key, std::forward<V>(value));
129#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
131 this->response_template_ = response_template;
132 this->flags_.has_response_template =
true;
138#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
140 return this->success_trigger_with_response_;
147 void play(
const Ts &...
x)
override {
149 std::string service_value = this->service_.value(
x...);
151 resp.
is_event = this->flags_.is_event;
158 this->populate_service_map(resp.
data, this->data_, data_storage,
x...);
159 this->populate_service_map(resp.
data_template, this->data_template_, data_template_storage,
x...);
160 this->populate_service_map(resp.
variables, this->variables_, variables_storage,
x...);
162#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
163#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
165 std::string response_template_value;
167 if (this->flags_.wants_status) {
169 static uint32_t call_id_counter = 1;
170 uint32_t call_id = call_id_counter++;
172#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
173 if (this->flags_.wants_response) {
176 if (this->flags_.has_response_template) {
177 response_template_value = this->response_template_.value(
x...);
183 auto captured_args = std::make_tuple(
x...);
184 this->parent_->register_action_response_callback(call_id, [
this, captured_args](
const ActionResponse &response) {
186 [
this, &response](
auto &&...args) {
188#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
189 if (this->flags_.wants_response) {
190 this->success_trigger_with_response_->trigger(response.
get_json(), args...);
194 this->success_trigger_->trigger(args...);
205 this->parent_->send_homeassistant_action(resp);
212 auto &kv = vec.emplace_back();
214 kv.value = std::forward<V>(value);
217 template<
typename VectorType,
typename SourceType>
220 dest.init(source.size());
223 size_t lambda_count = 0;
224 for (
const auto &it : source) {
225 if (!it.value.is_static_string()) {
229 value_storage.
init(lambda_count);
231 for (
auto &it : source) {
232 auto &kv = dest.emplace_back();
235 if (it.value.is_static_string()) {
237 kv.value =
StringRef(it.value.get_static_string());
240 value_storage.
push_back(it.value.value(
x...));
251#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
252#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
254 Trigger<JsonObjectConst, Ts...> *success_trigger_with_response_ =
new Trigger<JsonObjectConst, Ts...>();
Fixed-capacity vector - allocates once at runtime, never reallocates This avoids std::vector template...
T & back()
Access last element (no bounds checking - matches std::vector behavior) Caller must ensure vector is ...
void push_back(const T &value)
Add element without bounds checking Caller must ensure sufficient capacity was allocated via init() S...
StringRef is a reference to a string owned by something else.
std::string value(X... x) const
ActionResponse(bool success, StringRef error_message)
JsonDocument json_document_
const StringRef & get_error_message() const
JsonObjectConst get_json() const
ActionResponse(bool success, StringRef error_message, const uint8_t *data, size_t data_len)
void set_service(T service)
HomeAssistantServiceCallAction(APIServer *parent, bool is_event)
void add_data(const char *key, V &&value)
void play(const Ts &...x) override
void add_variable(const char *key, V &&value)
Trigger< JsonObjectConst, Ts... > * get_success_trigger_with_response() const
FixedVector< TemplatableKeyValuePair< Ts... > > data_
void add_kv_(FixedVector< TemplatableKeyValuePair< Ts... > > &vec, const char *key, V &&value)
Trigger< Ts... > * get_success_trigger() const
FixedVector< TemplatableKeyValuePair< Ts... > > variables_
void set_response_template(T response_template)
void init_data(size_t count)
FixedVector< TemplatableKeyValuePair< Ts... > > data_template_
void add_data_template(const char *key, V &&value)
void init_data_template(size_t count)
static void populate_service_map(VectorType &dest, SourceType &source, FixedVector< std::string > &value_storage, Ts... x)
void init_variables(size_t count)
void set_wants_response()
Trigger< std::string, Ts... > * get_error_trigger() const
FixedVector< HomeassistantServiceMap > variables
FixedVector< HomeassistantServiceMap > data
StringRef response_template
FixedVector< HomeassistantServiceMap > data_template
TemplatableStringValue< Ts... > value
TemplatableKeyValuePair(const char *key, T value)
TemplatableKeyValuePair()=default
TemplatableStringValue(F value)
TemplatableStringValue(F f)
std::function< void(const ActionResponse &, Ts...)> ActionResponseCallback
uint8_t has_response_template