Skip to content

Commit 01c49f7

Browse files
feat: add direction change delay between stop and reverse
Merge of Sese-Schneider#55. Adds a 1s pause between stopping and changing direction to let the motor settle. Toggle mode overrides with pulse_time. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b0a32a0 commit 01c49f7

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

custom_components/cover_time_based/cover_base.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ async def async_close_cover(self, **kwargs):
322322
if self.is_opening:
323323
self._log("async_close_cover :: currently opening, stopping first")
324324
await self.async_stop_cover()
325+
await self._direction_change_delay()
325326
await self._async_move_to_endpoint(target=0)
326327

327328
async def async_open_cover(self, **kwargs):
@@ -331,8 +332,16 @@ async def async_open_cover(self, **kwargs):
331332
if self.is_closing:
332333
self._log("async_open_cover :: currently closing, stopping first")
333334
await self.async_stop_cover()
335+
await self._direction_change_delay()
334336
await self._async_move_to_endpoint(target=100)
335337

338+
async def _direction_change_delay(self):
339+
"""Pause between stop and direction change to let the motor settle.
340+
341+
Toggle mode overrides this with pulse_time (the relay pulse duration).
342+
"""
343+
await sleep(1.0)
344+
336345
async def async_stop_cover(self, **kwargs):
337346
"""Turn the device stop."""
338347
self._require_configured()
@@ -627,6 +636,7 @@ async def set_position(self, position):
627636
if self._has_tilt_support() and self.tilt_calc.is_traveling():
628637
self.tilt_calc.stop()
629638
await self._async_handle_command(SERVICE_STOP_COVER)
639+
await self._direction_change_delay()
630640
current = self.travel_calc.current_position()
631641
if target == current:
632642
return

tests/test_cover_toggle_mode.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,48 @@ async def test_open_while_closing_stops_first(self):
345345
mock_stop.assert_awaited_once()
346346
await _cancel_tasks(cover)
347347

348+
@pytest.mark.asyncio
349+
async def test_close_while_opening_waits_direction_change_delay(self):
350+
"""Direction change must wait between stop and new direction."""
351+
cover = _make_toggle_cover()
352+
cover.travel_calc.set_position(0)
353+
cover.travel_calc.start_travel_up()
354+
cover._last_command = SERVICE_OPEN_COVER
355+
356+
with (
357+
patch.object(cover, "async_write_ha_state"),
358+
patch.object(cover, "async_stop_cover", new_callable=AsyncMock),
359+
patch(
360+
"custom_components.cover_time_based.cover_base.sleep",
361+
new_callable=AsyncMock,
362+
) as mock_sleep,
363+
):
364+
await cover.async_close_cover()
365+
366+
mock_sleep.assert_awaited_once_with(1.0)
367+
await _cancel_tasks(cover)
368+
369+
@pytest.mark.asyncio
370+
async def test_open_while_closing_waits_direction_change_delay(self):
371+
"""Direction change must wait between stop and new direction."""
372+
cover = _make_toggle_cover()
373+
cover.travel_calc.set_position(100)
374+
cover.travel_calc.start_travel_down()
375+
cover._last_command = SERVICE_CLOSE_COVER
376+
377+
with (
378+
patch.object(cover, "async_write_ha_state"),
379+
patch.object(cover, "async_stop_cover", new_callable=AsyncMock),
380+
patch(
381+
"custom_components.cover_time_based.cover_base.sleep",
382+
new_callable=AsyncMock,
383+
) as mock_sleep,
384+
):
385+
await cover.async_open_cover()
386+
387+
mock_sleep.assert_awaited_once_with(1.0)
388+
await _cancel_tasks(cover)
389+
348390

349391
# ===================================================================
350392
# Stop with tilt: snap_trackers_to_physical

0 commit comments

Comments
 (0)