milb upcoming game debug logging

This commit is contained in:
Chuck
2025-08-10 18:26:25 -05:00
parent 10c1342bdb
commit edce5fae85
4 changed files with 23 additions and 12 deletions

View File

@@ -151,10 +151,12 @@ class DisplayController:
self.milb_live = MiLBLiveManager(self.config, self.display_manager, self.cache_manager) if milb_display_modes.get('milb_live', True) else None
self.milb_recent = MiLBRecentManager(self.config, self.display_manager, self.cache_manager) if milb_display_modes.get('milb_recent', True) else None
self.milb_upcoming = MiLBUpcomingManager(self.config, self.display_manager, self.cache_manager) if milb_display_modes.get('milb_upcoming', True) else None
logger.info(f"MiLB managers initialized - live: {self.milb_live is not None}, recent: {self.milb_recent is not None}, upcoming: {self.milb_upcoming is not None}")
else:
self.milb_live = None
self.milb_recent = None
self.milb_upcoming = None
logger.info("MiLB managers disabled")
logger.info("MiLB managers initialized in %.3f seconds", time.time() - milb_time)
# Initialize Soccer managers if enabled
@@ -1137,6 +1139,7 @@ class DisplayController:
manager_to_display = self.milb_recent
elif self.current_display_mode == 'milb_upcoming' and self.milb_upcoming:
manager_to_display = self.milb_upcoming
logger.info("Set manager_to_display to milb_upcoming")
elif self.current_display_mode == 'soccer_recent' and self.soccer_recent:
manager_to_display = self.soccer_recent
elif self.current_display_mode == 'soccer_upcoming' and self.soccer_upcoming:
@@ -1169,6 +1172,8 @@ class DisplayController:
logger.info(f"Showing {self.current_display_mode}")
self._last_logged_mode = self.current_display_mode
logger.info(f"manager_to_display is {type(manager_to_display).__name__ if manager_to_display else 'None'}")
if self.current_display_mode == 'music' and self.music_manager:
# Call MusicManager's display method
self.music_manager.display(force_clear=self.force_clear)
@@ -1230,6 +1235,7 @@ class DisplayController:
# Special handling for live managers that need update before display
if self.current_display_mode.endswith('_live') and hasattr(manager_to_display, 'update'):
manager_to_display.update()
logger.info(f"Calling display method for {self.current_display_mode}")
manager_to_display.display(force_clear=self.force_clear)
else:
logger.warning(f"Manager {type(manager_to_display).__name__} for mode {self.current_display_mode} does not have a standard 'display' method.")

View File

@@ -641,6 +641,11 @@ class DisplayManager:
except Exception:
# Fallback to direct save if replace not supported
self.image.save(self._snapshot_path, format='PNG')
# Try to make the snapshot world-readable so the web UI can read it regardless of user
try:
os.chmod(self._snapshot_path, 0o644)
except Exception:
pass
self._last_snapshot_ts = now
except Exception as e:
# Snapshot failures should never break display; log at debug to avoid noise

View File

@@ -211,6 +211,7 @@ class BaseMiLBManager:
def _create_game_display(self, game_data: Dict[str, Any]) -> Image.Image:
"""Create a display image for an MiLB game with team logos, score, and game state."""
self.logger.info(f"[MiLB] Creating game display for: {game_data.get('away_team')} @ {game_data.get('home_team')}")
width = self.display_manager.matrix.width
height = self.display_manager.matrix.height
image = Image.new('RGB', (width, height), color=(0, 0, 0))
@@ -417,6 +418,7 @@ class BaseMiLBManager:
def _fetch_milb_api_data(self, use_cache: bool = True) -> Dict[str, Any]:
"""Fetch MiLB game data from the MLB Stats API."""
self.logger.info("[MiLB] _fetch_milb_api_data called")
cache_key = "milb_live_api_data"
if use_cache:
cached_data = self.cache_manager.get_with_auto_strategy(cache_key)
@@ -616,6 +618,7 @@ class BaseMiLBManager:
self.cache_manager.set(cache_key, all_games)
else:
self.logger.error(f"[MiLB] Cannot cache invalid data type: {type(all_games)}")
self.logger.info(f"[MiLB] Returning {len(all_games)} games from API")
return all_games
except Exception as e:
@@ -1531,6 +1534,7 @@ class MiLBUpcomingManager(BaseMiLBManager):
def update(self):
"""Update upcoming games data."""
self.logger.info("[MiLB] Update method called")
current_time = time.time()
# Add a check to see if the manager is enabled
@@ -1602,6 +1606,7 @@ class MiLBUpcomingManager(BaseMiLBManager):
new_upcoming_games = []
self.logger.info(f"[MiLB] Processing {len(games)} games for upcoming games...")
self.logger.info(f"[MiLB] Games keys: {list(games.keys()) if games else 'None'}")
now_utc = datetime.now(timezone.utc)
for game_id, game in games.items():
@@ -1646,6 +1651,7 @@ class MiLBUpcomingManager(BaseMiLBManager):
# Sort by game time (soonest first) and limit to upcoming_games_to_show
new_upcoming_games.sort(key=lambda x: x.get('start_time', ''))
new_upcoming_games = new_upcoming_games[:self.upcoming_games_to_show]
self.logger.info(f"[MiLB] Found {len(new_upcoming_games)} upcoming games after processing")
# Compare new list with old list to see if an update is needed
if self.upcoming_games != new_upcoming_games:
@@ -1660,8 +1666,10 @@ class MiLBUpcomingManager(BaseMiLBManager):
self.current_game_index = 0
self.current_game = self.upcoming_games[0]
self.last_game_switch = current_time
self.logger.info(f"[MiLB] Set current game to: {self.current_game.get('away_team')} @ {self.current_game.get('home_team')}")
else:
self.current_game = None # No upcoming games
self.logger.info("[MiLB] No upcoming games, cleared current game")
self.last_update = current_time
@@ -1671,7 +1679,7 @@ class MiLBUpcomingManager(BaseMiLBManager):
def display(self, force_clear: bool = False):
"""Display upcoming games."""
self.logger.debug(f"[MiLB] Display called with {len(self.upcoming_games)} upcoming games")
self.logger.info(f"[MiLB] Display called with {len(self.upcoming_games)} upcoming games")
if not self.upcoming_games:
current_time = time.time()
if current_time - self.last_warning_time > self.warning_cooldown:

View File

@@ -63,12 +63,12 @@ class DisplayMonitor:
# Prefer service-provided snapshot if available (works when ledmatrix service is running)
if os.path.exists(snapshot_path):
# Read atomically by reopening; ignore partials by skipping this frame
img_bytes = None
try:
with open(snapshot_path, 'rb') as f:
img_bytes = f.read()
except Exception:
img_bytes = None
if img_bytes:
img_str = base64.b64encode(img_bytes).decode()
# If we can infer dimensions from display_manager, include them; else leave 0
@@ -84,16 +84,8 @@ class DisplayMonitor:
# Yield and continue to next frame
socketio.sleep(0.1)
continue
# If we can infer dimensions from display_manager, include them; else leave 0
width = display_manager.width if display_manager else 0
height = display_manager.height if display_manager else 0
current_display_data = {
'image': img_str,
'width': width,
'height': height,
'timestamp': time.time()
}
socketio.emit('display_update', current_display_data)
# If snapshot exists but couldn't be read (partial write/permissions), skip this frame
# and try again on next loop rather than emitting an invalid payload.
elif display_manager and hasattr(display_manager, 'image'):
# Fallback to in-process manager image
img_buffer = io.BytesIO()