Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/display_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,7 @@
self._sleep_with_plugin_updates(60)
continue

logger.info(f"Display active, processing mode: {self.current_display_mode}")
logger.debug("Display active, processing mode: %s", self.current_display_mode)

# Plugins update on their own schedules - no forced sync updates needed
# Each plugin has its own update_interval and background services
Expand Down Expand Up @@ -1803,7 +1803,7 @@
if self.plugin_manager and hasattr(self.plugin_manager, 'health_tracker') and self.plugin_manager.health_tracker:
should_skip = self.plugin_manager.health_tracker.should_skip_plugin(plugin_id)
if should_skip:
logger.info(f"Skipping plugin {plugin_id} due to circuit breaker (mode: {active_mode})")
logger.info("Skipping plugin %s due to circuit breaker (mode: %s)", plugin_id, active_mode)
display_result = False
# Skip to next mode - let existing logic handle it
manager_to_display = None
Expand Down Expand Up @@ -1861,7 +1861,7 @@
if isinstance(result, bool):
display_result = result
if not display_result:
logger.info(f"Plugin {plugin_id} display() returned False for mode {active_mode}")
logger.info("Plugin %s display() returned False for mode %s", plugin_id, active_mode)

# Record success if display completed without exception
if self.plugin_manager and hasattr(self.plugin_manager, 'health_tracker') and self.plugin_manager.health_tracker:
Expand Down Expand Up @@ -2354,6 +2354,15 @@
Returns None on any error or if message is expired/invalid.
"""
try:
# Throttle the existence stat to ~1 Hz: this runs on every render
# iteration (60+ fps), and the file usually doesn't exist — the
# status message's lifetime is measured in seconds anyway.
now = time.time()
if (now - getattr(self, '_wifi_status_check_ts', 0.0)) < 1.0:
return self._wifi_status_last_result

Check warning on line 2362 in src/display_controller.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/display_controller.py#L2362

Access to member '_wifi_status_last_result' before its definition line 2364
self._wifi_status_check_ts = now
self._wifi_status_last_result = None

# Check if file exists
if not self.wifi_status_file or not self.wifi_status_file.exists():
return None
Expand Down Expand Up @@ -2404,13 +2413,14 @@
pass
return None

# Message is valid and not expired
return {
# Message is valid and not expired — cache for the throttle window
self._wifi_status_last_result = {
'message': message,
'timestamp': timestamp,
'duration': duration,
'expires_at': expires_at
}
return self._wifi_status_last_result

except Exception as e:
# Catch-all for any unexpected errors - log but don't break the display
Expand Down
20 changes: 16 additions & 4 deletions src/vegas_mode/render_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ def __init__(
else display_manager.height
)

# Reusable blank frame for cycle-end pushes (allocated lazily,
# re-blacked before each reuse)
self._blank_frame = None

# ScrollHelper for optimized scrolling
self.scroll_helper = ScrollHelper(
self.display_width,
Expand Down Expand Up @@ -234,11 +238,19 @@ def render_frame(self) -> bool:
)
# Push blank immediately so the hardware never shows any
# post-wrap content while the coordinator recomposes the
# next cycle (~100 ms).
# next cycle (~100 ms). The blank is allocated once and
# reused across cycle wraps (fresh paste each time in case
# a consumer drew on the previous one).
try:
from PIL import Image as _Image
blank = _Image.new('RGB', (self.display_width, self.display_height))
self.display_manager.image = blank
if self._blank_frame is None or self._blank_frame.size != (
self.display_width, self.display_height):
self._blank_frame = Image.new(
'RGB', (self.display_width, self.display_height))
else:
self._blank_frame.paste(
(0, 0, 0),
(0, 0, self.display_width, self.display_height))
self.display_manager.image = self._blank_frame
self.display_manager.update_display()
except Exception:
logger.exception("Failed to write blank frame to display at cycle end")
Expand Down
Loading