Pārlūkot izejas kodu

Fix SK6812 RGBW LED support and add frontend build to pre-commit hook

Write 4-tuples (r,g,b,w) for RGBW strips in Segment.set_pixel_color()
and use correct off-color fill tuples in DWLEDController. Previously,
selecting GRBW/RGBW pixel order in settings would crash the effect loop
because NeoPixel enforces tuple length matching bpp.

Also widen pre-commit hook to trigger frontend build on any UI file
change (CSS, config, HTML) and auto-stage static/dist/ output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tuanchris 4 mēneši atpakaļ
vecāks
revīzija
ed8e7bc966

+ 5 - 3
modules/led/dw_led_controller.py

@@ -34,6 +34,8 @@ class DWLEDController:
         self.gpio_pin = gpio_pin
         self.brightness = brightness
         self.pixel_order = pixel_order
+        self.is_rgbw = 'W' in pixel_order.upper()
+        self._off_color = (0, 0, 0, 0) if self.is_rgbw else (0, 0, 0)
 
         # State
         self._powered_on = False
@@ -116,7 +118,7 @@ class DWLEDController:
             )
 
             # Create segment for the entire strip
-            self._segment = Segment(self._pixels, 0, self.num_leds)
+            self._segment = Segment(self._pixels, 0, self.num_leds, is_rgbw=self.is_rgbw)
             self._segment.speed = self._speed
             self._segment.intensity = self._intensity
             self._segment.palette_id = self._current_palette_id
@@ -188,7 +190,7 @@ class DWLEDController:
 
             # Turn off all pixels immediately when powering off
             if not self._powered_on and self._pixels:
-                self._pixels.fill((0, 0, 0))
+                self._pixels.fill(self._off_color)
                 self._pixels.show()
 
             # Start effect thread if not running
@@ -522,7 +524,7 @@ class DWLEDController:
 
         with self._lock:
             if self._pixels:
-                self._pixels.fill((0, 0, 0))
+                self._pixels.fill(self._off_color)
                 self._pixels.show()
                 self._pixels.deinit()
             self._pixels = None

+ 8 - 2
modules/led/dw_leds/segment.py

@@ -11,16 +11,18 @@ from .utils.palettes import color_from_palette, get_palette
 class Segment:
     """LED segment with effect support"""
 
-    def __init__(self, pixels, start: int, stop: int):
+    def __init__(self, pixels, start: int, stop: int, is_rgbw: bool = False):
         """
         Initialize a segment
         pixels: neopixel.NeoPixel object
         start: starting LED index
         stop: ending LED index (exclusive)
+        is_rgbw: True for RGBW strips (SK6812), writes 4-tuples instead of 3
         """
         self.pixels = pixels
         self.start = start
         self.stop = stop
+        self.is_rgbw = is_rgbw
         self.length = stop - start
 
         # Colors (up to 3 colors like WLED)
@@ -67,7 +69,11 @@ class Segment:
         r = get_r(color)
         g = get_g(color)
         b = get_b(color)
-        self.pixels[actual_idx] = (r, g, b)
+        if self.is_rgbw:
+            w = get_w(color)
+            self.pixels[actual_idx] = (r, g, b, w)
+        else:
+            self.pixels[actual_idx] = (r, g, b)
 
     def fill(self, color: int):
         """Fill entire segment with color"""

+ 17 - 5
scripts/pre-commit

@@ -1,5 +1,5 @@
 #!/bin/sh
-# Pre-commit hook: runs Ruff on staged Python files and frontend tests on staged TS/TSX files
+# Pre-commit hook: runs Ruff on staged Python files, frontend tests and build on staged TS/TSX/CSS files
 #
 # Install: cp scripts/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
 
@@ -27,18 +27,30 @@ if [ -n "$STAGED_PY" ]; then
     fi
 fi
 
-# --- Frontend tests on staged TS/TSX files ---
-STAGED_FE=$(git diff --cached --name-only --diff-filter=ACM -- 'frontend/src/**/*.ts' 'frontend/src/**/*.tsx')
+# --- Frontend checks on staged UI files ---
+STAGED_FE=$(git diff --cached --name-only --diff-filter=ACM -- 'frontend/src/**/*.ts' 'frontend/src/**/*.tsx' 'frontend/src/**/*.css' 'frontend/index.html' 'frontend/vite.config.ts' 'frontend/tsconfig*.json' 'frontend/tailwind.config.*' 'frontend/components.json')
 
 if [ -n "$STAGED_FE" ]; then
-    printf "${YELLOW}Running frontend tests...${NC}\n"
     if [ -d "frontend/node_modules" ]; then
+        # Run tests first
+        printf "${YELLOW}Running frontend tests...${NC}\n"
         if ! (cd frontend && npx vitest run --reporter=dot 2>&1); then
             printf "${RED}Frontend tests failed. Fix them before committing.${NC}\n"
             exit 1
         fi
         printf "${GREEN}Frontend tests passed.${NC}\n"
+
+        # Build production bundle
+        printf "${YELLOW}Building frontend...${NC}\n"
+        if ! (cd frontend && npm run build 2>&1); then
+            printf "${RED}Frontend build failed. Fix errors before committing.${NC}\n"
+            exit 1
+        fi
+        printf "${GREEN}Frontend build succeeded.${NC}\n"
+
+        # Stage the updated build output so it's included in this commit
+        git add static/dist/
     else
-        printf "${YELLOW}frontend/node_modules not found, skipping tests. Run: cd frontend && npm install${NC}\n"
+        printf "${YELLOW}frontend/node_modules not found, skipping tests and build. Run: cd frontend && npm install${NC}\n"
     fi
 fi