ypdated to check player playlist

This commit is contained in:
2025-06-19 16:07:22 +03:00
parent 19ec84b941
commit 8052b564b2
19 changed files with 117 additions and 62 deletions

View File

@@ -1 +1 @@
{"screen_orientation": "Landscape", "screen_name": "tv-panou1", "quickconnect_key": "8887779", "server_ip":"172.20.10.9", "port": "80"}
{"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"}

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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."""

View File

@@ -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"}]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB