Rename manager.py and expose its interfaces to all applications

This is a big change that break compatiblity with existing applications
*and* with existing installed versions of main.py.

When upgrading it is import to update main.py:

    ./tools/wasptool --upload wasp/main.py
This commit is contained in:
Daniel Thompson 2020-03-22 12:37:19 +00:00
parent 5a234c16ad
commit f8bd1a7461
8 changed files with 75 additions and 62 deletions

View File

@ -4,7 +4,7 @@ WASP Internals
System management
-----------------
.. automodule:: manager
.. automodule:: wasp
:members:
:undoc-members:

View File

@ -14,6 +14,11 @@ import string
import sys
def sync(c):
"""Stop the watch and synchronize with the command prompt.
Sending a random print ensure the final export (of the prompt)
does not accidentally match a previously issued prompt.
"""
tag = ''.join([random.choice(string.ascii_uppercase) for i in range(6)])
c.send('\x03')
@ -23,8 +28,14 @@ def sync(c):
c.expect('>>> ')
def unsync(c):
# Set the watch running again
c.sendline('wasp.run()')
"""Set the watch running again.
There must be an expect (or a sleep) since if we kill the subordinate
process too early then the sendline will not have completed.
"""
c.sendline('wasp.system.run()')
c.expect('Watch is running, use Ctrl-C to stop')
c.send('\x18')
def paste(c, f, verbose=False):
docstring = False

View File

