apps: WordClock: Add a new word-based clock app
Signed-off-by: Brendan M. Sleight <bms.git@barwap.com> [daniel@redfelineninja.org.uk: Squashed down into a single commit and updated subject] Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk
This commit is contained in:
parent
867ed324b5
commit
cec8d97aeb
4 changed files with 201 additions and 0 deletions
|
@ -219,3 +219,7 @@ application (and the "blank" white screen is a torch application):
|
|||
.. image:: res/TimerApp.png
|
||||
:alt: Countdown timer application running in the wasp-os simulator
|
||||
:width: 179
|
||||
|
||||
.. image:: res/WordClkApp.png
|
||||
:alt: Shows a time as words in the wasp-os simulator
|
||||
:width: 179
|
||||
|
|
|
@ -15,6 +15,8 @@ Watch faces
|
|||
|
||||
.. automodule:: apps.fibonacci_clock
|
||||
|
||||
.. automodule:: apps.word_clock
|
||||
|
||||
Built-in
|
||||
--------
|
||||
|
||||
|
|
BIN
res/WordClkApp.png
Normal file
BIN
res/WordClkApp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
195
wasp/apps/word_clock.py
Normal file
195
wasp/apps/word_clock.py
Normal file
|
@ -0,0 +1,195 @@
|
|||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
# Copyright (C) 2020 Daniel Thompson
|
||||
# Copyright (C) 2021 Brendan Sleight
|
||||
|
||||
|
||||
"""Word clock
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Shows a time as words together with a battery meter and the date.
|
||||
|
||||
.. figure:: res/WordClkApp.png
|
||||
:width: 179
|
||||
"""
|
||||
|
||||
import wasp
|
||||
|
||||
import icons
|
||||
|
||||
MONTH = 'JanFebMarAprMayJunJulAugSepOctNovDec'
|
||||
|
||||
|
||||
class WordClockApp():
|
||||
"""Simple digital clock application."""
|
||||
NAME = 'WordClk'
|
||||
ICON = icons.app
|
||||
|
||||
def foreground(self):
|
||||
"""Activate the application.
|
||||
|
||||
Configure the status bar, redraw the display and request a periodic
|
||||
tick callback every second.
|
||||
"""
|
||||
wasp.system.bar.clock = False
|
||||
self._draw(True)
|
||||
wasp.system.request_tick(1000)
|
||||
|
||||
def sleep(self):
|
||||
"""Prepare to enter the low power mode.
|
||||
|
||||
:returns: True, which tells the system manager not to automatically
|
||||
switch to the default application before sleeping.
|
||||
"""
|
||||
return True
|
||||
|
||||
def wake(self):
|
||||
"""Return from low power mode.
|
||||
|
||||
Time will have changes whilst we have been asleep so we must
|
||||
udpate the display (but there is no need for a full redraw because
|
||||
the display RAM is preserved during a sleep.
|
||||
"""
|
||||
self._draw()
|
||||
|
||||
def tick(self, ticks):
|
||||
"""Periodic callback to update the display."""
|
||||
self._draw()
|
||||
|
||||
def _draw(self, redraw=False):
|
||||
"""Draw or lazily update the display.
|
||||
|
||||
The updates are as lazy by default and avoid spending time redrawing
|
||||
if the time on display has not changed. However if redraw is set to
|
||||
True then a full redraw is be performed.
|
||||
"""
|
||||
draw = wasp.watch.drawable
|
||||
hi = wasp.system.theme('bright')
|
||||
|
||||
if redraw:
|
||||
now = wasp.watch.rtc.get_localtime()
|
||||
|
||||
# Clear the display and draw that static parts of the watch face
|
||||
draw.fill()
|
||||
|
||||
# Redraw the status bar
|
||||
wasp.system.bar.draw()
|
||||
else:
|
||||
# The update is doubly lazy... we update the status bar and if
|
||||
# the status bus update reports a change in the time of day
|
||||
# then we compare the minute on display to make sure we
|
||||
# only update the main clock once per minute.
|
||||
now = wasp.system.bar.update()
|
||||
if not now or self._min == now[4]:
|
||||
# Skip the update
|
||||
return
|
||||
draw.set_color(hi)
|
||||
|
||||
# Format the month as text
|
||||
month = now[1] - 1
|
||||
month = MONTH[month*3:(month+1)*3]
|
||||
# Record the minute that is currently being displayed
|
||||
self._hour = now[3]
|
||||
self._min = now[4]
|
||||
|
||||
# Testing
|
||||
# self._hour = 23
|
||||
# self._min = 59
|
||||
|
||||
# Convert to words
|
||||
part_day = ""
|
||||
hour = ""
|
||||
part_hour = ""
|
||||
minute_words= ""
|
||||
|
||||
part_day = ""
|
||||
|
||||
hours_a = ["midnight", "one", "two",
|
||||
"three", "four", "five",
|
||||
"six", "seven", "eight",
|
||||
"nine", "ten", "eleven",
|
||||
"twelve",
|
||||
"one", "two",
|
||||
"three", "four", "five",
|
||||
"six", "seven", "eight",
|
||||
"nine", "ten", "eleven"]
|
||||
if (self._min > 32):
|
||||
hour = hours_a[(self._hour + 1) % 24]
|
||||
else:
|
||||
hour = hours_a[self._hour % 24]
|
||||
if (hour != "midnight" and hour != "twelve"):
|
||||
if (self._hour >= 22):
|
||||
part_day = " at night"
|
||||
elif (self._hour >= 18):
|
||||
part_day = " in the evening"
|
||||
elif (self._hour >= 12):
|
||||
part_day = " in the afternoon"
|
||||
elif (self._hour >= 6):
|
||||
part_day = " in the morning"
|
||||
elif (self._hour >= 3):
|
||||
part_day = " in the early hours"
|
||||
elif (self._hour >= 0):
|
||||
part_day = " at night"
|
||||
|
||||
if (self._min > 57):
|
||||
part_hour = ""
|
||||
elif (self._min > 52):
|
||||
part_hour = "five to "
|
||||
elif (self._min > 47):
|
||||
part_hour = "ten to "
|
||||
elif (self._min > 42):
|
||||
part_hour = "quarter to "
|
||||
elif (self._min > 37):
|
||||
part_hour = "twenty to "
|
||||
elif (self._min > 32):
|
||||
part_hour = "twenty-five to "
|
||||
elif (self._min > 27):
|
||||
part_hour = "half past "
|
||||
elif (self._min > 22):
|
||||
part_hour = "twenty-five past "
|
||||
elif (self._min > 17):
|
||||
part_hour = "twenty past "
|
||||
elif (self._min > 12):
|
||||
part_hour = "quarter past "
|
||||
elif (self._min > 7):
|
||||
part_hour = "ten past "
|
||||
elif (self._min > 2):
|
||||
part_hour = "five past "
|
||||
else:
|
||||
part_hour = ""
|
||||
|
||||
minute_words_int = (self._min % 5)
|
||||
if (minute_words_int == 4):
|
||||
minute_words = "almost"
|
||||
if (minute_words_int == 3):
|
||||
minute_words = "coming up to"
|
||||
if (minute_words_int == 2):
|
||||
minute_words = "after"
|
||||
if (minute_words_int == 1):
|
||||
minute_words = "just gone"
|
||||
|
||||
self._words = ""
|
||||
if (minute_words !=""):
|
||||
self._words = minute_words + "\n"
|
||||
if (part_hour !=""):
|
||||
self._words = self._words + part_hour + "\n"
|
||||
self._words = self._words + hour + "\n"
|
||||
if (part_day !=""):
|
||||
self._words = self._words + part_day
|
||||
|
||||
# No capitilise in Micropython
|
||||
# ASCII convert
|
||||
self._words = chr(ord(self._words[0])-32) + self._words[1:]
|
||||
|
||||
# Some phases may be 5 lines long, some may be 1
|
||||
draw.fill(0, 0, 48)
|
||||
|
||||
chunks = draw.wrap(self._words, 240)
|
||||
lines_of_text = len(chunks)-1
|
||||
offset_y=int(((5-lines_of_text/2)*26))
|
||||
|
||||
for i in range(len(chunks)-1):
|
||||
sub = self._words[chunks[i]:chunks[i+1]].rstrip()
|
||||
draw.string(sub, 0, offset_y+26*i, 240)
|
||||
|
||||
draw.string('{} {} {}'.format(now[2], month, now[0]),
|
||||
0, 214, width=240)
|
Loading…
Reference in a new issue