Use shortened preset fields in driver

Switch led-driver patterns and main loop to use compact preset keys (p, d, b, c, a, n1..n6) and remove unused settings defaults.
This commit is contained in:
2026-01-28 23:28:54 +13:00
parent 02db2b629c
commit 337e8c9906
3 changed files with 47 additions and 49 deletions

View File

@@ -9,7 +9,7 @@ import json
settings = Settings()
print(settings)
patterns = Patterns(settings["led_pin"], settings["num_leds"], selected=settings["pattern"])
patterns = Patterns(settings["led_pin"], settings["num_leds"])
wdt = WDT(timeout=10000)
wdt.feed()
@@ -30,11 +30,12 @@ while True:
data = json.loads(msg)
if data["v"] != "1":
continue
print(data)
if "presets" in data:
for name, preset_data in data["presets"].items():
# Convert hex color strings to RGB tuples and reorder based on device color order
if "colors" in preset_data:
preset_data["colors"] = convert_and_reorder_colors(preset_data["colors"], settings)
if "c" in preset_data:
preset_data["c"] = convert_and_reorder_colors(preset_data["c"], settings)
patterns.edit(name, preset_data)
if settings.get("name") in data.get("select", {}):
select_list = data["select"][settings.get("name")]

View File

@@ -25,11 +25,11 @@ param_mapping = {
class Preset:
def __init__(self, data):
# Set default values for all preset attributes
self.pattern = "off"
self.delay = 100
self.brightness = 127
self.colors = [(255, 255, 255)]
self.auto = True
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
@@ -48,15 +48,15 @@ class Preset:
return True
class Patterns:
def __init__(self, pin, num_leds, brightness=127, selected="off", delay=100):
def __init__(self, pin, num_leds):
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds)
self.num_leds = num_leds
self.brightness = brightness
self.step = 0
self.selected = selected
self.generator = None
self.presets = {}
self.selected = None
# Register all pattern methods
self.patterns = {
@@ -70,8 +70,7 @@ class Patterns:
"circle": self.circle,
}
self.select(self.selected)
def edit(self, name, data):
"""Create or update a preset with the given name."""
if name in self.presets:
@@ -99,13 +98,13 @@ class Patterns:
def select(self, preset_name, step=None):
if preset_name in self.presets:
preset = self.presets[preset_name]
if preset.pattern in self.patterns:
if preset.p in self.patterns:
# Set step value if explicitly provided
if step is not None:
self.step = step
elif preset.pattern == "off" or self.selected != preset_name:
elif preset.p == "off" or self.selected != preset_name:
self.step = 0
self.generator = self.patterns[preset.pattern](preset)
self.generator = self.patterns[preset.p](preset)
self.selected = preset_name # Store the preset name, not the object
return True
# If preset doesn't exist or pattern not found, default to "off"
@@ -136,9 +135,9 @@ class Patterns:
self.fill((0, 0, 0))
def on(self, preset):
colors = preset.colors
colors = preset.c
color = colors[0] if colors else (255, 255, 255)
self.fill(self.apply_brightness(color, preset.brightness))
self.fill(self.apply_brightness(color, preset.b))
def wheel(self, pos):
if pos < 85:
@@ -156,10 +155,10 @@ class Patterns:
while True:
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, last_update) >= preset.delay:
if utime.ticks_diff(current_time, last_update) >= preset.d:
if state:
color = preset.colors[0] if preset.colors else (255, 255, 255)
self.fill(self.apply_brightness(color, preset.brightness))
color = preset.c[0] if preset.c else (255, 255, 255)
self.fill(self.apply_brightness(color, preset.b))
else:
self.fill((0, 0, 0))
state = not state
@@ -172,10 +171,10 @@ class Patterns:
step_amount = max(1, int(preset.n1)) # n1 controls step increment
# If auto is False, run a single step and then stop
if not preset.auto:
if not preset.a:
for i in range(self.num_leds):
rc_index = (i * 256 // self.num_leds) + step
self.n[i] = self.apply_brightness(self.wheel(rc_index & 255), preset.brightness)
self.n[i] = self.apply_brightness(self.wheel(rc_index & 255), preset.b)
self.n.write()
# Increment step by n1 for next manual call
self.step = (step + step_amount) % 256
@@ -187,11 +186,11 @@ class Patterns:
while True:
current_time = utime.ticks_ms()
sleep_ms = max(1, int(preset.delay)) # Get delay from preset
sleep_ms = max(1, int(preset.d)) # Get delay from preset
if utime.ticks_diff(current_time, last_update) >= sleep_ms:
for i in range(self.num_leds):
rc_index = (i * 256 // self.num_leds) + step
self.n[i] = self.apply_brightness(self.wheel(rc_index & 255), preset.brightness)
self.n[i] = self.apply_brightness(self.wheel(rc_index & 255), preset.b)
self.n.write()
step = (step + step_amount) % 256
self.step = step
@@ -203,7 +202,7 @@ class Patterns:
self.off()
# Get colors from preset
colors = preset.colors
colors = preset.c
if not colors:
colors = [(255, 255, 255)]
@@ -216,7 +215,7 @@ class Patterns:
attack_ms = max(0, int(preset.n1)) # Attack time in ms
hold_ms = max(0, int(preset.n2)) # Hold time in ms
decay_ms = max(0, int(preset.n3)) # Decay time in ms
delay_ms = max(0, int(preset.delay))
delay_ms = max(0, int(preset.d))
total_ms = attack_ms + hold_ms + decay_ms + delay_ms
if total_ms <= 0:
@@ -231,16 +230,16 @@ class Patterns:
# Attack: fade 0 -> 1
factor = elapsed / attack_ms
color = tuple(int(c * factor) for c in base_color)
self.fill(self.apply_brightness(color, preset.brightness))
self.fill(self.apply_brightness(color, preset.b))
elif elapsed < attack_ms + hold_ms:
# Hold: full brightness
self.fill(self.apply_brightness(base_color, preset.brightness))
self.fill(self.apply_brightness(base_color, preset.b))
elif elapsed < attack_ms + hold_ms + decay_ms and decay_ms > 0:
# Decay: fade 1 -> 0
dec_elapsed = elapsed - attack_ms - hold_ms
factor = max(0.0, 1.0 - (dec_elapsed / decay_ms))
color = tuple(int(c * factor) for c in base_color)
self.fill(self.apply_brightness(color, preset.brightness))
self.fill(self.apply_brightness(color, preset.b))
elif elapsed < total_ms:
# Delay phase: LEDs off between pulses
self.fill((0, 0, 0))
@@ -248,7 +247,7 @@ class Patterns:
# End of cycle, move to next color and restart timing
color_index += 1
cycle_start = now
if not preset.auto:
if not preset.a:
break
# Skip drawing this tick, start next cycle
yield
@@ -259,7 +258,7 @@ class Patterns:
def transition(self, preset):
"""Transition between colors, blending over `delay` ms."""
colors = preset.colors
colors = preset.c
if not colors:
self.off()
yield
@@ -268,7 +267,7 @@ class Patterns:
# Only one color: just keep it on
if len(colors) == 1:
while True:
self.fill(self.apply_brightness(colors[0], preset.brightness))
self.fill(self.apply_brightness(colors[0], preset.b))
yield
return
@@ -283,15 +282,15 @@ class Patterns:
c1 = colors[color_index % len(colors)]
c2 = colors[(color_index + 1) % len(colors)]
duration = max(10, int(preset.delay)) # At least 10ms
duration = max(10, int(preset.d)) # At least 10ms
now = utime.ticks_ms()
elapsed = utime.ticks_diff(now, start_time)
if elapsed >= duration:
# End of this transition step
if not preset.auto:
if not preset.a:
# One-shot: transition from first to second color only
self.fill(self.apply_brightness(c2, preset.brightness))
self.fill(self.apply_brightness(c2, preset.b))
break
# Auto: move to next pair
color_index = (color_index + 1) % len(colors)
@@ -304,14 +303,14 @@ class Patterns:
interpolated = tuple(
int(c1[i] + (c2[i] - c1[i]) * factor) for i in range(3)
)
self.fill(self.apply_brightness(interpolated, preset.brightness))
self.fill(self.apply_brightness(interpolated, preset.b))
yield
def chase(self, preset):
"""Chase pattern: n1 LEDs of color0, n2 LEDs of color1, repeating.
Moves by n3 on even steps, n4 on odd steps (n3/n4 can be positive or negative)"""
colors = preset.colors
colors = preset.c
if len(colors) < 1:
# Need at least 1 color
return
@@ -327,8 +326,8 @@ class Patterns:
color0 = colors[0]
color1 = colors[1]
color0 = self.apply_brightness(color0, preset.brightness)
color1 = self.apply_brightness(color1, preset.brightness)
color0 = self.apply_brightness(color0, preset.b)
color1 = self.apply_brightness(color1, preset.b)
n1 = max(1, int(preset.n1)) # LEDs of color 0
n2 = max(1, int(preset.n2)) # LEDs of color 1
@@ -354,7 +353,7 @@ class Patterns:
position += max_pos
# If auto is False, run a single step and then stop
if not preset.auto:
if not preset.a:
# Clear all LEDs
self.n.fill((0, 0, 0))
@@ -381,8 +380,9 @@ class Patterns:
return
# Auto mode: continuous loop
last_update = utime.ticks_ms()
transition_duration = max(10, int(preset.delay))
# Use transition_duration for timing and force the first update to happen immediately
transition_duration = max(10, int(preset.d))
last_update = utime.ticks_ms() - transition_duration
while True:
current_time = utime.ticks_ms()
@@ -445,7 +445,7 @@ class Patterns:
phase = "growing" # "growing", "shrinking", or "off"
colors = preset.colors
color = self.apply_brightness(colors[0] if colors else (255, 255, 255), preset.brightness)
color = self.apply_brightness(colors[0] if colors else (255, 255, 255), preset.b)
while True:
current_time = utime.ticks_ms()

View File

@@ -14,13 +14,10 @@ class Settings(dict):
def set_defaults(self):
self["led_pin"] = 10
self["num_leds"] = 50
self["pattern"] = "on"
self["delay"] = 100
self["brightness"] = 10
self["color_order"] = "rgb"
self["name"] = f"led-{ubinascii.hexlify(network.WLAN(network.AP_IF).config('mac')).decode()}"
self["ap_password"] = ""
self["id"] = 0
self["debug"] = False
def save(self):