Migrate lock LockStateTrigger to callback automation

This commit is contained in:
J. Nick Koston
2026-03-26 10:16:07 -10:00
parent 150e0775b9
commit 2dec1ee46e
5 changed files with 28 additions and 35 deletions
+15 -19
View File
@@ -10,7 +10,6 @@ from esphome.const import (
CONF_MQTT_ID,
CONF_ON_LOCK,
CONF_ON_UNLOCK,
CONF_TRIGGER_ID,
CONF_WEB_SERVER,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
@@ -31,8 +30,7 @@ OpenAction = lock_ns.class_("OpenAction", automation.Action)
LockPublishAction = lock_ns.class_("LockPublishAction", automation.Action)
LockCondition = lock_ns.class_("LockCondition", Condition)
LockLockTrigger = lock_ns.class_("LockLockTrigger", automation.Trigger.template())
LockUnlockTrigger = lock_ns.class_("LockUnlockTrigger", automation.Trigger.template())
LockStateForwarder = lock_ns.class_("LockStateForwarder")
LockState = lock_ns.enum("LockState")
@@ -52,16 +50,8 @@ _LOCK_SCHEMA = (
.extend(
{
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTLockComponent),
cv.Optional(CONF_ON_LOCK): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LockLockTrigger),
}
),
cv.Optional(CONF_ON_UNLOCK): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LockUnlockTrigger),
}
),
cv.Optional(CONF_ON_LOCK): automation.validate_automation({}),
cv.Optional(CONF_ON_UNLOCK): automation.validate_automation({}),
}
)
)
@@ -93,12 +83,18 @@ def lock_schema(
@setup_entity("lock")
async def _setup_lock_core(var, config):
for conf in config.get(CONF_ON_LOCK, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_UNLOCK, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf_key, state_enum in (
(CONF_ON_LOCK, "lock::LockState::LOCK_STATE_LOCKED"),
(CONF_ON_UNLOCK, "lock::LockState::LOCK_STATE_UNLOCKED"),
):
for conf in config.get(conf_key, []):
await automation.build_callback_automation(
var,
"add_on_state_callback",
[],
conf,
forwarder=LockStateForwarder.template(cg.RawExpression(state_enum)),
)
if mqtt_id := config.get(CONF_MQTT_ID):
mqtt_ = cg.new_Pvariable(mqtt_id, var)
+9 -13
View File
@@ -49,21 +49,17 @@ template<typename... Ts> class LockCondition : public Condition<Ts...> {
bool state_;
};
template<LockState State> class LockStateTrigger : public Trigger<> {
public:
explicit LockStateTrigger(Lock *a_lock) : lock_(a_lock) {
a_lock->add_on_state_callback([this]() {
if (this->lock_->state == State) {
this->trigger();
}
});
/// Callback forwarder that triggers an Automation<> only when a specific lock state is entered.
/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_.
template<LockState State> struct LockStateForwarder {
Automation<> *automation;
void operator()(LockState state) const {
if (state == State)
this->automation->trigger();
}
protected:
Lock *lock_;
};
using LockLockTrigger = LockStateTrigger<LockState::LOCK_STATE_LOCKED>;
using LockUnlockTrigger = LockStateTrigger<LockState::LOCK_STATE_UNLOCKED>;
static_assert(sizeof(LockStateForwarder<LockState::LOCK_STATE_LOCKED>) <= sizeof(void *));
static_assert(std::is_trivially_copyable_v<LockStateForwarder<LockState::LOCK_STATE_LOCKED>>);
} // namespace esphome::lock
+1 -1
View File
@@ -42,7 +42,7 @@ void Lock::publish_state(LockState state) {
this->state = state;
this->rtc_.save(&this->state);
ESP_LOGV(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state)));
this->state_callback_.call();
this->state_callback_.call(state);
#if defined(USE_LOCK) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_lock_update(this);
#endif
+1 -1
View File
@@ -178,7 +178,7 @@ class Lock : public EntityBase {
*/
virtual void control(const LockCall &call) = 0;
LazyCallbackManager<void()> state_callback_{};
LazyCallbackManager<void(LockState)> state_callback_{};
Deduplicator<LockState> publish_dedup_;
ESPPreferenceObject rtc_;
};
+2 -1
View File
@@ -28,7 +28,8 @@ void MQTTLockComponent::setup() {
this->status_momentary_warning("state", 5000);
}
});
this->lock_->add_on_state_callback([this]() { this->defer("send", [this]() { this->publish_state(); }); });
this->lock_->add_on_state_callback(
[this](LockState /*state*/) { this->defer("send", [this]() { this->publish_state(); }); });
}
void MQTTLockComponent::dump_config() {
ESP_LOGCONFIG(TAG, "MQTT Lock '%s': ", this->lock_->get_name().c_str());