* docs: rename FONT_MANAGER_USAGE.md to FONT_MANAGER.md Renamed for clearer naming convention. Part of documentation consolidation effort. * docs: consolidate Plugin Store guides (2→1) Merged: - PLUGIN_STORE_USER_GUIDE.md - PLUGIN_STORE_QUICK_REFERENCE.md Into: PLUGIN_STORE_GUIDE.md - Unified writing style to professional technical - Added Quick Reference section at top for easy access - Removed duplicate content - Added cross-references to related documentation - Updated formatting to match style guidelines * docs: create user-focused Web Interface Guide Created WEB_INTERFACE_GUIDE.md consolidating: - V3_INTERFACE_README.md (technical details) - User-facing interface documentation - Focused on end-user tasks and navigation - Removed technical implementation details - Added common tasks section - Included troubleshooting - Professional technical writing style * docs: consolidate WiFi setup guides (4→1) Merged: - WIFI_SETUP.md - OPTIMAL_WIFI_AP_FAILOVER_SETUP.md - AP_MODE_MANUAL_ENABLE.md - WIFI_ETHERNET_AP_MODE_FIX.md (behavior documentation) Into: WIFI_NETWORK_SETUP.md - Comprehensive coverage of WiFi setup and configuration - Clear explanation of AP mode failover and grace period - Configuration scenarios and best practices - Troubleshooting section combining all sources - Professional technical writing style - Added quick reference table for behavior * docs: consolidate troubleshooting guides (4→1) Merged: - TROUBLESHOOTING_QUICK_START.md - WEB_INTERFACE_TROUBLESHOOTING.md - CAPTIVE_PORTAL_TROUBLESHOOTING.md - WEATHER_TROUBLESHOOTING.md Into: TROUBLESHOOTING.md - Organized by issue category (web, WiFi, plugins) - Comprehensive diagnostic commands reference - Quick diagnosis steps at the top - Service file template preserved - Complete diagnostic script included - Professional technical writing style * docs: create consolidated Advanced Features guide Merged: - VEGAS_SCROLL_MODE.md - ON_DEMAND_DISPLAY_QUICK_START.md - ON_DEMAND_DISPLAY_API.md - ON_DEMAND_CACHE_MANAGEMENT.md - BACKGROUND_SERVICE_README.md - PERMISSION_MANAGEMENT_GUIDE.md Into: ADVANCED_FEATURES.md - Comprehensive guide covering all advanced features - Vegas scroll mode with integration examples - On-demand display with API reference - Cache management troubleshooting - Background service documentation - Permission management patterns - Professional technical writing style * docs: create Getting Started guide for first-time users Created GETTING_STARTED.md: - Quick start guide (5 minutes) - Initial configuration walkthrough - Common first-time issues and solutions - Next steps and quick reference - User-friendly tone for beginners - Links to detailed documentation * docs: archive consolidated source files and ephemeral docs Archived files that have been consolidated: - Plugin Store guides (2 files → PLUGIN_STORE_GUIDE.md) - Web Interface guide (V3_INTERFACE_README.md → WEB_INTERFACE_GUIDE.md) - WiFi Setup guides (4 files → WIFI_NETWORK_SETUP.md) - Troubleshooting guides (4 files → TROUBLESHOOTING.md) - Advanced Features (6 files → ADVANCED_FEATURES.md) Archived ephemeral/debug documentation: - DEBUG_WEB_ISSUE.md - BROWSER_ERRORS_EXPLANATION.md - FORM_VALIDATION_FIXES.md - WEB_UI_RELIABILITY_IMPROVEMENTS.md - CAPTIVE_PORTAL_TESTING.md - NEXT_STEPS_COMMANDS.md - STATIC_IMAGE_MULTI_UPLOAD_PLAN.md - RECONNECT_AFTER_CAPTIVE_PORTAL_TESTING.md Archived implementation summaries: - PLUGIN_CONFIG_TABS_SUMMARY.md - PLUGIN_CONFIG_SYSTEM_VERIFICATION.md - PLUGIN_SCHEMA_AUDIT_SUMMARY.md - STARTUP_OPTIMIZATION_SUMMARY.md - PLUGIN_DISPATCH_IMPLEMENTATION.md - NESTED_SCHEMA_IMPLEMENTATION.md - AP_MODE_MANUAL_ENABLE_CHANGES.md - PLUGIN_CONFIG_SYSTEM_EXPLANATION.md Total archived: 27 files Preserves git history while cleaning up main docs directory * docs: rename API_REFERENCE.md to REST_API_REFERENCE.md Renamed for clarity - this is specifically the REST API reference for the web interface, not a general API reference. * docs: update README.md to reflect consolidated documentation structure Updated documentation index: - Reflects new consolidated guides (51 → 16-17 files) - Updated Quick Start sections with new file names - Added consolidation history (January 2026) - Updated file references (API_REFERENCE → REST_API_REFERENCE) - Documented archival of 33 files - Added benefits of consolidation - Updated statistics and highlights - Removed outdated references - Professional writing style maintained throughout * docs: add Vegas scroll mode system architecture documentation Added comprehensive internal architecture section for Vegas mode: - Component overview with diagram - VegasModeCoordinator responsibilities and main loop - StreamManager buffering strategy and content flow - PluginAdapter integration and fallback behavior - RenderPipeline 125 FPS rendering process - Component interaction flows - Thread safety patterns - Performance characteristics Covers: - How the four components work together - Initialization and render loop flows - Config update handling - Frame rate management and optimization - Memory usage and CPU characteristics --------- Co-authored-by: Chuck <chuck@example.com>
12 KiB
On-Demand Display - Quick Start Guide
🎯 What Is It?
On-Demand Display lets users manually trigger specific plugins to show on the LED matrix - perfect for "Show Now" buttons in your web interface!
2025 update: The LEDMatrix web interface now ships with first-class on-demand controls. You can trigger plugins directly from the Plugin Management page or by calling the new
/api/v3/display/on-demand/*endpoints described below. The legacy quick-start steps are still documented for bespoke integrations.
✅ Built-In Controls
Web Interface (no-code)
- Navigate to Settings → Plugin Management.
- Each installed plugin now exposes a Run On-Demand button:
- Choose the display mode (when a plugin exposes multiple views).
- Optionally set a fixed duration (leave blank to use the plugin default or
0to run until you stop it). - Pin the plugin so rotation stays paused.
- The dashboard shows real-time status and lets you stop the session. Shift+click the stop button to stop the display service after clearing the plugin.
- The status card refreshes automatically and indicates whether the display service is running.
REST Endpoints
All endpoints live under /api/v3/display/on-demand.
| Endpoint | Method | Description |
|---|---|---|
/status |
GET | Returns the current on-demand state plus display service health. |
/start |
POST | Requests a plugin/mode to run. Automatically starts the display service (unless start_service: false). |
/stop |
POST | Clears on-demand mode. Include {"stop_service": true} to stop the systemd service. |
Example curl calls:
# Start the default mode for football-scoreboard for 45 seconds
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
-H "Content-Type: application/json" \
-d '{
"plugin_id": "football-scoreboard",
"duration": 45,
"pinned": true
}'
# Start by mode name (plugin id inferred automatically)
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
-H "Content-Type: application/json" \
-d '{ "mode": "football_live" }'
# Stop on-demand and shut down the display service
curl -X POST http://localhost:5000/api/v3/display/on-demand/stop \
-H "Content-Type: application/json" \
-d '{ "stop_service": true }'
# Check current status
curl http://localhost:5000/api/v3/display/on-demand/status | jq
Notes
- The display controller will honour the plugin’s configured
display_durationwhen no duration is provided. - When you pass
duration: 0(or omit it) andpinned: true, the plugin stays active until you issue/stop. - The service automatically resumes normal rotation after the on-demand session expires or is cleared.
🚀 Quick Implementation (3 Steps)
The steps below describe a lightweight custom implementation that predates the built-in API. You generally no longer need this unless you are integrating with a separate control surface.
Step 1: Add API Endpoint
# In web_interface/blueprints/api_v3.py
@api_v3.route('/display/show', methods=['POST'])
def show_on_demand():
data = request.json
mode = data.get('mode')
duration = data.get('duration', 30) # Default 30 seconds
# Get display controller (implementation depends on your setup)
controller = get_display_controller()
success = controller.show_on_demand(mode, duration=duration)
return jsonify({'success': success})
@api_v3.route('/display/clear', methods=['POST'])
def clear_on_demand():
controller = get_display_controller()
controller.clear_on_demand()
return jsonify({'success': True})
Step 2: Add UI Button
<!-- Show weather button -->
<button onclick="showWeather()">Show Weather Now</button>
<script>
async function showWeather() {
await fetch('/api/v3/display/show', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
mode: 'weather',
duration: 30 // Show for 30 seconds
})
});
}
</script>
Step 3: Done! 🎉
Users can now click the button to show weather immediately!
📋 Complete Web UI Example
<!DOCTYPE html>
<html>
<head>
<title>Display Control</title>
<style>
.plugin-card {
border: 1px solid #ccc;
padding: 15px;
margin: 10px;
border-radius: 5px;
}
.show-now-btn {
background: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.pin-btn {
background: #2196F3;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.clear-btn {
background: #f44336;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
#status-bar {
background: #ff9800;
color: white;
padding: 15px;
text-align: center;
display: none;
}
</style>
</head>
<body>
<!-- Status bar (shown when on-demand is active) -->
<div id="status-bar">
<span id="status-text"></span>
<button class="clear-btn" onclick="clearOnDemand()">
Return to Rotation
</button>
</div>
<!-- Plugin controls -->
<div class="plugin-grid">
<div class="plugin-card">
<h3>⛅ Weather</h3>
<button class="show-now-btn" onclick="showPlugin('weather', 30)">
Show for 30s
</button>
<button class="pin-btn" onclick="pinPlugin('weather')">
Pin Weather
</button>
</div>
<div class="plugin-card">
<h3>🏒 Hockey</h3>
<button class="show-now-btn" onclick="showPlugin('hockey_live', 45)">
Show Live Game
</button>
<button class="pin-btn" onclick="pinPlugin('hockey_live')">
Pin Game
</button>
</div>
<div class="plugin-card">
<h3>🎵 Music</h3>
<button class="show-now-btn" onclick="showPlugin('music', 20)">
Show Now Playing
</button>
</div>
</div>
<script>
// Show plugin for specific duration
async function showPlugin(mode, duration) {
const response = await fetch('/api/v3/display/show', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mode, duration })
});
const data = await response.json();
if (data.success) {
updateStatus();
} else {
alert('Failed to show plugin');
}
}
// Pin plugin (stays until cleared)
async function pinPlugin(mode) {
const response = await fetch('/api/v3/display/show', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
mode,
pinned: true
})
});
const data = await response.json();
if (data.success) {
updateStatus();
}
}
// Clear on-demand and return to rotation
async function clearOnDemand() {
await fetch('/api/v3/display/clear', { method: 'POST' });
updateStatus();
}
// Update status display
async function updateStatus() {
const response = await fetch('/api/v3/display/on-demand-info');
const info = await response.json();
const statusBar = document.getElementById('status-bar');
const statusText = document.getElementById('status-text');
if (info.active) {
let text = `Showing: ${info.mode}`;
if (info.remaining) {
text += ` (${Math.ceil(info.remaining)}s remaining)`;
} else if (info.pinned) {
text += ' (pinned)';
}
statusText.textContent = text;
statusBar.style.display = 'block';
} else {
statusBar.style.display = 'none';
}
}
// Poll for status updates every second
setInterval(updateStatus, 1000);
// Initial status check
updateStatus();
</script>
</body>
</html>
⚡ Usage Patterns
Pattern 1: Timed Preview
// Show for 30 seconds then return to rotation
showPlugin('weather', 30);
Pattern 2: Pinned Display
// Stay on this plugin until manually cleared
pinPlugin('hockey_live');
Pattern 3: Quick Check
// Show for 10 seconds
showPlugin('clock', 10);
Pattern 4: Indefinite Display
// Show until cleared (duration=0)
fetch('/api/v3/display/show', {
method: 'POST',
body: JSON.stringify({ mode: 'weather', duration: 0 })
});
📊 Priority Order
User clicks "Show Weather" button
↓
1. On-Demand (Highest) ← Shows immediately
2. Live Priority ← Overridden
3. Normal Rotation ← Paused
On-demand has highest priority - it overrides everything!
🎮 Common Use Cases
Quick Weather Check
<button onclick="showPlugin('weather', 20)">
Check Weather
</button>
Monitor Live Game
<button onclick="pinPlugin('hockey_live')">
Watch Game
</button>
Test Plugin Configuration
<button onclick="showPlugin('my-plugin', 15)">
Preview Plugin
</button>
Emergency Message
<button onclick="pinPlugin('text-display')">
Show Alert
</button>
🔧 Duration Options
| Value | Behavior | Example |
|---|---|---|
30 |
Show for 30s then return | Quick preview |
0 |
Show until cleared | Extended viewing |
null |
Use plugin's default | Let plugin decide |
pinned: true |
Stay until unpinned | Monitor mode |
❓ FAQ
Q: What happens when duration expires?
A: Display automatically returns to normal rotation (or live priority if active).
Q: Can I show multiple modes at once?
A: No, only one mode at a time. Last request wins.
Q: Does it override live games?
A: Yes! On-demand has highest priority, even over live priority.
Q: How do I go back to normal rotation?
A: Either wait for duration to expire, or call clearOnDemand().
Q: What if the mode doesn't exist?
A: API returns success: false and logs a warning.
🐛 Testing
Test 1: Show for 30 seconds
curl -X POST http://pi-ip:5001/api/v3/display/show \
-H "Content-Type: application/json" \
-d '{"mode": "weather", "duration": 30}'
Test 2: Pin mode
curl -X POST http://pi-ip:5001/api/v3/display/show \
-H "Content-Type: application/json" \
-d '{"mode": "hockey_live", "pinned": true}'
Test 3: Clear on-demand
curl -X POST http://pi-ip:5001/api/v3/display/clear
Test 4: Check status
curl http://pi-ip:5001/api/v3/display/on-demand-info
📝 Implementation Checklist
- Add API endpoints to web interface
- Add "Show Now" buttons to plugin cards
- Add status bar showing current on-demand mode
- Add "Clear" button when on-demand active
- Add authentication to API endpoints
- Test with multiple plugins
- Test duration expiration
- Test pinned mode
📚 Full Documentation
See ON_DEMAND_DISPLAY_API.md for:
- Complete API reference
- Security best practices
- Troubleshooting guide
- Advanced examples
🎯 Key Points
- User-triggered - Manual control from web UI
- Highest priority - Overrides everything
- Auto-clear - Returns to rotation after duration
- Pin mode - Stay on mode until manually cleared
- Simple API - Just 3 endpoints needed
That's it! Your users can now control what shows on the display! 🚀