| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- """
- Idle LED Timeout Manager
- Handles automatic LED turn-off after a period of inactivity.
- """
- import asyncio
- import logging
- from datetime import datetime
- from typing import Optional
- logger = logging.getLogger(__name__)
- class IdleTimeoutManager:
- """
- Manages idle timeout for LED effects.
- When idle effect is played, starts a timer. When timer expires,
- checks if table is still idle and turns off LEDs if so.
- """
- def __init__(self):
- self._timeout_task: Optional[asyncio.Task] = None
- self._last_idle_time: Optional[datetime] = None
- def start_idle_timeout(self, timeout_minutes: float, state, check_idle_callback):
- """
- Start or restart the idle timeout timer.
- Args:
- timeout_minutes: Minutes to wait before turning off LEDs
- state: Application state object
- check_idle_callback: Async callback to check if table is still idle
- """
- # Cancel any existing timeout
- self.cancel_timeout()
- if timeout_minutes <= 0:
- logger.debug("Idle timeout disabled (timeout <= 0)")
- return
- # Record when idle effect was started
- self._last_idle_time = datetime.now()
- logger.info(f"Starting idle LED timeout: {timeout_minutes} minutes")
- # Create background task to handle timeout
- self._timeout_task = asyncio.create_task(
- self._timeout_handler(timeout_minutes, state, check_idle_callback)
- )
- async def _timeout_handler(self, timeout_minutes: float, state, check_idle_callback):
- """
- Background task that waits for timeout and turns off LEDs if still idle.
- """
- try:
- # Wait for the specified timeout
- timeout_seconds = timeout_minutes * 60
- await asyncio.sleep(timeout_seconds)
- # Check if we should turn off the LEDs
- logger.debug("Idle timeout expired, checking table state...")
- # Check if table is still idle (not playing anything)
- is_idle = await check_idle_callback()
- if is_idle:
- logger.info("Table is still idle after timeout - turning off LEDs")
- if state.led_controller:
- try:
- state.led_controller.set_power(0) # Turn off LEDs
- logger.info("LEDs turned off successfully")
- except Exception as e:
- logger.error(f"Failed to turn off LEDs: {e}")
- else:
- logger.warning("LED controller not configured")
- else:
- logger.debug("Table is not idle - skipping LED turn-off")
- except asyncio.CancelledError:
- logger.debug("Idle timeout cancelled")
- except Exception as e:
- logger.error(f"Error in idle timeout handler: {e}")
- def cancel_timeout(self):
- """Cancel any running timeout task."""
- if self._timeout_task and not self._timeout_task.done():
- logger.debug("Cancelling existing idle timeout")
- self._timeout_task.cancel()
- self._timeout_task = None
- def is_timeout_active(self) -> bool:
- """Check if a timeout is currently active."""
- return self._timeout_task is not None and not self._timeout_task.done()
- # Singleton instance
- idle_timeout_manager = IdleTimeoutManager()
|