Rename patterns module to presets

Rename the driver module and update imports so tests and main entry use the new presets naming, while moving Preset to its own file.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-07 11:40:04 +13:00
parent f35d8f7084
commit 43957adb28
14 changed files with 253 additions and 225 deletions

View File

@@ -26,7 +26,7 @@ MicroPython-based LED driver application for ESP32 microcontrollers.
led-driver/ led-driver/
├── src/ ├── src/
│ ├── main.py # Main application code │ ├── main.py # Main application code
│ ├── patterns.py # LED pattern implementations (includes Preset and Patterns classes) │ ├── presets.py # LED pattern implementations (includes Preset and Presets classes)
│ ├── settings.py # Settings management │ ├── settings.py # Settings management
│ └── p2p.py # Peer-to-peer communication │ └── p2p.py # Peer-to-peer communication
├── test/ # Pattern tests ├── test/ # Pattern tests

View File

@@ -2,14 +2,14 @@ from settings import Settings
from machine import WDT from machine import WDT
from espnow import ESPNow from espnow import ESPNow
import network import network
from patterns import Patterns from presets import Presets
from utils import convert_and_reorder_colors from utils import convert_and_reorder_colors
import json import json
settings = Settings() settings = Settings()
print(settings) print(settings)
patterns = Patterns(settings["led_pin"], settings["num_leds"]) presets = Presets(settings["led_pin"], settings["num_leds"])
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
wdt.feed() wdt.feed()
@@ -24,7 +24,7 @@ e.active(True)
while True: while True:
wdt.feed() wdt.feed()
patterns.tick() presets.tick()
if e.any(): if e.any():
host, msg = e.recv() host, msg = e.recv()
data = json.loads(msg) data = json.loads(msg)
@@ -35,7 +35,7 @@ while True:
# Global brightness (0255) for this device # Global brightness (0255) for this device
if "b" in data: if "b" in data:
try: try:
patterns.b = max(0, min(255, int(data["b"]))) presets.b = max(0, min(255, int(data["b"])))
except (TypeError, ValueError): except (TypeError, ValueError):
pass pass
if "presets" in data: if "presets" in data:
@@ -43,11 +43,11 @@ while True:
# Convert hex color strings to RGB tuples and reorder based on device color order # Convert hex color strings to RGB tuples and reorder based on device color order
if "c" in preset_data: if "c" in preset_data:
preset_data["c"] = convert_and_reorder_colors(preset_data["c"], settings) preset_data["c"] = convert_and_reorder_colors(preset_data["c"], settings)
patterns.edit(name, preset_data) presets.edit(name, preset_data)
if settings.get("name") in data.get("select", {}): if settings.get("name") in data.get("select", {}):
select_list = data["select"][settings.get("name")] select_list = data["select"][settings.get("name")]
# Select value is always a list: ["preset_name"] or ["preset_name", step] # Select value is always a list: ["preset_name"] or ["preset_name", step]
if select_list: if select_list:
preset_name = select_list[0] preset_name = select_list[0]
step = select_list[1] if len(select_list) > 1 else None step = select_list[1] if len(select_list) > 1 else None
patterns.select(preset_name, step=step) presets.select(preset_name, step=step)

24
src/preset.py Normal file
View File

@@ -0,0 +1,24 @@
class Preset:
def __init__(self, data):
# Set default values for all preset attributes
self.p = "off"
self.d = 100
self.b = 127
self.c = [(255, 255, 255)]
self.a = True
self.n1 = 0
self.n2 = 0
self.n3 = 0
self.n4 = 0
self.n5 = 0
self.n6 = 0
# Override defaults with provided data
self.edit(data)
def edit(self, data=None):
if not data:
return False
for key, value in data.items():
setattr(self, key, value)
return True

View File

