apps: steps: Add a history graph
The steplogger records steps but currently there is no way to see the data recorded on the device itself. Make a first attempt at graphing the step data. Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
This commit is contained in:
parent
72f5322cc3
commit
7a5990072c
3 changed files with 82 additions and 9 deletions
|
@ -47,7 +47,7 @@ class StepCounterApp():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
watch.accel.reset()
|
watch.accel.reset()
|
||||||
self._count = 0
|
self._scroll = wasp.widgets.ScrollIndicator()
|
||||||
self._wake = 0
|
self._wake = 0
|
||||||
|
|
||||||
def foreground(self):
|
def foreground(self):
|
||||||
|
@ -63,7 +63,9 @@ class StepCounterApp():
|
||||||
"""
|
"""
|
||||||
wasp.system.cancel_alarm(self._wake, self._reset)
|
wasp.system.cancel_alarm(self._wake, self._reset)
|
||||||
wasp.system.bar.clock = True
|
wasp.system.bar.clock = True
|
||||||
|
self._page = -1
|
||||||
self._draw()
|
self._draw()
|
||||||
|
wasp.system.request_event(wasp.EventMask.SWIPE_UPDOWN)
|
||||||
wasp.system.request_tick(1000)
|
wasp.system.request_tick(1000)
|
||||||
|
|
||||||
def background(self):
|
def background(self):
|
||||||
|
@ -83,25 +85,48 @@ class StepCounterApp():
|
||||||
self._wake += 24 * 60 * 60
|
self._wake += 24 * 60 * 60
|
||||||
wasp.system.set_alarm(self._wake, self._reset)
|
wasp.system.set_alarm(self._wake, self._reset)
|
||||||
|
|
||||||
|
def swipe(self, event):
|
||||||
|
if event[0] == wasp.EventType.DOWN:
|
||||||
|
if self._page == -1:
|
||||||
|
return
|
||||||
|
self._page -= 1
|
||||||
|
else:
|
||||||
|
self._page += 1
|
||||||
|
|
||||||
|
mute = wasp.watch.display.mute
|
||||||
|
mute(True)
|
||||||
|
self._draw()
|
||||||
|
mute(False)
|
||||||
|
|
||||||
def tick(self, ticks):
|
def tick(self, ticks):
|
||||||
self._count += 686;
|
if self._page == -1:
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def _draw(self):
|
def _draw(self):
|
||||||
"""Draw the display from scratch."""
|
"""Draw the display from scratch."""
|
||||||
draw = wasp.watch.drawable
|
draw = wasp.watch.drawable
|
||||||
draw.fill()
|
draw.fill()
|
||||||
draw.blit(feet, 12, 132-24)
|
|
||||||
|
|
||||||
|
if self._page == -1:
|
||||||
self._update()
|
self._update()
|
||||||
wasp.system.bar.draw()
|
wasp.system.bar.draw()
|
||||||
|
else:
|
||||||
|
self._update_graph()
|
||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
draw = wasp.watch.drawable
|
draw = wasp.watch.drawable
|
||||||
|
|
||||||
|
# Draw the icon
|
||||||
|
draw.blit(feet, 12, 132-24)
|
||||||
|
|
||||||
# Update the status bar
|
# Update the status bar
|
||||||
now = wasp.system.bar.update()
|
now = wasp.system.bar.update()
|
||||||
|
|
||||||
|
# Update the scroll indicator
|
||||||
|
scroll = self._scroll
|
||||||
|
scroll.up = False
|
||||||
|
scroll.draw()
|
||||||
|
|
||||||
# Update the step count
|
# Update the step count
|
||||||
count = watch.accel.steps
|
count = watch.accel.steps
|
||||||
t = str(count)
|
t = str(count)
|
||||||
|
@ -109,3 +134,44 @@ class StepCounterApp():
|
||||||
draw.set_font(fonts.sans36)
|
draw.set_font(fonts.sans36)
|
||||||
draw.set_color(draw.lighten(wasp.system.theme('spot1'), wasp.system.theme('contrast')))
|
draw.set_color(draw.lighten(wasp.system.theme('spot1'), wasp.system.theme('contrast')))
|
||||||
draw.string(t, 228-w, 132-18)
|
draw.string(t, 228-w, 132-18)
|
||||||
|
|
||||||
|
def _update_graph(self):
|
||||||
|
draw = watch.drawable
|
||||||
|
draw.set_font(fonts.sans24)
|
||||||
|
draw.set_color(0xffff)
|
||||||
|
|
||||||
|
# Draw the date
|
||||||
|
now = int(watch.rtc.time())
|
||||||
|
then = now - ((24*60*60) * self._page)
|
||||||
|
walltime = time.localtime(then)
|
||||||
|
draw.string('{:02d}-{:02d}'.format(walltime[2], walltime[1]), 0, 0)
|
||||||
|
|
||||||
|
# Get the iterable step date for the currently selected date
|
||||||
|
data = wasp.system.steps.data(then)
|
||||||
|
|
||||||
|
# Bail if there is no data
|
||||||
|
if not data:
|
||||||
|
draw.string('No data', 239-160, 0, 160, right=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
color = wasp.system.theme('spot2')
|
||||||
|
|
||||||
|
# Draw the frame
|
||||||
|
draw.fill(0x3969, 0, 39, 240, 1)
|
||||||
|
draw.fill(0x3969, 0, 239, 240, 1)
|
||||||
|
for i in (0, 60, 90, 120, 150, 180, 239):
|
||||||
|
draw.fill(0x3969, i, 39, 1, 201)
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
for x, d in enumerate(data):
|
||||||
|
if d == 0 or x < 2:
|
||||||
|
# TODO: the x < 2 conceals BUGZ
|
||||||
|
continue
|
||||||
|
total += d
|
||||||
|
d = d // 3
|
||||||
|
if d > 200:
|
||||||
|
draw.fill(0xffff, x, 239-200, 1, 200)
|
||||||
|
else:
|
||||||
|
draw.fill(color, x, 239-d, 1, d)
|
||||||
|
|
||||||
|
draw.string(str(total), 239-160, 0, 160, right=True)
|
||||||
|
|
|
@ -58,7 +58,7 @@ class StepIterator:
|
||||||
self._f = None
|
self._f = None
|
||||||
|
|
||||||
class StepLogger:
|
class StepLogger:
|
||||||
def __init__(self):
|
def __init__(self, manager):
|
||||||
self._data = array.array('H', (0,) * DUMP_LENGTH)
|
self._data = array.array('H', (0,) * DUMP_LENGTH)
|
||||||
self._steps = wasp.watch.accel.steps
|
self._steps = wasp.watch.accel.steps
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class StepLogger:
|
||||||
|
|
||||||
# Queue a tick
|
# Queue a tick
|
||||||
self._t = int(wasp.watch.rtc.time()) // TICK_PERIOD * TICK_PERIOD
|
self._t = int(wasp.watch.rtc.time()) // TICK_PERIOD * TICK_PERIOD
|
||||||
wasp.system.set_alarm(self._t + TICK_PERIOD, self._tick)
|
manager.set_alarm(self._t + TICK_PERIOD, self._tick)
|
||||||
|
|
||||||
def _tick(self):
|
def _tick(self):
|
||||||
"""Capture the current step count in N minute intervals.
|
"""Capture the current step count in N minute intervals.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import gc
|
import gc
|
||||||
import machine
|
import machine
|
||||||
import micropython
|
import micropython
|
||||||
|
import steplogger
|
||||||
import watch
|
import watch
|
||||||
import widgets
|
import widgets
|
||||||
|
|
||||||
|
@ -153,7 +154,13 @@ class Manager():
|
||||||
(SoftwareApp, False),
|
(SoftwareApp, False),
|
||||||
(SettingsApp, False) ):
|
(SettingsApp, False) ):
|
||||||
try:
|
try:
|
||||||
self.register(app(), qr)
|
a = app()
|
||||||
|
|
||||||
|
# Special case for watches with working step counters!
|
||||||
|
if isinstance(a, StepCounterApp):
|
||||||
|
self.steps = steplogger.StepLogger(self)
|
||||||
|
|
||||||
|
self.register(a, qr)
|
||||||
except:
|
except:
|
||||||
# Let's not bring the whole device down just because there's
|
# Let's not bring the whole device down just because there's
|
||||||
# an exception starting one of the apps...
|
# an exception starting one of the apps...
|
||||||
|
|
Loading…
Reference in a new issue