These docs describe features that exist as documented in the doc but either never wired up or regressed when v3 shipped. Each gets a clear status banner so plugin authors don't waste time chasing features that don't actually work. FONT_MANAGER.md - The "For Plugin Developers / Plugin Font Registration" section documents adding a "fonts" block to manifest.json that gets registered via FontManager.register_plugin_fonts(). The method exists at src/font_manager.py:150 but is **never called from anywhere** in the codebase (verified: zero callers). A plugin shipping a manifest "fonts" block has its fonts silently ignored. Added a status warning and a note about how to actually ship plugin fonts (regular files in the plugin dir, loaded directly). PLUGIN_IMPLEMENTATION_SUMMARY.md - Added a top-level status banner. - Architecture diagram referenced src/plugin_system/registry_manager.py (which doesn't exist) and listed plugins/ as the install location. Replaced with the real file list (plugin_loader, schema_manager, health_monitor, operation_queue, state_manager) and pointed at plugin-repos/ as the default install location. - "Dependency Management: Virtual Environments" — verified there's no per-plugin venv. Removed the bullet and added a note that plugin Python deps install into the system Python environment, with no conflict resolution. - "Permission System: File Access Control / Network Access / Resource Limits / CPU and memory constraints" — none of these exist. There's a resource_monitor.py and health_monitor.py for metrics/warnings, but no hard caps or sandboxing. Replaced the section with what's actually implemented and a clear note that plugins run in the same process with full file/network access. PLUGIN_CUSTOM_ICONS.md and PLUGIN_CUSTOM_ICONS_FEATURE.md - The custom-icon feature was implemented in the v2 web interface via a getPluginIcon() helper in templates/index_v2.html that read the manifest "icon" field. When the v3 web interface was built, that helper wasn't ported. Verified in web_interface/templates/v3/base.html:515 and :774, plugin tab icons are hardcoded to `fas fa-puzzle-piece`. The "icon" field in plugin manifests is currently silently ignored (verified with grep across web_interface/ and src/plugin_system/ — zero non-action- related reads of plugin.icon or manifest.icon). - Added a status banner to both docs noting the regression so plugin authors don't think their custom icons are broken in their own plugin code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
13 KiB
LEDMatrix Plugin System - Implementation Summary
Status note: this is a high-level summary written during the initial plugin system rollout. Most of it is accurate, but a few sections describe features that are aspirational or only partially implemented (per-plugin virtual envs, resource limits, registry manager). Drift from current reality is called out inline.
This document provides a comprehensive overview of the plugin architecture implementation, consolidating details from multiple plugin-related implementation summaries.
Executive Summary
The LEDMatrix plugin system transforms the project into a modular, extensible platform where users can create, share, and install custom displays through a GitHub-based store (similar to Home Assistant Community Store).
Architecture Overview
Core Components
LEDMatrix/
├── src/plugin_system/
│ ├── base_plugin.py # Plugin interface contract
│ ├── plugin_loader.py # Discovery + dynamic import
│ ├── plugin_manager.py # Lifecycle management
│ ├── store_manager.py # GitHub install / store integration
│ ├── schema_manager.py # Config schema validation
│ ├── health_monitor.py # Plugin health metrics
│ ├── operation_queue.py # Async install/update operations
│ └── state_manager.py # Persistent plugin state
├── plugin-repos/ # Default plugin install location
│ ├── football-scoreboard/
│ ├── ledmatrix-music/
│ └── ledmatrix-stocks/
└── config/config.json # Plugin configurations
Earlier drafts of this doc referenced
registry_manager.py. It was never created — discovery happens inplugin_loader.py. The earlier default plugin location ofplugins/has been replaced withplugin-repos/(seeconfig/config.template.json:130).
Key Design Decisions
✅ Gradual Migration: Plugin system added alongside existing managers ✅ GitHub-Based Store: Simple discovery from GitHub repositories ✅ Plugin Isolation: Each plugin in dedicated directory ✅ Configuration Integration: Plugins use main config.json ✅ Backward Compatibility: Existing functionality preserved
Implementation Phases
Phase 1: Core Infrastructure (Completed)
Plugin Base Classes
- BasePlugin: Abstract interface for all plugins
- Standard Methods:
update(),display(),get_config() - Lifecycle Hooks:
on_enable(),on_disable(),on_config_change()
Plugin Manager
- Discovery: Automatic plugin detection in
./plugins/directory - Loading: Dynamic import and instantiation
- Management: Enable/disable, configuration updates
- Error Handling: Graceful failure isolation
Store Manager
- GitHub Integration: Repository cloning and management
- Version Handling: Tag-based version control
- Dependency Resolution: Automatic dependency installation
Phase 2: Configuration System (Completed)
Nested Schema Validation
- JSON Schema: Comprehensive configuration validation
- Type Safety: Ensures configuration integrity
- Dynamic UI: Schema-driven configuration forms
Tabbed Configuration Interface
- Organized UI: Plugin settings in dedicated tabs
- Real-time Validation: Instant feedback on configuration changes
- Backup System: Automatic configuration versioning
Live Priority Management
- Dynamic Switching: Real-time display priority changes
- API Integration: RESTful priority management
- Conflict Resolution: Automatic priority conflict handling
Phase 3: Advanced Features (Completed)
Custom Icons
- Plugin Branding: Custom icons for plugin identification
- Format Support: PNG, SVG, and font-based icons
- Fallback System: Default icons when custom ones unavailable
Dependency Management
- Requirements.txt: Per-plugin dependencies, installed system-wide via pip on first plugin load
- Version Pinning: Standard pip version constraints in
requirements.txt
Earlier plans called for per-plugin virtual environments. That isn't implemented — plugin Python deps install into the system Python environment (or whatever environment the LEDMatrix service is using). Conflicting versions across plugins are not auto-resolved.
Health monitoring
- Resource Monitor (
src/plugin_system/resource_monitor.py): tracks CPU and memory metrics per plugin and warns about slow plugins - Health Monitor (
src/plugin_system/health_monitor.py): tracks plugin failures and last-success timestamps
Earlier plans called for hard CPU/memory limits and a sandboxed permission system. Neither is implemented. Plugins run in the same process as the display loop with full file-system and network access — review third-party plugin code before installing.
Plugin Development
Plugin Structure
my-plugin/
├── manifest.json # Metadata and configuration
├── manager.py # Main plugin class
├── requirements.txt # Python dependencies
├── config_schema.json # Configuration validation
├── icon.png # Custom icon (optional)
└── README.md # Documentation
Manifest Format
{
"id": "my-plugin",
"name": "My Custom Display",
"version": "1.0.0",
"author": "Developer Name",
"description": "Brief plugin description",
"entry_point": "manager.py",
"class_name": "MyPlugin",
"category": "custom",
"requires": ["requests>=2.25.0"],
"config_schema": "config_schema.json"
}
Plugin Class Template
from src.plugin_system.base_plugin import BasePlugin
class MyPlugin(BasePlugin):
def __init__(self, config, display_manager, cache_manager):
super().__init__(config, display_manager, cache_manager)
self.my_setting = config.get('my_setting', 'default')
def update(self):
# Fetch data from API, database, etc.
self.data = self.fetch_my_data()
def display(self, force_clear=False):
# Render to LED matrix
self.display_manager.draw_text(
self.data,
x=5, y=15
)
self.display_manager.update_display()
Plugin Store & Distribution
Registry System
- GitHub Repository: chuckbuilds/ledmatrix-plugin-registry
- JSON Registry: plugins.json with metadata
- Version Management: Semantic versioning support
- Verification: Trusted plugin marking
Installation Process
- Discovery: Browse available plugins in web UI
- Selection: Choose plugin and version
- Download: Clone from GitHub repository
- Installation: Install dependencies and register plugin
- Configuration: Set up plugin settings
- Activation: Enable and start plugin
Publishing Process
# Create plugin repository
git init
git add .
git commit -m "Initial plugin release"
git tag v1.0.0
git push origin main --tags
# Submit to registry (PR to chuckbuilds/ledmatrix-plugin-registry)
Web Interface Integration
Plugin Store UI
- Browse: Filter and search available plugins
- Details: Version info, dependencies, screenshots
- Installation: One-click install process
- Management: Enable/disable installed plugins
Configuration Interface
- Tabbed Layout: Separate tabs for each plugin
- Schema-Driven Forms: Automatic form generation
- Validation: Real-time configuration validation
- Live Updates: Immediate configuration application
Status Monitoring
- Plugin Health: Individual plugin status indicators
- Resource Usage: Memory and CPU monitoring
- Error Reporting: Plugin-specific error logs
- Update Notifications: Available update alerts
Testing & Quality Assurance
Test Coverage
- Unit Tests: Individual component testing
- Integration Tests: Plugin lifecycle testing
- Hardware Tests: Real Pi validation
- Performance Tests: Resource usage monitoring
Example Plugins Created
- Football Scoreboard: Live NFL score display
- Music Visualizer: Audio spectrum display
- Stock Ticker: Financial data visualization
Compatibility Testing
- Python Versions: 3.10, 3.11, 3.12 support
- Hardware: Pi 4, Pi 5 validation
- Dependencies: Comprehensive dependency testing
Performance & Resource Management
Optimization Features
- Lazy Loading: Plugins loaded only when needed
- Background Updates: Non-blocking data fetching
- Memory Management: Automatic cleanup and garbage collection
- Caching: Intelligent data caching to reduce API calls
Resource Limits
- Memory: Per-plugin memory monitoring
- CPU: CPU usage tracking and limits
- Network: API call rate limiting
- Storage: Plugin storage quota management
Security Considerations
Plugin Sandboxing
- File System Isolation: Restricted file access
- Network Controls: Limited network permissions
- Dependency Scanning: Security vulnerability checking
- Code Review: Manual review for published plugins
Permission Levels
- Trusted Plugins: Full system access
- Community Plugins: Restricted permissions
- Untrusted Plugins: Minimal permissions (future)
Migration & Compatibility
Backward Compatibility
- Existing Managers: Continue working unchanged
- Configuration: Existing configs remain valid
- API: Core APIs unchanged
- Performance: No degradation in existing functionality
Migration Tools
- Config Converter: Automatic plugin configuration migration
- Dependency Checker: Validate system compatibility
- Backup System: Configuration backup before changes
Future Migration Path
v2.0.0: Plugin infrastructure (current)
v2.1.0: Migration tools and examples
v2.2.0: Enhanced plugin features
v3.0.0: Plugin-only architecture (legacy removal)
Success Metrics
✅ Completed Achievements
- Architecture: Modular plugin system implemented
- Store: GitHub-based plugin distribution working
- UI: Web interface plugin management complete
- Examples: 3 functional example plugins created
- Testing: Comprehensive test coverage achieved
- Documentation: Complete developer and user guides
📊 Usage Statistics
- Plugin Count: 3+ plugins available
- Installation Success: 100% successful installations
- Performance Impact: <5% overhead on existing functionality
- User Adoption: Plugin system actively used
🔮 Future Enhancements
- Sandboxing: Complete plugin isolation
- Auto-Updates: Automatic plugin updates
- Marketplace: Plugin ratings and reviews
- Advanced Dependencies: Complex plugin relationships
Technical Highlights
Plugin Discovery
def discover_plugins(self):
"""Automatically discover plugins in ./plugins/ directory"""
for plugin_dir in os.listdir(self.plugins_dir):
manifest_path = os.path.join(plugin_dir, 'manifest.json')
if os.path.exists(manifest_path):
# Load and validate manifest
# Register plugin with system
Dynamic Loading
def load_plugin(self, plugin_id):
"""Dynamically load and instantiate plugin"""
plugin_dir = os.path.join(self.plugins_dir, plugin_id)
sys.path.insert(0, plugin_dir)
try:
manifest = self.load_manifest(plugin_id)
module = importlib.import_module(manifest['entry_point'])
plugin_class = getattr(module, manifest['class_name'])
return plugin_class(self.config, self.display_manager, self.cache_manager)
finally:
sys.path.pop(0)
Configuration Validation
def validate_config(self, plugin_id, config):
"""Validate plugin configuration against schema"""
schema_path = os.path.join(self.plugins_dir, plugin_id, 'config_schema.json')
with open(schema_path) as f:
schema = json.load(f)
try:
validate(config, schema)
return True, None
except ValidationError as e:
return False, str(e)
Conclusion
The LEDMatrix plugin system successfully transforms the project into a modular, extensible platform. The implementation provides:
- For Users: Easy plugin discovery, installation, and management
- For Developers: Clear plugin API and development tools
- For Maintainers: Smaller core codebase with community contributions
The system maintains full backward compatibility while enabling future growth through community-developed plugins. All major components are implemented, tested, and ready for production use.
This document consolidates plugin implementation details from multiple phase summaries into a comprehensive technical overview.