feat: update code and build script for circuitpython 8.1.0

This commit is contained in:
Himadri Bhattacharjee
2023-06-11 10:46:35 +05:30
parent 1acae6a5e6
commit a1f69f5ecc
6 changed files with 36 additions and 44 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
build
*.uf2
mpy-cross*
adafruit-circuitpython-bundle*

22
build.py Normal file → Executable file
View File

@@ -1,16 +1,17 @@
#!/usr/bin/env python3
"""
Builder script to compile .py files to .mpy bytecode using mpy-cross
"""
import glob
from subprocess import PIPE, Popen
from errno import ENOTDIR
from os import listdir, makedirs
from os.path import join, splitext
from shutil import copytree, copy, rmtree
from errno import ENOTDIR
from shutil import copy, copytree, rmtree
from subprocess import PIPE, Popen
SRC = 'src'
DST = 'build'
SRC = "src"
DST = "build"
def recursive_copy(src: str, dst: str):
@@ -58,20 +59,21 @@ def main():
# Remove the build directory if it exists, then create it again
rmtree(DST, ignore_errors=True)
makedirs(DST, exist_ok=True)
makedirs(join(DST, "lib"), exist_ok=True)
# Find the path of the mpy-cross binary
# Find the path of the mpy-cross binary
mpy_cross_bin = join(".", glob.glob("mpy-cross.static*")[0])
# Process each entry in the source directory
# Process each entry in the source directory
for entry in listdir(SRC):
src_path = join(SRC, entry)
# If the entry is a Python source file that needs to be compiled
if name := to_compile(entry):
# Compile the file using mpy-cross
with Popen(
[mpy_cross_bin, "-o", join(DST, f"{name}.mpy"), src_path],
stdout=PIPE,
[mpy_cross_bin, "-o",
join(DST, "lib", f"{name}.mpy"), src_path],
stdout=PIPE,
) as process:
process.communicate()
else:

View File

@@ -1,9 +1,10 @@
"""
Handler code to interact with the backend for each incoming web request
"""
import json
import os
from adafruit_httpserver import JSONResponse, Request
import logs
from ducky import run_script, run_script_file
@@ -16,25 +17,24 @@ def create(path, contents=b""):
file.write(contents)
def handle(body, response):
def handle(request: Request):
"""
Handle all the API requests from the web interface like
create, load, store, delete and run.
"""
body = request.json()
action = body["action"]
if action == "list":
response.send(json.dumps(os.listdir("payloads")))
return
return JSONResponse(request, os.listdir("payloads"))
if action == "logs":
response.send(logs.consume())
return
return JSONResponse(request, logs.consume())
filename = body.get("filename")
path = f"payloads/{filename}"
if action == "load":
with open(path) as file:
response.send(json.dumps({"contents": file.read()}))
return JSONResponse(request, {"contents": file.read()})
elif action == "store":
create(path, body["contents"].encode())
elif action == "delete":
@@ -46,3 +46,4 @@ def handle(body, response):
run_script_file(path)
elif contents := body["contents"]:
run_script(contents)
return JSONResponse(request, {})

View File

@@ -3,17 +3,12 @@ The entrypoint for our circuitpython board.
"""
import asyncio
import json
import os
import microcontroller
import socketpool
import wifi
from adafruit_httpserver.methods import HTTPMethod
from adafruit_httpserver.mime_type import MIMEType
from adafruit_httpserver.request import HTTPRequest
from adafruit_httpserver.response import HTTPResponse
from adafruit_httpserver.server import HTTPServer
from adafruit_httpserver import POST, FileResponse, Request, Server
from api import handle
@@ -28,27 +23,23 @@ async def main():
"""
wifi.radio.start_ap(ssid=os.getenv("SSID"), password=os.getenv("PASSWORD"))
pool = socketpool.SocketPool(wifi.radio)
server = HTTPServer(pool)
server = Server(pool)
@server.route("/")
def base(request: HTTPRequest):
with HTTPResponse(request, content_type=MIMEType.TYPE_HTML) as response:
response.send_file("static/index.html")
def base(request: Request):
return FileResponse(request, "index.html", root_path="/static")
@server.route("/main.css")
def css(request: HTTPRequest):
with HTTPResponse(request, content_type=MIMEType.TYPE_CSS) as response:
response.send_file("static/main.css")
def css(request: Request):
return FileResponse(request, "main.css", root_path="/static")
@server.route("/script.js")
def javascript(request: HTTPRequest):
with HTTPResponse(request, content_type=MIMEType.TYPE_JS) as response:
response.send_file("static/script.js")
def javascript(request: Request):
return FileResponse(request, "script.js", root_path="/static")
@server.route("/api", HTTPMethod.POST)
def api(request: HTTPRequest):
with HTTPResponse(request, content_type=MIMEType.TYPE_JSON) as response:
handle(json.loads(request.body), response)
@server.route("/api", POST)
def api(request: Request):
return handle(request)
server.serve_forever(str(wifi.radio.ipv4_address_ap))

View File

@@ -54,15 +54,14 @@ def press_keys(line: str):
Really useful for keyboard shortcuts like Meta+R.
"""
# loop on each key filtering empty values
for key in filter(None, line.split(" ")):
key = key.upper()
for key in filter(None, line.upper().split(" ")):
if command_keycode := Keycode.__dict__.get(key):
# If this is a valid key, send its keycode
kbd.press(command_keycode)
continue
# If it's not a known key name, log it for diagnosis
warn(f"unknown key: <{key}>")
kbd.release_all()
kbd.release_all()
def repeat(contents: str, times: int):
@@ -98,7 +97,7 @@ def run_script(contents):
elif path := after("IMPORT"):
run_script_file(path)
elif millis := after("DEFAULT_DELAY", "DEFAULTDELAY"):
default_delay = int(millis) * 10
default_delay = int(millis)
elif after("LED") is not None:
LED.value ^= True
elif string := after("STRING"):

View File

@@ -3,8 +3,6 @@ A very bare-bones logging implementation
for the bottom pane of the Web UI.
"""
import json
logs = []
@@ -13,7 +11,7 @@ def consume() -> str:
Convert all the log entries from the module's global mutable
list to json return them, clearing the list after the dump.
"""
dump = json.dumps(logs)
dump = logs.copy()
logs.clear()
return dump