A second-pass content audit checked the guides' substantive claims against the code (the first pass only fixed mechanical drift). Fixes: - GETTING_STARTED: described booting a prebuilt SD image and seeing default clock/weather plugins — neither exists. Now documents the real install (Pi OS Lite + one-shot installer / first_time_install.sh) and that displays come from the Plugin Store. Duration and ordering instructions moved to the Rotation tab where the controls actually live. - WEB_INTERFACE_GUIDE: three whole tabs were undocumented (Rotation, Backup & Restore, Tools) and the Display tab's Vegas Scroll section was unmentioned. Fonts overrides are per display element (not per plugin); Logs has an Auto-scroll checkbox (not a Pause button); the aspirational keyboard-shortcut list and no-JS claim removed. - TROUBLESHOOTING: the hand-written service-file template (wrong user, wrong ExecStart, dropped the autostart gate) replaced with the real systemd/ units + install scripts; recovery steps no longer copy placeholder units verbatim; WiFi curl endpoint corrected to /api/v3/; cache-clearing advice now targets the real cache locations. - ADVANCED_FEATURES: removed a false claim that CacheManager has no delete(); fixed two example snippets that raise TypeError (BackgroundDataService and get_config_file_mode signatures); fixed cache paths, a 5-minute TTL that is actually 1 hour, and the vegas table now links the complete 26-key reference. - EMULATOR_SETUP_GUIDE: documented run.py flags that don't exist (--plugin/--test-plugins) removed in favor of dev_server.py and check_plugin.py; shipped emulator config values corrected (browser adapter default on :8888, not pygame). - PLUGIN_QUICK_REFERENCE: drag-and-drop reordering is shipped, not 'not yet supported'; discovery-fallback and registry-repo claims corrected. PLUGIN_API_REFERENCE: get_vegas_segment_width returns panels, not pixels. CONTRIBUTING: the repo uses flake8/mypy/bandit pre-commit hooks, not black/ruff, and tests need requirements-test.txt. - SKIN_SYSTEM/DEVELOPER_QUICK_REFERENCE: stale module paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXb4mKcAkVaxkeTb3YnAdr
6.2 KiB
LEDMatrix Plugin Architecture - Quick Reference
Overview
LEDMatrix is a modular, plugin-based system where users create, share, and install custom displays via a GitHub-based store (similar in spirit to HACS for Home Assistant). This page is a quick reference; for the full design see PLUGIN_ARCHITECTURE_SPEC.md and PLUGIN_DEVELOPMENT_GUIDE.md.
Key Decisions
✅ Plugin-First: All display features (calendar excepted) are now plugins
✅ GitHub Store: Discovery from ledmatrix-plugins registry plus
any GitHub URL
✅ Plugin Location: configured by plugin_system.plugins_directory
in config.json (default plugin-repos/). Plugin discovery scans
only this directory — there is no loader fallback to plugins/
(only Plugin Store operations and schema lookup additionally probe
plugins/)
File Structure
LEDMatrix/
├── src/
│ └── plugin_system/
│ ├── base_plugin.py # Plugin interface
│ ├── plugin_manager.py # Load/unload plugins
│ ├── plugin_loader.py # Discovery + dynamic import
│ └── store_manager.py # Install from GitHub
├── plugin-repos/ # Default plugin install location
│ ├── clock-simple/
│ │ ├── manifest.json # Metadata
│ │ ├── manager.py # Main plugin class
│ │ ├── requirements.txt # Dependencies
│ │ ├── config_schema.json # Validation
│ │ └── README.md
│ └── hockey-scoreboard/
│ └── ... (same structure)
└── config/config.json # Plugin configs
Creating a Plugin
1. Minimal Plugin Structure
manifest.json:
{
"id": "my-plugin",
"name": "My Display",
"version": "1.0.0",
"author": "YourName",
"entry_point": "manager.py",
"class_name": "MyPlugin",
"category": "custom"
}
manager.py:
from src.plugin_system.base_plugin import BasePlugin
class MyPlugin(BasePlugin):
def update(self):
# Fetch data
pass
def display(self, force_clear=False):
# Render to display
self.display_manager.draw_text("Hello!", x=5, y=15)
self.display_manager.update_display()
2. Configuration
config_schema.json:
{
"type": "object",
"properties": {
"enabled": {"type": "boolean", "default": true},
"message": {"type": "string", "default": "Hello"}
}
}
User's config.json:
{
"my-plugin": {
"enabled": true,
"message": "Custom text",
"display_duration": 15
}
}
3. Publishing
# Create repo
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/YourName/ledmatrix-my-plugin
git push -u origin main
# Tag release
git tag v1.0.0
git push origin v1.0.0
# Submit to registry (PR to ChuckBuilds/ledmatrix-plugins)
Using Plugins
Web UI
- Browse Store: Plugin Manager tab → Plugin Store section → Search/filter
- Install: Click Install in the plugin's row
- Configure: open the plugin's tab in the second nav row
- Enable/Disable: toggle switch in the Installed Plugins list
- Reorder: use the drag-and-drop Rotation Order list in the
Rotation tab (saved to
display.plugin_rotation_order)
REST API
The API is mounted at /api/v3 (web_interface/app.py:199).
# Install plugin from the registry
curl -X POST http://your-pi-ip:5000/api/v3/plugins/install \
-H "Content-Type: application/json" \
-d '{"plugin_id": "hockey-scoreboard"}'
# Install from custom URL
curl -X POST http://your-pi-ip:5000/api/v3/plugins/install-from-url \
-H "Content-Type: application/json" \
-d '{"repo_url": "https://github.com/User/plugin"}'
# List installed
curl http://your-pi-ip:5000/api/v3/plugins/installed
# Toggle
curl -X POST http://your-pi-ip:5000/api/v3/plugins/toggle \
-H "Content-Type: application/json" \
-d '{"plugin_id": "hockey-scoreboard", "enabled": true}'
See REST_API_REFERENCE.md for the full list.
Plugin Registry Structure
The official registry lives at
ChuckBuilds/ledmatrix-plugins.
The Plugin Store reads plugins.json at the root of that repo, which
follows this shape:
{
"plugins": [
{
"id": "clock-simple",
"name": "Simple Clock",
"author": "ChuckBuilds",
"category": "time",
"repo": "https://github.com/ChuckBuilds/ledmatrix-clock-simple",
"versions": [
{
"version": "1.0.0",
"ledmatrix_min_version": "2.0.0",
"download_url": "https://github.com/.../v1.0.0.zip"
}
],
"verified": true
}
]
}
Benefits
For Users
- ✅ Install only what you need
- ✅ Easy discovery of new displays
- ✅ Simple updates
- ✅ Community-created content
For Developers
- ✅ Lower barrier to contribute
- ✅ No need to fork core repo
- ✅ Faster iteration
- ✅ Clear plugin API
For Maintainers
- ✅ Smaller core codebase
- ✅ Less merge conflicts
- ✅ Community handles custom displays
- ✅ Easier to review changes
Known Limitations
The plugin system is shipped and stable, but some things are still intentionally simple:
- Sandboxing: plugins run in the same process as the display loop; there is no isolation. Review code before installing third-party plugins.
- Resource limits: there's a resource monitor that warns about slow plugins, but no hard CPU/memory caps.
- Plugin ratings: not yet — the Plugin Store shows version, author, and category but no community rating system.
- Auto-updates: manual via the Plugin Manager tab; no automatic background updates.
- Dependency conflicts: each plugin's
requirements.txtis installed via pip; conflicting versions across plugins are not resolved automatically. - Plugin testing framework: see HOW_TO_RUN_TESTS.md and DEV_PREVIEW.md — there are tools, but no mandatory test gate.
See PLUGIN_ARCHITECTURE_SPEC.md for the full architectural specification.