Existing accounts (including admin) seeded before new demos shipped had no easy way to pull in the latest copies — the registration-time seeder is intentionally non-destructive. The new badge action fetches src/static/bundled-demos/manifest.json, confirms the overwrite, and re-copies each canonical demo into code/. Open tabs of those files are refreshed in place so the user sees the new content immediately. src/static/bundled-demos/ ships the six canonical files plus the manifest so this works in local mode and on a static-only host. The Dockerfile now mirrors workspace/code/<demo>.py into bundled-demos/ during the image build, keeping the two locations in sync. Co-authored-by: Cursor <cursoragent@cursor.com>
91 lines
2.1 KiB
Python
91 lines
2.1 KiB
Python
"""Serial in/out demo.
|
|
|
|
When this script runs, a "Serial monitor" pane appears below the editor.
|
|
|
|
Try this:
|
|
* type hello and press Enter -> Python echoes "echo: hello"
|
|
* type color red -> the strip turns red
|
|
* try color 0,128,255 -> any (r,g,b) tuple works
|
|
* type off -> strip blanks
|
|
* type bye -> script exits cleanly
|
|
|
|
Anything Python `write()`s to the UART shows up in green; what you type back
|
|
is shown in white.
|
|
"""
|
|
|
|
import time
|
|
|
|
from machine import Pin, UART
|
|
from neopixel import NeoPixel
|
|
|
|
|
|
NUM_LEDS = 16
|
|
strip = NeoPixel(Pin(5, Pin.OUT), NUM_LEDS)
|
|
uart = UART(0, baudrate=115200)
|
|
|
|
PALETTE = {
|
|
"red": (255, 0, 0),
|
|
"green": (0, 255, 0),
|
|
"blue": (0, 0, 255),
|
|
"white": (200, 200, 200),
|
|
"purple": (160, 0, 200),
|
|
"orange": (255, 110, 0),
|
|
}
|
|
|
|
|
|
def fill(color):
|
|
strip.fill(color)
|
|
strip.write()
|
|
|
|
|
|
def parse_color(arg):
|
|
arg = arg.strip().lower()
|
|
if arg in PALETTE:
|
|
return PALETTE[arg]
|
|
parts = [p for p in arg.replace(",", " ").split() if p]
|
|
if len(parts) == 3:
|
|
try:
|
|
return tuple(max(0, min(255, int(p))) for p in parts)
|
|
except ValueError:
|
|
return None
|
|
return None
|
|
|
|
|
|
uart.write("ready. commands: color <name|r,g,b> | off | bye\n")
|
|
fill((0, 0, 0))
|
|
|
|
running = True
|
|
while running:
|
|
line = uart.readline()
|
|
if line is None:
|
|
time.sleep(0.05)
|
|
continue
|
|
|
|
text = line.decode("utf-8", errors="replace").strip()
|
|
if not text:
|
|
continue
|
|
|
|
if text == "bye":
|
|
uart.write("goodbye!\n")
|
|
running = False
|
|
break
|
|
|
|
if text == "off":
|
|
fill((0, 0, 0))
|
|
uart.write("strip off\n")
|
|
continue
|
|
|
|
if text.startswith("color"):
|
|
rest = text[len("color"):].strip()
|
|
color = parse_color(rest) if rest else None
|
|
if color is None:
|
|
uart.write("usage: color <name> | color r,g,b\n")
|
|
else:
|
|
fill(color)
|
|
uart.write(f"strip = {color}\n")
|
|
continue
|
|
|
|
uart.write(f"echo: {text}\n")
|
|
|
|
fill((0, 0, 0))
|