@ -1,7 +1,6 @@
import wasp
import fonts.clock as digits
import watch
import widgets
import manager
DIGITS = (
digits.clock_0,
@ -18,28 +17,28 @@ DIGITS = (
MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec'
class ClockApp(object):
class ClockApp():
"""Simple digital clock application.
Shows a time (as HH:MM) together with a battery meter and the date.
"""
def __init__(self):
self.meter = widgets.BatteryMeter()
self.meter = wasp.widgets.BatteryMeter()
def handle_event(self, event_view):
"""Process events that the app is subscribed to."""
if event_view[0] == manager.EVENT_TICK:
if event_view[0] == wasp.EVENT_TICK:
self.update()
else:
# TODO: Raise an unexpected event exception
pass
def foreground(self, manager, effect=None):
def foreground(self, effect=None):
"""Activate the application."""
self.on_screen = ( -1, -1, -1, -1, -1, -1 )
self.draw(effect)
manager.request_tick(1000)
wasp.system.request_tick(1000)
def tick(self, ticks):
self.update()
@ -56,7 +55,7 @@ class ClockApp(object):
def draw(self, effect=None):
"""Redraw the display from scratch."""
draw = watch.drawable
draw = wasp.watch.drawable
draw.fill()
draw.rleblit(digits.clock_colon, pos=(2*48, 80), fg=0xb5b6)
@ -70,14 +69,14 @@ class ClockApp(object):
The updates are a lazy as possible and rely on an prior call to
draw() to ensure the screen is suitably prepared.
"""
now = watch.rtc.get_localtime()
now = wasp.watch.rtc.get_localtime()
if now[3] == self.on_screen[3] and now[4] == self.on_screen[4]:
if now[5] != self.on_screen[5]:
self.meter.update()
self.on_screen = now
return False
draw = watch.drawable
draw = wasp.watch.drawable
draw.rleblit(DIGITS[now[4] % 10], pos=(4*48, 80))
draw.rleblit(DIGITS[now[4] // 10], pos=(3*48, 80), fg=0xbdb6)
draw.rleblit(DIGITS[now[3] % 10], pos=(1*48, 80))

View File

@ -1,5 +1,4 @@
import watch
import manager
import wasp
class FlashlightApp(object):
"""Trivial flashlight application.
@ -10,11 +9,11 @@ class FlashlightApp(object):
def __init__(self):
self.backlight = None
def foreground(self, manager, effect=None):
def foreground(self, effect=None):
"""Activate the application."""
self.on_screen = ( -1, -1, -1, -1, -1, -1 )
self.draw(effect)
manager.request_tick(1000)
wasp.system.request_tick(1000)
def background(self):
"""De-activate the application (without losing state)."""
@ -28,5 +27,5 @@ class FlashlightApp(object):
def draw(self, effect=None):
"""Redraw the display from scratch."""
display = watch.display
display = wasp.watch.display
display.fill(0xffff)

View File

@ -1,7 +1,5 @@
import watch
import widgets
import manager
import machine
import wasp
class TestApp():
"""Simple test application.
@ -11,11 +9,11 @@ class TestApp():
self.tests = ('Touch', 'String')
self.test = self.tests[0]
def foreground(self, system, effect=None):
def foreground(self, effect=None):
"""Activate the application."""
self.on_screen = ( -1, -1, -1, -1, -1, -1 )
self.draw(effect)
system.request_event(manager.EVENT_TOUCH | manager.EVENT_SWIPE_UPDOWN)
wasp.system.request_event(wasp.EVENT_TOUCH | wasp.EVENT_SWIPE_UPDOWN)
def background(self):
"""De-activate the application (without losing state)."""
@ -33,7 +31,7 @@ class TestApp():
self.draw()
def touch(self, event):
draw = watch.drawable
draw = wasp.watch.drawable
if self.test == 'Touch':
draw.string('({}, {})'.format(event[1], event[2]),
0, 108, width=240)
@ -55,8 +53,8 @@ class TestApp():
def draw(self, effect=None):
"""Redraw the display from scratch."""
watch.display.mute(True)
watch.drawable.fill()
watch.drawable.string('{} test'.format(self.test),
wasp.watch.display.mute(True)
wasp.watch.drawable.fill()
wasp.watch.drawable.string('{} test'.format(self.test),
0, 6, width=240)
watch.display.mute(False)
wasp.watch.display.mute(False)

View File

@ -17,8 +17,8 @@ freeze('../..',
'fonts/sans24.py',
'icons.py',
'logo.py',
'manager.py',
'shell.py',
'wasp.py',
'widgets.py',
),
opt=3

View File

@ -1,3 +1,2 @@
import manager, watch
wasp = manager.Manager(watch)
wasp.run()
import wasp
wasp.system.run()

View File

@ -1,5 +1,7 @@
import gc
import machine
import watch
import widgets
from apps.clock import ClockApp
from apps.flashlight import FlashlightApp
@ -16,9 +18,7 @@ EVENT_SWIPE_UPDOWN = 0x0004
EVENT_BUTTON = 0x0008
class Manager(object):
def __init__(self, watch):
self.watch = watch
def __init__(self):
self.app = None
self.applications = [
@ -26,17 +26,17 @@ class Manager(object):
FlashlightApp(),
TestApp()
]
self.watch.display.poweron()
self.switch(self.applications[0])
self.watch.backlight.set(2)
self.sleep_at = watch.rtc.uptime + 90
self.charging = True
def switch(self, app):
if self.app:
self.app.background()
else:
# System start up...
watch.display.poweron()
watch.display.mute(True)
watch.backlight.set(2)
self.sleep_at = watch.rtc.uptime + 90
# Clear out any configuration from the old application
self.event_mask = 0
@ -44,9 +44,9 @@ class Manager(object):
self.tick_expiry = None
self.app = app
self.watch.display.mute(True)
app.foreground(self)
self.watch.display.mute(False)
watch.display.mute(True)
app.foreground()
watch.display.mute(False)
def navigate(self, direction=None):
"""Navigate between different applications.
@ -76,10 +76,10 @@ class Manager(object):
tick intervals are not possible.
"""
self.tick_period_ms = period_ms
self.tick_expiry = self.watch.rtc.get_uptime_ms() + period_ms
self.tick_expiry = watch.rtc.get_uptime_ms() + period_ms
def handle_event(self, event):
self.sleep_at = self.watch.rtc.uptime + 15
self.sleep_at = watch.rtc.uptime + 15
event_mask = self.event_mask
if event[0] < 5:
@ -94,7 +94,7 @@ class Manager(object):
self.app.touch(event)
def tick(self):
rtc = self.watch.rtc
rtc = watch.rtc
if self.sleep_at:
if rtc.update() and self.tick_expiry:
@ -107,36 +107,36 @@ class Manager(object):
ticks += 1
self.app.tick(ticks)
if self.watch.button.value():
self.sleep_at = self.watch.rtc.uptime + 15
if watch.button.value():
self.sleep_at = watch.rtc.uptime + 15
event = self.watch.touch.get_event()
event = watch.touch.get_event()
if event:
self.handle_event(event)
if self.watch.rtc.uptime > self.sleep_at:
self.watch.backlight.set(0)
if watch.rtc.uptime > self.sleep_at:
watch.backlight.set(0)
if not self.app.sleep():
self.switch(self.applications[0])
self.app.sleep()
self.watch.display.poweroff()
self.charging = self.watch.battery.charging()
watch.display.poweroff()
self.charging = watch.battery.charging()
self.sleep_at = None
gc.collect()
else:
self.watch.rtc.update()
watch.rtc.update()
charging = self.watch.battery.charging()
if self.watch.button.value() or self.charging != charging:
self.watch.display.poweron()
charging = watch.battery.charging()
if watch.button.value() or self.charging != charging:
watch.display.poweron()
self.app.wake()
self.watch.backlight.set(2)
watch.backlight.set(2)
# Discard any pending touch events
_ = self.watch.touch.get_event()
_ = watch.touch.get_event()
self.sleep_at = self.watch.rtc.uptime + 15
self.sleep_at = watch.rtc.uptime + 15
def run(self):
"""Run the system manager synchronously.
@ -145,6 +145,13 @@ class Manager(object):
normal execution context meaning any exceptions and other problems
can be observed interactively via the console.
"""
if not self.app:
self.switch(self.applications[0])
print('Watch is running, use Ctrl-C to stop')
while True:
self.tick()
machine.deepsleep()
system = Manager()