troubleshooting of the day manager

This commit is contained in:
Chuck
2025-09-15 14:53:26 -04:00
parent f8f4539015
commit 7618eafaa6
2 changed files with 66 additions and 38 deletions

View File

@@ -27,10 +27,7 @@ except ImportError:
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Define paths relative to this file's location # Note: Config is now passed in from DisplayController instead of being loaded separately
CONFIG_DIR = os.path.join(os.path.dirname(__file__), '..', 'config')
CONFIG_PATH = os.path.join(CONFIG_DIR, 'config.json')
# SECRETS_PATH is handled within SpotifyClient
class MusicSource(Enum): class MusicSource(Enum):
NONE = auto() NONE = auto()
@@ -72,37 +69,32 @@ class MusicManager:
def _load_config(self): def _load_config(self):
default_interval = 2 default_interval = 2
# default_preferred_source = "auto" # Removed
self.enabled = False # Assume disabled until config proves otherwise self.enabled = False # Assume disabled until config proves otherwise
if not os.path.exists(CONFIG_PATH): # Use the config that was already loaded and passed to us instead of loading our own
logging.warning(f"Config file not found at {CONFIG_PATH}. Music manager disabled.") if self.config is None:
logging.warning("No config provided to MusicManager. Music manager disabled.")
return return
try: try:
with open(CONFIG_PATH, 'r') as f: music_config = self.config.get("music", {})
config_data = json.load(f)
music_config = config_data.get("music", {})
self.enabled = music_config.get("enabled", False) self.enabled = music_config.get("enabled", False)
if not self.enabled: if not self.enabled:
logging.info("Music manager is disabled in config.json (top level 'enabled': false).") logging.info("Music manager is disabled in config.json (top level 'enabled': false).")
return # Don't proceed further if disabled return # Don't proceed further if disabled
self.polling_interval = music_config.get("POLLING_INTERVAL_SECONDS", default_interval) self.polling_interval = music_config.get("POLLING_INTERVAL_SECONDS", default_interval)
configured_source = music_config.get("preferred_source", "spotify").lower() configured_source = music_config.get("preferred_source", "spotify").lower()
if configured_source in ["spotify", "ytm"]: if configured_source in ["spotify", "ytm"]:
self.preferred_source = configured_source self.preferred_source = configured_source
logging.info(f"Music manager enabled. Polling interval: {self.polling_interval}s. Preferred source: {self.preferred_source}") logging.info(f"Music manager enabled. Polling interval: {self.polling_interval}s. Preferred source: {self.preferred_source}")
else: else:
logging.warning(f"Invalid 'preferred_source' ('{configured_source}') in config.json. Must be 'spotify' or 'ytm'. Music manager disabled.") logging.warning(f"Invalid 'preferred_source' ('{configured_source}') in config.json. Must be 'spotify' or 'ytm'. Music manager disabled.")
self.enabled = False self.enabled = False
return return
except json.JSONDecodeError:
logging.error(f"Error decoding JSON from {CONFIG_PATH}. Music manager disabled.")
self.enabled = False
except Exception as e: except Exception as e:
logging.error(f"Error loading music config: {e}. Music manager disabled.") logging.error(f"Error loading music config: {e}. Music manager disabled.")
self.enabled = False self.enabled = False
@@ -916,15 +908,12 @@ if __name__ == '__main__':
# The MusicManager expects the overall config, not just the music part directly for its _load_config # The MusicManager expects the overall config, not just the music part directly for its _load_config
# So we simulate a config object that has a .get('music', {}) method. # So we simulate a config object that has a .get('music', {}) method.
# However, MusicManager's _load_config reads from CONFIG_PATH. # MusicManager now uses the passed config instead of loading from file.
# For a true standalone test, we might need to mock file IO or provide a test config file.
# Simplified test: # Simplified test:
# manager = MusicManager(display_manager=mock_display, config=mock_config_main) # This won't work due to file reading manager = MusicManager(display_manager=mock_display, config=mock_config_main)
# To truly test, you'd point CONFIG_PATH to a test config.json or mock open() logger.info("MusicManager standalone test setup completed.")
# For now, this __main__ block is mostly a placeholder.
logger.info("MusicManager standalone test setup is complex due to file dependencies for config.")
logger.info("To test: run the main application and observe logs from MusicManager.") logger.info("To test: run the main application and observe logs from MusicManager.")
# if manager.enabled: # if manager.enabled:
# manager.start_polling() # manager.start_polling()

View File

