ソースを参照

add options for selecting pixel order

tuanchris 3 ヶ月 前
コミット
1535d5c18c
5 ファイル変更55 行追加10 行削除
  1. 7 2
      main.py
  2. 3 0
      modules/core/state.py
  3. 8 6
      modules/led/led_interface.py
  4. 8 0
      static/js/settings.js
  5. 29 2
      templates/settings.html

+ 7 - 2
main.py

@@ -105,11 +105,12 @@ async def lifespan(app: FastAPI):
                 "dw_leds",
                 num_leds=state.dw_led_num_leds,
                 gpio_pin=state.dw_led_gpio_pin,
+                pixel_order=state.dw_led_pixel_order,
                 brightness=state.dw_led_brightness / 100.0,
                 speed=state.dw_led_speed,
                 intensity=state.dw_led_intensity
             )
-            logger.info(f"LED controller initialized: DW LEDs ({state.dw_led_num_leds} LEDs on GPIO{state.dw_led_gpio_pin})")
+            logger.info(f"LED controller initialized: DW LEDs ({state.dw_led_num_leds} LEDs on GPIO{state.dw_led_gpio_pin}, pixel order: {state.dw_led_pixel_order})")
         else:
             state.led_controller = None
             logger.info("LED controller not configured")
@@ -234,6 +235,7 @@ class LEDConfigRequest(BaseModel):
     # DW LED specific fields
     num_leds: Optional[int] = None
     gpio_pin: Optional[int] = None
+    pixel_order: Optional[str] = None
     brightness: Optional[int] = None
 
 class DeletePlaylistRequest(BaseModel):
@@ -1156,17 +1158,19 @@ async def set_led_config(request: LEDConfigRequest):
     elif request.provider == "dw_leds":
         state.dw_led_num_leds = request.num_leds or 60
         state.dw_led_gpio_pin = request.gpio_pin or 12
+        state.dw_led_pixel_order = request.pixel_order or "GRB"
         state.dw_led_brightness = request.brightness or 35
         state.wled_ip = None
         state.led_controller = LEDInterface(
             "dw_leds",
             num_leds=state.dw_led_num_leds,
             gpio_pin=state.dw_led_gpio_pin,
+            pixel_order=state.dw_led_pixel_order,
             brightness=state.dw_led_brightness / 100.0,
             speed=state.dw_led_speed,
             intensity=state.dw_led_intensity
         )
-        logger.info(f"DW LEDs configured: {state.dw_led_num_leds} LEDs on GPIO{state.dw_led_gpio_pin}")
+        logger.info(f"DW LEDs configured: {state.dw_led_num_leds} LEDs on GPIO{state.dw_led_gpio_pin}, pixel order: {state.dw_led_pixel_order}")
 
         # Check if initialization succeeded by checking status
         status = state.led_controller.check_status()
@@ -1217,6 +1221,7 @@ async def get_led_config():
         "wled_ip": state.wled_ip,
         "dw_led_num_leds": state.dw_led_num_leds,
         "dw_led_gpio_pin": state.dw_led_gpio_pin,
+        "dw_led_pixel_order": state.dw_led_pixel_order,
         "dw_led_brightness": state.dw_led_brightness,
         "dw_led_idle_effect": state.dw_led_idle_effect,
         "dw_led_playing_effect": state.dw_led_playing_effect

+ 3 - 0
modules/core/state.py

@@ -46,6 +46,7 @@ class AppState:
         # DW LED settings
         self.dw_led_num_leds = 60  # Number of LEDs in strip
         self.dw_led_gpio_pin = 12  # GPIO pin (12, 13, 18, or 19)
+        self.dw_led_pixel_order = "GRB"  # Pixel color order for WS281x (GRB, RGB, BGR, etc.)
         self.dw_led_brightness = 35  # Brightness 0-100
         self.dw_led_speed = 128  # Effect speed 0-255
         self.dw_led_intensity = 128  # Effect intensity 0-255
