mirror of
https://github.com/esphome/esphome.git
synced 2026-09-03 19:46:02 +00:00
[multiple] Fix codegen type mismatches and raw value setter calls
- sprinkler: fix codegen to use cg.size_t for valve_number (was cg.uint8) - remote_base/toto: move send_times/send_wait defaults to codegen - remote_base/abbwelcome: wrap auto_message_id bool via cg.templatable - http_request: wrap capture_response bool via cg.templatable - core/automation.h: add casting trampoline to TemplatableValue (same as TemplatableFn) for codegen with mismatched return types
This commit is contained in:
@@ -307,7 +307,8 @@ async def http_request_action_to_code(config, action_id, template_arg, args):
|
||||
|
||||
capture_response = config[CONF_CAPTURE_RESPONSE]
|
||||
if capture_response:
|
||||
cg.add(var.set_capture_response(capture_response))
|
||||
template_ = await cg.templatable(capture_response, args, cg.bool_)
|
||||
cg.add(var.set_capture_response(template_))
|
||||
cg.add_define("USE_HTTP_REQUEST_RESPONSE")
|
||||
|
||||
cg.add(var.set_max_response_buffer_size(config[CONF_MAX_RESPONSE_BUFFER_SIZE]))
|
||||
|
||||
@@ -2123,7 +2123,8 @@ async def abbwelcome_action(var, config, args):
|
||||
await cg.templatable(config[CONF_MESSAGE_TYPE], args, cg.uint8)
|
||||
)
|
||||
)
|
||||
cg.add(var.set_auto_message_id(CONF_MESSAGE_ID not in config))
|
||||
template_ = await cg.templatable(CONF_MESSAGE_ID not in config, args, cg.bool_)
|
||||
cg.add(var.set_auto_message_id(template_))
|
||||
if CONF_MESSAGE_ID in config:
|
||||
cg.add(
|
||||
var.set_message_id(
|
||||
@@ -2231,3 +2232,9 @@ async def Toto_action(var, config, args):
|
||||
cg.add(var.set_rc_code_2(template_))
|
||||
template_ = await cg.templatable(config[CONF_COMMAND], args, cg.uint8)
|
||||
cg.add(var.set_command(template_))
|
||||
# Set toto-specific defaults (only if user didn't configure repeat)
|
||||
if CONF_REPEAT not in config:
|
||||
template_ = await cg.templatable(3, args, cg.uint32)
|
||||
cg.add(var.set_send_times(template_))
|
||||
template_ = await cg.templatable(36000, args, cg.uint32)
|
||||
cg.add(var.set_send_wait(template_))
|
||||
|
||||
@@ -35,8 +35,6 @@ template<typename... Ts> class TotoAction : public RemoteTransmitterActionBase<T
|
||||
data.rc_code_1 = this->rc_code_1_.value(x...);
|
||||
data.rc_code_2 = this->rc_code_2_.value(x...);
|
||||
data.command = this->command_.value(x...);
|
||||
this->set_send_times(this->send_times_.value_or(x..., 3));
|
||||
this->set_send_wait(this->send_wait_.value_or(x..., 36000));
|
||||
TotoProtocol().encode(dst, data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -455,7 +455,7 @@ async def sprinkler_set_multiplier_to_code(config, action_id, template_arg, args
|
||||
async def sprinkler_set_queued_valve_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(config[CONF_VALVE_NUMBER], args, cg.uint8)
|
||||
template_ = await cg.templatable(config[CONF_VALVE_NUMBER], args, cg.size_t)
|
||||
cg.add(var.set_valve_number(template_))
|
||||
template_ = await cg.templatable(config[CONF_RUN_DURATION], args, cg.uint32)
|
||||
cg.add(var.set_valve_run_duration(template_))
|
||||
@@ -487,7 +487,7 @@ async def sprinkler_set_valve_run_duration_to_code(
|
||||
):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(config[CONF_VALVE_NUMBER], args, cg.uint8)
|
||||
template_ = await cg.templatable(config[CONF_VALVE_NUMBER], args, cg.size_t)
|
||||
cg.add(var.set_valve_number(template_))
|
||||
template_ = await cg.templatable(config[CONF_RUN_DURATION], args, cg.uint32)
|
||||
cg.add(var.set_valve_run_duration(template_))
|
||||
@@ -525,7 +525,7 @@ async def sprinkler_start_full_cycle_to_code(config, action_id, template_arg, ar
|
||||
async def sprinkler_start_single_valve_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(config[CONF_VALVE_NUMBER], args, cg.uint8)
|
||||
template_ = await cg.templatable(config[CONF_VALVE_NUMBER], args, cg.size_t)
|
||||
cg.add(var.set_valve_to_start(template_))
|
||||
if CONF_RUN_DURATION in config:
|
||||
template_ = await cg.templatable(config[CONF_RUN_DURATION], args, cg.uint32)
|
||||
|
||||
@@ -108,8 +108,7 @@ template<typename... Ts> class StartSingleValveAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit StartSingleValveAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
// valve_to_start uses TemplatableValue (not TemplatableFn) because it is set
|
||||
// from both codegen (lambdas) and C++ (raw values in sprinkler.cpp).
|
||||
// TemplatableValue (not TemplatableFn) — also set from C++ with raw values in sprinkler.cpp
|
||||
template<typename V> void set_valve_to_start(V valve_to_start) { this->valve_to_start_ = valve_to_start; }
|
||||
TEMPLATABLE_VALUE(uint32_t, valve_run_duration)
|
||||
|
||||
|
||||
@@ -110,9 +110,21 @@ template<typename T, typename... X> class TemplatableValue {
|
||||
// Accept stateless lambdas (convertible to function pointer)
|
||||
template<typename F> TemplatableValue(F f) requires std::convertible_to<F, T (*)(X...)> : tag_(FN) { this->f_ = f; }
|
||||
|
||||
// Reject stateful lambdas at compile time
|
||||
// Convertible return type (e.g., int -> uint8_t) — casting trampoline
|
||||
template<typename F>
|
||||
TemplatableValue(F) requires std::invocable<F, X...> &&(!std::convertible_to<F, T (*)(X...)>) = delete;
|
||||
[[deprecated("Lambda return type does not match TemplatableValue<T> — use the correct type in "
|
||||
"codegen")]] TemplatableValue(F) requires(!std::convertible_to<F, T (*)(X...)>) &&
|
||||
std::invocable<F, X...> &&std::convertible_to<std::invoke_result_t<F, X...>, T> &&std::is_empty_v<F>
|
||||
&&std::default_initializable<F> : tag_(FN) {
|
||||
this->f_ = [](X... x) -> T { return static_cast<T>(F{}(x...)); };
|
||||
}
|
||||
|
||||
// Reject any callable that didn't match the above
|
||||
template<typename F>
|
||||
TemplatableValue(F) requires std::invocable<F, X...> &&
|
||||
(!std::convertible_to<F, T (*)(X...)>) &&(!std::is_empty_v<F> ||
|
||||
!std::convertible_to<std::invoke_result_t<F, X...>, T> ||
|
||||
!std::default_initializable<F>) = delete;
|
||||
|
||||
TemplatableValue(const TemplatableValue &other) : tag_(other.tag_) {
|
||||
if (this->tag_ == VALUE) {
|
||||
|
||||
Reference in New Issue
Block a user