""" Menu Script =========== You can customize this script however you want :) If you want to go back to the default version, just delete this file; the firmware will recreate it on next run. """ import collections import color import display import os import simple_menu import sys import ujson import utime App = collections.namedtuple("App", ["name", "path"]) def enumerate_apps(): """List all installed apps.""" for f in os.listdir("/"): if f == "main.py": yield App("Home", f) for app in sorted(os.listdir("/apps")): if app.startswith("."): continue if app.endswith(".py") or app.endswith(".elf"): yield App(app, "/apps/" + app) continue try: with open("/apps/" + app + "/metadata.json") as f: info = ujson.load(f) yield App( info["name"], "/apps/{}/{}".format(app, info.get("bin", "__init__.py")) ) except Exception as e: print("Could not load /apps/{}/metadata.json!".format(app)) sys.print_exception(e) class MainMenu(simple_menu.Menu): timeout = 30.0 def entry2name(self, app): return app.name def on_select(self, app, index): self.disp.clear().update() try: print("Trying to load " + app.path) os.exec(app.path) except OSError as e: print("Loading failed: ") sys.print_exception(e) self.error("Loading", "failed") utime.sleep(1.0) os.exit(1) def on_timeout(self): try: f = open("main.py") f.close() os.exec("main.py") except OSError: pass def no_apps_message(): """Display a warning if no apps are installed.""" with display.open() as disp: disp.clear(color.COMMYELLOW) disp.print( " No apps ", posx=17, posy=20, fg=color.COMMYELLOW_DARK, bg=color.COMMYELLOW ) disp.print( "available", posx=17, posy=40, fg=color.COMMYELLOW_DARK, bg=color.COMMYELLOW ) disp.update() while True: utime.sleep(0.5) if __name__ == "__main__": try: apps = list(enumerate_apps()) except OSError: apps = [] if not apps: no_apps_message() MainMenu(apps).run()