@@ -203,6 +204,7 @@ class AppState:
             "led_provider": self.led_provider,
             "dw_led_num_leds": self.dw_led_num_leds,
             "dw_led_gpio_pin": self.dw_led_gpio_pin,
+            "dw_led_pixel_order": self.dw_led_pixel_order,
             "dw_led_brightness": self.dw_led_brightness,
             "dw_led_speed": self.dw_led_speed,
             "dw_led_intensity": self.dw_led_intensity,
@@ -250,6 +252,7 @@ class AppState:
         self.led_provider = data.get('led_provider', "none")
         self.dw_led_num_leds = data.get('dw_led_num_leds', 60)
         self.dw_led_gpio_pin = data.get('dw_led_gpio_pin', 12)
+        self.dw_led_pixel_order = data.get('dw_led_pixel_order', "GRB")
         self.dw_led_brightness = data.get('dw_led_brightness', 35)
         self.dw_led_speed = data.get('dw_led_speed', 128)
         self.dw_led_intensity = data.get('dw_led_intensity', 128)

+ 8 - 6
modules/led/led_interface.py

@@ -17,8 +17,8 @@ class LEDInterface:
     """
 
     def __init__(self, provider: LEDProviderType = "none", ip_address: Optional[str] = None,
-                 num_leds: Optional[int] = None, gpio_pin: Optional[int] = None, brightness: Optional[float] = None,
-                 speed: Optional[int] = None, intensity: Optional[int] = None):
+                 num_leds: Optional[int] = None, gpio_pin: Optional[int] = None, pixel_order: Optional[str] = None,
+                 brightness: Optional[float] = None, speed: Optional[int] = None, intensity: Optional[int] = None):
         self.provider = provider
         self._controller = None
 
@@ -28,10 +28,11 @@ class LEDInterface:
             # DW LEDs uses local GPIO, no IP needed
             num_leds = num_leds or 60
             gpio_pin = gpio_pin or 12
+            pixel_order = pixel_order or "GRB"
             brightness = brightness if brightness is not None else 0.35
             speed = speed if speed is not None else 128
             intensity = intensity if intensity is not None else 128
-            self._controller = DWLEDController(num_leds, gpio_pin, brightness, speed=speed, intensity=intensity)
+            self._controller = DWLEDController(num_leds, gpio_pin, brightness, pixel_order=pixel_order, speed=speed, intensity=intensity)
 
     @property
     def is_configured(self) -> bool:
@@ -39,8 +40,8 @@ class LEDInterface:
         return self._controller is not None
 
     def update_config(self, provider: LEDProviderType, ip_address: Optional[str] = None,
-                     num_leds: Optional[int] = None, gpio_pin: Optional[int] = None, brightness: Optional[float] = None,
-                     speed: Optional[int] = None, intensity: Optional[int] = None):
+                     num_leds: Optional[int] = None, gpio_pin: Optional[int] = None, pixel_order: Optional[str] = None,
+                     brightness: Optional[float] = None, speed: Optional[int] = None, intensity: Optional[int] = None):
         """Update LED provider configuration"""
         self.provider = provider
 
@@ -56,10 +57,11 @@ class LEDInterface:
         elif provider == "dw_leds":
             num_leds = num_leds or 60
             gpio_pin = gpio_pin or 12
+            pixel_order = pixel_order or "GRB"
             brightness = brightness if brightness is not None else 0.35
             speed = speed if speed is not None else 128
             intensity = intensity if intensity is not None else 128
-            self._controller = DWLEDController(num_leds, gpio_pin, brightness, speed=speed, intensity=intensity)
+            self._controller = DWLEDController(num_leds, gpio_pin, brightness, pixel_order=pixel_order, speed=speed, intensity=intensity)
         else:
             self._controller = None
 

+ 8 - 0
static/js/settings.js

@@ -207,6 +207,12 @@ async function loadLedConfig() {
                     gpioPinInput.value = data.dw_led_gpio_pin;
                 }
             }
+            if (data.dw_led_pixel_order) {
+                const pixelOrderInput = document.getElementById('dwLedPixelOrder');
+                if (pixelOrderInput) {
+                    pixelOrderInput.value = data.dw_led_pixel_order;
+                }
+            }
 
             // Update UI to show correct config section
             updateLedProviderUI();
@@ -455,9 +461,11 @@ function setupEventListeners() {
             } else if (provider === 'dw_leds') {
                 const numLeds = parseInt(document.getElementById('dwLedNumLeds')?.value) || 60;
                 const gpioPin = parseInt(document.getElementById('dwLedGpioPin')?.value) || 12;
+                const pixelOrder = document.getElementById('dwLedPixelOrder')?.value || 'GRB';
 
                 requestBody.num_leds = numLeds;
                 requestBody.gpio_pin = gpioPin;
+                requestBody.pixel_order = pixelOrder;
             }
 
             try {

+ 29 - 2
templates/settings.html

@@ -525,6 +525,16 @@ input:checked + .slider:before {
 
       <!-- DW LEDs Configuration (shown when DW LEDs is selected) -->
       <div id="dwLedsConfig" class="flex flex-col gap-4 hidden">
+        <div class="bg-blue-50 border border-blue-200 rounded-lg p-3">
+          <div class="flex items-start gap-2">
+            <span class="material-icons text-blue-600 text-base">info</span>
+            <div class="text-xs text-blue-700">
+              <p class="font-medium text-blue-800">Supported LED Strips: WS281x Only</p>
+              <p class="mt-1">Compatible with WS2811, WS2812, WS2812B, WS2813, WS2815 (12V), and other WS281x RGB LED strips. RGBW strips (SK6812, SK6812W) are not supported.</p>
+            </div>
+          </div>
+        </div>
+
         <label class="flex flex-col gap-1.5">
           <span class="text-slate-700 text-sm font-medium leading-normal">Number of LEDs</span>
           <input
@@ -537,7 +547,7 @@ input:checked + .slider:before {
             max="1000"
           />
           <p class="text-xs text-slate-500">
-            Total number of LEDs in your strip
+            Total number of LEDs in your WS281x strip
           </p>
         </label>
         <label class="flex flex-col gap-1.5">
@@ -552,7 +562,24 @@ input:checked + .slider:before {
             <option value="19">GPIO 19 (PWM1)</option>
           </select>
           <p class="text-xs text-slate-500">
-            Select a PWM-capable GPIO pin for best performance
+            Select a PWM-capable GPIO pin for WS281x timing
+          </p>
+        </label>
+        <label class="flex flex-col gap-1.5">
+          <span class="text-slate-700 text-sm font-medium leading-normal">Pixel Color Order (WS281x)</span>
+          <select
+            id="dwLedPixelOrder"
+            class="form-select flex w-full min-w-0 resize-none overflow-hidden rounded-lg text-slate-900 focus:outline-0 focus:ring-2 focus:ring-sky-500 border border-slate-300 bg-white focus:border-sky-500 h-10 px-4 text-base font-normal leading-normal transition-colors"
+          >
+            <option value="GRB" selected>GRB - WS2812/WS2812B/WS2815 (most common)</option>
+            <option value="RGB">RGB - WS2811 and some variants</option>
+            <option value="BGR">BGR - Some WS2811 variants</option>
+            <option value="RBG">RBG - Rare variant</option>
+            <option value="GBR">GBR - Rare variant</option>
+            <option value="BRG">BRG - Rare variant</option>
+          </select>
+          <p class="text-xs text-slate-500">
+            Most WS2812B and WS2815 strips use GRB. WS2811 often uses RGB. If colors appear wrong, try different orders.
           </p>
         </label>
       </div>