Fix cameras, improve weather, delegate health renderer to a helper,
[kiosk.git] / kiosk.py
index 514fbac69ea64f32a08070a4d1232881fe8e290a..99d40c30b7f7ebbf427d54d5adef02f7bdf7dc29 100755 (executable)
--- a/kiosk.py
+++ b/kiosk.py
@@ -102,7 +102,7 @@ def guess_page(command: str, page_chooser: chooser.chooser) -> str:
         page = page.replace('mynorthwest', 'northwest news')
         page = page.replace('myq', 'myq garage door status')
         page = page.replace('gomenu', 'dinner menu')
-        page = page.replace('wsdot', 'traffic')
+        page = page.replace('gmaps-seattle-unwrapped', 'traffic')
         page = page.replace('gomenu', 'dinner menu')
         page = page.replace('WSJNews', 'news')
         page = page.replace('telma', 'telma cabin')
@@ -111,6 +111,7 @@ def guess_page(command: str, page_chooser: chooser.chooser) -> str:
         logger.debug(f'normalize_page output: {page}')
         return page
 
+    logger.info(f'No exact match for f{command}; trying to guess...')
     best_page = None
     best_score = None
     for page in page_chooser.get_page_list():
@@ -118,12 +119,15 @@ def guess_page(command: str, page_chooser: chooser.chooser) -> str:
         score = SequenceMatcher(None, command, npage).ratio()
         if best_score is None or score > best_score:
             best_page = page
+            best_score = score
     assert best_page is not None
+    logger.info(f'Best guess for f{command} => {best_page} (score = {best_score})')
     return best_page
 
 
 def process_command(command: str, page_history: List[str], page_chooser) -> str:
-    logger.debug(f'Parsing verbal command: {command}')
+    command = command.lower()
+    logger.info(f'Parsing verbal command: {command}')
     page = None
     if 'hold' in command:
         page = page_history[0]
@@ -186,7 +190,7 @@ def process_command(command: str, page_history: List[str], page_chooser) -> str:
     elif 'twitter' in command:
         page = 'twitter_10_3600.html'
     elif 'traffic' in command:
-        page = 'wsdot-bridges_3_none.html'
+        page = 'gmaps-seattle-unwrapped_5_none.html'
     elif 'front' in command and 'door' in command:
         page = 'hidden/frontdoor.html'
     elif 'driveway' in command:
@@ -196,7 +200,7 @@ def process_command(command: str, page_history: List[str], page_chooser) -> str:
     else:
         page = guess_page(command, page_chooser)
     assert page is not None
-    logger.debug(f'Chose page {page}')
+    logger.info(f'Parsed to {page}')
     return page
 
 
@@ -256,7 +260,7 @@ def thread_change_current(command_queue: Queue) -> None:
                 # Set current.shtml to the right page.
                 try:
                     with open(current_file, "w") as f:
-                        emit_wrapped(
+                        emit(
                             f,
                             page,
                             override_refresh_sec = constants.emergency_refresh_period_sec,
@@ -275,7 +279,7 @@ def thread_change_current(command_queue: Queue) -> None:
 
                 # Fix this hack... maybe read the webserver logs and see if it
                 # actually was picked up?
-                time.sleep(0.95)
+                time.sleep(0.999)
                 os.remove(emergency_file)
                 logger.debug(f'chooser: ...and removed {emergency_file}.')
 
@@ -287,7 +291,7 @@ def thread_change_current(command_queue: Queue) -> None:
             swap_page_target = now + constants.refresh_period_sec
             try:
                 with open(current_file, "w") as f:
-                    emit_wrapped(f, page)
+                    emit(f, page)
                 logger.debug(f'chooser: Wrote {current_file}.')
             except Exception as e:
                 logger.exception(e)
@@ -298,6 +302,23 @@ def thread_change_current(command_queue: Queue) -> None:
         time.sleep(0.5)
 
 
+def emit(f,
+         filename: str,
+         *,
+         override_refresh_sec: int = None,
+         command: str = None):
+    if 'unwrapped' not in filename:
+        logger.debug(f'Emitting {filename} wrapped.')
+        emit_wrapped(f, filename, override_refresh_sec=override_refresh_sec, command=command)
+    else:
+        logger.debug(f'Emitting {filename} raw.')
+        emit_raw(f, filename)
+
+
+def emit_raw(f, filename: str):
+    f.write(f'<!--#include virtual="{filename}"-->')
+
+
 def emit_wrapped(f,
                  filename: str,
                  *,
@@ -583,9 +604,7 @@ def renderer_update_internal_stats_page(
                 p75 = np.percentile(latency, 75)
                 p90 = np.percentile(latency, 90)
                 p99 = np.percentile(latency, 99)
-            except IndexError:
-                pass
-            f.write(
+                f.write(
 f'''
     <TR>
     <TD {style}>{name}&nbsp;</TD>
@@ -594,8 +613,10 @@ f'''
     <TD {style}>&nbsp;p25={p25:5.2f}, p50={p50:5.2f}, p75={p75:5.2f}, p90={p90:5.2f}, p99={p99:5.2f}</TD>
     </TR>
 '''
-            )
-            f.write('</TABLE>')
+                )
+            except IndexError:
+                pass
+        f.write('</TABLE>')
 
 
 def thread_invoke_renderers() -> None:
@@ -603,6 +624,9 @@ def thread_invoke_renderers() -> None:
     render_counts: collections.Counter = collections.Counter()
     last_render: Dict[str, datetime] = {}
 
+    # Touch the internal render page now to signal that we're alive.
+    renderer_update_internal_stats_page(last_render, render_counts, render_times)
+
     # Main renderer loop
     while True:
         logger.info(