Compare commits
4 Commits
3ee89ce3b4
...
beta-1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| fbebe9f4f9 | |||
| a79c6f4dd3 | |||
|
|
2fcaf2f064 | ||
|
|
3b38264b70 |
@@ -46,6 +46,8 @@ def process_data(payload, settings, presets, controller_ip=None):
|
|||||||
presets.save()
|
presets.save()
|
||||||
if "save" in data and "clear_presets" in data:
|
if "save" in data and "clear_presets" in data:
|
||||||
presets.save()
|
presets.save()
|
||||||
|
if "save" in data and "b" in data:
|
||||||
|
settings.save()
|
||||||
|
|
||||||
|
|
||||||
def apply_brightness(data, settings, presets):
|
def apply_brightness(data, settings, presets):
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ sta_if.active(True)
|
|||||||
sta_if.config(pm=network.WLAN.PM_NONE)
|
sta_if.config(pm=network.WLAN.PM_NONE)
|
||||||
sta_if.connect(settings["ssid"], settings["password"])
|
sta_if.connect(settings["ssid"], settings["password"])
|
||||||
while not sta_if.isconnected():
|
while not sta_if.isconnected():
|
||||||
|
print("Connecting")
|
||||||
utime.sleep(1)
|
utime.sleep(1)
|
||||||
wdt.feed()
|
wdt.feed()
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,23 @@ class BarGraph:
|
|||||||
|
|
||||||
def run(self, preset):
|
def run(self, preset):
|
||||||
colors = preset.c if preset.c else [(0, 255, 0), (255, 80, 0)]
|
colors = preset.c if preset.c else [(0, 255, 0), (255, 80, 0)]
|
||||||
|
last_update = utime.ticks_ms()
|
||||||
|
while True:
|
||||||
|
delay_ms = max(1, int(preset.d))
|
||||||
|
now = utime.ticks_ms()
|
||||||
|
if utime.ticks_diff(now, last_update) >= delay_ms:
|
||||||
level = max(0, min(100, int(preset.n1) if int(preset.n1) >= 0 else 50))
|
level = max(0, min(100, int(preset.n1) if int(preset.n1) >= 0 else 50))
|
||||||
target = (self.driver.num_leds * level) // 100
|
target = (self.driver.num_leds * level) // 100
|
||||||
lit = self.driver.apply_brightness(colors[0], preset.b)
|
lit = self.driver.apply_brightness(colors[0], preset.b)
|
||||||
unlit = self.driver.apply_brightness(colors[1] if len(colors) > 1 else (0, 0, 0), preset.b)
|
unlit = self.driver.apply_brightness(
|
||||||
while True:
|
colors[-1],
|
||||||
|
preset.b,
|
||||||
|
)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = lit if i < target else unlit
|
self.driver.n[i] = lit if i < target else unlit
|
||||||
self.driver.n.write()
|
self.driver.n.write()
|
||||||
yield
|
last_update = utime.ticks_add(last_update, delay_ms)
|
||||||
if not preset.a:
|
if not preset.a:
|
||||||
|
yield
|
||||||
return
|
return
|
||||||
utime.sleep_ms(max(1, int(preset.d)))
|
yield
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Blink:
|
|||||||
# Advance to next color for the next "on" phase
|
# Advance to next color for the next "on" phase
|
||||||
color_index += 1
|
color_index += 1
|
||||||
else:
|
else:
|
||||||
# "Off" phase: turn all LEDs off
|
# "Off" phase should actually be off.
|
||||||
self.driver.fill((0, 0, 0))
|
self.driver.fill((0, 0, 0))
|
||||||
state = not state
|
state = not state
|
||||||
last_update = utime.ticks_add(last_update, delay_ms)
|
last_update = utime.ticks_add(last_update, delay_ms)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class Chase:
|
|||||||
|
|
||||||
color0 = self.driver.apply_brightness(color0, preset.b)
|
color0 = self.driver.apply_brightness(color0, preset.b)
|
||||||
color1 = self.driver.apply_brightness(color1, preset.b)
|
color1 = self.driver.apply_brightness(color1, preset.b)
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], 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
|
||||||
@@ -53,7 +54,7 @@ class Chase:
|
|||||||
# 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.a:
|
if not preset.a:
|
||||||
# Clear all LEDs
|
# Clear all LEDs
|
||||||
self.driver.n.fill((0, 0, 0))
|
self.driver.n.fill(bg_color)
|
||||||
|
|
||||||
# Draw repeating pattern starting at position
|
# Draw repeating pattern starting at position
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
@@ -98,7 +99,7 @@ class Chase:
|
|||||||
position += max_pos
|
position += max_pos
|
||||||
|
|
||||||
# Clear all LEDs
|
# Clear all LEDs
|
||||||
self.driver.n.fill((0, 0, 0))
|
self.driver.n.fill(bg_color)
|
||||||
|
|
||||||
# Draw repeating pattern starting at position
|
# Draw repeating pattern starting at position
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ class Circle:
|
|||||||
base0 = base1 = (255, 255, 255)
|
base0 = base1 = (255, 255, 255)
|
||||||
elif len(colors) == 1:
|
elif len(colors) == 1:
|
||||||
base0 = colors[0]
|
base0 = colors[0]
|
||||||
base1 = (0, 0, 0)
|
base1 = colors[-1]
|
||||||
else:
|
else:
|
||||||
base0 = colors[0]
|
base0 = colors[0]
|
||||||
base1 = colors[1]
|
base1 = colors[-1]
|
||||||
|
|
||||||
color0 = self.driver.apply_brightness(base0, preset.b)
|
color0 = self.driver.apply_brightness(base0, preset.b)
|
||||||
color1 = self.driver.apply_brightness(base1, preset.b)
|
color1 = self.driver.apply_brightness(base1, preset.b)
|
||||||
@@ -46,7 +46,7 @@ class Circle:
|
|||||||
if phase == "off":
|
if phase == "off":
|
||||||
self.driver.n.fill(color1)
|
self.driver.n.fill(color1)
|
||||||
else:
|
else:
|
||||||
self.driver.n.fill((0, 0, 0))
|
self.driver.n.fill(color1)
|
||||||
|
|
||||||
# Calculate segment length
|
# Calculate segment length
|
||||||
segment_length = (head - tail) % self.driver.num_leds
|
segment_length = (head - tail) % self.driver.num_leds
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ClockSweep:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
bg = self.driver.apply_brightness(colors[1] if len(colors) > 1 else (0, 0, 0), preset.b)
|
bg = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
fg = self.driver.apply_brightness(colors[0], preset.b)
|
fg = self.driver.apply_brightness(colors[0], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = bg
|
self.driver.n[i] = bg
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ class CometDual:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
c1 = self.driver.apply_brightness(colors[0 % len(colors)], preset.b)
|
c1 = self.driver.apply_brightness(colors[0 % len(colors)], preset.b)
|
||||||
c2 = self.driver.apply_brightness(colors[1 % len(colors)] if len(colors) > 1 else colors[0], preset.b)
|
c2 = self.driver.apply_brightness(colors[1 % len(colors)] if len(colors) > 1 else colors[0], preset.b)
|
||||||
for t in range(tail):
|
for t in range(tail):
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ class Fireflies:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
for b in bugs:
|
for b in bugs:
|
||||||
idx, ph = b
|
idx, ph = b
|
||||||
tri = 255 - abs(128 - ph) * 2
|
tri = 255 - abs(128 - ph) * 2
|
||||||
|
|||||||
@@ -7,19 +7,30 @@ class Heartbeat:
|
|||||||
|
|
||||||
def run(self, preset):
|
def run(self, preset):
|
||||||
colors = preset.c if preset.c else [(255, 0, 40)]
|
colors = preset.c if preset.c else [(255, 0, 40)]
|
||||||
|
phase = 0
|
||||||
|
phase_start = utime.ticks_ms()
|
||||||
|
did_manual_pulse = False
|
||||||
|
while True:
|
||||||
p1 = max(20, int(preset.n1) if int(preset.n1) > 0 else 120)
|
p1 = max(20, int(preset.n1) if int(preset.n1) > 0 else 120)
|
||||||
p2 = max(20, int(preset.n2) if int(preset.n2) > 0 else 80)
|
p2 = max(20, int(preset.n2) if int(preset.n2) > 0 else 80)
|
||||||
pause = max(20, int(preset.n3) if int(preset.n3) > 0 else 500)
|
pause = max(20, int(preset.n3) if int(preset.n3) > 0 else 500)
|
||||||
while True:
|
beat_gap = max(20, int(preset.d))
|
||||||
c = self.driver.apply_brightness(colors[0], preset.b)
|
colors = preset.c if preset.c else [(255, 0, 40)]
|
||||||
self.driver.fill(c)
|
lit_color = self.driver.apply_brightness(colors[0], preset.b)
|
||||||
utime.sleep_ms(p1)
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
self.driver.fill((0, 0, 0))
|
phase_durations = (p1, beat_gap, p2, pause)
|
||||||
utime.sleep_ms(max(20, int(preset.d)))
|
phase_colors = (lit_color, bg_color, lit_color, bg_color)
|
||||||
self.driver.fill(c)
|
|
||||||
utime.sleep_ms(p2)
|
now = utime.ticks_ms()
|
||||||
self.driver.fill((0, 0, 0))
|
while utime.ticks_diff(now, phase_start) >= phase_durations[phase]:
|
||||||
utime.sleep_ms(pause)
|
phase_start = utime.ticks_add(phase_start, phase_durations[phase])
|
||||||
|
phase = (phase + 1) % 4
|
||||||
|
|
||||||
|
self.driver.fill(phase_colors[phase])
|
||||||
yield
|
yield
|
||||||
if not preset.a:
|
if not preset.a:
|
||||||
|
if did_manual_pulse or phase == 0:
|
||||||
|
self.driver.fill(bg_color)
|
||||||
|
yield
|
||||||
return
|
return
|
||||||
|
did_manual_pulse = True
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ class Marquee:
|
|||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
c = self.driver.apply_brightness(colors[0], preset.b)
|
c = self.driver.apply_brightness(colors[0], preset.b)
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
m = (i + phase) % (on_len + off_len)
|
m = (i + phase) % (on_len + off_len)
|
||||||
self.driver.n[i] = c if m < on_len else (0, 0, 0)
|
self.driver.n[i] = c if m < on_len else bg_color
|
||||||
self.driver.n.write()
|
self.driver.n.write()
|
||||||
phase = (phase + step) % (on_len + off_len)
|
phase = (phase + step) % (on_len + off_len)
|
||||||
self.driver.step = phase
|
self.driver.step = phase
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ class Orbit:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
for k in range(orbits):
|
for k in range(orbits):
|
||||||
idx = ((phase * (k + 1)) // 8 + (k * self.driver.num_leds // max(1, orbits))) % max(1, self.driver.num_leds)
|
idx = ((phase * (k + 1)) // 8 + (k * self.driver.num_leds // max(1, orbits))) % max(1, self.driver.num_leds)
|
||||||
self.driver.n[idx] = self.driver.apply_brightness(colors[k % len(colors)], preset.b)
|
self.driver.n[idx] = self.driver.apply_brightness(colors[k % len(colors)], preset.b)
|
||||||
|
|||||||
@@ -34,9 +34,15 @@ class PaletteMorph:
|
|||||||
base_idx = 0
|
base_idx = 0
|
||||||
start = utime.ticks_ms()
|
start = utime.ticks_ms()
|
||||||
phase = self.driver.step % 256
|
phase = self.driver.step % 256
|
||||||
|
last_update = start
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
|
delay_ms = max(1, int(preset.d))
|
||||||
|
if utime.ticks_diff(now, last_update) < delay_ms:
|
||||||
|
yield
|
||||||
|
continue
|
||||||
|
last_update = utime.ticks_add(last_update, delay_ms)
|
||||||
age = utime.ticks_diff(now, start)
|
age = utime.ticks_diff(now, start)
|
||||||
if age < morph:
|
if age < morph:
|
||||||
t = (age * 255) // morph
|
t = (age * 255) // morph
|
||||||
@@ -72,5 +78,4 @@ class PaletteMorph:
|
|||||||
return
|
return
|
||||||
phase = (phase + warp_rate) & 255
|
phase = (phase + warp_rate) & 255
|
||||||
self.driver.step = phase
|
self.driver.step = phase
|
||||||
utime.sleep_ms(max(1, int(preset.d)))
|
|
||||||
yield
|
yield
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Pulse:
|
|||||||
|
|
||||||
# State machine based pulse using a single generator loop
|
# State machine based pulse using a single generator loop
|
||||||
while True:
|
while True:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
# Read current timing parameters from preset
|
# Read current timing parameters from preset
|
||||||
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
|
||||||
@@ -49,7 +50,7 @@ class Pulse:
|
|||||||
self.driver.fill(self.driver.apply_brightness(color, preset.b))
|
self.driver.fill(self.driver.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.driver.fill((0, 0, 0))
|
self.driver.fill(bg_color)
|
||||||
else:
|
else:
|
||||||
# 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
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Radiate:
|
|||||||
"""
|
"""
|
||||||
colors = preset.c if preset.c else [(255, 255, 255)]
|
colors = preset.c if preset.c else [(255, 255, 255)]
|
||||||
base_on = colors[0]
|
base_on = colors[0]
|
||||||
base_off = colors[1] if len(colors) > 1 else (0, 0, 0)
|
base_off = colors[-1]
|
||||||
|
|
||||||
spacing = max(1, int(preset.n1))
|
spacing = max(1, int(preset.n1))
|
||||||
outward_ms = max(1, int(preset.n2))
|
outward_ms = max(1, int(preset.n2))
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ class RainDrops:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
if random.randint(0, 255) < rate:
|
if random.randint(0, 255) < rate:
|
||||||
drops.append([random.randint(0, max(0, self.driver.num_leds - 1)), 0])
|
drops.append([random.randint(0, max(0, self.driver.num_leds - 1)), 0])
|
||||||
nd = []
|
nd = []
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ class Scanner:
|
|||||||
if utime.ticks_diff(now, last_update) >= delay_ms:
|
if utime.ticks_diff(now, last_update) >= delay_ms:
|
||||||
base = colors[color_index % len(colors)]
|
base = colors[color_index % len(colors)]
|
||||||
base = self.driver.apply_brightness(base, preset.b)
|
base = self.driver.apply_brightness(base, preset.b)
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
dist = i - center
|
dist = i - center
|
||||||
if dist < 0:
|
if dist < 0:
|
||||||
dist = -dist
|
dist = -dist
|
||||||
if dist > width:
|
if dist > width:
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
else:
|
else:
|
||||||
scale = ((width - dist) * 255) // max(1, width)
|
scale = ((width - dist) * 255) // max(1, width)
|
||||||
self.driver.n[i] = (
|
self.driver.n[i] = (
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ class SegmentChase:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
seg_idx = i // seg
|
seg_idx = i // seg
|
||||||
in_seg = i % seg
|
in_seg = i % seg
|
||||||
local_phase = (phase + seg_idx * seg_offset) % seg
|
local_phase = (phase + seg_idx * seg_offset) % seg
|
||||||
lit_idx = (in_seg + local_phase) % seg
|
lit_idx = (in_seg + local_phase) % seg
|
||||||
if gap > 0 and lit_idx >= max(1, seg - gap):
|
if gap > 0 and lit_idx >= max(1, seg - gap):
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
else:
|
else:
|
||||||
color_idx = seg_idx % len(colors)
|
color_idx = seg_idx % len(colors)
|
||||||
self.driver.n[i] = self.driver.apply_brightness(colors[color_idx], preset.b)
|
self.driver.n[i] = self.driver.apply_brightness(colors[color_idx], preset.b)
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ class Snowfall:
|
|||||||
d = max(1, int(preset.d))
|
d = max(1, int(preset.d))
|
||||||
now = utime.ticks_ms()
|
now = utime.ticks_ms()
|
||||||
if utime.ticks_diff(now, last) >= d:
|
if utime.ticks_diff(now, last) >= d:
|
||||||
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
if random.randint(0, 255) < density:
|
if random.randint(0, 255) < density:
|
||||||
flakes.append([self.driver.num_leds - 1, random.randint(0, len(colors)-1)])
|
flakes.append([self.driver.num_leds - 1, random.randint(0, len(colors)-1)])
|
||||||
for i in range(self.driver.num_leds):
|
for i in range(self.driver.num_leds):
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
nf = []
|
nf = []
|
||||||
for pos, ci in flakes:
|
for pos, ci in flakes:
|
||||||
if 0 <= pos < self.driver.num_leds:
|
if 0 <= pos < self.driver.num_leds:
|
||||||
|
|||||||
@@ -7,18 +7,39 @@ class StrobeBurst:
|
|||||||
|
|
||||||
def run(self, preset):
|
def run(self, preset):
|
||||||
colors = preset.c if preset.c else [(255, 255, 255)]
|
colors = preset.c if preset.c else [(255, 255, 255)]
|
||||||
|
state = "flash_on"
|
||||||
|
flash_idx = 0
|
||||||
|
state_start = utime.ticks_ms()
|
||||||
|
while True:
|
||||||
count = max(1, int(preset.n1) if int(preset.n1) > 0 else 3)
|
count = max(1, int(preset.n1) if int(preset.n1) > 0 else 3)
|
||||||
gap = max(1, int(preset.n2) if int(preset.n2) > 0 else 60)
|
gap = max(1, int(preset.n2) if int(preset.n2) > 0 else 60)
|
||||||
cooldown = max(1, int(preset.n3) if int(preset.n3) > 0 else 400)
|
cooldown = max(1, int(preset.n3) if int(preset.n3) > 0 else 400)
|
||||||
|
on_ms = max(1, int(preset.d) // 2)
|
||||||
c = self.driver.apply_brightness(colors[0], preset.b)
|
c = self.driver.apply_brightness(colors[0], preset.b)
|
||||||
while True:
|
bg_color = self.driver.apply_brightness(colors[-1], preset.b)
|
||||||
for _ in range(count):
|
now = utime.ticks_ms()
|
||||||
|
|
||||||
|
if state == "flash_on":
|
||||||
self.driver.fill(c)
|
self.driver.fill(c)
|
||||||
utime.sleep_ms(max(1, int(preset.d)//2))
|
if utime.ticks_diff(now, state_start) >= on_ms:
|
||||||
self.driver.fill((0, 0, 0))
|
state = "flash_off"
|
||||||
utime.sleep_ms(gap)
|
state_start = utime.ticks_add(state_start, on_ms)
|
||||||
yield
|
elif state == "flash_off":
|
||||||
utime.sleep_ms(cooldown)
|
self.driver.fill(bg_color)
|
||||||
yield
|
if utime.ticks_diff(now, state_start) >= gap:
|
||||||
|
flash_idx += 1
|
||||||
|
if flash_idx >= count:
|
||||||
if not preset.a:
|
if not preset.a:
|
||||||
return
|
return
|
||||||
|
state = "cooldown"
|
||||||
|
flash_idx = 0
|
||||||
|
state_start = utime.ticks_add(state_start, gap)
|
||||||
|
else:
|
||||||
|
state = "flash_on"
|
||||||
|
state_start = utime.ticks_add(state_start, gap)
|
||||||
|
else:
|
||||||
|
self.driver.fill(bg_color)
|
||||||
|
if utime.ticks_diff(now, state_start) >= cooldown:
|
||||||
|
state = "flash_on"
|
||||||
|
state_start = utime.ticks_add(state_start, cooldown)
|
||||||
|
yield
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class Twinkle:
|
|||||||
"""Twinkle: n1 activity, n2 density; n3/n4 min/max length of adjacent on/off runs."""
|
"""Twinkle: n1 activity, n2 density; n3/n4 min/max length of adjacent on/off runs."""
|
||||||
palette = self._palette(preset)
|
palette = self._palette(preset)
|
||||||
num = self.driver.num_leds
|
num = self.driver.num_leds
|
||||||
|
bg_color = self.driver.apply_brightness(palette[-1], preset.b)
|
||||||
if num <= 0:
|
if num <= 0:
|
||||||
while True:
|
while True:
|
||||||
yield
|
yield
|
||||||
@@ -125,7 +126,7 @@ class Twinkle:
|
|||||||
base = palette[colour_i[i] % len(palette)]
|
base = palette[colour_i[i] % len(palette)]
|
||||||
self.driver.n[i] = self.driver.apply_brightness(base, preset.b)
|
self.driver.n[i] = self.driver.apply_brightness(base, preset.b)
|
||||||
else:
|
else:
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
self.driver.n.write()
|
self.driver.n.write()
|
||||||
yield
|
yield
|
||||||
return
|
return
|
||||||
@@ -185,7 +186,7 @@ class Twinkle:
|
|||||||
base = palette[next_ci[i] % len(palette)]
|
base = palette[next_ci[i] % len(palette)]
|
||||||
self.driver.n[i] = self.driver.apply_brightness(base, preset.b)
|
self.driver.n[i] = self.driver.apply_brightness(base, preset.b)
|
||||||
else:
|
else:
|
||||||
self.driver.n[i] = (0, 0, 0)
|
self.driver.n[i] = bg_color
|
||||||
self.driver.n.write()
|
self.driver.n.write()
|
||||||
on = next_on
|
on = next_on
|
||||||
colour_i = next_ci
|
colour_i = next_ci
|
||||||
|
|||||||
31
tests/all.py
31
tests/all.py
@@ -184,6 +184,36 @@ def test_pattern_smoke():
|
|||||||
ctx.tick_for_ms(120)
|
ctx.tick_for_ms(120)
|
||||||
|
|
||||||
|
|
||||||
|
def test_patterns_do_not_use_blocking_sleep():
|
||||||
|
pattern_dir = "patterns"
|
||||||
|
offenders = []
|
||||||
|
try:
|
||||||
|
files = os.listdir(pattern_dir)
|
||||||
|
except OSError:
|
||||||
|
raise AssertionError("patterns directory is missing")
|
||||||
|
|
||||||
|
for filename in files:
|
||||||
|
if not filename.endswith(".py") or filename in ("__init__.py", "main.py"):
|
||||||
|
continue
|
||||||
|
path = pattern_dir + "/" + filename
|
||||||
|
try:
|
||||||
|
with open(path, "r") as f:
|
||||||
|
src = f.read()
|
||||||
|
except OSError:
|
||||||
|
offenders.append(filename + " (unreadable)")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (
|
||||||
|
"utime.sleep(" in src
|
||||||
|
or "utime.sleep_ms(" in src
|
||||||
|
or "time.sleep(" in src
|
||||||
|
or "time.sleep_ms(" in src
|
||||||
|
):
|
||||||
|
offenders.append(filename)
|
||||||
|
|
||||||
|
assert not offenders, "blocking sleep found in patterns: %s" % ", ".join(offenders)
|
||||||
|
|
||||||
|
|
||||||
def test_default_requires_existing_preset():
|
def test_default_requires_existing_preset():
|
||||||
ctx = _TestContext()
|
ctx = _TestContext()
|
||||||
_process_message(ctx, {"v": "1", "default": "missing"})
|
_process_message(ctx, {"v": "1", "default": "missing"})
|
||||||
@@ -242,6 +272,7 @@ def run_all():
|
|||||||
test_preset_edit_sanitization,
|
test_preset_edit_sanitization,
|
||||||
test_colour_conversion_and_transition,
|
test_colour_conversion_and_transition,
|
||||||
test_pattern_smoke,
|
test_pattern_smoke,
|
||||||
|
test_patterns_do_not_use_blocking_sleep,
|
||||||
test_default_requires_existing_preset,
|
test_default_requires_existing_preset,
|
||||||
test_default_targets_gate_by_device_name,
|
test_default_targets_gate_by_device_name,
|
||||||
test_save_and_load_roundtrip,
|
test_save_and_load_roundtrip,
|
||||||
|
|||||||
Reference in New Issue
Block a user