[output] Use register_apply_action for the output actions (#19512)

This commit is contained in:
J. Nick Koston
2026-09-23 17:21:21 -05:00
committed by GitHub
parent bd1efeae94
commit 606525ed18
3 changed files with 48 additions and 137 deletions
+45 -68
View File
@@ -1,3 +1,5 @@
from dataclasses import dataclass
from esphome import automation
from esphome.automation import maybe_simple_id
import esphome.codegen as cg
@@ -12,12 +14,26 @@ from esphome.const import (
CONF_POWER_SUPPLY,
)
from esphome.core import CORE
from esphome.types import ConfigType
CODEOWNERS = ["@esphome/core"]
IS_PLATFORM_COMPONENT = True
DOMAIN = "output"
CONF_ZERO_MEANS_ZERO = "zero_means_zero"
@dataclass
class OutputData:
power_scaling: bool = False
def _get_data() -> OutputData:
if DOMAIN not in CORE.data:
CORE.data[DOMAIN] = OutputData()
return CORE.data[DOMAIN]
BINARY_OUTPUT_SCHEMA = cv.Schema(
{
cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply),
@@ -39,13 +55,6 @@ BinaryOutputPtr = BinaryOutput.operator("ptr")
FloatOutput = output_ns.class_("FloatOutput", BinaryOutput)
FloatOutputPtr = FloatOutput.operator("ptr")
# Actions
TurnOffAction = output_ns.class_("TurnOffAction", automation.Action)
TurnOnAction = output_ns.class_("TurnOnAction", automation.Action)
SetLevelAction = output_ns.class_("SetLevelAction", automation.Action)
SetMinPowerAction = output_ns.class_("SetMinPowerAction", automation.Action)
SetMaxPowerAction = output_ns.class_("SetMaxPowerAction", automation.Action)
async def setup_output_platform_(obj, config):
if CONF_INVERTED in config:
@@ -85,81 +94,49 @@ BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id(
)
@automation.register_action(
"output.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA, synchronous=True
)
async def output_turn_on_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
def _enable_power_scaling(config: ConfigType) -> ConfigType:
# set_min_power/set_max_power only exist with the define; to_code emits it from this fact.
_get_data().power_scaling = True
return config
@automation.register_action(
"output.turn_off", TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA, synchronous=True
)
async def output_turn_off_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
for _name, _call in (
("output.turn_on", "turn_on()"),
("output.turn_off", "turn_off()"),
):
automation.register_apply_action(
_name, BINARY_OUTPUT_ACTION_SCHEMA, automation.ApplyCall(_call)
)
@automation.register_action(
automation.register_apply_action(
"output.set_level",
SetLevelAction,
cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(FloatOutput),
cv.Required(CONF_LEVEL): cv.templatable(cv.percentage),
}
),
synchronous=True,
automation.ApplyField(CONF_LEVEL, "set_level", cg.float_),
)
async def output_set_level_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_LEVEL], args, cg.float_)
cg.add(var.set_level(template_))
return var
@automation.register_action(
"output.set_min_power",
SetMinPowerAction,
cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(FloatOutput),
cv.Required(CONF_MIN_POWER): cv.templatable(cv.percentage),
}
),
synchronous=True,
)
async def output_set_min_power_to_code(config, action_id, template_arg, args):
cg.add_define("USE_OUTPUT_FLOAT_POWER_SCALING")
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
template_ = await cg.templatable(config[CONF_MIN_POWER], args, cg.float_)
cg.add(var.set_min_power(template_))
return var
@automation.register_action(
"output.set_max_power",
SetMaxPowerAction,
cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(FloatOutput),
cv.Required(CONF_MAX_POWER): cv.templatable(cv.percentage),
}
),
synchronous=True,
)
async def output_set_max_power_to_code(config, action_id, template_arg, args):
cg.add_define("USE_OUTPUT_FLOAT_POWER_SCALING")
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
template_ = await cg.templatable(config[CONF_MAX_POWER], args, cg.float_)
cg.add(var.set_max_power(template_))
return var
for _name, _key, _target in (
("output.set_min_power", CONF_MIN_POWER, "set_min_power"),
("output.set_max_power", CONF_MAX_POWER, "set_max_power"),
):
automation.register_apply_action(
_name,
cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(FloatOutput),
cv.Required(_key): cv.templatable(cv.percentage),
}
).add_extra(_enable_power_scaling),
automation.ApplyField(_key, _target, cg.float_),
)
async def to_code(config):
cg.add_define("USE_OUTPUT")
if _get_data().power_scaling:
cg.add_define("USE_OUTPUT_FLOAT_POWER_SCALING")
cg.add_global(output_ns.using)
-69
View File
@@ -1,69 +0,0 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/automation.h"
#include "esphome/core/defines.h"
#include "esphome/components/output/binary_output.h"
#include "esphome/components/output/float_output.h"
namespace esphome::output {
template<typename... Ts> class TurnOffAction final : public Action<Ts...> {
public:
TurnOffAction(BinaryOutput *output) : output_(output) {}
void play(const Ts &...x) override { this->output_->turn_off(); }
protected:
BinaryOutput *output_;
};
template<typename... Ts> class TurnOnAction final : public Action<Ts...> {
public:
TurnOnAction(BinaryOutput *output) : output_(output) {}
void play(const Ts &...x) override { this->output_->turn_on(); }
protected:
BinaryOutput *output_;
};
template<typename... Ts> class SetLevelAction final : public Action<Ts...> {
public:
SetLevelAction(FloatOutput *output) : output_(output) {}
TEMPLATABLE_VALUE(float, level)
void play(const Ts &...x) override { this->output_->set_level(this->level_.value(x...)); }
protected:
FloatOutput *output_;
};
#ifdef USE_OUTPUT_FLOAT_POWER_SCALING
template<typename... Ts> class SetMinPowerAction final : public Action<Ts...> {
public:
SetMinPowerAction(FloatOutput *output) : output_(output) {}
TEMPLATABLE_VALUE(float, min_power)
void play(const Ts &...x) override { this->output_->set_min_power(this->min_power_.value(x...)); }
protected:
FloatOutput *output_;
};
template<typename... Ts> class SetMaxPowerAction final : public Action<Ts...> {
public:
SetMaxPowerAction(FloatOutput *output) : output_(output) {}
TEMPLATABLE_VALUE(float, max_power)
void play(const Ts &...x) override { this->output_->set_max_power(this->max_power_.value(x...)); }
protected:
FloatOutput *output_;
};
#endif // USE_OUTPUT_FLOAT_POWER_SCALING
} // namespace esphome::output
+3
View File
@@ -6,6 +6,9 @@ esphome:
- output.set_level:
id: output_light_output_1
level: 50%
- output.set_level:
id: output_light_output_1
level: !lambda return 0.25f;
- output.set_min_power:
id: output_light_output_1
min_power: 20%