mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 21:03:01 +00:00
docs: fix ADVANCED_FEATURES and REST_API_REFERENCE
REST_API_REFERENCE.md
- Wrong path: /fonts/delete/<font_family> -> /fonts/<font_family>
(verified the real DELETE route in
web_interface/blueprints/api_v3.py).
- Diffed the documented routes against the real api_v3 blueprint
(92 routes vs the 71 documented). Added missing sections:
- Error tracking (/errors/summary, /errors/plugin/<id>, /errors/clear)
- Health (/health)
- Schedule dim/power (/config/dim-schedule GET/POST)
- Plugin-specific endpoints (calendar/list-calendars,
of-the-day/json/upload+delete, plugins/<id>/static/<path>)
- Starlark Apps (12 endpoints: status, install-pixlet, apps CRUD,
repository browse/install, upload)
- Font preview (/fonts/preview)
- Updated table of contents with the new sections.
- Added a footer note that the API blueprint mounts at /api/v3
(app.py:144) and that SSE stream endpoints are defined directly on
the Flask app at app.py:607-615.
ADVANCED_FEATURES.md
- Vegas Scroll Mode section was actually accurate (verified all
config keys match src/vegas_mode/config.py:15-30).
- On-Demand Display section had multiple bugs:
- 5 occurrences of port 5050 -> 5000
- All API paths missing /v3 (e.g. /api/display/on-demand/start
should be /api/v3/display/on-demand/start)
- "Settings -> Plugin Management -> Show Now Button" UI flow doesn't
exist. Real flow: open the plugin's tab in the second nav row,
click Run On-Demand / Stop On-Demand.
- "Python API Methods" section showed
controller.show_on_demand() / clear_on_demand() /
is_on_demand_active() / get_on_demand_info() — none of these
methods exist on DisplayController. The on-demand machinery is
all internal (_set_on_demand_*, _activate_on_demand, etc) and
is driven through the cache_manager. Replaced the section with
a note pointing to the REST API.
- All Use Case Examples used the same fictional Python calls.
Replaced with curl examples against the real API.
- Cache Management section claimed "On-demand display uses Redis cache
keys". LEDMatrix doesn't use Redis — verified with grep that
src/cache_manager.py has no redis import. The cache is file-based,
managed by CacheManager (file at /var/cache/ledmatrix/ or fallback
paths). Rewrote the manual recovery section:
- Removed redis-cli commands
- Replaced cache.delete() Python calls with cache.clear_cache()
(the real public method per the same bug already flagged in
PLUGIN_API_REFERENCE.md)
- Replaced "Settings -> Cache Management" with the real Cache tab
- Documented the actual cache directory candidates
- Background Data Service section:
- Used "nfl_scoreboard" as the plugin id in the example.
The real plugin is "football-scoreboard" (handles both NFL and
NCAA). Fixed.
- "Implementation Status: Phase 1 NFL only / Phase 2 planned"
section was severely outdated. The background service is now
used by all sports scoreboards (football, hockey, baseball,
basketball, soccer, lacrosse, F1, UFC), the odds ticker, and
the leaderboard plugin. Replaced with a current "Plugins using
the background service" note.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -437,26 +437,26 @@ When on-demand expires or is cleared, the display returns to the next highest pr
|
||||
|
||||
### Web Interface Controls
|
||||
|
||||
**Access:** Navigate to Settings → Plugin Management
|
||||
Each installed plugin has its own tab in the second nav row of the web
|
||||
UI. Inside the plugin's tab, scroll to **On-Demand Controls**:
|
||||
|
||||
**Controls:**
|
||||
- **Show Now Button** - Triggers plugin immediately
|
||||
- **Duration Slider** - Set display time (0 = indefinite)
|
||||
- **Pin Checkbox** - Keep showing until manually cleared
|
||||
- **Stop Button** - Clear on-demand and return to rotation
|
||||
- **Shift+Click Stop** - Stop the entire display service
|
||||
- **Run On-Demand** — triggers the plugin immediately, even if it's
|
||||
disabled in the rotation
|
||||
- **Stop On-Demand** — clears on-demand and returns to the normal
|
||||
rotation
|
||||
|
||||
**Status Card:**
|
||||
- Real-time status updates
|
||||
- Shows active plugin and remaining time
|
||||
- Pin status indicator
|
||||
The display service must be running. The status banner at the top of
|
||||
the plugin tab shows the active on-demand plugin, mode, and remaining
|
||||
time when something is active.
|
||||
|
||||
### REST API Reference
|
||||
|
||||
The API is mounted at `/api/v3` (`web_interface/app.py:144`).
|
||||
|
||||
#### Start On-Demand Display
|
||||
|
||||
```bash
|
||||
POST /api/display/on-demand/start
|
||||
POST /api/v3/display/on-demand/start
|
||||
|
||||
# Body:
|
||||
{
|
||||
@@ -467,20 +467,20 @@ POST /api/display/on-demand/start
|
||||
|
||||
# Examples:
|
||||
# 30-second preview
|
||||
curl -X POST http://localhost:5050/api/display/on-demand/start \
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"plugin_id": "weather", "duration": 30}'
|
||||
|
||||
# Pin indefinitely
|
||||
curl -X POST http://localhost:5050/api/display/on-demand/start \
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"plugin_id": "hockey-scores", "pinned": true}'
|
||||
-d '{"plugin_id": "hockey-scoreboard", "pinned": true}'
|
||||
```
|
||||
|
||||
#### Stop On-Demand Display
|
||||
|
||||
```bash
|
||||
POST /api/display/on-demand/stop
|
||||
POST /api/v3/display/on-demand/stop
|
||||
|
||||
# Body:
|
||||
{
|
||||
@@ -489,10 +489,10 @@ POST /api/display/on-demand/stop
|
||||
|
||||
# Examples:
|
||||
# Clear on-demand
|
||||
curl -X POST http://localhost:5050/api/display/on-demand/stop
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/stop
|
||||
|
||||
# Stop service too
|
||||
curl -X POST http://localhost:5050/api/display/on-demand/stop \
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/stop \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"stop_service": true}'
|
||||
```
|
||||
@@ -500,10 +500,10 @@ curl -X POST http://localhost:5050/api/display/on-demand/stop \
|
||||
#### Get On-Demand Status
|
||||
|
||||
```bash
|
||||
GET /api/display/on-demand/status
|
||||
GET /api/v3/display/on-demand/status
|
||||
|
||||
# Example:
|
||||
curl http://localhost:5050/api/display/on-demand/status
|
||||
curl http://localhost:5000/api/v3/display/on-demand/status
|
||||
|
||||
# Response:
|
||||
{
|
||||
@@ -516,35 +516,10 @@ curl http://localhost:5050/api/display/on-demand/status
|
||||
}
|
||||
```
|
||||
|
||||
### Python API Methods
|
||||
|
||||
```python
|
||||
from src.display_controller import DisplayController
|
||||
|
||||
controller = DisplayController()
|
||||
|
||||
# Show plugin for 30 seconds
|
||||
controller.show_on_demand('weather', duration=30)
|
||||
|
||||
# Pin plugin until manually cleared
|
||||
controller.show_on_demand('hockey-scores', pinned=True)
|
||||
|
||||
# Show indefinitely (not pinned, clears on expiry if duration set later)
|
||||
controller.show_on_demand('weather', duration=0)
|
||||
|
||||
# Use plugin's default duration
|
||||
controller.show_on_demand('weather')
|
||||
|
||||
# Clear on-demand
|
||||
controller.clear_on_demand()
|
||||
|
||||
# Check status
|
||||
is_active = controller.is_on_demand_active()
|
||||
|
||||
# Get detailed info
|
||||
info = controller.get_on_demand_info()
|
||||
# Returns: {'active': bool, 'mode': str, 'duration': float, 'remaining': float, 'pinned': bool}
|
||||
```
|
||||
> There is no public Python on-demand API. The display controller's
|
||||
> on-demand machinery is internal — drive it through the REST endpoints
|
||||
> above (or the web UI buttons), which write a request into the cache
|
||||
> manager (`display_on_demand_config` key) that the controller polls.
|
||||
|
||||
### Duration Modes
|
||||
|
||||
@@ -557,27 +532,31 @@ info = controller.get_on_demand_info()
|
||||
|
||||
### Use Case Examples
|
||||
|
||||
**Quick Check (30-second preview):**
|
||||
```python
|
||||
controller.show_on_demand('weather', duration=30)
|
||||
**Quick check (30-second preview):**
|
||||
```bash
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"plugin_id": "ledmatrix-weather", "duration": 30}'
|
||||
```
|
||||
|
||||
**Pin Important Information:**
|
||||
```python
|
||||
controller.show_on_demand('game-score', pinned=True)
|
||||
**Pin important information:**
|
||||
```bash
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"plugin_id": "hockey-scoreboard", "pinned": true}'
|
||||
# ... later ...
|
||||
controller.clear_on_demand()
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/stop
|
||||
```
|
||||
|
||||
**Indefinite Display:**
|
||||
```python
|
||||
controller.show_on_demand('welcome-message', duration=0)
|
||||
**Indefinite display:**
|
||||
```bash
|
||||
curl -X POST http://localhost:5000/api/v3/display/on-demand/start \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"plugin_id": "text-display", "duration": 0}'
|
||||
```
|
||||
|
||||
**Testing Plugin:**
|
||||
```python
|
||||
controller.show_on_demand('my-new-plugin', duration=60)
|
||||
```
|
||||
**Testing a plugin during development:** the same call works, or just
|
||||
click **Run On-Demand** in the plugin's tab.
|
||||
|
||||
### Best Practices
|
||||
|
||||
@@ -613,7 +592,10 @@ controller.show_on_demand('my-new-plugin', duration=60)
|
||||
|
||||
### Overview
|
||||
|
||||
On-demand display uses Redis cache keys to manage state across service restarts and coordinate between web interface and display controller. Understanding these keys helps troubleshoot stuck states.
|
||||
On-demand display uses cache keys (managed by `src/cache_manager.py` —
|
||||
file-based, not Redis) to coordinate state between the web interface
|
||||
and the display controller across service restarts. Understanding these
|
||||
keys helps troubleshoot stuck states.
|
||||
|
||||
### Cache Keys
|
||||
|
||||
@@ -688,19 +670,26 @@ On-demand display uses Redis cache keys to manage state across service restarts
|
||||
### Manual Recovery Procedures
|
||||
|
||||
**Via Web Interface (Recommended):**
|
||||
1. Navigate to Settings → Cache Management
|
||||
2. Search for "on_demand" keys
|
||||
3. Select keys to delete
|
||||
4. Click "Delete Selected"
|
||||
5. Restart display: `sudo systemctl restart ledmatrix`
|
||||
1. Open the **Cache** tab in the web UI
|
||||
2. Find the `display_on_demand_*` entries
|
||||
3. Delete them
|
||||
4. Restart display: `sudo systemctl restart ledmatrix`
|
||||
|
||||
**Via Command Line:**
|
||||
```bash
|
||||
# Clear specific key
|
||||
redis-cli DEL display_on_demand_config
|
||||
|
||||
# Clear all on-demand keys
|
||||
redis-cli KEYS "display_on_demand_*" | xargs redis-cli DEL
|
||||
The cache is stored as JSON files under one of:
|
||||
|
||||
- `/var/cache/ledmatrix/` (preferred when the service has permission)
|
||||
- `~/.cache/ledmatrix/`
|
||||
- `/opt/ledmatrix/cache/`
|
||||
- `/tmp/ledmatrix-cache/` (fallback)
|
||||
|
||||
```bash
|
||||
# Find the cache dir actually in use
|
||||
journalctl -u ledmatrix | grep -i "cache directory" | tail -1
|
||||
|
||||
# Clear all on-demand keys (replace path with the one above)
|
||||
rm /var/cache/ledmatrix/display_on_demand_*
|
||||
|
||||
# Restart service
|
||||
sudo systemctl restart ledmatrix
|
||||
@@ -711,19 +700,22 @@ sudo systemctl restart ledmatrix
|
||||
from src.cache_manager import CacheManager
|
||||
|
||||
cache = CacheManager()
|
||||
cache.delete('display_on_demand_config')
|
||||
cache.delete('display_on_demand_state')
|
||||
cache.delete('display_on_demand_request')
|
||||
cache.delete('display_on_demand_processed_id')
|
||||
cache.clear_cache('display_on_demand_config')
|
||||
cache.clear_cache('display_on_demand_state')
|
||||
cache.clear_cache('display_on_demand_request')
|
||||
cache.clear_cache('display_on_demand_processed_id')
|
||||
```
|
||||
|
||||
> The actual public method is `clear_cache(key=None)` — there is no
|
||||
> `delete()` method on `CacheManager`.
|
||||
|
||||
### Cache Impact on Running Service
|
||||
|
||||
**IMPORTANT:** Clearing cache keys does NOT immediately affect the running controller in memory.
|
||||
|
||||
**To fully reset:**
|
||||
1. Stop the service: `sudo systemctl stop ledmatrix`
|
||||
2. Clear cache keys (web UI or redis-cli)
|
||||
2. Clear cache keys (web UI Cache tab or `rm` from the cache directory)
|
||||
3. Clear systemd environment: `sudo systemctl daemon-reload`
|
||||
4. Start the service: `sudo systemctl start ledmatrix`
|
||||
|
||||
@@ -767,7 +759,7 @@ Enable background service per plugin in `config/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"nfl_scoreboard": {
|
||||
"football-scoreboard": {
|
||||
"enabled": true,
|
||||
"background_service": {
|
||||
"enabled": true,
|
||||
@@ -801,18 +793,13 @@ Enable background service per plugin in `config/config.json`:
|
||||
- Returns immediately: < 0.1 seconds
|
||||
- Background refresh (if stale): async, no blocking
|
||||
|
||||
### Implementation Status
|
||||
### Plugins using the background service
|
||||
|
||||
**Phase 1 (Complete):**
|
||||
- ✅ NFL scoreboard implemented
|
||||
- ✅ Background threading architecture
|
||||
- ✅ Cache integration
|
||||
- ✅ Error handling and retry logic
|
||||
|
||||
**Phase 2 (Planned):**
|
||||
- ⏳ NCAAFB (college football)
|
||||
- ⏳ NBA (basketball)
|
||||
- ⏳ NHL (hockey)
|
||||
The background data service is now used by all of the sports scoreboard
|
||||
plugins (football, hockey, baseball, basketball, soccer, lacrosse, F1,
|
||||
UFC), the odds ticker, and the leaderboard plugin. Each plugin's
|
||||
`background_service` block (under its own config namespace) follows the
|
||||
same shape as the example above.
|
||||
- ⏳ MLB (baseball)
|
||||
|
||||
### Error Handling & Fallback
|
||||
|
||||
@@ -24,6 +24,17 @@ All endpoints return JSON responses with a standard format:
|
||||
- [Cache](#cache)
|
||||
- [WiFi](#wifi)
|
||||
- [Streams](#streams)
|
||||
- [Logs](#logs)
|
||||
- [Error tracking](#error-tracking)
|
||||
- [Health](#health)
|
||||
- [Schedule (dim/power)](#schedule-dimpower)
|
||||
- [Plugin-specific endpoints](#plugin-specific-endpoints)
|
||||
- [Starlark Apps](#starlark-apps)
|
||||
|
||||
> The API blueprint is mounted at `/api/v3` (`web_interface/app.py:144`).
|
||||
> SSE stream endpoints (`/api/v3/stream/*`) are defined directly on the
|
||||
> Flask app at `app.py:607-615`. There are about 92 routes total — see
|
||||
> `web_interface/blueprints/api_v3.py` for the canonical list.
|
||||
|
||||
---
|
||||
|
||||
@@ -1201,10 +1212,16 @@ Upload a custom font file.
|
||||
|
||||
### Delete Font
|
||||
|
||||
**DELETE** `/api/v3/fonts/delete/<font_family>`
|
||||
**DELETE** `/api/v3/fonts/<font_family>`
|
||||
|
||||
Delete an uploaded font.
|
||||
|
||||
### Font Preview
|
||||
|
||||
**GET** `/api/v3/fonts/preview?family=<font_family>&text=<sample>`
|
||||
|
||||
Render a small preview image of a font for use in the web UI font picker.
|
||||
|
||||
---
|
||||
|
||||
## Cache
|
||||
@@ -1439,6 +1456,130 @@ Get recent log entries.
|
||||
|
||||
---
|
||||
|
||||
## Error tracking
|
||||
|
||||
### Get Error Summary
|
||||
|
||||
**GET** `/api/v3/errors/summary`
|
||||
|
||||
Aggregated counts of recent errors across all plugins and core
|
||||
components, used by the web UI's error indicator.
|
||||
|
||||
### Get Plugin Errors
|
||||
|
||||
**GET** `/api/v3/errors/plugin/<plugin_id>`
|
||||
|
||||
Recent errors for a specific plugin.
|
||||
|
||||
### Clear Errors
|
||||
|
||||
**POST** `/api/v3/errors/clear`
|
||||
|
||||
Clear the in-memory error aggregator.
|
||||
|
||||
---
|
||||
|
||||
## Health
|
||||
|
||||
### Health Check
|
||||
|
||||
**GET** `/api/v3/health`
|
||||
|
||||
Lightweight liveness check used by the WiFi monitor and external
|
||||
monitoring tools.
|
||||
|
||||
---
|
||||
|
||||
## Schedule (dim/power)
|
||||
|
||||
### Get Dim Schedule
|
||||
|
||||
**GET** `/api/v3/config/dim-schedule`
|
||||
|
||||
Read the dim/power schedule that automatically reduces brightness or
|
||||
turns the display off at configured times.
|
||||
|
||||
### Update Dim Schedule
|
||||
|
||||
**POST** `/api/v3/config/dim-schedule`
|
||||
|
||||
Update the dim schedule. Body matches the structure returned by GET.
|
||||
|
||||
---
|
||||
|
||||
## Plugin-specific endpoints
|
||||
|
||||
A handful of endpoints belong to individual built-in or shipped plugins.
|
||||
|
||||
### Calendar
|
||||
|
||||
**GET** `/api/v3/plugins/calendar/list-calendars`
|
||||
|
||||
List the calendars available on the authenticated Google account.
|
||||
Used by the calendar plugin's config UI.
|
||||
|
||||
### Of The Day
|
||||
|
||||
**POST** `/api/v3/plugins/of-the-day/json/upload`
|
||||
|
||||
Upload a JSON data file for the Of-The-Day plugin's category data.
|
||||
|
||||
**POST** `/api/v3/plugins/of-the-day/json/delete`
|
||||
|
||||
Delete a previously uploaded Of-The-Day data file.
|
||||
|
||||
### Plugin Static Assets
|
||||
|
||||
**GET** `/api/v3/plugins/<plugin_id>/static/<path:file_path>`
|
||||
|
||||
Serve a static asset (image, font, etc.) from a plugin's directory.
|
||||
Used internally by the web UI to render plugin previews and icons.
|
||||
|
||||
---
|
||||
|
||||
## Starlark Apps
|
||||
|
||||
The Starlark plugin lets you run [Tronbyt](https://github.com/tronbyt/apps)
|
||||
Starlark apps on the matrix. These endpoints expose its UI.
|
||||
|
||||
### Status
|
||||
|
||||
**GET** `/api/v3/starlark/status`
|
||||
|
||||
Returns whether the Pixlet binary is installed and the Starlark plugin
|
||||
is operational.
|
||||
|
||||
### Install Pixlet
|
||||
|
||||
**POST** `/api/v3/starlark/install-pixlet`
|
||||
|
||||
Download and install the Pixlet binary on the Pi.
|
||||
|
||||
### Apps
|
||||
|
||||
**GET** `/api/v3/starlark/apps` — list installed Starlark apps
|
||||
**GET** `/api/v3/starlark/apps/<app_id>` — get app details
|
||||
**DELETE** `/api/v3/starlark/apps/<app_id>` — uninstall an app
|
||||
**GET** `/api/v3/starlark/apps/<app_id>/config` — get app config schema
|
||||
**PUT** `/api/v3/starlark/apps/<app_id>/config` — update app config
|
||||
**POST** `/api/v3/starlark/apps/<app_id>/render` — render app to a frame
|
||||
**POST** `/api/v3/starlark/apps/<app_id>/toggle` — enable/disable app
|
||||
|
||||
### Repository (Tronbyt community apps)
|
||||
|
||||
**GET** `/api/v3/starlark/repository/categories` — browse categories
|
||||
**GET** `/api/v3/starlark/repository/browse?category=<cat>` — browse apps
|
||||
**POST** `/api/v3/starlark/repository/install` — install an app from the
|
||||
community repository
|
||||
|
||||
### Upload custom app
|
||||
|
||||
**POST** `/api/v3/starlark/upload`
|
||||
|
||||
Upload a custom Starlark `.star` file as a new app.
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
All endpoints may return error responses in the following format:
|
||||
|
||||
Reference in New Issue
Block a user