kopia lustrzana https://github.com/pimoroni/pimoroni-pico
PicoWireless: ppwhttp add wildcard routes
This slightly reckless extension to ppwhttp adds support for wildcard routes, eg: /get_led/<int:index> Which will serve URLs in the form: /get_led/10 /get_led/22 etc. The wildcard includes <type:key>, attempting to match the behaviour of Flask. Only type "int" is supported currently. /get_led/<index> - would set data["index"] to a string /get_led/<int:index> - would attempt to parse the URL part to an int, and would not serve eg: /get_led/hi See plasma_ws2812_http.py for example usage.pull/208/head
rodzic
b92d77a2f9
commit
78d50c2986
|
@ -9,6 +9,8 @@ except ImportError:
|
|||
"""
|
||||
This example uses the Plasma WS2812 LED library to drive a string of LEDs alongside the built-in RGB LED.
|
||||
You should wire your LEDs to VBUS/GND and connect the data pin to pin 27 (unused by Pico Wireless).
|
||||
|
||||
Go to: https://<address>:<port>/set_led/<index> to set a single LED
|
||||
"""
|
||||
|
||||
NUM_LEDS = 30 # Number of connected LEDs
|
||||
|
@ -27,7 +29,7 @@ led_strip = plasma.WS2812(NUM_LEDS, LED_PIO, LED_SM, LED_PIN)
|
|||
# Edit your routes here
|
||||
# Nothing fancy is supported, just plain ol' URLs and GET/POST methods
|
||||
@ppwhttp.route("/", methods=["GET", "POST"])
|
||||
def get_home(method, url, data=None):
|
||||
def get_home(method, url, data):
|
||||
if method == "POST":
|
||||
global r, g, b
|
||||
r = int(data.get("r", 0))
|
||||
|
@ -46,6 +48,45 @@ def get_home(method, url, data=None):
|
|||
</form>""".format(r=r, g=g, b=b)
|
||||
|
||||
|
||||
# This wildcard route allows us to visit eg `/set_led/<index>`
|
||||
# to get/set the state of LED <index>
|
||||
# You should *probably* not modify state with GET, even though you can
|
||||
# so we use a form and POST to handle changing things.
|
||||
@ppwhttp.route("/set_led/<int:index>", methods=["GET", "POST"])
|
||||
def set_led(method, url, data):
|
||||
i = int(data.get("index", 0))
|
||||
|
||||
if method == "POST":
|
||||
r = int(data.get("r", 0))
|
||||
g = int(data.get("g", 0))
|
||||
b = int(data.get("b", 0))
|
||||
led_strip.set_rgb(i, r, g, b)
|
||||
print("Set LED to {} {} {}".format(r, g, b))
|
||||
else:
|
||||
# TODO Fix WS2812 / APA102 get methods to correct for colour order/alignment
|
||||
r, g, b, w = led_strip.get(i)
|
||||
r = int(r)
|
||||
g = int(g)
|
||||
b = int(b)
|
||||
|
||||
return """LED: {i}<br /><form method="post" action="/set_led/{i}">
|
||||
<input id="r" name="r" type="number" value="{r}" />
|
||||
<input name="g" type="number" value="{g}" />
|
||||
<input name="b" type="number" value="{b}" />
|
||||
<input type="submit" value="Set LED" />
|
||||
</form>""".format(i=i, r=r, g=g, b=b)
|
||||
|
||||
|
||||
# This wildcard route allows us to visit eg `/get_led/<index>`
|
||||
# to get the state of LED <index>
|
||||
@ppwhttp.route("/get_led/<int:index>", methods="GET")
|
||||
def get_led(method, url, data):
|
||||
i = data.get("index", 0)
|
||||
# TODO Fix WS2812 / APA102 get methods to correct for colour order/alignment
|
||||
r, g, b, w = led_strip.get(i)
|
||||
return "LED: {}<br />R: {:0.0f}<br />G: {:0.0f}<br />B: {:0.0f}".format(i, r, g, b)
|
||||
|
||||
|
||||
@ppwhttp.route("/test", methods="GET")
|
||||
def get_test(method, url):
|
||||
return "Hello World!"
|
||||
|
|
|
@ -181,6 +181,38 @@ Connection: close
|
|||
picowireless.client_stop(client_sock)
|
||||
|
||||
|
||||
def find_route(route, url, method, data):
|
||||
if len(url) > 0:
|
||||
for key, value in route.items():
|
||||
if key == url[0]:
|
||||
return find_route(route[url[0]], url[1:], method, data)
|
||||
|
||||
elif key.startswith("<") and key.endswith(">"):
|
||||
key = key[1:-1]
|
||||
if ":" in key:
|
||||
dtype, key = key.split(":")
|
||||
else:
|
||||
dtype = "str"
|
||||
|
||||
if dtype == "int":
|
||||
try:
|
||||
data[key] = int(url[0])
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
else:
|
||||
data[key] = url[0]
|
||||
|
||||
return find_route(value, url[1:], method, data)
|
||||
|
||||
return None, None
|
||||
|
||||
if method in route:
|
||||
return route[method], data
|
||||
|
||||
return None, None
|
||||
|
||||
|
||||
def handle_http_request(server_sock, timeout=5000):
|
||||
t_start = time.ticks_ms()
|
||||
|
||||
|
@ -221,16 +253,24 @@ def handle_http_request(server_sock, timeout=5000):
|
|||
|
||||
response = None
|
||||
|
||||
data = {}
|
||||
|
||||
if url.startswith("/"):
|
||||
url = url[1:]
|
||||
url = url.split("/")
|
||||
handler, data = find_route(routes, url, method, data)
|
||||
|
||||
# Dispatch the request to the relevant route
|
||||
if url in routes and method in routes[url] and callable(routes[url][method]):
|
||||
if callable(handler):
|
||||
if method == "POST":
|
||||
data = {}
|
||||
for var in body.split("&"):
|
||||
key, value = var.split("=")
|
||||
data[key] = value
|
||||
response = routes[url][method](method, url, data)
|
||||
|
||||
if data == {}:
|
||||
response = handler(method, url)
|
||||
else:
|
||||
response = routes[url][method](method, url)
|
||||
response = handler(method, url, data)
|
||||
|
||||
if response is not None:
|
||||
response = "HTTP/1.1 200 OK\r\nContent-Length: {}\r\nContent-Type: text/html\r\n\r\n".format(len(response)) + response
|
||||
|
@ -249,10 +289,20 @@ def route(url, methods="GET"):
|
|||
if type(methods) is str:
|
||||
methods = [methods]
|
||||
|
||||
if url.startswith("/"):
|
||||
url = url[1:]
|
||||
|
||||
url = url.split("/")
|
||||
|
||||
def decorate(handler):
|
||||
route = routes
|
||||
for part in url:
|
||||
if part not in route:
|
||||
route[part] = {}
|
||||
|
||||
route = route[part]
|
||||
|
||||
for method in methods:
|
||||
if url not in routes:
|
||||
routes[url] = {}
|
||||
routes[url][method] = handler
|
||||
route[method] = handler
|
||||
|
||||
return decorate
|
||||
|
|
Ładowanie…
Reference in New Issue