summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrendan M. Sleight <bms.git@barwap.com>2021-03-05 19:43:06 (GMT)
committerDaniel Thompson <daniel@redfelineninja.org.uk>2021-03-10 20:55:18 (GMT)
commitcec8d97aeb47002697c07ea9ad6d8b0bd5a9b6bf (patch)
tree43d8a282481a4160d5decf2036a8c14c2f421308
parent867ed324b5044e09df7d28ec67c2bc94812297bb (diff)
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
-rw-r--r--README.rst4
-rw-r--r--docs/apps.rst2
-rw-r--r--res/WordClkApp.pngbin0 -> 11841 bytes
-rw-r--r--wasp/apps/word_clock.py195
4 files changed, 201 insertions, 0 deletions
diff --git a/README.rst b/README.rst
index 2a8d1e3..11c3ad4 100644
--- a/README.rst
+++ b/README.rst
@@ -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
diff --git a/docs/apps.rst b/docs/apps.rst
index d015852..a326006 100644
--- a/docs/apps.rst
+++ b/docs/apps.rst
@@ -15,6 +15,8 @@ Watch faces
.. automodule:: apps.fibonacci_clock
+.. automodule:: apps.word_clock
+
Built-in
--------
diff --git a/res/WordClkApp.png b/res/WordClkApp.png
new file mode 100644
index 0000000..686b07e
--- /dev/null
+++ b/res/WordClkApp.png
Binary files differ
diff --git a/wasp/apps/word_clock.py b/wasp/apps/word_clock.py
new file mode 100644
index 0000000..a7f2d63
--- /dev/null
+++ b/wasp/apps/word_clock.py
@@ -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)