[copy] Forward cover toggle and lock open to the source (#21598)

Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
authored and GitHub committed 2026-10-26 11:22:58 -10:00
1 parent 4e68f1d324
commit e05f2fc74e
7 files changed
+120 -3

No files matched your search

+2 -3
View File
@@ -45,9 +45,8 @@ void CopyCover::control(const cover::CoverCall &call) {
auto position = call.get_position();
if (position.has_value())
call2.set_position(*position);
auto tilt2 = call.get_tilt();
if (tilt2.has_value())
call2.set_tilt(*tilt2);
if (call.get_toggle().has_value())
call2.set_command_toggle();
call2.perform();
}
@@ -21,4 +21,6 @@ void CopyLock::control(const lock::LockCall &call) {
call2.perform();
}
void CopyLock::open_latch() { this->source_->open(); }
} // namespace esphome::copy
+1
View File
@@ -13,6 +13,7 @@ class CopyLock final : public lock::Lock, public Component {
protected:
void control(const lock::LockCall &call) override;
void open_latch() override;
lock::Lock *source_;
};
@@ -0,0 +1,26 @@
esphome:
name: copy-cover-toggle-test
host:
api:
logger:
level: DEBUG
cover:
- platform: template
name: "Source Cover"
id: source_cover
toggle_action:
- cover.template.publish:
id: source_cover
position: 0.5
- platform: copy
name: "Copy Cover"
id: copy_cover
source_id: source_cover
button:
- platform: template
name: "Toggle Copy"
id: toggle_copy
on_press:
- cover.toggle: copy_cover
@@ -0,0 +1,27 @@
esphome:
name: copy-lock-open-test
host:
api:
logger:
level: DEBUG
lock:
- platform: template
name: "Source Lock"
id: source_lock
lock_action:
- lock.template.publish:
id: source_lock
state: LOCKED
unlock_action:
- lock.template.publish:
id: source_lock
state: UNLOCKED
open_action:
- lock.template.publish:
id: source_lock
state: OPEN
- platform: copy
name: "Copy Lock"
id: copy_lock
source_id: source_lock
@@ -0,0 +1,32 @@
"""A toggle sent to a copy cover runs the toggle action of its source cover."""
from __future__ import annotations
from aioesphomeapi import CoverInfo, CoverState
import pytest
from .state_utils import press_and_wait, require_entity, subscribe_after_initial_states
from .types import APIClientConnectedFactory, RunCompiledFunction
@pytest.mark.asyncio
async def test_copy_cover_toggle(
yaml_config: str,
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
async with run_compiled(yaml_config), api_client_connected() as client:
entities, _ = await client.list_entities_services()
sub = await subscribe_after_initial_states(client, entities)
copy_cover = require_entity(entities, "copy_cover", CoverInfo)
# Both covers start fully open (1.0); the source's toggle_action publishes 0.5
state = await press_and_wait(
client,
entities,
sub.waiter,
"toggle_copy",
CoverState,
key=copy_cover.key,
)
assert state.position == pytest.approx(0.5, abs=0.01)
+30
View File
@@ -0,0 +1,30 @@
"""An open command sent to a copy lock runs the open action of its source lock."""
from __future__ import annotations
from aioesphomeapi import LockCommand, LockEntityState, LockInfo, LockState
import pytest
from .state_utils import require_entity, subscribe_after_initial_states
from .types import APIClientConnectedFactory, RunCompiledFunction
@pytest.mark.asyncio
async def test_copy_lock_open(
yaml_config: str,
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
async with run_compiled(yaml_config), api_client_connected() as client:
entities, _ = await client.list_entities_services()
sub = await subscribe_after_initial_states(client, entities)
copy_lock = require_entity(entities, "copy_lock", LockInfo)
assert copy_lock.supports_open
# The source's unlock_action would publish UNLOCKED; only its open_action publishes OPEN
next_state = sub.waiter.next_state(
key=copy_lock.key, state_type=LockEntityState
)
client.lock_command(key=copy_lock.key, command=LockCommand.OPEN)
state = await next_state
assert state.state == LockState.OPEN