diff --git a/ledpatterns.py b/ledpatterns.py index 0fab6de2ea06311dcff5a0370c4eab4e9ac14932..4874c799fd9f05f636f38424c12416e54f2b9331 100644 --- a/ledpatterns.py +++ b/ledpatterns.py @@ -1,5 +1,5 @@ from absled import ILedString -from num_utils import color_hex_to_tuple +from utils.num_utils import color_hex_to_tuple def wheel(pos): diff --git a/main.py b/main.py index a48ad245a4674aa1290d36ae708291e071be7746..d95f3c8e4522dcf70db9c5a8a1f55f3c65fc1c20 100644 --- a/main.py +++ b/main.py @@ -221,7 +221,12 @@ def load_pattern(pattern_name: str, leds: ILedString, config_override: dict=None return getattr(ledpatterns, pattern_name)(pattern_props, leds) -def run_screen(): + +################## +# Loop Functions # +################## + +def run_screen(start_widget: str): # Initialise Pygame and create a window pygame.init() @@ -239,7 +244,7 @@ def run_screen(): clock = pygame.time.Clock() # Init widgets - widget_to_load = PROP_AVAILABLE_WIDGETS[0] # TODO change to load multiple widgets + widget_to_load = start_widget current_widget = load_widget(widget_to_load) @@ -295,7 +300,7 @@ def run_screen(): # Quit Pygame pygame.quit() -def run_leds(): +def run_leds(start_pattern: str): # Load LEDs if PROP_LEDS_DRIVER == "dummy": from absled.dummy import DummyLedString @@ -306,8 +311,10 @@ def run_leds(): else: raise ValueError("Invalid LED driver") - current_pattern = load_pattern(PROP_AVAILABLE_PATTERNS[0], leds) - pattern_timer = module_config.get(PROP_AVAILABLE_PATTERNS[0], {}).get("tick_rate", -1) + pattern_name = start_pattern + + current_pattern = load_pattern(pattern_name, leds) + pattern_timer = module_config.get(pattern_name, {}).get("tick_rate", -1) current_pattern.tick() while True: @@ -339,19 +346,30 @@ def run_leds(): if __name__ == "__main__": # Load configuration load_module_config() + load_sequences() + + initial_widget = widget_sequence[0].get("type") if len(widget_sequence) > 0 else PROP_AVAILABLE_WIDGETS[0] + initial_pattern = pattern_sequence[0].get("type") if len(pattern_sequence) > 0 else PROP_AVAILABLE_PATTERNS[0] # Fork off pygame - pygame_thread = threading.Thread(target=run_screen, daemon=True) + pygame_thread = threading.Thread( + target=lambda: run_screen(initial_widget), + daemon=True + ) pygame_thread.start() # Fork off flask server flask_thread = threading.Thread( target=lambda: app.run(debug=PROP_FLASK_DEBUG, host=PROP_FLASK_HOST, port=PROP_FLASK_PORT, use_reloader=False), - daemon=True) + daemon=True + ) flask_thread.start() # Fork off LED thread - led_thread = threading.Thread(target=run_leds, daemon=True) + led_thread = threading.Thread( + target=lambda: run_leds(initial_pattern), + daemon=True + ) led_thread.start() # Wait for the threads to finish diff --git a/num_utils.py b/num_utils.py deleted file mode 100644 index 229d995af414033f0ac26dd215ce1dffa0d32753..0000000000000000000000000000000000000000 --- a/num_utils.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -import re - -from config import * -import socket - -def get_screen_centre(): - return (PROP_SCREEN_WIDTH * PROP_WINDOW_SCALE) / 2, (PROP_SCREEN_HEIGHT * PROP_WINDOW_SCALE) / 2 - - -# noinspection PyTypeChecker -def color_hex_to_tuple(hx: str) -> tuple[int, int, int]: - """ - Convert a 6-digit hex colour string to a tuple of RGB values. - If a hash symbol is present, it is removed. - :param hx: the hex colour string - :return: the RGB tuple - """ - hx = hx.removeprefix("#") - return tuple(int(hx[i:i + 2], 16) for i in (0, 2, 4)) - - -def get_ip(): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.settimeout(0) - try: - # doesn't even have to be reachable - s.connect(('10.254.254.254', 1)) - ip_addr = s.getsockname()[0] - except Exception: - ip_addr = '127.0.0.1' - finally: - s.close() - return ip_addr - -def get_font_path_or_default(pygame, font_name: str|None, bold=False, italic=False) -> str: - if font_name is not None: - if re.match(r".+\.ttf", font_name): - if os.path.exists(font_name): - font_path = font_name - else: - font_path = pygame.font.get_default_font() - else: - font_path = pygame.font.match_font(font_name, bold, italic) - else: - font_path = pygame.font.get_default_font() - return font_path diff --git a/screenwidgets.py b/screenwidgets.py index 1f74d6d20ccc86b2771b5ae990f7a38d240ff626..12884e02e916bfbdf56cc6c4905d17e16931f3c9 100644 --- a/screenwidgets.py +++ b/screenwidgets.py @@ -1,10 +1,10 @@ import math -import os.path -import re from datetime import datetime from config import PROP_WINDOW_SCALE, PROP_SCREEN_WIDTH, PROP_SCREEN_HEIGHT -from num_utils import get_screen_centre, get_ip, get_font_path_or_default +from utils.num import get_screen_centre +from utils.net import get_ip +from utils.fonts import get_font_path_or_default class IWidgetMeta(type): diff --git a/utils/fonts.py b/utils/fonts.py new file mode 100644 index 0000000000000000000000000000000000000000..006d206366ed07c83ad9e5e180c6801d1608403e --- /dev/null +++ b/utils/fonts.py @@ -0,0 +1,16 @@ +import os +import re + + +def get_font_path_or_default(pygame, font_name: str|None, bold=False, italic=False) -> str: + if font_name is not None: + if re.match(r".+\.ttf", font_name): + if os.path.exists(font_name): + font_path = font_name + else: + font_path = pygame.font.get_default_font() + else: + font_path = pygame.font.match_font(font_name, bold, italic) + else: + font_path = pygame.font.get_default_font() + return font_path diff --git a/utils/net.py b/utils/net.py new file mode 100644 index 0000000000000000000000000000000000000000..ffc3f0e986255800d9c029771bf8cda9708c9676 --- /dev/null +++ b/utils/net.py @@ -0,0 +1,15 @@ +import socket + + +def get_ip(): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.settimeout(0) + try: + # doesn't even have to be reachable + s.connect(('10.254.254.254', 1)) + ip_addr = s.getsockname()[0] + except Exception: + ip_addr = '127.0.0.1' + finally: + s.close() + return ip_addr \ No newline at end of file diff --git a/utils/num.py b/utils/num.py new file mode 100644 index 0000000000000000000000000000000000000000..8eeacf48328601b48dc86b5ece9e68464356f32c --- /dev/null +++ b/utils/num.py @@ -0,0 +1,17 @@ +from config import PROP_SCREEN_WIDTH, PROP_SCREEN_HEIGHT, PROP_WINDOW_SCALE + + +def get_screen_centre(): + return (PROP_SCREEN_WIDTH * PROP_WINDOW_SCALE) / 2, (PROP_SCREEN_HEIGHT * PROP_WINDOW_SCALE) / 2 + + +# noinspection PyTypeChecker +def color_hex_to_tuple(hx: str) -> tuple[int, int, int]: + """ + Convert a 6-digit hex colour string to a tuple of RGB values. + If a hash symbol is present, it is removed. + :param hx: the hex colour string + :return: the RGB tuple + """ + hx = hx.removeprefix("#") + return tuple(int(hx[i:i + 2], 16) for i in (0, 2, 4))