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) {
29 return to_string(std::forward<T>(
val));
33 static std::string value_to_string(
char *
val) {
34 return val ? std::string(
val) : std::string();
36 static std::string value_to_string(
const char *
val) {
return std::string(
val); }
37 static std::string value_to_string(
const std::string &
val) {
return val; }
38 static std::string value_to_string(std::string &&
val) {
return std::move(
val); }
39 static std::string value_to_string(
const StringRef &
val) {
return val.str(); }
40 static std::string value_to_string(
StringRef &&
val) {
return val.str(); }
45 template<
typename F, enable_if_t<!is_invocable<F, X...>
::value,
int> = 0>
48 template<
typename F, enable_if_t<is_invocable<F, X...>
::value,
int> = 0>
50 :
TemplatableValue<std::string, X...>([f](X...
x) -> std::string { return value_to_string(f(
x...)); }) {}
63 const char *key{
nullptr};
67#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
76#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
78 : success_(success), error_message_(error_message) {
79 if (data ==
nullptr || data_len == 0)
81 this->json_document_ = json::parse_json(data, data_len);
89#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
91 JsonObjectConst
get_json()
const {
return this->json_document_.as<JsonObjectConst>(); }
97#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
109 this->flags_.is_event = is_event;
112 template<
typename T>
void set_service(T service) { this->service_ = service; }
116 void init_data(
size_t count) { this->data_.init(count); }
123 template<
typename V>
void add_data(
const char *key, V &&value) {
124 this->add_kv_(this->data_, key, std::forward<V>(value));
127 this->add_kv_(this->data_template_, key, std::forward<V>(value));
130 this->add_kv_(this->variables_, key, std::forward<V>(value));
136 template<
typename V>
void add_data(
const __FlashStringHelper *key, V &&value) {
137 this->add_kv_(this->data_,
reinterpret_cast<const char *
>(key), std::forward<V>(value));
140 this->add_kv_(this->data_template_,
reinterpret_cast<const char *
>(key), std::forward<V>(value));
142 template<
typename V>
void add_variable(
const __FlashStringHelper *key, V &&value) {
143 this->add_kv_(this->variables_,
reinterpret_cast<const char *
>(key), std::forward<V>(value));
147#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
149 this->response_template_ = response_template;
150 this->flags_.has_response_template =
true;
156#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
163 void play(
const Ts &...
x)
override {
165 std::string service_value = this->service_.value(
x...);
167 resp.
is_event = this->flags_.is_event;
174 this->populate_service_map(resp.
data, this->data_, data_storage,
x...);
175 this->populate_service_map(resp.
data_template, this->data_template_, data_template_storage,
x...);
176 this->populate_service_map(resp.
variables, this->variables_, variables_storage,
x...);
178#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
179#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
181 std::string response_template_value;
183 if (this->flags_.wants_status) {
185 static uint32_t call_id_counter = 1;
186 uint32_t call_id = call_id_counter++;
188#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
189 if (this->flags_.wants_response) {
192 if (this->flags_.has_response_template) {
193 response_template_value = this->response_template_.value(
x...);
199 auto captured_args = std::make_tuple(
x...);
200 this->parent_->register_action_response_callback(call_id, [
this, captured_args](
const ActionResponse &response) {
202 [
this, &response](
auto &&...args) {
204#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
205 if (this->flags_.wants_response) {
206 this->success_trigger_with_response_.trigger(response.
get_json(), args...);
210 this->success_trigger_.trigger(args...);
221 this->parent_->send_homeassistant_action(resp);
228 auto &kv = vec.emplace_back();
230 kv.value = std::forward<V>(value);
233 template<
typename VectorType,
typename SourceType>
236 dest.init(source.size());
244 value_storage.
init(source.size() * 2);
246 for (
auto &it : source) {
247 auto &kv = dest.emplace_back();
251 size_t key_len = strlen_P(it.key);
252 value_storage.
push_back(std::string(key_len,
'\0'));
253 memcpy_P(value_storage.
back().data(), it.key, key_len);
258 value_storage.
push_back(it.value.value(
x...));
264 size_t lambda_count = 0;
265 for (
const auto &it : source) {
266 if (!it.value.is_static_string()) {
270 value_storage.
init(lambda_count);
272 for (
auto &it : source) {
273 auto &kv = dest.emplace_back();
276 if (it.value.is_static_string()) {
278 kv.value =
StringRef(it.value.get_static_string());
281 value_storage.
push_back(it.value.value(
x...));
293#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
294#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
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)
Trigger< JsonObjectConst, Ts... > success_trigger_with_response_
void add_variable(const __FlashStringHelper *key, V &&value)
HomeAssistantServiceCallAction(APIServer *parent, bool is_event)
Trigger< std::string, Ts... > error_trigger_
void add_data(const char *key, V &&value)
void play(const Ts &...x) override
void add_variable(const char *key, V &&value)
FixedVector< TemplatableKeyValuePair< Ts... > > data_
Trigger< Ts... > * get_success_trigger()
void add_data(const __FlashStringHelper *key, V &&value)
Trigger< std::string, Ts... > * get_error_trigger()
void add_kv_(FixedVector< TemplatableKeyValuePair< Ts... > > &vec, const char *key, V &&value)
Trigger< Ts... > success_trigger_
FixedVector< TemplatableKeyValuePair< Ts... > > variables_
Trigger< JsonObjectConst, Ts... > * get_success_trigger_with_response()
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()
void add_data_template(const __FlashStringHelper *key, V &&value)
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