Browse Source

tools/ in .gitignore — kein offizieller Teil von Trixy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
patrick 2 months ago
parent
commit
684b798cb7
3 changed files with 3 additions and 480 deletions
  1. 3 0
      .gitignore
  2. 0 479
      tools/led_test/led_test.py
  3. 0 1
      tools/led_test/requirements.txt

+ 3 - 0
.gitignore

@@ -59,6 +59,9 @@ trainer/cache/
 # ---------- Cache ----------
 cache/
 
+# ---------- Entwickler-Tools (nicht Teil von Trixy) ----------
+tools/
+
 # ---------- Laufzeit-Daten ----------
 satellites/*.json
 sync_data/

+ 0 - 479
tools/led_test/led_test.py

@@ -1,479 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-LED-Test-Script fuer WS2812/NeoPixel LEDs am Raspberry Pi.
-
-Unabhaengig von Trixy — braucht nur rpi-ws281x.
-Testet alle Animationen fuer die drei LED-Typen:
-  - Breakout (1 LED)
-  - Jewel 7 (7 LEDs, Mitte + 6 Ring)
-  - Ring 12 (12 LEDs im Kreis)
-
-Verkabelung:
-  Pi GPIO 18 (Pin 12)  ──[330Ω]──  DIN (Daten)
-  Pi 5V (Pin 2 oder 4)  ─────────  VCC (Strom)
-  Pi GND (Pin 6)         ─────────  GND
-
-Ausfuehrung:
-  sudo pip install rpi-ws281x
-  sudo python3 led_test.py --leds 7 --type jewel
-
-WICHTIG: Muss als root/sudo laufen (GPIO-Zugriff)!
-"""
-
-import argparse
-import math
-import random
-import signal
-import sys
-import time
-
-try:
-    from rpi_ws281x import PixelStrip, Color
-except ImportError:
-    print("FEHLER: rpi-ws281x nicht installiert!")
-    print("  sudo pip install rpi-ws281x")
-    sys.exit(1)
-
-
-# === Hardware-Konfiguration ===
-LED_FREQ_HZ = 800000
-LED_DMA = 10
-LED_INVERT = False
-LED_CHANNEL = 0
-
-
-# === Farb-Helfer ===
-
-def rgb(r, g, b):
-    return Color(r, g, b)
-
-def hsv_to_rgb(h, s, v):
-    """HSV (0-1) zu RGB (0-255)."""
-    if s == 0:
-        r = g = b = int(v * 255)
-        return r, g, b
-    i = int(h * 6)
-    f = (h * 6) - i
-    p = int(v * (1 - s) * 255)
-    q = int(v * (1 - s * f) * 255)
-    t = int(v * (1 - s * (1 - f)) * 255)
-    v = int(v * 255)
-    i %= 6
-    if i == 0: return v, t, p
-    if i == 1: return q, v, p
-    if i == 2: return p, v, t
-    if i == 3: return p, q, v
-    if i == 4: return t, p, v
-    return v, p, q
-
-
-# === Layout-Definitionen ===
-
-class Layout:
-    def __init__(self, name, count, center=None, ring=None):
-        self.name = name
-        self.count = count
-        self.center = center  # Index der Mitte (None bei Ring/Single)
-        self.ring = ring or list(range(count))  # Ring-Indizes
-
-LAYOUTS = {
-    "single":  Layout("Breakout 1x", 1, center=None, ring=[0]),
-    "jewel":   Layout("Jewel 7x", 7, center=0, ring=[1, 2, 3, 4, 5, 6]),
-    "ring12":  Layout("Ring 12x", 12, center=None, ring=list(range(12))),
-    "ring16":  Layout("Ring 16x", 16, center=None, ring=list(range(16))),
-    "ring24":  Layout("Ring 24x", 24, center=None, ring=list(range(24))),
-}
-
-
-# === Animationen ===
-
-def clear(strip):
-    """Alle LEDs aus."""
-    for i in range(strip.numPixels()):
-        strip.setPixelColor(i, Color(0, 0, 0))
-    strip.show()
-
-
-def test_single_color(strip, layout, color, name, duration=2.0):
-    """Alle LEDs eine Farbe."""
-    print(f"  {name}...", end="", flush=True)
-    for i in range(strip.numPixels()):
-        strip.setPixelColor(i, color)
-    strip.show()
-    time.sleep(duration)
-    clear(strip)
-    print(" OK")
-
-
-def test_blink(strip, layout, color, times=3, speed=0.2):
-    """Blinken."""
-    print(f"  Blink ({times}x)...", end="", flush=True)
-    for _ in range(times):
-        for i in range(strip.numPixels()):
-            strip.setPixelColor(i, color)
-        strip.show()
-        time.sleep(speed)
-        clear(strip)
-        time.sleep(speed)
-    print(" OK")
-
-
-def test_breathe(strip, layout, color, cycles=3, steps=60):
-    """Sanftes Atmen (Sinus-Kurve)."""
-    print(f"  Breathe ({cycles} Zyklen)...", end="", flush=True)
-    r = (color >> 16) & 0xFF
-    g = (color >> 8) & 0xFF
-    b = color & 0xFF
-
-    for cycle in range(cycles):
-        for step in range(steps):
-            brightness = (math.sin(step / steps * 2 * math.pi - math.pi / 2) + 1) / 2
-            cr = int(r * brightness)
-            cg = int(g * brightness)
-            cb = int(b * brightness)
-            for i in range(strip.numPixels()):
-                strip.setPixelColor(i, Color(cr, cg, cb))
-            strip.show()
-            time.sleep(0.03)
-    clear(strip)
-    print(" OK")
-
-
-def test_circulate(strip, layout, color, rounds=3, speed=0.08):
-    """Eine LED wandert im Kreis."""
-    if len(layout.ring) <= 1:
-        print("  Circulate (uebersprungen — nur 1 LED)")
-        return
-
-    print(f"  Circulate ({rounds} Runden)...", end="", flush=True)
-    center_color = Color(0, 30, 0)  # Mitte gedimmt gruen
-
-    for _ in range(rounds):
-        for pos in range(len(layout.ring)):
-            clear(strip)
-            # Mitte (Jewel)
-            if layout.center is not None:
-                strip.setPixelColor(layout.center, center_color)
-            # Aktive LED
-            strip.setPixelColor(layout.ring[pos], color)
-            strip.show()
-            time.sleep(speed)
-    clear(strip)
-    print(" OK")
-
-
-def test_circular_fade(strip, layout, color, rounds=3, tail=3, speed=0.06):
-    """Kreis mit Nachleuchten."""
-    ring = layout.ring
-    if len(ring) <= 1:
-        print("  Circular-Fade (uebersprungen — nur 1 LED)")
-        return
-
-    print(f"  Circular-Fade (tail={tail})...", end="", flush=True)
-    r = (color >> 16) & 0xFF
-    g = (color >> 8) & 0xFF
-    b = color & 0xFF
-
-    center_color = Color(0, 20, 0)
-
-    for _ in range(rounds):
-        for pos in range(len(ring)):
-            clear(strip)
-            if layout.center is not None:
-                strip.setPixelColor(layout.center, center_color)
-
-            # Haupt-LED
-            strip.setPixelColor(ring[pos], color)
-
-            # Nachleuchtende LEDs
-            for t in range(1, tail + 1):
-                fade = 1.0 - (t / (tail + 1))
-                fade_idx = (pos - t) % len(ring)
-                strip.setPixelColor(
-                    ring[fade_idx],
-                    Color(int(r * fade), int(g * fade), int(b * fade)),
-                )
-            strip.show()
-            time.sleep(speed)
-    clear(strip)
-    print(" OK")
-
-
-def test_rainbow(strip, layout, rounds=2, speed=0.02):
-    """Regenbogen-Rotation."""
-    print(f"  Rainbow ({rounds} Runden)...", end="", flush=True)
-    ring = layout.ring
-
-    for offset in range(rounds * len(ring) * 5):
-        for i, led_idx in enumerate(ring):
-            hue = ((i / len(ring)) + (offset / (len(ring) * 5))) % 1.0
-            r, g, b = hsv_to_rgb(hue, 1.0, 1.0)
-            strip.setPixelColor(led_idx, Color(r, g, b))
-        if layout.center is not None:
-            strip.setPixelColor(layout.center, Color(50, 50, 50))
-        strip.show()
-        time.sleep(speed)
-    clear(strip)
-    print(" OK")
-
-
-def test_chase(strip, layout, color, rounds=4, group=3, speed=0.06):
-    """Lauflicht (Gruppe von LEDs)."""
-    ring = layout.ring
-    if len(ring) <= 1:
-        print("  Chase (uebersprungen — nur 1 LED)")
-        return
-
-    print(f"  Chase ({group} LEDs Gruppe)...", end="", flush=True)
-    r = (color >> 16) & 0xFF
-    g = (color >> 8) & 0xFF
-    b = color & 0xFF
-
-    for _ in range(rounds):
-        for pos in range(len(ring)):
-            clear(strip)
-            if layout.center is not None:
-                strip.setPixelColor(layout.center, Color(0, 20, 0))
-            for j in range(group):
-                idx = (pos + j) % len(ring)
-                fade = 1.0 - (j / group) * 0.5
-                strip.setPixelColor(
-                    ring[idx],
-                    Color(int(r * fade), int(g * fade), int(b * fade)),
-                )
-            strip.show()
-            time.sleep(speed)
-    clear(strip)
-    print(" OK")
-
-
-def test_sparkle(strip, layout, color, duration=3.0, speed=0.05):
-    """Zufaelliges Funkeln."""
-    print(f"  Sparkle ({duration}s)...", end="", flush=True)
-    r = (color >> 16) & 0xFF
-    g = (color >> 8) & 0xFF
-    b = color & 0xFF
-
-    end_time = time.monotonic() + duration
-    while time.monotonic() < end_time:
-        clear(strip)
-        # 1-2 zufaellige LEDs
-        for _ in range(random.randint(1, min(3, strip.numPixels()))):
-            idx = random.choice(layout.ring)
-            strip.setPixelColor(idx, color)
-        if layout.center is not None:
-            strip.setPixelColor(layout.center, Color(r // 4, g // 4, b // 4))
-        strip.show()
-        time.sleep(speed)
-    clear(strip)
-    print(" OK")
-
-
-def test_wave(strip, layout, color, rounds=4, speed=0.03):
-    """Helligkeits-Welle (Knight Rider)."""
-    ring = layout.ring
-    if len(ring) <= 2:
-        print("  Wave (uebersprungen — zu wenige LEDs)")
-        return
-
-    print(f"  Wave (Knight Rider)...", end="", flush=True)
-    r = (color >> 16) & 0xFF
-    g = (color >> 8) & 0xFF
-    b = color & 0xFF
-
-    positions = list(range(len(ring))) + list(range(len(ring) - 2, 0, -1))
-
-    for _ in range(rounds):
-        for center_pos in positions:
-            for i, led_idx in enumerate(ring):
-                dist = abs(i - center_pos)
-                brightness = max(0, 1.0 - dist * 0.3)
-                brightness = brightness ** 2  # Quadratischer Abfall
-                strip.setPixelColor(
-                    led_idx,
-                    Color(int(r * brightness), int(g * brightness), int(b * brightness)),
-                )
-            if layout.center is not None:
-                strip.setPixelColor(layout.center, Color(r // 5, g // 5, b // 5))
-            strip.show()
-            time.sleep(speed)
-    clear(strip)
-    print(" OK")
-
-
-def test_fill_sequential(strip, layout, color, speed=0.1):
-    """LEDs nacheinander auffuellen."""
-    print(f"  Fill Sequential...", end="", flush=True)
-    clear(strip)
-
-    for led_idx in layout.ring:
-        strip.setPixelColor(led_idx, color)
-        strip.show()
-        time.sleep(speed)
-
-    if layout.center is not None:
-        strip.setPixelColor(layout.center, color)
-        strip.show()
-        time.sleep(speed)
-
-    time.sleep(0.5)
-    clear(strip)
-    print(" OK")
-
-
-def test_trixy_states(strip, layout):
-    """Simuliert die Trixy-Zustandsmaschine."""
-    print("\n=== Trixy-Zustandssimulation ===")
-
-    # Boot
-    print("  [BOOT] Gruen hell...")
-    test_single_color(strip, layout, rgb(0, 255, 0), "Boot", 1.5)
-
-    # Standby
-    print("  [STANDBY] Gruen gedimmt...")
-    test_single_color(strip, layout, rgb(0, 60, 0), "Standby", 2.0)
-
-    # Wakeword
-    print("  [WAKEWORD] 2x Blau blinken...")
-    test_blink(strip, layout, rgb(0, 0, 255), times=2, speed=0.15)
-
-    # Listening
-    print("  [LISTENING] Rot (Mikrofon aktiv)...")
-    test_single_color(strip, layout, rgb(255, 0, 0), "Listening", 2.0)
-
-    # Thinking
-    print("  [THINKING] Orange pulsierend...")
-    test_breathe(strip, layout, rgb(255, 165, 0).intColor if hasattr(rgb(255, 165, 0), 'intColor') else Color(255, 165, 0), cycles=2, steps=30)
-
-    # Speaking
-    print("  [SPEAKING] Blau atmend...")
-    test_breathe(strip, layout, Color(0, 100, 255), cycles=2, steps=60)
-
-    # Error
-    print("  [ERROR] 3x Rot blinken...")
-    test_blink(strip, layout, rgb(255, 0, 0), times=3, speed=0.15)
-
-    # Disconnect
-    print("  [DISCONNECT] Rot pulsierend...")
-    test_breathe(strip, layout, Color(255, 0, 0), cycles=2, steps=40)
-
-    # Zurueck zu Standby
-    print("  [STANDBY] Gruen gedimmt...")
-    test_single_color(strip, layout, rgb(0, 60, 0), "Standby", 1.0)
-
-    clear(strip)
-    print("  Simulation fertig!")
-
-
-# === Hauptprogramm ===
-
-def main():
-    parser = argparse.ArgumentParser(
-        description="WS2812/NeoPixel LED-Test fuer Raspberry Pi",
-        formatter_class=argparse.RawDescriptionHelpFormatter,
-        epilog="""
-Beispiele:
-  sudo python3 led_test.py --type jewel             # Jewel 7x testen
-  sudo python3 led_test.py --leds 12 --type ring12   # Ring 12x
-  sudo python3 led_test.py --leds 1 --type single    # Breakout 1x
-  sudo python3 led_test.py --type jewel --test states # Nur Trixy-Simulation
-  sudo python3 led_test.py --type jewel --brightness 50  # Niedrigere Helligkeit
-  sudo python3 led_test.py --pin 12 --type ring12    # Anderer GPIO Pin
-
-Verkabelung:
-  Pi GPIO 18 (Pin 12)  --[330 Ohm]--  DIN (Daten-Eingang)
-  Pi 5V (Pin 2 oder 4)  ------------  VCC (Strom)
-  Pi GND (Pin 6)         ------------  GND
-
-WICHTIG: Muss als root/sudo ausgefuehrt werden!
-        """,
-    )
-    parser.add_argument(
-        "--type", choices=list(LAYOUTS.keys()), default="jewel",
-        help="LED-Typ (default: jewel)",
-    )
-    parser.add_argument(
-        "--leds", type=int, default=0,
-        help="Anzahl LEDs (ueberschreibt --type Default)",
-    )
-    parser.add_argument(
-        "--pin", type=int, default=18,
-        help="GPIO BCM Pin (default: 18 = PWM0)",
-    )
-    parser.add_argument(
-        "--brightness", type=int, default=80,
-        help="Helligkeit 0-255 (default: 80)",
-    )
-    parser.add_argument(
-        "--test", choices=["all", "colors", "animations", "states"],
-        default="all",
-        help="Test-Modus (default: all)",
-    )
-    args = parser.parse_args()
-
-    layout = LAYOUTS[args.type]
-    led_count = args.leds if args.leds > 0 else layout.count
-
-    print(f"╔═══════════════════════════════════════════╗")
-    print(f"║       WS2812 LED Test — Trixy            ║")
-    print(f"╠═══════════════════════════════════════════╣")
-    print(f"║  Typ:        {layout.name:28s} ║")
-    print(f"║  LEDs:       {led_count:<28d} ║")
-    print(f"║  GPIO Pin:   {args.pin:<28d} ║")
-    print(f"║  Helligkeit: {args.brightness:<28d} ║")
-    print(f"╚═══════════════════════════════════════════╝")
-    print()
-
-    # LED-Strip initialisieren
-    strip = PixelStrip(
-        led_count, args.pin,
-        LED_FREQ_HZ, LED_DMA, LED_INVERT,
-        args.brightness, LED_CHANNEL,
-    )
-    strip.begin()
-
-    # SIGINT abfangen → LEDs aus
-    def cleanup(sig, frame):
-        print("\n\nAbbruch — LEDs werden ausgeschaltet...")
-        clear(strip)
-        sys.exit(0)
-    signal.signal(signal.SIGINT, cleanup)
-
-    try:
-        if args.test in ("all", "colors"):
-            print("=== Farbtest ===")
-            test_single_color(strip, layout, rgb(255, 0, 0), "Rot")
-            test_single_color(strip, layout, rgb(0, 255, 0), "Gruen")
-            test_single_color(strip, layout, rgb(0, 0, 255), "Blau")
-            test_single_color(strip, layout, rgb(255, 255, 0), "Gelb")
-            test_single_color(strip, layout, rgb(255, 0, 255), "Magenta")
-            test_single_color(strip, layout, rgb(0, 255, 255), "Cyan")
-            test_single_color(strip, layout, rgb(255, 255, 255), "Weiss")
-            test_single_color(strip, layout, rgb(255, 165, 0), "Orange")
-            print()
-
-        if args.test in ("all", "animations"):
-            print("=== Animationen ===")
-            test_blink(strip, layout, rgb(0, 0, 255), times=3)
-            test_breathe(strip, layout, Color(0, 100, 255), cycles=2)
-            test_circulate(strip, layout, rgb(0, 255, 0))
-            test_circular_fade(strip, layout, rgb(0, 0, 255), tail=3)
-            test_chase(strip, layout, rgb(255, 165, 0), group=3)
-            test_rainbow(strip, layout, rounds=2)
-            test_wave(strip, layout, rgb(255, 0, 0))
-            test_sparkle(strip, layout, rgb(255, 255, 255), duration=3.0)
-            test_fill_sequential(strip, layout, rgb(0, 255, 0))
-            print()
-
-        if args.test in ("all", "states"):
-            test_trixy_states(strip, layout)
-
-        print("\n✓ Alle Tests abgeschlossen!")
-
-    finally:
-        clear(strip)
-
-
-if __name__ == "__main__":
-    main()

+ 0 - 1
tools/led_test/requirements.txt

@@ -1 +0,0 @@
-rpi-ws281x