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:
@@ -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")]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user