led_interface.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. """
  2. Unified LED interface for different LED control systems
  3. Provides a common abstraction layer for pattern manager integration.
  4. """
  5. from typing import Optional, Literal
  6. from modules.led.led_controller import LEDController, effect_loading as wled_loading, effect_idle as wled_idle, effect_connected as wled_connected, effect_playing as wled_playing
  7. # Try to import DW LED controller - it requires RPi-specific dependencies
  8. try:
  9. from modules.led.dw_led_controller import DWLEDController, effect_loading as dw_led_loading, effect_idle as dw_led_idle, effect_connected as dw_led_connected, effect_playing as dw_led_playing
  10. DW_LEDS_AVAILABLE = True
  11. except ImportError:
  12. # Running on non-RPi platform - DW LEDs not available
  13. DWLEDController = None
  14. dw_led_loading = None
  15. dw_led_idle = None
  16. dw_led_connected = None
  17. dw_led_playing = None
  18. DW_LEDS_AVAILABLE = False
  19. LEDProviderType = Literal["wled", "dw_leds", "none"]
  20. class LEDInterface:
  21. """
  22. Unified interface for LED control that works with multiple backends.
  23. Automatically delegates to the appropriate controller based on configuration.
  24. """
  25. def __init__(self, provider: LEDProviderType = "none", ip_address: Optional[str] = None,
  26. num_leds: Optional[int] = None, gpio_pin: Optional[int] = None, pixel_order: Optional[str] = None,
  27. brightness: Optional[float] = None, speed: Optional[int] = None, intensity: Optional[int] = None):
  28. self.provider = provider
  29. self._controller = None
  30. if provider == "wled" and ip_address:
  31. self._controller = LEDController(ip_address)
  32. elif provider == "dw_leds":
  33. if not DW_LEDS_AVAILABLE:
  34. raise ImportError("DW LED controller requires Raspberry Pi GPIO libraries. Install with: pip install -r requirements.txt")
  35. # DW LEDs uses local GPIO, no IP needed
  36. num_leds = num_leds or 60
  37. gpio_pin = gpio_pin or 12
  38. pixel_order = pixel_order or "GRB"
  39. brightness = brightness if brightness is not None else 0.35
  40. speed = speed if speed is not None else 128
  41. intensity = intensity if intensity is not None else 128
  42. self._controller = DWLEDController(num_leds, gpio_pin, brightness, pixel_order=pixel_order, speed=speed, intensity=intensity)
  43. @property
  44. def is_configured(self) -> bool:
  45. """Check if LED controller is configured"""
  46. return self._controller is not None
  47. def update_config(self, provider: LEDProviderType, ip_address: Optional[str] = None,
  48. num_leds: Optional[int] = None, gpio_pin: Optional[int] = None, pixel_order: Optional[str] = None,
  49. brightness: Optional[float] = None, speed: Optional[int] = None, intensity: Optional[int] = None):
  50. """Update LED provider configuration"""
  51. self.provider = provider
  52. # Stop existing controller if switching providers
  53. if self._controller and hasattr(self._controller, 'stop'):
  54. try:
  55. self._controller.stop()
  56. except:
  57. pass
  58. if provider == "wled" and ip_address:
  59. self._controller = LEDController(ip_address)
  60. elif provider == "dw_leds":
  61. if not DW_LEDS_AVAILABLE:
  62. raise ImportError("DW LED controller requires Raspberry Pi GPIO libraries. Install with: pip install -r requirements.txt")
  63. num_leds = num_leds or 60
  64. gpio_pin = gpio_pin or 12
  65. pixel_order = pixel_order or "GRB"
  66. brightness = brightness if brightness is not None else 0.35
  67. speed = speed if speed is not None else 128
  68. intensity = intensity if intensity is not None else 128
  69. self._controller = DWLEDController(num_leds, gpio_pin, brightness, pixel_order=pixel_order, speed=speed, intensity=intensity)
  70. else:
  71. self._controller = None
  72. def effect_loading(self) -> bool:
  73. """Show loading effect"""
  74. if not self.is_configured:
  75. return False
  76. if self.provider == "wled":
  77. return wled_loading(self._controller)
  78. elif self.provider == "dw_leds":
  79. return dw_led_loading(self._controller)
  80. return False
  81. def effect_idle(self, effect_name: Optional[str] = None) -> bool:
  82. """Show idle effect"""
  83. if not self.is_configured:
  84. return False
  85. if self.provider == "wled":
  86. return wled_idle(self._controller)
  87. elif self.provider == "dw_leds":
  88. return dw_led_idle(self._controller, effect_name)
  89. return False
  90. def effect_connected(self) -> bool:
  91. """Show connected effect"""
  92. if not self.is_configured:
  93. return False
  94. if self.provider == "wled":
  95. return wled_connected(self._controller)
  96. elif self.provider == "dw_leds":
  97. return dw_led_connected(self._controller)
  98. return False
  99. def effect_playing(self, effect_name: Optional[str] = None) -> bool:
  100. """Show playing effect"""
  101. if not self.is_configured:
  102. return False
  103. if self.provider == "wled":
  104. return wled_playing(self._controller)
  105. elif self.provider == "dw_leds":
  106. return dw_led_playing(self._controller, effect_name)
  107. return False
  108. def set_power(self, state: int) -> dict:
  109. """Set power state (0=Off, 1=On, 2=Toggle)"""
  110. if not self.is_configured:
  111. return {"connected": False, "message": "No LED controller configured"}
  112. return self._controller.set_power(state)
  113. def check_status(self) -> dict:
  114. """Check controller status"""
  115. if not self.is_configured:
  116. return {"connected": False, "message": "No LED controller configured"}
  117. if self.provider == "wled":
  118. return self._controller.check_wled_status()
  119. elif self.provider == "dw_leds":
  120. return self._controller.check_status()
  121. return {"connected": False, "message": "Unknown provider"}
  122. def get_controller(self):
  123. """Get the underlying controller instance (for advanced usage)"""
  124. return self._controller