diff --git a/src/Resurse/app_config.txt b/src/Resurse/app_config.txt index 6bc3ba1..b36229d 100644 --- a/src/Resurse/app_config.txt +++ b/src/Resurse/app_config.txt @@ -1 +1 @@ -{"screen_orientation": "Landscape", "screen_name": "tv-panou1", "quickconnect_key": "8887779", "server_ip":"172.20.10.9", "port": "80"} \ No newline at end of file +{"screen_orientation": "Landscape", "screen_name": "tv-terasa", "quickconnect_key": "8887779", "server_ip": "digi-signage.moto-adv.com", "port": "80", "screen_w": "1920", "screen_h": "1080"} \ No newline at end of file diff --git a/src/Resurse/log.txt b/src/Resurse/log.txt index 8371ae3..9521e97 100644 --- a/src/Resurse/log.txt +++ b/src/Resurse/log.txt @@ -1,44 +1,13 @@ -2025-05-14 13:27:33 - STARTED: IMG_20250503_220547.jpg -2025-05-14 13:27:36 - STARTED: IMG_20250506_080609.jpg -2025-05-14 13:27:51 - STARTED: VID-20250502-WA0066.mp4 -2025-05-14 13:27:51 - STARTED: VID_20250502_113903.mp4 -2025-05-14 13:27:52 - STARTED: VID-20250503-WA0036.mp4 -2025-05-14 14:09:15 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:09:27 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:09:42 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:09:51 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:09:53 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:09:55 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:09:57 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:11:12 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:20:31 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:20:43 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:20:58 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:21:13 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:21:28 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:21:43 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:21:58 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:22:13 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:23:08 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:35:11 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:35:23 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:39:50 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:40:01 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:40:16 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:40:31 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:40:46 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:41:01 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:41:16 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:41:31 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:41:46 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:42:01 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:42:16 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:42:31 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:42:46 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:43:01 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:43:16 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:43:31 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:43:46 - STARTED: Office_audit_overview_5S-1.jpg -2025-05-14 14:44:01 - STARTED: 03.03.2025_5S_Organigramm_Office-1.jpg -2025-05-14 14:44:16 - STARTED: Operational_Plan_FY25-1.jpg -2025-05-14 14:44:31 - STARTED: Office_audit_overview_5S-1.jpg +2025-06-19 16:03:02 - STARTED: IMG-20250526-WA0003.jpg +2025-06-19 16:03:03 - STARTED: IMG-20250602-WA0011.jpg +2025-06-19 16:03:23 - STARTED: IMG_20250601_192845.jpg +2025-06-19 16:03:43 - STARTED: IMG_20250601_185017.jpg +2025-06-19 16:04:03 - STARTED: IMG_20250601_185019.jpg +2025-06-19 16:04:23 - STARTED: IMG_20250601_180727.jpg +2025-06-19 16:04:43 - STARTED: IMG_20250601_174724.jpg +2025-06-19 16:05:03 - STARTED: IMG-20250531-WA0070.jpg +2025-06-19 16:05:23 - STARTED: IMG-20250604-WA0006.jpg +2025-06-19 16:05:43 - STARTED: IMG-20250526-WA0003.jpg +2025-06-19 16:06:03 - STARTED: IMG-20250602-WA0011.jpg +2025-06-19 16:06:23 - STARTED: IMG_20250601_192845.jpg +2025-06-19 16:06:43 - STARTED: IMG_20250601_185017.jpg diff --git a/src/__pycache__/python_functions.cpython-311.pyc b/src/__pycache__/python_functions.cpython-311.pyc index 069f53e..22747cf 100644 Binary files a/src/__pycache__/python_functions.cpython-311.pyc and b/src/__pycache__/python_functions.cpython-311.pyc differ diff --git a/src/kv/media_player.kv b/src/kv/media_player.kv index eb19747..49929c8 100644 --- a/src/kv/media_player.kv +++ b/src/kv/media_player.kv @@ -5,7 +5,6 @@ Video: id: video_player allow_stretch: True - keep_ratio: True size_hint: (1, 1) pos_hint: {'center_x': 0.5, 'center_y': 0.5} opacity: 0 @@ -79,7 +78,7 @@ # Input fields in the upper half of the screen BoxLayout: orientation: 'vertical' - size_hint_y: 0.2 # Allocate 60% of the screen height for input fields + size_hint_y: 0.4 # Allocate 85% of the screen height for input fields Label: text: "Screen Orientation" @@ -140,6 +139,28 @@ multiline: False size_hint_y: None height: 40 + Label: + text: "Screen Size Width / Height" + size_hint_y: None + height: 40 + + # New row for Screen Size Width / Height + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: 40 + spacing: 10 + TextInput: + id: screen_width_input + hint_text: "Width" + multiline: False + size_hint_x: 0.3 + + TextInput: + id: screen_height_input + hint_text: "Height" + multiline: False + size_hint_x: 0.3 # Buttons in the lower part of the screen BoxLayout: diff --git a/src/media_player.py b/src/media_player.py index 4a7ae23..eec21fd 100644 --- a/src/media_player.py +++ b/src/media_player.py @@ -47,6 +47,9 @@ class MediaPlayer(Screen): self.reset_timer = None # Timer to reset the button state after 3 minutes self.image_timer = None # Timer for scheduling the next media for images + # Load screen size from the configuration file + self.load_screen_size() + # Schedule periodic updates to check for playlist updates Clock.schedule_interval(self.check_playlist_updates, 300) # Every 5 minutes # Bind key events to handle fullscreen toggle @@ -55,6 +58,21 @@ class MediaPlayer(Screen): # Start a timer to hide the buttons after 10 seconds self.hide_button_timer = Clock.schedule_once(self.hide_buttons, 10) + def load_screen_size(self): + """Load screen size from the configuration file and set the window size.""" + if os.path.exists(CONFIG_FILE): + with open(CONFIG_FILE, 'r') as file: + config_data = json.load(file) + screen_w = config_data.get("screen_w", "1920") + screen_h = config_data.get("screen_h", "1080") + + # Set the window size + try: + Window.size = (int(screen_w), int(screen_h)) + Logger.info(f"Screen size set to {screen_w}x{screen_h}") + except ValueError: + Logger.error("Invalid screen size values in configuration file.") + def on_touch_down(self, touch): # Handle touch events to reset the button visibility. self.show_buttons() # Make all buttons visible @@ -83,12 +101,15 @@ class MediaPlayer(Screen): Window.fullscreen = not Window.fullscreen def on_enter(self): - # Called when the screen is entered. - self.playlist = load_playlist() # Load the playlist - download_media_files(self.playlist) # Download media files from the playlist - clean_unused_files(self.playlist) # Remove unused files from the resource folder - self.play_media() # Start playing media - self.show_buttons() # Ensure buttons are visible when the screen is entered + """Called when the screen is entered.""" + self.playlist = load_playlist() # Load the playlist (local or server) + if self.playlist: # Only proceed if the playlist is not empty + download_media_files(self.playlist) # Download media files if the playlist has changed + clean_unused_files(self.playlist) # Remove unused files from the resource folder + self.play_media() # Start playing media + self.show_buttons() # Ensure buttons are visible when the screen is entered + else: + Logger.warning("MediaPlayer: Playlist is empty. No media to play.") def log_event(self, file_name, event): # Log the start or stop event of a media file and clean up old logs. @@ -325,7 +346,9 @@ class SettingsScreen(Screen): "screen_name": "", "quickconnect_key": "", "server_ip": "", - "port": "" # Default port + "port": "", + "screen_w": "", # Default width + "screen_h": "" # Default height } def save_config(self): @@ -335,6 +358,8 @@ class SettingsScreen(Screen): self.config_data["quickconnect_key"] = self.ids.quickconnect_key_input.text self.config_data["server_ip"] = self.ids.server_ip_input.text self.config_data["port"] = self.ids.port_input.text + self.config_data["screen_w"] = self.ids.screen_width_input.text + self.config_data["screen_h"] = self.ids.screen_height_input.text with open(CONFIG_FILE, 'w') as file: json.dump(self.config_data, file) @@ -350,6 +375,8 @@ class SettingsScreen(Screen): self.ids.quickconnect_key_input.text = self.config_data.get("quickconnect_key", "") self.ids.server_ip_input.text = self.config_data.get("server_ip", "") self.ids.port_input.text = self.config_data.get("port", "8080") + self.ids.screen_width_input.text = self.config_data.get("screen_w", "") + self.ids.screen_height_input.text = self.config_data.get("screen_h", "") def show_exit_popup(self): # Create the popup layout diff --git a/src/python_functions.py b/src/python_functions.py index 6c86b84..2ccf9fa 100644 --- a/src/python_functions.py +++ b/src/python_functions.py @@ -1,10 +1,10 @@ -import requests import os import json +import requests from kivy.logger import Logger CONFIG_FILE = './Resurse/app_config.txt' - +LOCAL_PLAYLIST_FILE = './static/local_playlist.json' # Path to the local playlist file def load_config(): """Load configuration from app_config.txt.""" if os.path.exists(CONFIG_FILE): @@ -46,6 +46,7 @@ else: Logger.info(f"python_functions: Configuration loaded: server={server}, host={host}, quick={quick}, port={port}") Logger.info(f"python_functions: Configuration status: {config_status}") + def load_playlist(): """Load playlist from the server or local storage.""" try: @@ -66,17 +67,53 @@ def load_playlist(): if response.status_code == 200: try: # Parse the JSON response - playlist = response.json().get('playlist', []) - Logger.info("python_functions: Playlist loaded successfully.") - Logger.debug(f"python_functions: Loaded playlist: {playlist}") - return playlist + server_data = response.json() + playlist = server_data.get('playlist', []) + + # Validate the playlist structure + if isinstance(playlist, list) and all(isinstance(item, dict) for item in playlist): + Logger.info("python_functions: Playlist loaded successfully.") + Logger.debug(f"python_functions: Loaded playlist: {playlist}") + + # Save the playlist locally + with open(LOCAL_PLAYLIST_FILE, 'w') as local_file: + json.dump(playlist, local_file) + Logger.info("python_functions: Updated local playlist with server data.") + + return playlist + else: + Logger.error("python_functions: Invalid playlist structure from server.") except json.JSONDecodeError as e: Logger.error(f"python_functions: Failed to parse JSON response: {e}") else: - Logger.error(f"python_functions: Failed to retrieve playlist: {response.text}") + Logger.error(f"python_functions: Failed to retrieve playlist. Status Code: {response.status_code}") except requests.exceptions.RequestException as e: Logger.error(f"python_functions: Failed to load playlist: {e}") - return [] + + # Fallback to local playlist + return load_local_playlist() + + +def load_local_playlist(): + """Load the playlist from local storage.""" + if os.path.exists(LOCAL_PLAYLIST_FILE): + try: + with open(LOCAL_PLAYLIST_FILE, 'r') as local_file: + local_playlist = json.load(local_file) + + # Validate the structure of the local playlist + if isinstance(local_playlist, list) and all(isinstance(item, dict) for item in local_playlist): + Logger.info("python_functions: Loaded and validated local playlist.") + return local_playlist + else: + Logger.error("python_functions: Invalid local playlist structure.") + return [] + except json.JSONDecodeError: + Logger.error("python_functions: Failed to parse local playlist file.") + return [] + else: + Logger.warning("python_functions: Local playlist file not found.") + return [] def download_media_files(playlist): """Download media files from the playlist.""" diff --git a/src/static/local_playlist.json b/src/static/local_playlist.json new file mode 100644 index 0000000..e9dfd9e --- /dev/null +++ b/src/static/local_playlist.json @@ -0,0 +1 @@ +[{"duration": 20, "file_name": "IMG-20250526-WA0003.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250526-WA0003.jpg"}, {"duration": 20, "file_name": "IMG-20250602-WA0011.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250602-WA0011.jpg"}, {"duration": 20, "file_name": "IMG_20250601_192845.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_192845.jpg"}, {"duration": 20, "file_name": "IMG_20250601_185017.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_185017.jpg"}, {"duration": 20, "file_name": "IMG_20250601_185019.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_185019.jpg"}, {"duration": 20, "file_name": "IMG_20250601_180727.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_180727.jpg"}, {"duration": 20, "file_name": "IMG_20250601_174724.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_174724.jpg"}, {"duration": 20, "file_name": "IMG-20250531-WA0070.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250531-WA0070.jpg"}, {"duration": 20, "file_name": "IMG-20250604-WA0006.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250604-WA0006.jpg"}] \ No newline at end of file diff --git a/src/static/resurse/03.03.2025_5S_Organigramm_Office-1.jpg b/src/static/resurse/03.03.2025_5S_Organigramm_Office-1.jpg deleted file mode 100644 index 325d6e2..0000000 Binary files a/src/static/resurse/03.03.2025_5S_Organigramm_Office-1.jpg and /dev/null differ diff --git a/src/static/resurse/IMG-20250526-WA0003.jpg b/src/static/resurse/IMG-20250526-WA0003.jpg new file mode 100644 index 0000000..8e0b2b3 Binary files /dev/null and b/src/static/resurse/IMG-20250526-WA0003.jpg differ diff --git a/src/static/resurse/IMG-20250531-WA0070.jpg b/src/static/resurse/IMG-20250531-WA0070.jpg new file mode 100644 index 0000000..7bf5432 Binary files /dev/null and b/src/static/resurse/IMG-20250531-WA0070.jpg differ diff --git a/src/static/resurse/IMG-20250602-WA0011.jpg b/src/static/resurse/IMG-20250602-WA0011.jpg new file mode 100644 index 0000000..4e6aad5 Binary files /dev/null and b/src/static/resurse/IMG-20250602-WA0011.jpg differ diff --git a/src/static/resurse/IMG-20250604-WA0006.jpg b/src/static/resurse/IMG-20250604-WA0006.jpg new file mode 100644 index 0000000..bc5f7e0 Binary files /dev/null and b/src/static/resurse/IMG-20250604-WA0006.jpg differ diff --git a/src/static/resurse/IMG_20250601_174724.jpg b/src/static/resurse/IMG_20250601_174724.jpg new file mode 100644 index 0000000..ca638cd Binary files /dev/null and b/src/static/resurse/IMG_20250601_174724.jpg differ diff --git a/src/static/resurse/IMG_20250601_180727.jpg b/src/static/resurse/IMG_20250601_180727.jpg new file mode 100644 index 0000000..04b2082 Binary files /dev/null and b/src/static/resurse/IMG_20250601_180727.jpg differ diff --git a/src/static/resurse/IMG_20250601_185017.jpg b/src/static/resurse/IMG_20250601_185017.jpg new file mode 100644 index 0000000..09feaa1 Binary files /dev/null and b/src/static/resurse/IMG_20250601_185017.jpg differ diff --git a/src/static/resurse/IMG_20250601_185019.jpg b/src/static/resurse/IMG_20250601_185019.jpg new file mode 100644 index 0000000..77b35f3 Binary files /dev/null and b/src/static/resurse/IMG_20250601_185019.jpg differ diff --git a/src/static/resurse/IMG_20250601_192845.jpg b/src/static/resurse/IMG_20250601_192845.jpg new file mode 100644 index 0000000..be083e5 Binary files /dev/null and b/src/static/resurse/IMG_20250601_192845.jpg differ diff --git a/src/static/resurse/Office_audit_overview_5S-1.jpg b/src/static/resurse/Office_audit_overview_5S-1.jpg deleted file mode 100644 index 4499a3c..0000000 Binary files a/src/static/resurse/Office_audit_overview_5S-1.jpg and /dev/null differ diff --git a/src/static/resurse/Operational_Plan_FY25-1.jpg b/src/static/resurse/Operational_Plan_FY25-1.jpg deleted file mode 100644 index 69903cc..0000000 Binary files a/src/static/resurse/Operational_Plan_FY25-1.jpg and /dev/null differ