@@ -44,6 +44,7 @@ class OfTheDayManager:
possible_font_dirs = [ possible_font_dirs = [
os.path.abspath(os.path.join(script_dir, '..', 'assets', 'fonts')), # Relative to src/ os.path.abspath(os.path.join(script_dir, '..', 'assets', 'fonts')), # Relative to src/
os.path.abspath(os.path.join(os.getcwd(), 'assets', 'fonts')), # Relative to project root os.path.abspath(os.path.join(os.getcwd(), 'assets', 'fonts')), # Relative to project root
os.path.abspath('assets/fonts'), # Simple relative path made absolute
'assets/fonts' # Simple relative path 'assets/fonts' # Simple relative path
] ]
@@ -63,6 +64,12 @@ class OfTheDayManager:
font_path = os.path.abspath(os.path.join(font_dir, filename)) font_path = os.path.abspath(os.path.join(font_dir, filename))
if not os.path.exists(font_path): if not os.path.exists(font_path):
logger.debug(f"Font file not found: {font_path}") logger.debug(f"Font file not found: {font_path}")
# List available fonts for debugging
try:
available_fonts = [f for f in os.listdir(font_dir) if f.endswith('.bdf')]
logger.debug(f"Available BDF fonts in {font_dir}: {available_fonts}")
except:
pass
return None return None
logger.debug(f"Loading BDF font: {font_path}") logger.debug(f"Loading BDF font: {font_path}")
return freetype.Face(font_path) return freetype.Face(font_path)
@@ -128,6 +135,16 @@ class OfTheDayManager:
logger.info(f"Loading data files for {len(self.categories)} categories") logger.info(f"Loading data files for {len(self.categories)} categories")
logger.info(f"Current working directory: {os.getcwd()}") logger.info(f"Current working directory: {os.getcwd()}")
logger.info(f"Script directory: {os.path.dirname(__file__)}") logger.info(f"Script directory: {os.path.dirname(__file__)}")
# Additional debugging for Pi environment
logger.debug(f"Absolute script directory: {os.path.abspath(os.path.dirname(__file__))}")
logger.debug(f"Absolute working directory: {os.path.abspath(os.getcwd())}")
# Check if we're running on Pi
if os.path.exists('/home/ledpi'):
logger.debug("Detected Pi environment (/home/ledpi exists)")
else:
logger.debug("Not running on Pi environment")
for category_name, category_config in self.categories.items(): for category_name, category_config in self.categories.items():
logger.debug(f"Processing category: {category_name}") logger.debug(f"Processing category: {category_name}")
@@ -143,6 +160,7 @@ class OfTheDayManager:
try: try:
# Try multiple possible paths for data files # Try multiple possible paths for data files
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
current_dir = os.getcwd()
possible_paths = [] possible_paths = []
if os.path.isabs(data_file): if os.path.isabs(data_file):
@@ -152,13 +170,15 @@ class OfTheDayManager:
if data_file.startswith('of_the_day/'): if data_file.startswith('of_the_day/'):
possible_paths.extend([ possible_paths.extend([
os.path.join(script_dir, '..', data_file), os.path.join(script_dir, '..', data_file),
os.path.join(os.getcwd(), data_file), os.path.join(current_dir, data_file),
os.path.join('/home/ledpi/LEDMatrix', data_file), # Explicit Pi path
data_file data_file
]) ])
else: else:
possible_paths.extend([ possible_paths.extend([
os.path.join(script_dir, '..', 'of_the_day', data_file), os.path.join(script_dir, '..', 'of_the_day', data_file),
os.path.join(os.getcwd(), 'of_the_day', data_file), os.path.join(current_dir, 'of_the_day', data_file),
os.path.join('/home/ledpi/LEDMatrix/of_the_day', data_file), # Explicit Pi path
os.path.join('of_the_day', data_file) os.path.join('of_the_day', data_file)
]) ])
@@ -174,6 +194,19 @@ class OfTheDayManager:
# Use the first attempted path for error reporting # Use the first attempted path for error reporting
file_path = os.path.abspath(possible_paths[0]) file_path = os.path.abspath(possible_paths[0])
logger.debug(f"No data file found for {category_name}, tried: {[os.path.abspath(p) for p in possible_paths]}") logger.debug(f"No data file found for {category_name}, tried: {[os.path.abspath(p) for p in possible_paths]}")
# Additional debugging - check if parent directory exists
parent_dir = os.path.dirname(file_path)
logger.debug(f"Parent directory: {parent_dir}")
logger.debug(f"Parent directory exists: {os.path.exists(parent_dir)}")
if os.path.exists(parent_dir):
try:
parent_contents = os.listdir(parent_dir)
logger.debug(f"Parent directory contents: {parent_contents}")
except PermissionError:
logger.debug(f"Permission denied accessing parent directory: {parent_dir}")
except Exception as e:
logger.debug(f"Error listing parent directory: {e}")
logger.debug(f"Attempting to load {category_name} from: {file_path}") logger.debug(f"Attempting to load {category_name} from: {file_path}")
@@ -200,11 +233,17 @@ class OfTheDayManager:
else: else:
logger.error(f"Data file not found for {category_name}: {file_path}") logger.error(f"Data file not found for {category_name}: {file_path}")
if os.path.exists(os.path.dirname(file_path)): parent_dir = os.path.dirname(file_path)
dir_contents = os.listdir(os.path.dirname(file_path)) if os.path.exists(parent_dir):
logger.error(f"Directory contents: {dir_contents}") try:
dir_contents = os.listdir(parent_dir)
logger.error(f"Directory contents of {parent_dir}: {dir_contents}")
except PermissionError:
logger.error(f"Permission denied accessing directory: {parent_dir}")
except Exception as e:
logger.error(f"Error listing directory {parent_dir}: {e}")
else: else:
logger.error(f"Parent directory does not exist: {os.path.dirname(file_path)}") logger.error(f"Parent directory does not exist: {parent_dir}")
logger.error(f"Tried paths: {[os.path.abspath(p) for p in possible_paths]}") logger.error(f"Tried paths: {[os.path.abspath(p) for p in possible_paths]}")
self.data_files[category_name] = {} self.data_files[category_name] = {}