diff --git a/.gitignore b/.gitignore index d396279..3e85e89 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ mqtt_config.json +config.json .idea/ *venv diff --git a/demos/prusa/main.py b/demos/prusa/main.py index 7ef797c..efee442 100644 --- a/demos/prusa/main.py +++ b/demos/prusa/main.py @@ -1,6 +1,8 @@ import os -import yaml + import requests +import yaml + class Prusa: """ @@ -35,11 +37,11 @@ def __init__(self, input_queue, output_queue, screen): self.screen = screen # init demo/game specific variables here - config_path = os.path.join(os.path.dirname(__file__), 'config.yaml') - with open(config_path, 'r') as f: + config_path = os.path.join(os.path.dirname(__file__), "config.yaml") + with open(config_path, "r") as f: config = yaml.safe_load(f) - self.prusalink_ip = config.get('prusalink_ip') - self.api_key = config.get('api_key') + self.prusalink_ip = config.get("prusalink_ip") + self.api_key = config.get("api_key") self.URL = f"http://{self.prusalink_ip}/api/v1/job" self.HEADERS = { "X-Api-Key": self.api_key, @@ -58,7 +60,6 @@ def __init__(self, input_queue, output_queue, screen): self.display_time_left = "0" self.display_progress = 0 - def get_stats(self): """ Returns static information. @@ -73,8 +74,8 @@ def get_stats(self): return self._get_default_stats() # Check content type - content_type = self.response.headers.get('content-type', '') - if 'application/json' not in content_type: + content_type = self.response.headers.get("content-type", "") + if "application/json" not in content_type: print(f"Unexpected content type: {content_type}") print(f"Response body: {self.response.text[:200]}") # First 200 chars return self._get_default_stats() @@ -86,7 +87,9 @@ def get_stats(self): self.progress = self.data.get("progress", 0) self.time_elapsed = self.data.get("time_printing", "N/A") self.time_left = self.data.get("time_remaining", "N/A") - self.minutes_left = self.time_left // 60 if isinstance(self.time_left, int) else "N/A" + self.minutes_left = ( + self.time_left // 60 if isinstance(self.time_left, int) else "N/A" + ) except requests.RequestException as e: # print(f"Request failed: {e}") @@ -123,21 +126,23 @@ def run(self): # Create generator here while True: self.stats = self.get_stats() - + # print("=== Printer Status ===") # print(f"time left: {self.stats['time_left']}") # print(f"Stats: {self.stats}") # draw the filename - self.display_status = self.stats['state'] + self.display_status = self.stats["state"] # print(f"Status: {self.display_status}") - if self.stats['state'] == "IDLE" and int(self.display_time_elapsed[0:8].strip()) > 0: + if ( + self.stats["state"] == "IDLE" + and int(self.display_time_elapsed[0:8].strip()) > 0 + ): self.display_progress = 0 self.display_time_elapsed = "0" self.display_time_left = "0" self.display_filename = "N/A" self.screen.clear() print("hit") - self.screen.draw_text( self.screen.x_width // 2 - 8, @@ -145,12 +150,12 @@ def run(self): self.display_status, push=True, ) - - if self.stats['state'] == "IDLE": + + if self.stats["state"] == "IDLE": yield continue - self.display_filename = self.stats['filename'][:16].upper() + self.display_filename = self.stats["filename"][:16].upper() # print(f"Filename: {self.display_filename}") self.screen.draw_text( self.screen.x_width // 2 - 8, @@ -159,9 +164,10 @@ def run(self): push=True, ) - # print(f"Time left: {self.stats['minutes_left']} minutes") - self.display_time_elapsed = f"{str(self.stats['time_elapsed']):>5} ELAPSED" + self.display_time_elapsed = ( + f"{str(self.stats['time_elapsed']):>5} ELAPSED" + ) self.screen.draw_text( self.screen.x_width // 2 - 8, self.screen.y_height // 2 - 2, @@ -179,7 +185,7 @@ def run(self): ) # Map progress (0-100) to a value between 0 and 16 - percentage_complete = int((self.stats['progress'] / 100) * 16) + percentage_complete = int((self.stats["progress"] / 100) * 16) percentage_complete = max(0, min(percentage_complete, 16)) # print(f"Progress: {self.stats['progress']}%, (mapped to {percentage_complete})") self.display_progress = f"{int(self.stats['progress']):>5} PROGRESS" diff --git a/display/physical_screen_v2.py b/display/physical_screen_v2.py index 0efac06..f4bea74 100644 --- a/display/physical_screen_v2.py +++ b/display/physical_screen_v2.py @@ -6,17 +6,19 @@ class PhysicalScreen: - def __init__(self, brightness=3): - self.brightness = brightness - self.num_segs_across = 1 - self.num_segs_down = 1 + def __init__(self, config): + self.brightness = config.get("brightness", 3) + self.num_segs_across = len(config.get("panels", [[]])[0]) + self.num_segs_down = len(config.get("panels", [])) + self.panels = config.get("panels", [[]]) + self.display = None + self._create_display() def _create_display(self): - # need to have an array of ip addresses if more panels panel_array = [ [ - SevenSegment(ip_address="172.0.0.3", brightness=self.brightness) + SevenSegment(ip_address=self.panels[i][j], brightness=self.brightness) for j in range(self.num_segs_across) ] for i in range(self.num_segs_down) diff --git a/example_config.json b/example_config.json new file mode 100644 index 0000000..af3b95d --- /dev/null +++ b/example_config.json @@ -0,0 +1,22 @@ +{ + "screen_v2": { + "brightness": 3, + "panels": [ + [ + "172.168.0.5", + "172.168.0.6", + "172.168.0.7" + ], + [ + "172.168.0.8", + "172.168.0.9", + "172.168.0.10" + ], + [ + "172.168.0.11", + "172.168.0.12", + "172.168.0.13" + ] + ] + } +} diff --git a/main.py b/main.py index c14cea5..e4ff464 100644 --- a/main.py +++ b/main.py @@ -71,9 +71,19 @@ def run_simulator(): help="Run in test mode. This shortens the demo time and user input time " "for testing purposes.", ) -def run_kiosk(simulate, new_hardware, testing): +@click.option( + "config_file", + "-c", + "--config_file", + type=click.Path(exists=True), + default="config.json", + help="Path to configuration file.", +) +def run_kiosk(simulate, new_hardware, testing, config_file): """CLI command to run kiosk.""" - kiosk.run(simulate, testing=testing, new_hardware=new_hardware) + kiosk.run( + simulate, testing=testing, new_hardware=new_hardware, config_file=config_file + ) @cli.command("demo") @@ -106,9 +116,17 @@ def run_kiosk(simulate, new_hardware, testing): help="Run in test mode. This provides feedback for if your demo is " "running fast enough relative to the set frame rate.", ) -def run_demo(name, simulate, new_hardware, testing): +@click.option( + "config_file", + "-c", + "--config_file", + type=click.Path(exists=True), + default="config.json", + help="Path to configuration file.", +) +def run_demo(name, simulate, new_hardware, testing, config_file): """CLI command to run demo.""" - demo.run(name, simulate, new_hardware, testing=testing) + demo.run(name, simulate, new_hardware, testing=testing, config_file=config_file) @cli.command("test") diff --git a/runners/demo.py b/runners/demo.py index 06806ed..16486e2 100644 --- a/runners/demo.py +++ b/runners/demo.py @@ -1,3 +1,4 @@ +import json import time from importlib import import_module @@ -8,14 +9,15 @@ from runners import utils -def run(demo_name, simulate, new_hardware, testing): +def run(demo_name, simulate, new_hardware, testing, config_file): """Main function that runs the demo. Args: demo_name (str): Name of the demo to run. simulate (bool): Whether to simulate the screen or use the physical screen. testing (bool): Whether to run the demo in testing mode. - + new_hardware (bool): Whether to use the new hardware configuration. + config_file (str): Path to configuration file. """ if simulate: @@ -30,8 +32,13 @@ def run(demo_name, simulate, new_hardware, testing): PhysicalScreen, ) + # Read in screen configuration + with open(config_file, "r") as f: + config = json.load(f) + screen_config = config.get("screen_v2", {}) + logger.debug("Starting new physical screen...") - screen = PhysicalScreen() + screen = PhysicalScreen(screen_config) else: from display.physical_screen import ( # pylint: disable=import-outside-toplevel PhysicalScreen, diff --git a/runners/kiosk.py b/runners/kiosk.py index ccb5bb8..9ef149c 100644 --- a/runners/kiosk.py +++ b/runners/kiosk.py @@ -1,3 +1,4 @@ +import json import random import sys import time @@ -233,12 +234,14 @@ def run_loop(screen, user_input_timeout=300, demo_time_override=None, simulated= screen.clear() -def run(simulate, testing=False, new_hardware=False): +def run(simulate, testing=False, new_hardware=False, config_file="config.json"): """Runs the kiosk Args: simulate (bool): If True, the kiosk will run in simulation mode. testing (bool): If True, the kiosk will run in testing mode. + new_hardware (bool): If True, the kiosk will run on the new hardware. + config_file (str): Path to configuration file. """ @@ -254,8 +257,13 @@ def run(simulate, testing=False, new_hardware=False): PhysicalScreen, ) + # Read in screen configuration + with open(config_file, "r") as f: + config = json.load(f) + screen_config = config.get("screen_v2", {}) + logger.debug("Starting new physical screen...") - screen = PhysicalScreen() + screen = PhysicalScreen(screen_config) else: from display.physical_screen import ( PhysicalScreen, # pylint: disable=import-outside-toplevel