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