Changes needed to get the kiosk to run on the rpi.
authorScott Gasch <[email protected]>
Wed, 24 Mar 2021 01:42:06 +0000 (18:42 -0700)
committerScott Gasch <[email protected]>
Wed, 24 Mar 2021 01:42:06 +0000 (18:42 -0700)
chooser.py
constants.py
health_renderer.py
kiosk.py
local_photos_mirror_renderer.py
reddit_renderer.py
renderer_catalog.py

index 743aa3a625aab18e7fbec57ab69c05394cad03d3..3fecc09717ff47c43988d76ac167b79cc2e4ef3d 100644 (file)
@@ -136,6 +136,7 @@ class weighted_random_chooser_with_triggers(weighted_random_chooser):
         triggered = self.check_for_triggers()
 
         # First try to satisfy from the page queue.
+        now = datetime.datetime.now()
         if len(self.page_queue) > 0:
             print("chooser: Pulling page from queue...")
             page = None
@@ -149,6 +150,12 @@ class weighted_random_chooser_with_triggers(weighted_random_chooser):
             self.page_queue.remove((page, priority))
             return (page, triggered)
 
+        # Always show the clock in the middle of the night.
+        elif now.hour < 7:
+            for page in self.pages:
+                if "clock" in page:
+                    return (page, False)
+
         # Fall back on weighted random choice.
         else:
             return (weighted_random_chooser.choose_next_page(self), False)
index 3c391d452169a3ed8d06177452f5cf86f95af5d8..3463ea6e2cc6b3d6518dab346724d62dcc8e9cf4 100644 (file)
@@ -4,6 +4,7 @@ hostname = 'kiosk.house'
 pages_dir = "/var/www/kiosk/pages"
 
 refresh_period_sec = 22.0
+refresh_period_night_sec = 600.0
 render_period_sec = 30.0
 
 seconds_per_minute = 60
index 302e793efda2b5e5ae968a38ffcaa8adab22e1a0..d369630429bb1441f4b1fe3d6dc058cce6d01dbe 100644 (file)
@@ -2,7 +2,7 @@
 
 import os
 import time
-from typing import Dict
+from typing import Dict, List
 
 import constants
 import file_writer
index 7ffce23d6d85a4b65eb465e231a52d87355b78cc..2c75dd09a50e76e895ba003e717600a3804ad97c 100755 (executable)
--- a/kiosk.py
+++ b/kiosk.py
@@ -1,11 +1,14 @@
 #!/usr/bin/env python3
 
 from datetime import datetime
+import gc
+import linecache
 import os
 import sys
 from threading import Thread
 import time
 import traceback
+import tracemalloc
 from typing import Optional
 
 import constants
@@ -32,6 +35,48 @@ def filter_news_during_dinnertime(page: str) -> bool:
     )
 
 
