From 48dffdf383ad8d01723ddd7f70b3a678c35516d7 Mon Sep 17 00:00:00 2001
From: TheJoeCoder <joe@radialbog9.uk>
Date: Tue, 1 Oct 2024 09:47:19 +0100
Subject: [PATCH] Reformat file and add fps counter + limit

---
 config.py |  4 ++-
 main.py   | 88 ++++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/config.py b/config.py
index 48ea056..f6b6532 100644
--- a/config.py
+++ b/config.py
@@ -12,7 +12,9 @@ default_hw_config = {
     "leds_length": 15,
     "flask_debug": False,
     "flask_host": "0.0.0.0",
-    "flask_port": 5000
+    "flask_port": 5000,
+    "show_fps": False,
+    "fps_max": 60
 }
 
 hw_config = default_hw_config.copy()
diff --git a/main.py b/main.py
index 35ce8a5..9a382cb 100644
--- a/main.py
+++ b/main.py
@@ -1,3 +1,5 @@
+import json
+import os
 import threading
 import time
 import queue
@@ -8,32 +10,43 @@ from flask import request, Flask, Response, Request
 
 import ledpatterns
 from absled import ILedString
-from config import *
 import screenwidgets
+from config import PROP_AVAILABLE_WIDGETS, PROP_AVAILABLE_PATTERNS, PROP_WINDOW_SCALE, PROP_WINDOW_FULLSCREEN, \
+    PROP_SCREEN_WIDTH, PROP_SCREEN_HEIGHT, PROP_HIDE_MOUSE, PROP_LEDS_DRIVER, PROP_LEDS_LENGTH, PROP_LEDS_LOCATION, \
+    PROP_FLASK_DEBUG, PROP_FLASK_HOST, PROP_FLASK_PORT, hw_config
 
 app = Flask(__name__)
 
-# Load defaults
-module_defaults = json.load(open("module_defaults.json"))
+
 module_config = {}
-for module_name, module_conf in module_defaults.items():
-    add_conf = {}
-    for setting, props in module_conf.items():
-        add_conf[setting] = props.get("default", None)
-    module_config[module_name] = add_conf
-
-# Load config over defaults
-if os.path.exists("module_config.json"):
-    mconf = json.load(open("module_config.json"))
-    for module_name, module_conf in mconf.items():
-        if module_name in module_config:
-            for setting, value in module_conf.items():
-                if setting in module_config[module_name]:
-                    module_config[module_name][setting] = value
-
-# Save config
-with open("module_config.json", "w") as f:
-    json.dump(module_config, f, indent=4)
+
+# Load defaults
+def load_module_config():
+    global module_config
+    module_defaults = json.load(open("module_defaults.json"))
+    module_config = {}
+    for module_name, module_conf in module_defaults.items():
+        add_conf = {}
+        for setting, props in module_conf.items():
+            add_conf[setting] = props.get("default", None)
+        module_config[module_name] = add_conf
+
+    # Load config over defaults
+    if os.path.exists("module_config.json"):
+        mconf = json.load(open("module_config.json"))
+        for module_name, module_conf in mconf.items():
+            if module_name in module_config:
+                for setting, value in module_conf.items():
+                    if setting in module_config[module_name]:
+                        module_config[module_name][setting] = value
+
+    # Save config
+    with open("module_config.json", "w") as f:
+        json.dump(module_config, f, indent=4)
+
+def save_module_config():
+    with open("module_config.json", "w") as f:
+        json.dump(module_config, f, indent=4)
 
 mainthread_queue = queue.Queue()
 display_queue = queue.Queue()
@@ -59,6 +72,11 @@ def verify_json_request(req: Request, required_fields=None):
 
     return True, None
 
+
+##############
+# Web Routes #
+##############
+
 @app.route("/")
 def wr_index():
     return f"""
@@ -156,6 +174,11 @@ def wr_set_pattern():
 def wr_get_config():
     return json_response(module_config)
 
+
+#####################
+# Loading functions #
+#####################
+
 def load_widget(widget_name: str, config_override: dict=None):
     # Get the widget properties from the config file
     widget_props = module_config.get(widget_name, {}).copy()
@@ -185,8 +208,8 @@ def load_pattern(pattern_name: str, leds: ILedString, config_override: dict=None
 def run_screen():
     # Initialise Pygame and create a window
     pygame.init()
+
     pg_options = 0x0
-    print(PROP_WINDOW_FULLSCREEN)
     if PROP_WINDOW_FULLSCREEN:
         pg_options |= pygame.FULLSCREEN
     screen = pygame.display.set_mode(
@@ -196,6 +219,9 @@ def run_screen():
     pygame.display.set_caption("Clock")
     pygame.mouse.set_visible(not PROP_HIDE_MOUSE)
 
+    # Create a clock for FPS counter and timing
+    clock = pygame.time.Clock()
+
     # Init widgets
     widget_to_load = PROP_AVAILABLE_WIDGETS[0]  # TODO change to load multiple widgets
 
@@ -231,6 +257,19 @@ def run_screen():
         # Draw stuff here
         current_widget.draw(screen)
 
+        # Display FPS counter
+        if hw_config["show_fps"]:
+            fps = clock.get_fps()
+            font = pygame.font.Font(None, 36)
+            text = font.render(f"FPS: {fps:.2f}", True, (255, 255, 255))
+            screen.blit(text, (10, 10))
+
+        # Tick the clock
+        if hw_config["fps_max"] > 0:
+            clock.tick(hw_config["fps_max"])
+        else:
+            clock.tick()
+
         # Update the screen
         pygame.display.flip()
 
@@ -282,6 +321,9 @@ def run_leds():
 
 
 if __name__ == "__main__":
+    # Load configuration
+    load_module_config()
+
     # Fork off pygame
     pygame_thread = threading.Thread(target=run_screen, daemon=True)
     pygame_thread.start()
@@ -311,4 +353,4 @@ if __name__ == "__main__":
             time.sleep(1)
     except KeyboardInterrupt:
         exit()
-    exit()
\ No newline at end of file
+    exit()
-- 
GitLab