@@ -1,6 +1,7 @@
from machine import Pin from machine import Pin
from neopixel import NeoPixel from neopixel import NeoPixel
import utime import utime
from preset import Preset
# Short-key parameter mapping for convenience setters # Short-key parameter mapping for convenience setters
@@ -22,32 +23,7 @@ param_mapping = {
"auto": "auto", "auto": "auto",
} }
class Preset: class Presets:
def __init__(self, data):
# Set default values for all preset attributes
self.p = "off"
self.d = 100
self.b = 127
self.c = [(255, 255, 255)]
self.a = True
self.n1 = 0
self.n2 = 0
self.n3 = 0
self.n4 = 0
self.n5 = 0
self.n6 = 0
# Override defaults with provided data
self.edit(data)
def edit(self, data=None):
if not data:
return False
for key, value in data.items():
setattr(self, key, value)
return True
class Patterns:
def __init__(self, pin, num_leds): def __init__(self, pin, num_leds):
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds) self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds)
self.num_leds = num_leds self.num_leds = num_leds
@@ -154,16 +130,26 @@ class Patterns:
return (0, pos * 3, 255 - pos * 3) return (0, pos * 3, 255 - pos * 3)
def blink(self, preset): def blink(self, preset):
"""Blink pattern: toggles LEDs on/off using preset delay, cycling through colors."""
# Use provided colors, or default to white if none
colors = preset.c if preset.c else [(255, 255, 255)]
color_index = 0
state = True # True = on, False = off state = True # True = on, False = off
last_update = utime.ticks_ms() last_update = utime.ticks_ms()
while True: while True:
current_time = utime.ticks_ms() current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, last_update) >= preset.d: # Re-read delay each loop so live updates to preset.d take effect
delay_ms = max(1, int(preset.d))
if utime.ticks_diff(current_time, last_update) >= delay_ms:
if state: if state:
color = preset.c[0] if preset.c else (255, 255, 255) base_color = colors[color_index % len(colors)]
self.fill(self.apply_brightness(color, preset.b)) color = self.apply_brightness(base_color, preset.b)
self.fill(color)
# Advance to next color for the next "on" phase
color_index += 1
else: else:
# "Off" phase: turn all LEDs off
self.fill((0, 0, 0)) self.fill((0, 0, 0))
state = not state state = not state
last_update = current_time last_update = current_time
@@ -447,25 +433,41 @@ class Patterns:
last_tail_move = utime.ticks_ms() last_tail_move = utime.ticks_ms()
phase = "growing" # "growing", "shrinking", or "off" phase = "growing" # "growing", "shrinking", or "off"
# Support up to two colors (like chase). If only one color is provided,
# use black for the second; if none, default to white.
colors = preset.c colors = preset.c
color = self.apply_brightness(colors[0] if colors else (255, 255, 255), preset.b) if not colors:
base0 = base1 = (255, 255, 255)
elif len(colors) == 1:
base0 = colors[0]
base1 = (0, 0, 0)
else:
base0 = colors[0]
base1 = colors[1]
color0 = self.apply_brightness(base0, preset.b)
color1 = self.apply_brightness(base1, preset.b)
while True: while True:
current_time = utime.ticks_ms() current_time = utime.ticks_ms()
# Clear all LEDs # Background: use second color during the "off" phase, otherwise clear to black
self.n.fill((0, 0, 0)) if phase == "off":
self.n.fill(color1)
else:
self.n.fill((0, 0, 0))
# Calculate segment length # Calculate segment length
segment_length = (head - tail) % self.num_leds segment_length = (head - tail) % self.num_leds
if segment_length == 0 and head != tail: if segment_length == 0 and head != tail:
segment_length = self.num_leds segment_length = self.num_leds
# Draw segment from tail to head # Draw segment from tail to head as a solid color (no per-LED alternation)
current_color = color0
for i in range(segment_length + 1): for i in range(segment_length + 1):
led_pos = (tail + i) % self.num_leds led_pos = (tail + i) % self.num_leds
self.n[led_pos] = color self.n[led_pos] = current_color
# Move head continuously at n1 LEDs per second # Move head continuously at n1 LEDs per second
if utime.ticks_diff(current_time, last_head_move) >= head_delay: if utime.ticks_diff(current_time, last_head_move) >= head_delay:
@@ -494,7 +496,7 @@ class Patterns:
elif min_length > 0 and current_length <= min_length: elif min_length > 0 and current_length <= min_length:
phase = "growing" # Cycle repeats phase = "growing" # Cycle repeats
else: # phase == "off" else: # phase == "off"
# Off phase: all LEDs off for 1 step, then restart # Off phase: second color fills the ring for 1 step, then restart
tail = head # Reset tail to head position to start fresh tail = head # Reset tail to head position to start fresh
phase = "growing" phase = "growing"

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def run_for(p, wdt, duration_ms): def run_for(p, wdt, duration_ms):
@@ -19,7 +19,7 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
print("=" * 50) print("=" * 50)
@@ -29,11 +29,11 @@ def main():
# Test 1: Rainbow in AUTO mode (continuous) # Test 1: Rainbow in AUTO mode (continuous)
print("\nTest 1: Rainbow pattern in AUTO mode (should run continuously)") print("\nTest 1: Rainbow pattern in AUTO mode (should run continuously)")
p.edit("rainbow_auto", { p.edit("rainbow_auto", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 128, "b": 128,
"delay": 50, "d": 50,
"n1": 2, "n1": 2,
"auto": True "a": True,
}) })
p.select("rainbow_auto") p.select("rainbow_auto")
print("Running rainbow_auto for 3 seconds...") print("Running rainbow_auto for 3 seconds...")
@@ -43,11 +43,11 @@ def main():
# Test 2: Rainbow in MANUAL mode (one step per tick) # Test 2: Rainbow in MANUAL mode (one step per tick)
print("\nTest 2: Rainbow pattern in MANUAL mode (one step per tick)") print("\nTest 2: Rainbow pattern in MANUAL mode (one step per tick)")
p.edit("rainbow_manual", { p.edit("rainbow_manual", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 128, "b": 128,
"delay": 50, "d": 50,
"n1": 2, "n1": 2,
"auto": False "a": False,
}) })
p.select("rainbow_manual") p.select("rainbow_manual")
print("Calling tick() 5 times (should advance 5 steps)...") print("Calling tick() 5 times (should advance 5 steps)...")
@@ -65,14 +65,14 @@ def main():
# Test 3: Pulse in AUTO mode (continuous cycles) # Test 3: Pulse in AUTO mode (continuous cycles)
print("\nTest 3: Pulse pattern in AUTO mode (should pulse continuously)") print("\nTest 3: Pulse pattern in AUTO mode (should pulse continuously)")
p.edit("pulse_auto", { p.edit("pulse_auto", {
"pattern": "pulse", "p": "pulse",
"brightness": 128, "b": 128,
"delay": 100, "d": 100,
"n1": 500, # Attack "n1": 500, # Attack
"n2": 200, # Hold "n2": 200, # Hold
"n3": 500, # Decay "n3": 500, # Decay
"colors": [(255, 0, 0)], "c": [(255, 0, 0)],
"auto": True "a": True,
}) })
p.select("pulse_auto") p.select("pulse_auto")
print("Running pulse_auto for 3 seconds...") print("Running pulse_auto for 3 seconds...")
@@ -82,14 +82,14 @@ def main():
# Test 4: Pulse in MANUAL mode (one cycle then stop) # Test 4: Pulse in MANUAL mode (one cycle then stop)
print("\nTest 4: Pulse pattern in MANUAL mode (one cycle then stop)") print("\nTest 4: Pulse pattern in MANUAL mode (one cycle then stop)")
p.edit("pulse_manual", { p.edit("pulse_manual", {
"pattern": "pulse", "p": "pulse",
"brightness": 128, "b": 128,
"delay": 100, "d": 100,
"n1": 300, # Attack "n1": 300, # Attack
"n2": 200, # Hold "n2": 200, # Hold
"n3": 300, # Decay "n3": 300, # Decay
"colors": [(0, 255, 0)], "c": [(0, 255, 0)],
"auto": False "a": False,
}) })
p.select("pulse_manual") p.select("pulse_manual")
print("Running pulse_manual until generator stops...") print("Running pulse_manual until generator stops...")
@@ -108,11 +108,11 @@ def main():
# Test 5: Transition in AUTO mode (continuous transitions) # Test 5: Transition in AUTO mode (continuous transitions)
print("\nTest 5: Transition pattern in AUTO mode (continuous transitions)") print("\nTest 5: Transition pattern in AUTO mode (continuous transitions)")
p.edit("transition_auto", { p.edit("transition_auto", {
"pattern": "transition", "p": "transition",
"brightness": 128, "b": 128,
"delay": 500, "d": 500,
"colors": [(255, 0, 0), (0, 255, 0), (0, 0, 255)], "c": [(255, 0, 0), (0, 255, 0), (0, 0, 255)],
"auto": True "a": True,
}) })
p.select("transition_auto") p.select("transition_auto")
print("Running transition_auto for 3 seconds...") print("Running transition_auto for 3 seconds...")
@@ -122,11 +122,11 @@ def main():
# Test 6: Transition in MANUAL mode (one transition then stop) # Test 6: Transition in MANUAL mode (one transition then stop)
print("\nTest 6: Transition pattern in MANUAL mode (one transition then stop)") print("\nTest 6: Transition pattern in MANUAL mode (one transition then stop)")
p.edit("transition_manual", { p.edit("transition_manual", {
"pattern": "transition", "p": "transition",
"brightness": 128, "b": 128,
"delay": 500, "d": 500,
"colors": [(255, 0, 0), (0, 255, 0)], "c": [(255, 0, 0), (0, 255, 0)],
"auto": False "a": False,
}) })
p.select("transition_manual") p.select("transition_manual")
print("Running transition_manual until generator stops...") print("Running transition_manual until generator stops...")
@@ -145,11 +145,11 @@ def main():
# Test 7: Switching between auto and manual modes # Test 7: Switching between auto and manual modes
print("\nTest 7: Switching between auto and manual modes") print("\nTest 7: Switching between auto and manual modes")
p.edit("switch_test", { p.edit("switch_test", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 128, "b": 128,
"delay": 50, "d": 50,
"n1": 2, "n1": 2,
"auto": True "a": True,
}) })
p.select("switch_test") p.select("switch_test")
print("Running in auto mode for 1 second...") print("Running in auto mode for 1 second...")
@@ -157,7 +157,7 @@ def main():
# Switch to manual mode by editing the preset # Switch to manual mode by editing the preset
print("Switching to manual mode...") print("Switching to manual mode...")
p.edit("switch_test", {"auto": False}) p.edit("switch_test", {"a": False})
p.select("switch_test") # Re-select to apply changes p.select("switch_test") # Re-select to apply changes
print("Calling tick() 3 times in manual mode...") print("Calling tick() 3 times in manual mode...")
@@ -168,7 +168,7 @@ def main():
# Switch back to auto mode # Switch back to auto mode
print("Switching back to auto mode...") print("Switching back to auto mode...")
p.edit("switch_test", {"auto": True}) p.edit("switch_test", {"a": True})
p.select("switch_test") p.select("switch_test")
print("Running in auto mode for 1 second...") print("Running in auto mode for 1 second...")
run_for(p, wdt, 1000) run_for(p, wdt, 1000)
@@ -176,7 +176,7 @@ def main():
# Cleanup # Cleanup
print("\nCleaning up...") print("\nCleaning up...")
p.edit("cleanup_off", {"pattern": "off"}) p.edit("cleanup_off", {"p": "off"})
p.select("cleanup_off") p.select("cleanup_off")
p.tick() p.tick()
utime.sleep_ms(100) utime.sleep_ms(100)

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def main(): def main():
@@ -10,15 +10,15 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Create blink preset # Create blink preset (use short-key fields: p=pattern, b=brightness, d=delay, c=colors)
p.edit("test_blink", { p.edit("test_blink", {
"pattern": "blink", "p": "blink",
"brightness": 64, "b": 64,
"delay": 200, "d": 200,
"colors": [(255, 0, 0), (0, 0, 255)] "c": [(255, 0, 0), (0, 0, 255)],
}) })
p.select("test_blink") p.select("test_blink")

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def run_for(p, wdt, ms): def run_for(p, wdt, ms):
@@ -19,20 +19,20 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Test 1: Basic chase (n1=5, n2=5, n3=1, n4=1) # Test 1: Basic chase (n1=5, n2=5, n3=1, n4=1)
print("Test 1: Basic chase (n1=5, n2=5, n3=1, n4=1)") print("Test 1: Basic chase (n1=5, n2=5, n3=1, n4=1)")
p.edit("chase1", { p.edit("chase1", {
"pattern": "chase", "p": "chase",
"brightness": 255, "b": 255,
"delay": 200, "d": 200,
"n1": 5, "n1": 5,
"n2": 5, "n2": 5,
"n3": 1, "n3": 1,
"n4": 1, "n4": 1,
"colors": [(255, 0, 0), (0, 255, 0)] "c": [(255, 0, 0), (0, 255, 0)],
}) })
p.select("chase1") p.select("chase1")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -40,13 +40,13 @@ def main():
# Test 2: Forward and backward (n3=2, n4=-1) # Test 2: Forward and backward (n3=2, n4=-1)
print("Test 2: Forward and backward (n3=2, n4=-1)") print("Test 2: Forward and backward (n3=2, n4=-1)")
p.edit("chase2", { p.edit("chase2", {
"pattern": "chase", "p": "chase",
"n1": 3, "n1": 3,
"n2": 3, "n2": 3,
"n3": 2, "n3": 2,
"n4": -1, "n4": -1,
"delay": 150, "d": 150,
"colors": [(0, 0, 255), (255, 255, 0)] "c": [(0, 0, 255), (255, 255, 0)],
}) })
p.select("chase2") p.select("chase2")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -54,13 +54,13 @@ def main():
# Test 3: Large segments (n1=10, n2=5) # Test 3: Large segments (n1=10, n2=5)
print("Test 3: Large segments (n1=10, n2=5, n3=3, n4=3)") print("Test 3: Large segments (n1=10, n2=5, n3=3, n4=3)")
p.edit("chase3", { p.edit("chase3", {
"pattern": "chase", "p": "chase",
"n1": 10, "n1": 10,
"n2": 5, "n2": 5,
"n3": 3, "n3": 3,
"n4": 3, "n4": 3,
"delay": 200, "d": 200,
"colors": [(255, 128, 0), (128, 0, 255)] "c": [(255, 128, 0), (128, 0, 255)],
}) })
p.select("chase3") p.select("chase3")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -68,13 +68,13 @@ def main():
# Test 4: Fast movement (n3=5, n4=5) # Test 4: Fast movement (n3=5, n4=5)
print("Test 4: Fast movement (n3=5, n4=5)") print("Test 4: Fast movement (n3=5, n4=5)")
p.edit("chase4", { p.edit("chase4", {
"pattern": "chase", "p": "chase",
"n1": 4, "n1": 4,
"n2": 4, "n2": 4,
"n3": 5, "n3": 5,
"n4": 5, "n4": 5,
"delay": 100, "d": 100,
"colors": [(255, 0, 255), (0, 255, 255)] "c": [(255, 0, 255), (0, 255, 255)],
}) })
p.select("chase4") p.select("chase4")
run_for(p, wdt, 2000) run_for(p, wdt, 2000)
@@ -82,13 +82,13 @@ def main():
# Test 5: Backward movement (n3=-2, n4=-2) # Test 5: Backward movement (n3=-2, n4=-2)
print("Test 5: Backward movement (n3=-2, n4=-2)") print("Test 5: Backward movement (n3=-2, n4=-2)")
p.edit("chase5", { p.edit("chase5", {
"pattern": "chase", "p": "chase",
"n1": 6, "n1": 6,
"n2": 4, "n2": 4,
"n3": -2, "n3": -2,
"n4": -2, "n4": -2,
"delay": 200, "d": 200,
"colors": [(255, 255, 255), (0, 0, 0)] "c": [(255, 255, 255), (0, 0, 0)],
}) })
p.select("chase5") p.select("chase5")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -96,13 +96,13 @@ def main():
# Test 6: Alternating forward/backward (n3=3, n4=-2) # Test 6: Alternating forward/backward (n3=3, n4=-2)
print("Test 6: Alternating forward/backward (n3=3, n4=-2)") print("Test 6: Alternating forward/backward (n3=3, n4=-2)")
p.edit("chase6", { p.edit("chase6", {
"pattern": "chase", "p": "chase",
"n1": 5, "n1": 5,
"n2": 5, "n2": 5,
"n3": 3, "n3": 3,
"n4": -2, "n4": -2,
"delay": 250, "d": 250,
"colors": [(255, 0, 0), (0, 255, 0)] "c": [(255, 0, 0), (0, 255, 0)],
}) })
p.select("chase6") p.select("chase6")
run_for(p, wdt, 4000) run_for(p, wdt, 4000)
@@ -110,14 +110,14 @@ def main():
# Test 7: Manual mode - advance one step per beat # Test 7: Manual mode - advance one step per beat
print("Test 7: Manual mode chase (auto=False, n3=2, n4=1)") print("Test 7: Manual mode chase (auto=False, n3=2, n4=1)")
p.edit("chase_manual", { p.edit("chase_manual", {
"pattern": "chase", "p": "chase",
"n1": 4, "n1": 4,
"n2": 4, "n2": 4,
"n3": 2, "n3": 2,
"n4": 1, "n4": 1,
"delay": 200, "d": 200,
"colors": [(255, 255, 0), (0, 255, 255)], "c": [(255, 255, 0), (0, 255, 255)],
"auto": False "a": False,
}) })
p.step = 0 # Reset step counter p.step = 0 # Reset step counter
print(" Advancing pattern with 10 beats (select + tick)...") print(" Advancing pattern with 10 beats (select + tick)...")
@@ -131,12 +131,12 @@ def main():
# Test 8: Verify step increments correctly in manual mode # Test 8: Verify step increments correctly in manual mode
print("Test 8: Verify step increments (auto=False)") print("Test 8: Verify step increments (auto=False)")
p.edit("chase_manual2", { p.edit("chase_manual2", {
"pattern": "chase", "p": "chase",
"n1": 3, "n1": 3,
"n2": 3, "n2": 3,
"n3": 1, "n3": 1,
"n4": 1, "n4": 1,
"auto": False "a": False,
}) })
p.step = 0 p.step = 0
initial_step = p.step initial_step = p.step
@@ -151,7 +151,7 @@ def main():
# Cleanup # Cleanup
print("Test complete, turning off") print("Test complete, turning off")
p.edit("cleanup_off", {"pattern": "off"}) p.edit("cleanup_off", {"p": "off"})
p.select("cleanup_off") p.select("cleanup_off")
run_for(p, wdt, 100) run_for(p, wdt, 100)

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def run_for(p, wdt, ms): def run_for(p, wdt, ms):
@@ -19,19 +19,19 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Test 1: Basic circle (n1=50, n2=100, n3=200, n4=0) # Test 1: Basic circle (n1=50, n2=100, n3=200, n4=0)
print("Test 1: Basic circle (n1=50, n2=100, n3=200, n4=0)") print("Test 1: Basic circle (n1=50, n2=100, n3=200, n4=0)")
p.edit("circle1", { p.edit("circle1", {
"pattern": "circle", "p": "circle",
"brightness": 255, "b": 255,
"n1": 50, # Head moves 50 LEDs/second "n1": 50, # Head moves 50 LEDs/second
"n2": 100, # Max length 100 LEDs "n2": 100, # Max length 100 LEDs
"n3": 200, # Tail moves 200 LEDs/second "n3": 200, # Tail moves 200 LEDs/second
"n4": 0, # Min length 0 LEDs "n4": 0, # Min length 0 LEDs
"colors": [(255, 0, 0)] # Red "c": [(255, 0, 0)], # Red
}) })
p.select("circle1") p.select("circle1")
run_for(p, wdt, 5000) run_for(p, wdt, 5000)
@@ -39,12 +39,12 @@ def main():
# Test 2: Slow growth, fast shrink (n1=20, n2=50, n3=100, n4=0) # Test 2: Slow growth, fast shrink (n1=20, n2=50, n3=100, n4=0)
print("Test 2: Slow growth, fast shrink (n1=20, n2=50, n3=100, n4=0)") print("Test 2: Slow growth, fast shrink (n1=20, n2=50, n3=100, n4=0)")
p.edit("circle2", { p.edit("circle2", {
"pattern": "circle", "p": "circle",
"n1": 20, "n1": 20,
"n2": 50, "n2": 50,
"n3": 100, "n3": 100,
"n4": 0, "n4": 0,
"colors": [(0, 255, 0)] # Green "c": [(0, 255, 0)], # Green
}) })
p.select("circle2") p.select("circle2")
run_for(p, wdt, 5000) run_for(p, wdt, 5000)
@@ -52,12 +52,12 @@ def main():
# Test 3: Fast growth, slow shrink (n1=100, n2=30, n3=20, n4=0) # Test 3: Fast growth, slow shrink (n1=100, n2=30, n3=20, n4=0)
print("Test 3: Fast growth, slow shrink (n1=100, n2=30, n3=20, n4=0)") print("Test 3: Fast growth, slow shrink (n1=100, n2=30, n3=20, n4=0)")
p.edit("circle3", { p.edit("circle3", {
"pattern": "circle", "p": "circle",
"n1": 100, "n1": 100,
"n2": 30, "n2": 30,
"n3": 20, "n3": 20,
"n4": 0, "n4": 0,
"colors": [(0, 0, 255)] # Blue "c": [(0, 0, 255)], # Blue
}) })
p.select("circle3") p.select("circle3")
run_for(p, wdt, 5000) run_for(p, wdt, 5000)
@@ -65,12 +65,12 @@ def main():
# Test 4: With minimum length (n1=50, n2=40, n3=100, n4=10) # Test 4: With minimum length (n1=50, n2=40, n3=100, n4=10)
print("Test 4: With minimum length (n1=50, n2=40, n3=100, n4=10)") print("Test 4: With minimum length (n1=50, n2=40, n3=100, n4=10)")
p.edit("circle4", { p.edit("circle4", {
"pattern": "circle", "p": "circle",
"n1": 50, "n1": 50,
"n2": 40, "n2": 40,
"n3": 100, "n3": 100,
"n4": 10, "n4": 10,
"colors": [(255, 255, 0)] # Yellow "c": [(255, 255, 0)], # Yellow
}) })
p.select("circle4") p.select("circle4")
run_for(p, wdt, 5000) run_for(p, wdt, 5000)
@@ -78,12 +78,12 @@ def main():
# Test 5: Very fast (n1=200, n2=20, n3=200, n4=0) # Test 5: Very fast (n1=200, n2=20, n3=200, n4=0)
print("Test 5: Very fast (n1=200, n2=20, n3=200, n4=0)") print("Test 5: Very fast (n1=200, n2=20, n3=200, n4=0)")
p.edit("circle5", { p.edit("circle5", {
"pattern": "circle", "p": "circle",
"n1": 200, "n1": 200,
"n2": 20, "n2": 20,
"n3": 200, "n3": 200,
"n4": 0, "n4": 0,
"colors": [(255, 0, 255)] # Magenta "c": [(255, 0, 255)], # Magenta
}) })
p.select("circle5") p.select("circle5")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -91,19 +91,19 @@ def main():
# Test 6: Very slow (n1=10, n2=25, n3=10, n4=0) # Test 6: Very slow (n1=10, n2=25, n3=10, n4=0)
print("Test 6: Very slow (n1=10, n2=25, n3=10, n4=0)") print("Test 6: Very slow (n1=10, n2=25, n3=10, n4=0)")
p.edit("circle6", { p.edit("circle6", {
"pattern": "circle", "p": "circle",
"n1": 10, "n1": 10,
"n2": 25, "n2": 25,
"n3": 10, "n3": 10,
"n4": 0, "n4": 0,
"colors": [(0, 255, 255)] # Cyan "c": [(0, 255, 255)], # Cyan
}) })
p.select("circle6") p.select("circle6")
run_for(p, wdt, 5000) run_for(p, wdt, 5000)
# Cleanup # Cleanup
print("Test complete, turning off") print("Test complete, turning off")
p.edit("cleanup_off", {"pattern": "off"}) p.edit("cleanup_off", {"p": "off"})
p.select("cleanup_off") p.select("cleanup_off")
run_for(p, wdt, 100) run_for(p, wdt, 100)

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def main(): def main():
@@ -10,11 +10,11 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Create an "off" preset # Create an "off" preset (use short-key field `p` for pattern)
p.edit("test_off", {"pattern": "off"}) p.edit("test_off", {"p": "off"})
p.select("test_off") p.select("test_off")
start = utime.ticks_ms() start = utime.ticks_ms()

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def main(): def main():
@@ -10,17 +10,19 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Create presets for on and off # Create presets for on and off using the short-key fields that Presets expects
# Preset fields:
# p = pattern name, b = brightness, d = delay, c = list of (r,g,b) colors
p.edit("test_on", { p.edit("test_on", {
"pattern": "on", "p": "on",
"brightness": 64, "b": 64,
"delay": 120, "d": 120,
"colors": [(255, 0, 0), (0, 0, 255)] "c": [(255, 0, 0), (0, 0, 255)],
}) })
p.edit("test_off", {"pattern": "off"}) p.edit("test_off", {"p": "off"})
# ON phase # ON phase
p.select("test_on") p.select("test_on")

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def run_for(p, wdt, ms): def run_for(p, wdt, ms):
@@ -19,20 +19,20 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Test 1: Simple single-color pulse # Test 1: Simple single-color pulse
print("Test 1: Single-color pulse (attack=500, hold=500, decay=500, delay=500)") print("Test 1: Single-color pulse (attack=500, hold=500, decay=500, delay=500)")
p.edit("pulse1", { p.edit("pulse1", {
"pattern": "pulse", "p": "pulse",
"brightness": 255, "b": 255,
"colors": [(255, 0, 0)], "c": [(255, 0, 0)],
"n1": 500, # attack ms "n1": 500, # attack ms
"n2": 500, # hold ms "n2": 500, # hold ms
"n3": 500, # decay ms "n3": 500, # decay ms
"delay": 500, # delay ms between pulses "d": 500, # delay ms between pulses
"auto": True "a": True,
}) })
p.select("pulse1") p.select("pulse1")
run_for(p, wdt, 5000) run_for(p, wdt, 5000)
@@ -40,12 +40,12 @@ def main():
# Test 2: Faster pulse # Test 2: Faster pulse
print("Test 2: Fast pulse (attack=100, hold=100, decay=100, delay=100)") print("Test 2: Fast pulse (attack=100, hold=100, decay=100, delay=100)")
p.edit("pulse2", { p.edit("pulse2", {
"pattern": "pulse", "p": "pulse",
"n1": 100, "n1": 100,
"n2": 100, "n2": 100,
"n3": 100, "n3": 100,
"delay": 100, "d": 100,
"colors": [(0, 255, 0)] "c": [(0, 255, 0)],
}) })
p.select("pulse2") p.select("pulse2")
run_for(p, wdt, 4000) run_for(p, wdt, 4000)
@@ -53,13 +53,13 @@ def main():
# Test 3: Multi-color pulse cycle # Test 3: Multi-color pulse cycle
print("Test 3: Multi-color pulse (red -> green -> blue)") print("Test 3: Multi-color pulse (red -> green -> blue)")
p.edit("pulse3", { p.edit("pulse3", {
"pattern": "pulse", "p": "pulse",
"n1": 300, "n1": 300,
"n2": 300, "n2": 300,
"n3": 300, "n3": 300,
"delay": 200, "d": 200,
"colors": [(255, 0, 0), (0, 255, 0), (0, 0, 255)], "c": [(255, 0, 0), (0, 255, 0), (0, 0, 255)],
"auto": True "a": True,
}) })
p.select("pulse3") p.select("pulse3")
run_for(p, wdt, 6000) run_for(p, wdt, 6000)
@@ -67,13 +67,13 @@ def main():
# Test 4: One-shot pulse (auto=False) # Test 4: One-shot pulse (auto=False)
print("Test 4: Single pulse, auto=False") print("Test 4: Single pulse, auto=False")
p.edit("pulse4", { p.edit("pulse4", {
"pattern": "pulse", "p": "pulse",
"n1": 400, "n1": 400,
"n2": 0, "n2": 0,
"n3": 400, "n3": 400,
"delay": 0, "d": 0,
"colors": [(255, 255, 255)], "c": [(255, 255, 255)],
"auto": False "a": False,
}) })
p.select("pulse4") p.select("pulse4")
# Run long enough to allow one full pulse cycle # Run long enough to allow one full pulse cycle
@@ -81,7 +81,7 @@ def main():
# Cleanup # Cleanup
print("Test complete, turning off") print("Test complete, turning off")
p.edit("cleanup_off", {"pattern": "off"}) p.edit("cleanup_off", {"p": "off"})
p.select("cleanup_off") p.select("cleanup_off")
run_for(p, wdt, 200) run_for(p, wdt, 200)

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def run_for(p, wdt, ms): def run_for(p, wdt, ms):
@@ -19,17 +19,17 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Test 1: Basic rainbow with auto=True (continuous) # Test 1: Basic rainbow with auto=True (continuous)
print("Test 1: Basic rainbow (auto=True, n1=1)") print("Test 1: Basic rainbow (auto=True, n1=1)")
p.edit("rainbow1", { p.edit("rainbow1", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 255, "b": 255,
"delay": 100, "d": 100,
"n1": 1, "n1": 1,
"auto": True "a": True,
}) })
p.select("rainbow1") p.select("rainbow1")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -37,10 +37,10 @@ def main():
# Test 2: Fast rainbow # Test 2: Fast rainbow
print("Test 2: Fast rainbow (low delay, n1=1)") print("Test 2: Fast rainbow (low delay, n1=1)")
p.edit("rainbow2", { p.edit("rainbow2", {
"pattern": "rainbow", "p": "rainbow",
"delay": 50, "d": 50,
"n1": 1, "n1": 1,
"auto": True "a": True,
}) })
p.select("rainbow2") p.select("rainbow2")
run_for(p, wdt, 2000) run_for(p, wdt, 2000)
@@ -48,10 +48,10 @@ def main():
# Test 3: Slow rainbow # Test 3: Slow rainbow
print("Test 3: Slow rainbow (high delay, n1=1)") print("Test 3: Slow rainbow (high delay, n1=1)")
p.edit("rainbow3", { p.edit("rainbow3", {
"pattern": "rainbow", "p": "rainbow",
"delay": 500, "d": 500,
"n1": 1, "n1": 1,
"auto": True "a": True,
}) })
p.select("rainbow3") p.select("rainbow3")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
@@ -59,11 +59,11 @@ def main():
# Test 4: Low brightness rainbow # Test 4: Low brightness rainbow
print("Test 4: Low brightness rainbow (n1=1)") print("Test 4: Low brightness rainbow (n1=1)")
p.edit("rainbow4", { p.edit("rainbow4", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 64, "b": 64,
"delay": 100, "d": 100,
"n1": 1, "n1": 1,
"auto": True "a": True,
}) })
p.select("rainbow4") p.select("rainbow4")
run_for(p, wdt, 2000) run_for(p, wdt, 2000)
@@ -71,11 +71,11 @@ def main():
# Test 5: Single-step rainbow (auto=False) # Test 5: Single-step rainbow (auto=False)
print("Test 5: Single-step rainbow (auto=False, n1=1)") print("Test 5: Single-step rainbow (auto=False, n1=1)")
p.edit("rainbow5", { p.edit("rainbow5", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 255, "b": 255,
"delay": 100, "d": 100,
"n1": 1, "n1": 1,
"auto": False "a": False,
}) })
p.step = 0 p.step = 0
for i in range(10): for i in range(10):
@@ -88,9 +88,9 @@ def main():
# Test 6: Verify step updates correctly # Test 6: Verify step updates correctly
print("Test 6: Verify step updates (auto=False, n1=1)") print("Test 6: Verify step updates (auto=False, n1=1)")
p.edit("rainbow6", { p.edit("rainbow6", {
"pattern": "rainbow", "p": "rainbow",
"n1": 1, "n1": 1,
"auto": False "a": False,
}) })
initial_step = p.step initial_step = p.step
p.select("rainbow6") p.select("rainbow6")
@@ -101,11 +101,11 @@ def main():
# Test 7: Fast step increment (n1=5) # Test 7: Fast step increment (n1=5)
print("Test 7: Fast rainbow (n1=5, auto=True)") print("Test 7: Fast rainbow (n1=5, auto=True)")
p.edit("rainbow7", { p.edit("rainbow7", {
"pattern": "rainbow", "p": "rainbow",
"brightness": 255, "b": 255,
"delay": 100, "d": 100,
"n1": 5, "n1": 5,
"auto": True "a": True,
}) })
p.select("rainbow7") p.select("rainbow7")
run_for(p, wdt, 2000) run_for(p, wdt, 2000)
@@ -113,9 +113,9 @@ def main():
# Test 8: Very fast step increment (n1=10) # Test 8: Very fast step increment (n1=10)
print("Test 8: Very fast rainbow (n1=10, auto=True)") print("Test 8: Very fast rainbow (n1=10, auto=True)")
p.edit("rainbow8", { p.edit("rainbow8", {
"pattern": "rainbow", "p": "rainbow",
"n1": 10, "n1": 10,
"auto": True "a": True,
}) })
p.select("rainbow8") p.select("rainbow8")
run_for(p, wdt, 2000) run_for(p, wdt, 2000)
@@ -123,9 +123,9 @@ def main():
# Test 9: Verify n1 controls step increment (auto=False) # Test 9: Verify n1 controls step increment (auto=False)
print("Test 9: Verify n1 step increment (auto=False, n1=5)") print("Test 9: Verify n1 step increment (auto=False, n1=5)")
p.edit("rainbow9", { p.edit("rainbow9", {
"pattern": "rainbow", "p": "rainbow",
"n1": 5, "n1": 5,
"auto": False "a": False,
}) })
p.step = 0 p.step = 0
initial_step = p.step initial_step = p.step
@@ -141,7 +141,7 @@ def main():
# Cleanup # Cleanup
print("Test complete, turning off") print("Test complete, turning off")
p.edit("cleanup_off", {"pattern": "off"}) p.edit("cleanup_off", {"p": "off"})
p.select("cleanup_off") p.select("cleanup_off")
run_for(p, wdt, 100) run_for(p, wdt, 100)

