[lock] Migrate LockStateTrigger to callback automation (#15199)

This commit is contained in:
J. Nick Koston
2026-03-27 08:20:35 -10:00
committed by GitHub
parent b41634e19a
commit dea8fdd906
6 changed files with 30 additions and 37 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ namespace copy {
static const char *const TAG = "copy.lock";
void CopyLock::setup() {
source_->add_on_state_callback([this]() { this->publish_state(source_->state); });
source_->add_on_state_callback([this](lock::LockState state) { this->publish_state(state); });
traits.set_assumed_state(source_->traits.get_assumed_state());
traits.set_requires_code(source_->traits.get_requires_code());
+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, LockState.LOCK_STATE_LOCKED),
(CONF_ON_UNLOCK, 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(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
+2 -2
View File
@@ -148,7 +148,7 @@ class Lock : public EntityBase {
/** Set callback for state changes.
*
* @param callback The void(bool) callback.
* @param callback The void(LockState) callback.
*/
template<typename F> void add_on_state_callback(F &&callback) {
this->state_callback_.add(std::forward<F>(callback));
@@ -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());