updated to show when is not online
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -6,6 +6,49 @@ import re
|
||||
import datetime
|
||||
from logging_config import Logger
|
||||
|
||||
# Global variable to track server connectivity status
|
||||
SERVER_CONNECTION_STATUS = {
|
||||
'is_online': True,
|
||||
'last_successful_connection': None,
|
||||
'last_playlist_update': None,
|
||||
'error_message': None
|
||||
}
|
||||
|
||||
def get_server_status():
|
||||
"""Get current server connection status"""
|
||||
return SERVER_CONNECTION_STATUS.copy()
|
||||
|
||||
def get_last_playlist_update_time():
|
||||
"""Get the timestamp of the last playlist update from filesystem"""
|
||||
try:
|
||||
playlist_dir = os.path.join(os.path.dirname(__file__), 'static_data', 'playlist')
|
||||
if os.path.exists(playlist_dir):
|
||||
playlist_files = [f for f in os.listdir(playlist_dir) if f.startswith('server_playlist_v') and f.endswith('.json')]
|
||||
if playlist_files:
|
||||
# Get the most recent playlist file
|
||||
latest_file = max([os.path.join(playlist_dir, f) for f in playlist_files], key=os.path.getmtime)
|
||||
mod_time = os.path.getmtime(latest_file)
|
||||
return datetime.datetime.fromtimestamp(mod_time)
|
||||
return None
|
||||
except Exception as e:
|
||||
Logger.error(f"Error getting last playlist update time: {e}")
|
||||
return None
|
||||
|
||||
def set_server_offline(error_message=None):
|
||||
"""Mark server as offline with optional error message"""
|
||||
global SERVER_CONNECTION_STATUS
|
||||
SERVER_CONNECTION_STATUS['is_online'] = False
|
||||
SERVER_CONNECTION_STATUS['error_message'] = error_message
|
||||
Logger.warning(f"Server marked as offline: {error_message}")
|
||||
|
||||
def set_server_online():
|
||||
"""Mark server as online and update connection time"""
|
||||
global SERVER_CONNECTION_STATUS
|
||||
SERVER_CONNECTION_STATUS['is_online'] = True
|
||||
SERVER_CONNECTION_STATUS['last_successful_connection'] = datetime.datetime.now()
|
||||
SERVER_CONNECTION_STATUS['error_message'] = None
|
||||
Logger.info("Server connection restored")
|
||||
|
||||
def send_player_feedback(config, message, status="active", playlist_version=None, error_details=None):
|
||||
"""
|
||||
Send feedback to the server about player status.
|
||||
@@ -51,16 +94,21 @@ def send_player_feedback(config, message, status="active", playlist_version=None
|
||||
|
||||
if response.status_code == 200:
|
||||
Logger.info(f"Feedback sent successfully: {message}")
|
||||
# Mark server as online on successful feedback
|
||||
set_server_online()
|
||||
return True
|
||||
else:
|
||||
Logger.warning(f"Feedback failed with status {response.status_code}: {response.text}")
|
||||
set_server_offline(f"Feedback failed with status {response.status_code}")
|
||||
return False
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
Logger.error(f"Failed to send feedback: {e}")
|
||||
set_server_offline(f"Network error during feedback: {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
Logger.error(f"Unexpected error sending feedback: {e}")
|
||||
set_server_offline(f"Unexpected error during feedback: {e}")
|
||||
return False
|
||||
|
||||
def send_playlist_check_feedback(config, playlist_version=None):
|
||||
@@ -187,25 +235,44 @@ def fetch_server_playlist(config):
|
||||
'quickconnect_code': quick
|
||||
}
|
||||
Logger.info(f"Fetching playlist from URL: {server_url} with params: {params}")
|
||||
response = requests.get(server_url, params=params)
|
||||
response = requests.get(server_url, params=params, timeout=15)
|
||||
|
||||
if response.status_code == 200:
|
||||
response_data = response.json()
|
||||
Logger.info(f"Server response: {response_data}")
|
||||
playlist = response_data.get('playlist', [])
|
||||
version = response_data.get('playlist_version', None)
|
||||
hashed_quickconnect = response_data.get('hashed_quickconnect', None)
|
||||
|
||||
if version is not None and hashed_quickconnect is not None:
|
||||
if bcrypt.checkpw(quick.encode('utf-8'), hashed_quickconnect.encode('utf-8')):
|
||||
Logger.info("Fetched updated playlist from server.")
|
||||
# Mark server as online on successful connection
|
||||
set_server_online()
|
||||
return {'playlist': playlist, 'version': version}
|
||||
else:
|
||||
Logger.error("Quickconnect code validation failed.")
|
||||
set_server_offline("Authentication failed - invalid quickconnect code")
|
||||
else:
|
||||
Logger.error("Failed to retrieve playlist or hashed quickconnect from the response.")
|
||||
set_server_offline("Invalid server response - missing playlist data")
|
||||
else:
|
||||
Logger.error(f"Failed to fetch playlist. Status Code: {response.status_code}")
|
||||
set_server_offline(f"Server returned error code: {response.status_code}")
|
||||
|
||||
except requests.exceptions.ConnectTimeout as e:
|
||||
Logger.error(f"Connection timeout while fetching playlist: {e}")
|
||||
set_server_offline("Connection timeout - server unreachable")
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
Logger.error(f"Connection error while fetching playlist: {e}")
|
||||
set_server_offline("Connection failed - server unreachable")
|
||||
except requests.exceptions.RequestException as e:
|
||||
Logger.error(f"Failed to fetch playlist: {e}")
|
||||
Logger.error(f"Request error while fetching playlist: {e}")
|
||||
set_server_offline(f"Network error: {str(e)}")
|
||||
except Exception as e:
|
||||
Logger.error(f"Unexpected error while fetching playlist: {e}")
|
||||
set_server_offline(f"Unexpected error: {str(e)}")
|
||||
|
||||
return {'playlist': [], 'version': 0}
|
||||
|
||||
def save_playlist_with_version(playlist_data, playlist_dir):
|
||||
@@ -292,6 +359,8 @@ def update_playlist_if_needed(local_playlist_path, config, media_dir, playlist_d
|
||||
Also sends feedback to server about playlist check.
|
||||
"""
|
||||
import json
|
||||
global SERVER_CONNECTION_STATUS
|
||||
|
||||
server_data = fetch_server_playlist(config)
|
||||
server_version = server_data.get('version', 0)
|
||||
if not os.path.exists(local_playlist_path):
|
||||
@@ -303,10 +372,11 @@ def update_playlist_if_needed(local_playlist_path, config, media_dir, playlist_d
|
||||
|
||||
Logger.info(f"Local playlist version: {local_version}, Server playlist version: {server_version}")
|
||||
|
||||
# Send feedback about server interrogation (checking for updates)
|
||||
# Only send feedback if server is online
|
||||
if SERVER_CONNECTION_STATUS['is_online']:
|
||||
send_playlist_check_feedback(config, server_version if server_version > 0 else local_version)
|
||||
|
||||
if local_version != server_version:
|
||||
if local_version != server_version and server_version > 0:
|
||||
if server_data and server_data.get('playlist'):
|
||||
updated_playlist = download_media_files(server_data['playlist'], media_dir)
|
||||
server_data['playlist'] = updated_playlist
|
||||
@@ -314,16 +384,15 @@ def update_playlist_if_needed(local_playlist_path, config, media_dir, playlist_d
|
||||
# Delete old playlists and unreferenced media
|
||||
delete_old_playlists_and_media(server_version, playlist_dir, media_dir)
|
||||
|
||||
# Update last playlist update time
|
||||
SERVER_CONNECTION_STATUS['last_playlist_update'] = datetime.datetime.now()
|
||||
|
||||
return True
|
||||
else:
|
||||
Logger.warning("No playlist data fetched from server or playlist is empty.")
|
||||
|
||||
# Send error feedback
|
||||
send_player_error_feedback(config, "No playlist data fetched from server or playlist is empty", local_version)
|
||||
|
||||
return False
|
||||
else:
|
||||
Logger.info("Local playlist is already up to date.")
|
||||
Logger.info("Local playlist is already up to date or server is offline.")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"screen_orientation": "Landscape",
|
||||
"screen_name": "tv-terasa",
|
||||
"quickconnect_key": "8887779",
|
||||
"server_ip": "192.168.1.22",
|
||||
"server_ip": "10.35.33.231",
|
||||
"port": "80",
|
||||
"screen_w": "1920",
|
||||
"screen_h": "1080",
|
||||
|
||||
@@ -12759,3 +12759,92 @@
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://192.168.1.22:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T16:15:46.726098', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[WARNING] [SignageApp] Server marked as offline: Test - server unreachable
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[WARNING] [SignageApp] Server marked as offline: Test - simulated network failure
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[WARNING] [SignageApp] Server marked as offline: Test offline mode
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://10.35.33.231:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'one-piece-season-2-5120x2880-23673.jpg', 'url': 'http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg'}, {'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4'}], 'playlist_version': 7}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 7
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, server interrogation, checking for updates : playlist v7', 'status': 'active', 'timestamp': '2025-09-09T16:48:54.345235', 'playlist_version': 7, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, server interrogation, checking for updates : playlist v7
|
||||
[INFO] [SignageApp] Preparing to download one-piece-season-2-5120x2880-23673.jpg from http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg...
|
||||
[INFO] [SignageApp] File one-piece-season-2-5120x2880-23673.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download call-of-duty-black-3840x2160-23674.jpg from http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg...
|
||||
[INFO] [SignageApp] File call-of-duty-black-3840x2160-23674.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] Successfully downloaded big-buck-bunny-1080p-60fps-30sec.mp4 to /home/pi/Desktop/tkinter_player/signage_player/static_data/media/big-buck-bunny-1080p-60fps-30sec.mp4
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T16:48:59.576471', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T16:50:01.605320', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T16:50:01.752876', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T16:51:03.726916', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T16:51:03.849472', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://10.35.33.231:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'one-piece-season-2-5120x2880-23673.jpg', 'url': 'http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg'}, {'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4'}], 'playlist_version': 8}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://10.35.33.231:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'one-piece-season-2-5120x2880-23673.jpg', 'url': 'http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg'}, {'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4'}], 'playlist_version': 8}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, server interrogation, checking for updates : playlist v8', 'status': 'active', 'timestamp': '2025-09-09T16:57:29.966333', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, server interrogation, checking for updates : playlist v8
|
||||
[INFO] [SignageApp] Preparing to download one-piece-season-2-5120x2880-23673.jpg from http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg...
|
||||
[INFO] [SignageApp] File one-piece-season-2-5120x2880-23673.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download call-of-duty-black-3840x2160-23674.jpg from http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg...
|
||||
[INFO] [SignageApp] File call-of-duty-black-3840x2160-23674.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] Successfully downloaded big-buck-bunny-1080p-60fps-30sec.mp4 to signage_player/static_data/media/big-buck-bunny-1080p-60fps-30sec.mp4
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://10.35.33.231:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'one-piece-season-2-5120x2880-23673.jpg', 'url': 'http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg'}, {'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4'}], 'playlist_version': 8}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, server interrogation, checking for updates : playlist v8', 'status': 'active', 'timestamp': '2025-09-09T16:58:29.211046', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, server interrogation, checking for updates : playlist v8
|
||||
[INFO] [SignageApp] Preparing to download one-piece-season-2-5120x2880-23673.jpg from http://10.35.33.231/media/one-piece-season-2-5120x2880-23673.jpg...
|
||||
[INFO] [SignageApp] File one-piece-season-2-5120x2880-23673.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download call-of-duty-black-3840x2160-23674.jpg from http://10.35.33.231/media/call-of-duty-black-3840x2160-23674.jpg...
|
||||
[INFO] [SignageApp] File call-of-duty-black-3840x2160-23674.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://10.35.33.231/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] File big-buck-bunny-1080p-60fps-30sec.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T16:58:34.434167', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T17:00:06.810997', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T17:00:07.101272', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T17:01:39.392553', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T17:01:39.514533', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T17:03:11.882623', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T17:03:12.026303', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://10.35.33.231:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[ERROR] [SignageApp] Connection error while fetching playlist: HTTPConnectionPool(host='10.35.33.231', port=80): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f7feccd90>: Failed to establish a new connection: [Errno 111] Connection refused'))
|
||||
[WARNING] [SignageApp] Server marked as offline: Connection failed - server unreachable
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 0
|
||||
[INFO] [SignageApp] Local playlist is already up to date or server is offline.
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T17:04:44.536396', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T17:04:44.650793', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist working in loop, cycle completed : playlist v8', 'status': 'restarting', 'timestamp': '2025-09-09T17:06:17.176559', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist working in loop, cycle completed : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T17:06:17.330975', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Sending feedback to http://10.35.33.231:80/api/player-feedback: {'player_name': 'tv-terasa', 'quickconnect_code': '8887779', 'message': 'player tv-terasa, playlist started : playlist v8', 'status': 'playing', 'timestamp': '2025-09-09T17:10:12.361728', 'playlist_version': 8, 'error_details': None}
|
||||
[INFO] [SignageApp] Feedback sent successfully: player tv-terasa, playlist started : playlist v8
|
||||
[INFO] [SignageApp] Server connection restored
|
||||
|
||||
@@ -4,7 +4,7 @@ import tkinter as tk
|
||||
import vlc
|
||||
import subprocess
|
||||
import sys
|
||||
from get_playlists import send_playlist_restart_feedback, send_player_error_feedback, send_playing_status_feedback, send_playlist_check_feedback
|
||||
from get_playlists import send_playlist_restart_feedback, send_player_error_feedback, send_playing_status_feedback, send_playlist_check_feedback, get_server_status, get_last_playlist_update_time
|
||||
|
||||
CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'main_data', 'app_config.txt')
|
||||
PLAYLIST_DIR = os.path.join(os.path.dirname(__file__), 'static_data', 'playlist')
|
||||
@@ -24,6 +24,10 @@ class SimpleTkPlayer:
|
||||
self.config = self.load_config()
|
||||
self.playlist_version = self.get_current_playlist_version()
|
||||
|
||||
# Offline notification tracking
|
||||
self.offline_notification = None
|
||||
self.last_server_status = True
|
||||
|
||||
# Initialize all timer variables to None
|
||||
self.hide_controls_timer = None
|
||||
self.video_watchdog = None
|
||||
@@ -104,6 +108,70 @@ class SimpleTkPlayer:
|
||||
except Exception as e:
|
||||
print(f"[FEEDBACK] Error sending server check feedback: {e}")
|
||||
|
||||
def check_server_status(self):
|
||||
"""Check server connectivity status and show/hide offline notification"""
|
||||
try:
|
||||
server_status = get_server_status()
|
||||
is_online = server_status['is_online']
|
||||
|
||||
# Only update notification if status changed
|
||||
if is_online != self.last_server_status:
|
||||
if not is_online:
|
||||
# Server went offline
|
||||
self.show_offline_notification(server_status)
|
||||
else:
|
||||
# Server came back online
|
||||
self.hide_offline_notification()
|
||||
|
||||
self.last_server_status = is_online
|
||||
|
||||
except Exception as e:
|
||||
print(f"[OFFLINE] Error checking server status: {e}")
|
||||
|
||||
def show_offline_notification(self, server_status):
|
||||
"""Show offline notification at bottom of screen"""
|
||||
try:
|
||||
if self.offline_notification:
|
||||
return # Already showing
|
||||
|
||||
# Get last playlist update time from filesystem
|
||||
last_update = get_last_playlist_update_time()
|
||||
if last_update:
|
||||
update_time = last_update.strftime("%Y-%m-%d %H:%M:%S")
|
||||
message = f"OFFLINE MODE: Playing last available playlist updated at: {update_time}"
|
||||
else:
|
||||
message = "OFFLINE MODE: Playing last available playlist"
|
||||
|
||||
# Create notification label at bottom of screen
|
||||
self.offline_notification = tk.Label(
|
||||
self.root,
|
||||
text=message,
|
||||
bg='orange',
|
||||
fg='black',
|
||||
font=('Arial', 14, 'bold'),
|
||||
relief='raised',
|
||||
bd=2
|
||||
)
|
||||
|
||||
# Position at bottom of screen
|
||||
self.offline_notification.pack(side='bottom', fill='x', padx=5, pady=5)
|
||||
self.offline_notification.lift() # Bring to front
|
||||
|
||||
print(f"[OFFLINE] Showing offline notification: {message}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[OFFLINE] Error showing offline notification: {e}")
|
||||
|
||||
def hide_offline_notification(self):
|
||||
"""Hide offline notification when server comes back online"""
|
||||
try:
|
||||
if self.offline_notification:
|
||||
self.offline_notification.destroy()
|
||||
self.offline_notification = None
|
||||
print("[OFFLINE] Server back online - hiding offline notification")
|
||||
except Exception as e:
|
||||
print(f"[OFFLINE] Error hiding offline notification: {e}")
|
||||
|
||||
def ensure_fullscreen(self):
|
||||
self.root.attributes('-fullscreen', True)
|
||||
self.root.update_idletasks()
|
||||
@@ -218,11 +286,49 @@ class SimpleTkPlayer:
|
||||
self.show_current_media()
|
||||
|
||||
def update_playlist_from_server(self):
|
||||
# Dummy implementation: replace with your actual update logic
|
||||
# For example, call a function to fetch and reload the playlist
|
||||
print("[INFO] Updating playlist from server...")
|
||||
# You can import and call your real update function here
|
||||
# Example: self.playlist = get_latest_playlist()
|
||||
"""Update playlist from server and reload if needed"""
|
||||
try:
|
||||
from get_playlists import update_playlist_if_needed
|
||||
import json
|
||||
|
||||
print("[INFO] Checking for playlist updates from server...")
|
||||
|
||||
# Get config
|
||||
config_path = os.path.join(os.path.dirname(__file__), 'main_data', 'app_config.txt')
|
||||
with open(config_path, 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
|
||||
# Define paths
|
||||
playlist_dir = os.path.join(os.path.dirname(__file__), 'static_data', 'playlist')
|
||||
media_dir = os.path.join(os.path.dirname(__file__), 'static_data', 'media')
|
||||
|
||||
# Find current playlist file
|
||||
playlist_files = [f for f in os.listdir(playlist_dir) if f.startswith('server_playlist_v') and f.endswith('.json')]
|
||||
if playlist_files:
|
||||
current_playlist_path = os.path.join(playlist_dir, max(playlist_files))
|
||||
else:
|
||||
current_playlist_path = os.path.join(playlist_dir, 'server_playlist_v0.json')
|
||||
|
||||
# Check and update if needed
|
||||
updated = update_playlist_if_needed(current_playlist_path, config, media_dir, playlist_dir)
|
||||
|
||||
if updated:
|
||||
print("[INFO] Playlist updated! Reloading...")
|
||||
# Reload the playlist
|
||||
self.update_playlist_version()
|
||||
# Restart playback with new playlist
|
||||
self.current_index = 0
|
||||
self.load_playlist()
|
||||
else:
|
||||
print("[INFO] Playlist is already up to date.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to update playlist: {e}")
|
||||
from get_playlists import send_player_error_feedback
|
||||
try:
|
||||
send_player_error_feedback(config, f"Playlist update failed: {str(e)}")
|
||||
except:
|
||||
pass
|
||||
|
||||
def toggle_pause(self):
|
||||
if not self.paused:
|
||||
@@ -321,6 +427,9 @@ class SimpleTkPlayer:
|
||||
|
||||
def show_current_media(self):
|
||||
try:
|
||||
# Check server status and update offline notification
|
||||
self.check_server_status()
|
||||
|
||||
self.root.attributes('-fullscreen', True)
|
||||
self.root.update_idletasks()
|
||||
if not self.playlist:
|
||||
@@ -859,6 +968,9 @@ class SimpleTkPlayer:
|
||||
try:
|
||||
print("[EXIT] Destroying controls...")
|
||||
|
||||
# Hide offline notification if showing
|
||||
self.hide_offline_notification()
|
||||
|
||||
# First, try to hide and destroy the main controls window
|
||||
if hasattr(self, 'controls_win') and self.controls_win:
|
||||
try:
|
||||
|
||||
Binary file not shown.
@@ -9,6 +9,11 @@
|
||||
"file_name": "call-of-duty-black-3840x2160-23674.jpg",
|
||||
"url": "media/call-of-duty-black-3840x2160-23674.jpg",
|
||||
"duration": 30
|
||||
},
|
||||
{
|
||||
"file_name": "big-buck-bunny-1080p-60fps-30sec.mp4",
|
||||
"url": "media/big-buck-bunny-1080p-60fps-30sec.mp4",
|
||||
"duration": 30
|
||||
}
|
||||
],
|
||||
"version": 8
|
||||
|
||||
43
test_complete_offline.py
Normal file
43
test_complete_offline.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test script to verify the complete offline notification system"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
# Add the signage_player directory to the path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'signage_player'))
|
||||
|
||||
def test_offline_notification():
|
||||
"""Test the offline notification display"""
|
||||
print("[TEST] Testing offline notification system...")
|
||||
|
||||
# Import after adding to path
|
||||
from get_playlists import get_last_playlist_update_time, get_server_status, set_server_offline, set_server_online
|
||||
|
||||
print(f"[TEST] Current server status: {get_server_status()}")
|
||||
|
||||
# Test getting playlist update time
|
||||
last_update = get_last_playlist_update_time()
|
||||
if last_update:
|
||||
print(f"[TEST] Last playlist update: {last_update.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
else:
|
||||
print("[TEST] No playlist file found")
|
||||
|
||||
# Test server offline mode
|
||||
print("\n[TEST] Setting server offline...")
|
||||
set_server_offline("Test - simulated network failure")
|
||||
status = get_server_status()
|
||||
print(f"[TEST] Server status after offline: {status}")
|
||||
|
||||
# Test server online mode
|
||||
time.sleep(1)
|
||||
print("\n[TEST] Setting server online...")
|
||||
set_server_online()
|
||||
status = get_server_status()
|
||||
print(f"[TEST] Server status after online: {status}")
|
||||
|
||||
print("\n[TEST] Offline notification system test completed!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_offline_notification()
|
||||
30
test_offline.py
Executable file
30
test_offline.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
|
||||
# Add the signage_player directory to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'signage_player'))
|
||||
|
||||
from get_playlists import get_server_status, set_server_offline, set_server_online
|
||||
|
||||
def test_offline():
|
||||
print("=== Testing Offline Status ===")
|
||||
|
||||
print("1. Initial status:")
|
||||
status = get_server_status()
|
||||
print(f" Online: {status['is_online']}")
|
||||
|
||||
print("2. Setting offline:")
|
||||
set_server_offline("Test - server unreachable")
|
||||
status = get_server_status()
|
||||
print(f" Online: {status['is_online']}")
|
||||
print(f" Error: {status['error_message']}")
|
||||
|
||||
print("3. Setting online:")
|
||||
set_server_online()
|
||||
status = get_server_status()
|
||||
print(f" Online: {status['is_online']}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_offline()
|
||||
88
test_ui_notification.py
Normal file
88
test_ui_notification.py
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Simple UI test for offline notification display"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import tkinter as tk
|
||||
|
||||
# Add the signage_player directory to the path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'signage_player'))
|
||||
|
||||
class TestNotificationApp:
|
||||
def __init__(self):
|
||||
self.root = tk.Tk()
|
||||
self.root.title("Offline Notification Test")
|
||||
self.root.geometry("800x600")
|
||||
self.root.configure(bg='black')
|
||||
|
||||
# Create main content area
|
||||
main_label = tk.Label(
|
||||
self.root,
|
||||
text="MAIN PLAYER CONTENT AREA",
|
||||
fg='white',
|
||||
bg='black',
|
||||
font=('Arial', 24)
|
||||
)
|
||||
main_label.pack(expand=True, fill='both')
|
||||
|
||||
# Test buttons
|
||||
button_frame = tk.Frame(self.root, bg='black')
|
||||
button_frame.pack(pady=10)
|
||||
|
||||
tk.Button(
|
||||
button_frame,
|
||||
text="Show Offline Notification",
|
||||
command=self.show_offline_notification,
|
||||
bg='red',
|
||||
fg='white'
|
||||
).pack(side=tk.LEFT, padx=5)
|
||||
|
||||
tk.Button(
|
||||
button_frame,
|
||||
text="Hide Notification",
|
||||
command=self.hide_offline_notification,
|
||||
bg='green',
|
||||
fg='white'
|
||||
).pack(side=tk.LEFT, padx=5)
|
||||
|
||||
self.offline_notification = None
|
||||
|
||||
def show_offline_notification(self):
|
||||
"""Show the offline notification at the bottom of the screen"""
|
||||
if self.offline_notification:
|
||||
return # Already showing
|
||||
|
||||
from get_playlists import get_last_playlist_update_time
|
||||
|
||||
last_update = get_last_playlist_update_time()
|
||||
if last_update:
|
||||
timestamp_str = last_update.strftime("%Y-%m-%d %H:%M:%S")
|
||||
message = f"OFFLINE MODE: Playing last available playlist updated at: {timestamp_str}"
|
||||
else:
|
||||
message = "OFFLINE MODE: Playing last available playlist"
|
||||
|
||||
self.offline_notification = tk.Label(
|
||||
self.root,
|
||||
text=message,
|
||||
fg='white',
|
||||
bg='red',
|
||||
font=('Arial', 12, 'bold'),
|
||||
pady=5
|
||||
)
|
||||
self.offline_notification.pack(side=tk.BOTTOM, fill=tk.X)
|
||||
print(f"[UI TEST] Notification shown: {message}")
|
||||
|
||||
def hide_offline_notification(self):
|
||||
"""Hide the offline notification"""
|
||||
if self.offline_notification:
|
||||
self.offline_notification.destroy()
|
||||
self.offline_notification = None
|
||||
print("[UI TEST] Notification hidden")
|
||||
|
||||
def run(self):
|
||||
print("[UI TEST] Starting offline notification UI test...")
|
||||
self.root.mainloop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = TestNotificationApp()
|
||||
app.run()
|
||||
Reference in New Issue
Block a user