Bootstrap 'app'
parent
68e0c97cbf
commit
5b8189a015
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB |
|
@ -6,7 +6,7 @@ To publish apps use https://badge.emfcamp.org"""
|
||||||
|
|
||||||
___license___ = "MIT"
|
___license___ = "MIT"
|
||||||
___title___ = "Badge Store"
|
___title___ = "Badge Store"
|
||||||
___dependencies___ = ["app", "badge_store", "dialogs", "ugfx_helper"]
|
___dependencies___ = ["app", "badge_store", "dialogs", "ugfx_helper", "app"]
|
||||||
___categories___ = ["System"]
|
___categories___ = ["System"]
|
||||||
___bootstrapped___ = True
|
___bootstrapped___ = True
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ def show_app(a):
|
||||||
|
|
||||||
if install:
|
if install:
|
||||||
with WaitingMessage(title="Installing %s" % a, text="Please wait...") as message:
|
with WaitingMessage(title="Installing %s" % a, text="Please wait...") as message:
|
||||||
installers = store.install(a)
|
installers = store.install(_get_current_apps + [a])
|
||||||
n = len(installers)
|
n = len(installers)
|
||||||
for i, installer in enumerate(installers):
|
for i, installer in enumerate(installers):
|
||||||
message.text = "%s (%s/%s)" % (installer.path, i + 1, n)
|
message.text = "%s (%s/%s)" % (installer.path, i + 1, n)
|
||||||
|
@ -89,6 +89,9 @@ def main_menu():
|
||||||
else:
|
else:
|
||||||
app.restart_to_default()
|
app.restart_to_default()
|
||||||
|
|
||||||
|
def _get_current_apps():
|
||||||
|
return [a.name for a in app.get_apps()]
|
||||||
|
|
||||||
wifi.connect(show_wait_message=True)
|
wifi.connect(show_wait_message=True)
|
||||||
main_menu()
|
main_menu()
|
||||||
#show_app("launcher")
|
#show_app("launcher")
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
"""App that gets backed into the firmware.
|
||||||
|
|
||||||
|
It's only purpose is to download the base operating system on first boot.
|
||||||
|
|
||||||
|
It's not meant to be executed from the launcher"""
|
||||||
|
|
||||||
|
___license___ = "MIT"
|
||||||
|
___title___ = "Bootstrap"
|
||||||
|
___categories___ = ["System"]
|
||||||
|
___dependencies___ = ["badge_store", "dialogs"]
|
||||||
|
___launchable___ = False
|
||||||
|
___builtin___ = True
|
||||||
|
|
||||||
|
import ugfx, wifi, badge_store, machine, dialogs
|
||||||
|
|
||||||
|
ugfx.init()
|
||||||
|
machine.Pin(machine.Pin.PWM_LCD_BLIGHT).on()
|
||||||
|
wifi.connect(show_wait_message=True)
|
||||||
|
with dialogs.WaitingMessage(title="Setting up TiLDA Mk4", text="Please wait...") as message:
|
||||||
|
installers = badge_store.BadgeStore().bootstrap()
|
||||||
|
n = len(installers)
|
||||||
|
for i, installer in enumerate(installers):
|
||||||
|
message.text = "%s (%s/%s)" % (installer.path, i + 1, n)
|
||||||
|
installer.download()
|
||||||
|
machine.reset()
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
"""Library to interact with the badge store"""
|
"""Library to interact with the badge store"""
|
||||||
|
|
||||||
___license___ = "MIT"
|
___license___ = "MIT"
|
||||||
___dependencies___ = ["http", "ospath", "app"]
|
___dependencies___ = ["http", "ospath"]
|
||||||
|
|
||||||
from ospath import *
|
from ospath import *
|
||||||
from http import *
|
from http import *
|
||||||
import hashlib, binascii, app
|
import hashlib, binascii
|
||||||
|
|
||||||
class BadgeStore:
|
class BadgeStore:
|
||||||
def __init__(self, url = "http://badge.marekventur.com", repo="emfcamp/Mk4-Apps", ref="master"):
|
def __init__(self, url = "http://badge.marekventur.com", repo="emfcamp/Mk4-Apps", ref="master"):
|
||||||
|
@ -28,8 +28,19 @@ class BadgeStore:
|
||||||
def get_app(self, app):
|
def get_app(self, app):
|
||||||
return self._call("app", {"app": app})
|
return self._call("app", {"app": app})
|
||||||
|
|
||||||
def call_install(self, apps):
|
def install(self, apps):
|
||||||
files = self._call("install", {"apps": ",".join(apps)})
|
return self._create_installers(self._call("install", {"apps": ",".join(apps)}))
|
||||||
|
|
||||||
|
def bootstrap(self):
|
||||||
|
return self._create_installers(self._call("bootstrap"))
|
||||||
|
|
||||||
|
def _call(self, command, params = {}):
|
||||||
|
params["repo"] = self.repo
|
||||||
|
params["ref"] = self.ref
|
||||||
|
with get("%s/%s" % (self.url, command), params=params).raise_for_status() as response:
|
||||||
|
return response.json() # todo: error handling
|
||||||
|
|
||||||
|
def _create_installers(self, files):
|
||||||
installers = []
|
installers = []
|
||||||
url = "%s/download" % (self.url)
|
url = "%s/download" % (self.url)
|
||||||
for path, hash in files.items():
|
for path, hash in files.items():
|
||||||
|
@ -39,24 +50,9 @@ class BadgeStore:
|
||||||
installers.append(Installer(path, url, params, hash))
|
installers.append(Installer(path, url, params, hash))
|
||||||
return installers
|
return installers
|
||||||
|
|
||||||
def install(self, app):
|
|
||||||
return self.call_install(self._get_current_apps() + [app])
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
return self.call_install(self._get_current_apps())
|
|
||||||
|
|
||||||
def _call(self, command, params = {}):
|
|
||||||
params["repo"] = self.repo
|
|
||||||
params["ref"] = self.ref
|
|
||||||
with get("%s/%s" % (self.url, command), params=params).raise_for_status() as response:
|
|
||||||
return response.json() # todo: error handling
|
|
||||||
|
|
||||||
def _is_file_up_to_date(self, path, hash):
|
def _is_file_up_to_date(self, path, hash):
|
||||||
return hash == _get_hash(path)
|
return hash == _get_hash(path)
|
||||||
|
|
||||||
def _get_current_apps(self):
|
|
||||||
return [a.name for a in app.get_apps()]
|
|
||||||
|
|
||||||
TEMP_FILE = ".tmp.download"
|
TEMP_FILE = ".tmp.download"
|
||||||
|
|
||||||
class Installer:
|
class Installer:
|
||||||
|
@ -70,7 +66,6 @@ class Installer:
|
||||||
count = 0
|
count = 0
|
||||||
while get_hash(TEMP_FILE) != self.hash:
|
while get_hash(TEMP_FILE) != self.hash:
|
||||||
count += 1
|
count += 1
|
||||||
print(count)
|
|
||||||
if count > 5:
|
if count > 5:
|
||||||
try:
|
try:
|
||||||
os.remove(TEMP_FILE)
|
os.remove(TEMP_FILE)
|
||||||
|
@ -78,7 +73,6 @@ class Installer:
|
||||||
pass
|
pass
|
||||||
raise OSError("Aborting download of %s after 5 unsuccessful attempts" % self.path)
|
raise OSError("Aborting download of %s after 5 unsuccessful attempts" % self.path)
|
||||||
try:
|
try:
|
||||||
print("download ", self.url, self.params)
|
|
||||||
get(self.url, params=self.params).raise_for_status().download_to(TEMP_FILE)
|
get(self.url, params=self.params).raise_for_status().download_to(TEMP_FILE)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if "404" in str(e):
|
if "404" in str(e):
|
||||||
|
|
|
@ -39,13 +39,19 @@ class TestBadgeStore(unittest.TestCase):
|
||||||
def test_install_integration(self):
|
def test_install_integration(self):
|
||||||
self._remove_download_file()
|
self._remove_download_file()
|
||||||
store = BadgeStore(url="http://badge.marekventur.com", repo="emfcamp/Mk4-Apps", ref="dont-delete-test-download-branch")
|
store = BadgeStore(url="http://badge.marekventur.com", repo="emfcamp/Mk4-Apps", ref="dont-delete-test-download-branch")
|
||||||
for installer in store.call_install(["launcher"]):
|
for installer in store.install(["launcher"]):
|
||||||
if installer.path == "shared/test/download.txt":
|
if installer.path == "shared/test/download.txt":
|
||||||
installer.download()
|
installer.download()
|
||||||
|
|
||||||
with open(self.download_file, "rt") as response:
|
with open(self.download_file, "rt") as response:
|
||||||
self.assertIn("I'm a download test", response.read())
|
self.assertIn("I'm a download test", response.read())
|
||||||
|
|
||||||
|
def test_bootstrap_integration(self):
|
||||||
|
self._remove_download_file()
|
||||||
|
store = BadgeStore(url="http://badge.marekventur.com")
|
||||||
|
installers = store.bootstrap()
|
||||||
|
self.assertTrue(len(installers) > 0)
|
||||||
|
|
||||||
def _remove_download_file(self):
|
def _remove_download_file(self):
|
||||||
if isdir(self.download_file) or isfile(self.download_file):
|
if isdir(self.download_file) or isfile(self.download_file):
|
||||||
os.remove(self.download_file)
|
os.remove(self.download_file)
|
||||||
|
|
Loading…
Reference in New Issue