View File

@@ -2,7 +2,7 @@
import utime import utime
from machine import WDT from machine import WDT
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
def run_for(p, wdt, ms): def run_for(p, wdt, ms):
@@ -19,17 +19,17 @@ def main():
pin = s.get("led_pin", 10) pin = s.get("led_pin", 10)
num = s.get("num_leds", 30) num = s.get("num_leds", 30)
p = Patterns(pin=pin, num_leds=num) p = Presets(pin=pin, num_leds=num)
wdt = WDT(timeout=10000) wdt = WDT(timeout=10000)
# Test 1: Simple two-color transition # Test 1: Simple two-color transition
print("Test 1: Two-color transition (red <-> blue, delay=1000)") print("Test 1: Two-color transition (red <-> blue, delay=1000)")
p.edit("transition1", { p.edit("transition1", {
"pattern": "transition", "p": "transition",
"brightness": 255, "b": 255,
"delay": 1000, # transition duration "d": 1000, # transition duration
"colors": [(255, 0, 0), (0, 0, 255)], "c": [(255, 0, 0), (0, 0, 255)],
"auto": True "a": True,
}) })
p.select("transition1") p.select("transition1")
run_for(p, wdt, 6000) run_for(p, wdt, 6000)
@@ -37,10 +37,10 @@ def main():
# Test 2: Multi-color transition # Test 2: Multi-color transition
print("Test 2: Multi-color transition (red -> green -> blue -> white)") print("Test 2: Multi-color transition (red -> green -> blue -> white)")
p.edit("transition2", { p.edit("transition2", {
"pattern": "transition", "p": "transition",
"delay": 800, "d": 800,
"colors": [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 255)], "c": [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 255)],
"auto": True "a": True,
}) })
p.select("transition2") p.select("transition2")
run_for(p, wdt, 8000) run_for(p, wdt, 8000)
@@ -48,10 +48,10 @@ def main():
# Test 3: One-shot transition (auto=False) # Test 3: One-shot transition (auto=False)
print("Test 3: One-shot transition (auto=False)") print("Test 3: One-shot transition (auto=False)")
p.edit("transition3", { p.edit("transition3", {
"pattern": "transition", "p": "transition",
"delay": 1000, "d": 1000,
"colors": [(255, 0, 0), (0, 255, 0)], "c": [(255, 0, 0), (0, 255, 0)],
"auto": False "a": False,
}) })
p.select("transition3") p.select("transition3")
# Run long enough for a single transition step # Run long enough for a single transition step
@@ -60,17 +60,17 @@ def main():
# Test 4: Single-color behavior (should just stay on) # Test 4: Single-color behavior (should just stay on)
print("Test 4: Single-color transition (should hold color)") print("Test 4: Single-color transition (should hold color)")
p.edit("transition4", { p.edit("transition4", {
"pattern": "transition", "p": "transition",
"colors": [(0, 0, 255)], "c": [(0, 0, 255)],
"delay": 500, "d": 500,
"auto": True "a": True,
}) })
p.select("transition4") p.select("transition4")
run_for(p, wdt, 3000) run_for(p, wdt, 3000)
# Cleanup # Cleanup
print("Test complete, turning off") print("Test complete, turning off")
p.edit("cleanup_off", {"pattern": "off"}) p.edit("cleanup_off", {"p": "off"})
p.select("cleanup_off") p.select("cleanup_off")
run_for(p, wdt, 200) run_for(p, wdt, 200)