+def thread_janitor() -> None:
+    tracemalloc.start()
+    tracemalloc_target = 0.0
+    gc_target = 0.0
+    gc.enable()
+
+    while True:
+        now = time.time()
+        if now > tracemalloc_target:
+            tracemalloc_target = now + 30.0
+            snapshot = tracemalloc.take_snapshot()
+            snapshot = snapshot.filter_traces((
+                tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
+                tracemalloc.Filter(False, "<unknown>"),
+            ))
+            key_type = 'lineno'
+            limit = 10
+            top_stats = snapshot.statistics(key_type)
+            print("janitor: Top %s lines" % limit)
+            for index, stat in enumerate(top_stats[:limit], 1):
+                frame = stat.traceback[0]
+                # replace "/path/to/module/file.py" with "module/file.py"
+                filename = os.sep.join(frame.filename.split(os.sep)[-2:])
+                print("janitor: #%s: %s:%s: %.1f KiB"
+                      % (index, filename, frame.lineno, stat.size / 1024))
+                line = linecache.getline(frame.filename, frame.lineno).strip()
+                if line:
+                    print('janitor:    %s' % line)
+
+            other = top_stats[limit:]
+            if other:
+                size = sum(stat.size for stat in other)
+                print("janitor: %s other: %.1f KiB" % (len(other), size / 1024))
+            total = sum(stat.size for stat in top_stats)
+            print("janitor: Total allocated size: %.1f KiB" % (total / 1024))
+        if now > gc_target:
+            print("janitor: Running gc operation")
+            gc_target = now + 60.0
+            gc.collect()
+        time.sleep(10.0)
+
+
 def thread_change_current() -> None:
     page_chooser = chooser.weighted_random_chooser_with_triggers(
         trigger_catalog.get_triggers(), [filter_news_during_dinnertime]
@@ -102,6 +147,13 @@ def emit_wrapped(f, filename) -> None:
         else:
             return "FFFFFF"
 
+    def get_refresh_period() -> float:
+        now = datetime.now()
+        if now.hour < 7:
+            return constants.refresh_period_night_sec * 1000
+        else:
+            return constants.refresh_period_sec * 1000
+
     age = utils.describe_age_of_file_briefly(f"pages/{filename}")
     bgcolor = pick_background_color()
     f.write(
@@ -292,7 +344,7 @@ def emit_wrapped(f, filename) -> None:
 </BODY>"""
         % (
             bgcolor,
-            constants.refresh_period_sec * 1000,
+            get_refresh_period(),
             constants.hostname,
             bgcolor,
             filename,
@@ -329,6 +381,7 @@ if __name__ == "__main__":
     logging.basicConfig()
     changer_thread: Optional[Thread] = None
     renderer_thread: Optional[Thread] = None
+    janitor_thread: Optional[Thread] = None
     while True:
         if changer_thread is None or not changer_thread.is_alive():
             print(
@@ -342,4 +395,10 @@ if __name__ == "__main__":
             )
             renderer_thread = Thread(target=thread_invoke_renderers, args=())
             renderer_thread.start()
+        if janitor_thread is None or not janitor_thread.is_alive():
+            print(
+                f"MAIN[{utils.timestamp()}] - (Re?)initializing janitor thread... (wtf?!)"
+            )
+            janitor_thread = Thread(target=thread_janitor, args=())
+            janitor_thread.start()
         time.sleep(60)
index b27a7918feba389de82897941806bda83ee6ac99..287bdd697ecdfad96c93e47aa12619463cee54f9 100644 (file)
@@ -5,7 +5,6 @@ import random
 import re
 from typing import Dict, Set
 
-import constants
 import file_writer
 import renderer
 
@@ -13,7 +12,7 @@ import renderer
 class local_photos_mirror_renderer(renderer.debuggable_abstaining_renderer):
     """A renderer that uses a local mirror of Google photos"""
 
-    ALBUM_ROOT_DIR = "/var/www/kiosk/pages/images/gphotos/albums"
+    album_root_directory = "/var/www/kiosk/pages/images/gphotos/albums"
 
     album_whitelist = frozenset(
         [
@@ -87,7 +86,7 @@ class local_photos_mirror_renderer(renderer.debuggable_abstaining_renderer):
         """Walk the filesystem looking for photos in whitelisted albums and
         keep their paths in memory.
         """
-        for root, subdirs, files in os.walk(self.ALBUM_ROOT_DIR):
+        for root, subdirs, files in os.walk(self.album_root_directory):
             last_dir = root.rsplit("/", 1)[1]
             if self.album_is_in_whitelist(last_dir):
                 for filename in files:
@@ -95,7 +94,7 @@ class local_photos_mirror_renderer(renderer.debuggable_abstaining_renderer):
                     if extension in self.extension_whitelist:
                         photo_path = os.path.join(root, filename)
                         photo_url = photo_path.replace(
-                            "/var/www/", f"http://{constants.hostname}/", 1
+                            "/var/www/", "http://kiosk.house/", 1
                         )
                         self.candidate_photos.add(photo_url)
         return True
index a4050a20f0f47dcd9b2e2ed6ce294c34d2b5411c..74bddaffa1b368e0163232855b400ab08c02be40 100644 (file)
@@ -179,7 +179,7 @@ class showerthoughts_reddit_renderer(reddit_renderer):
         super(showerthoughts_reddit_renderer, self).__init__(
             name_to_timeout_dict,
             ["showerthoughts"],
-            min_votes=350,
+            min_votes=250,
             additional_filters=[
                 showerthoughts_reddit_renderer.dont_tell_me_about_gift_cards
             ],
index 3fa9d2ad61a757cc2fce447ecc25041d692d3c63..6eccb6ebab3fbb8e9b49ba6bac44568f1e7a484b 100644 (file)
@@ -128,12 +128,13 @@ __registry = [
         "Seattle Times Segments",
     ),
     weather_renderer.weather_renderer(
-        {"Fetch Weather (Bellevue)": (hours * 4)}, "home"
+        {"Fetch Weather (Bellevue)": (hours * 6)}, "home"
     ),
     weather_renderer.weather_renderer(
-        {"Fetch Weather (Stevens)": (hours * 4)}, "stevens"
+        {"Fetch Weather (Stevens)": (hours * 6)}, "stevens"
     ),
-    weather_renderer.weather_renderer({"Fetch Weather (Telma)": (hours * 4)}, "telma"),
+    weather_renderer.weather_renderer(
+        {"Fetch Weather (Telma)": (hours * 6)}, "telma"),
     local_photos_mirror_renderer.local_photos_mirror_renderer(
         {"Index Photos": (hours * 24), "Choose Photo": (always)}
     ),