View File

@@ -3,7 +3,7 @@
import json import json
import utime import utime
from settings import Settings from settings import Settings
from patterns import Patterns from presets import Presets
from utils import convert_and_reorder_colors from utils import convert_and_reorder_colors
@@ -93,7 +93,7 @@ def test_version_check():
"""Test that messages with wrong version are rejected.""" """Test that messages with wrong version are rejected."""
print("Test 1: Version check") print("Test 1: Version check")
settings = Settings() settings = Settings()
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -119,7 +119,7 @@ def test_preset_creation():
"""Test preset creation from ESPNow messages.""" """Test preset creation from ESPNow messages."""
print("\nTest 2: Preset creation") print("\nTest 2: Preset creation")
settings = Settings() settings = Settings()
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -164,7 +164,7 @@ def test_color_conversion():
print("\nTest 3: Color conversion") print("\nTest 3: Color conversion")
settings = Settings() settings = Settings()
settings["color_order"] = "rgb" # Default RGB order settings["color_order"] = "rgb" # Default RGB order
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -190,7 +190,7 @@ def test_color_conversion():
# Test GRB order # Test GRB order
settings["color_order"] = "grb" settings["color_order"] = "grb"
patterns2 = Patterns(settings["led_pin"], settings["num_leds"]) patterns2 = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow2 = MockESPNow() mock_espnow2 = MockESPNow()
msg2 = { msg2 = {
"v": "1", "v": "1",
@@ -213,7 +213,7 @@ def test_preset_update():
"""Test that editing an existing preset updates it.""" """Test that editing an existing preset updates it."""
print("\nTest 4: Preset update") print("\nTest 4: Preset update")
settings = Settings() settings = Settings()
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -256,7 +256,7 @@ def test_select():
print("\nTest 5: Preset selection") print("\nTest 5: Preset selection")
settings = Settings() settings = Settings()
settings["name"] = "device1" settings["name"] = "device1"
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -291,7 +291,7 @@ def test_full_message():
print("\nTest 6: Full message (presets + select)") print("\nTest 6: Full message (presets + select)")
settings = Settings() settings = Settings()
settings["name"] = "test_device" settings["name"] = "test_device"
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -331,7 +331,7 @@ def test_switch_presets():
print("\nTest 7: Switch between presets") print("\nTest 7: Switch between presets")
settings = Settings() settings = Settings()
settings["name"] = "switch_device" settings["name"] = "switch_device"
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -427,7 +427,7 @@ def test_beat_functionality():
print("\nTest 8: Beat functionality") print("\nTest 8: Beat functionality")
settings = Settings() settings = Settings()
settings["name"] = "beat_device" settings["name"] = "beat_device"
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -551,7 +551,7 @@ def test_select_with_step():
print("\nTest 9: Select with step value") print("\nTest 9: Select with step value")
settings = Settings() settings = Settings()
settings["name"] = "step_device" settings["name"] = "step_device"
patterns = Patterns(settings["led_pin"], settings["num_leds"]) patterns = Presets(settings["led_pin"], settings["num_leds"])
mock_espnow = MockESPNow() mock_espnow = MockESPNow()
wdt = get_wdt() wdt = get_wdt()
@@ -602,7 +602,7 @@ def test_select_with_step():
print(" ✓ Step preserved when selecting same preset without step (tick advances it)") print(" ✓ Step preserved when selecting same preset without step (tick advances it)")
# Select different preset with step # Select different preset with step
patterns.edit("other_preset", {"pattern": "rainbow", "auto": False}) patterns.edit("other_preset", {"p": "rainbow", "a": False})
mock_espnow.clear() mock_espnow.clear()
msg4 = { msg4 = {
"v": "1", "v": "1",