Files
LEDMatrix/.cursor/plugin_templates/QUICK_START.md
Chuck 93e2d29af6 docs: fix .cursor/ helper docs
The .cursor/ directory holds the dev-side helper docs that Cursor and
contributors using AI tooling rely on to bootstrap plugin development.
Several of them had the same bug patterns as the user-facing docs.

.cursor/plugin_templates/QUICK_START.md
- "Adding Image Rendering" section showed
  display_manager.draw_image(image, x=0, y=0). That method doesn't
  exist on DisplayManager (same bug as PLUGIN_API_REFERENCE.md and
  PLUGIN_DEVELOPMENT_GUIDE.md). Replaced with the canonical
  display_manager.image.paste((x,y)) pattern, including the
  transparency-mask form.

.cursor/plugins_guide.md
- 10 occurrences of ./dev_plugin_setup.sh — the script lives at
  scripts/dev/dev_plugin_setup.sh, so anyone copy-pasting these
  examples gets "command not found". Bulk fixed via sed.
- "Test with emulator: python run.py --emulator" — there's no
  --emulator flag. Replaced with the real options:
  EMULATOR=true python3 run.py for the full display, or
  scripts/dev_server.py for the dev preview.
- Secrets management section showed a fictional
  "config_secrets": { "api_key": "my-plugin.api_key" } reference
  field. Verified in src/config_manager.py:162-172 that secrets are
  loaded by deep-merging config_secrets.json into the main config.
  There is no separate reference field — just put the secret under
  the same plugin namespace and read it from the merged config.
  Rewrote the section with the real pattern.
- "ssh pi@raspberrypi" -> "ssh ledpi@your-pi-ip" (consistent with
  the rest of LEDMatrix docs which use ledpi as the default user)

.cursor/README.md
- Same ./dev_plugin_setup.sh -> ./scripts/dev/dev_plugin_setup.sh
  fix (×6 occurrences via replace_all).
- Same "python run.py --emulator" -> "EMULATOR=true python3 run.py"
  fix. Also added a pointer to scripts/dev_server.py for previewing
  plugins without running the full display.
- "Example Plugins: plugins/hockey-scoreboard/" — the canonical
  source is the ledmatrix-plugins repo. Installed copies land in
  plugin-repos/ or plugins/. Updated the line to point at the
  ledmatrix-plugins repo and explain both local locations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:08:46 -04:00

248 lines
5.3 KiB
Markdown

# Quick Start: Creating a New Plugin
This guide will help you create a new plugin using the templates in `.cursor/plugin_templates/`.
## Step 1: Create Plugin Directory
```bash
cd /path/to/LEDMatrix
mkdir -p plugins/my-plugin
cd plugins/my-plugin
```
## Step 2: Copy Templates
```bash
# Copy all template files
cp ../../.cursor/plugin_templates/manifest.json.template ./manifest.json
cp ../../.cursor/plugin_templates/manager.py.template ./manager.py
cp ../../.cursor/plugin_templates/config_schema.json.template ./config_schema.json
cp ../../.cursor/plugin_templates/README.md.template ./README.md
cp ../../.cursor/plugin_templates/requirements.txt.template ./requirements.txt
```
## Step 3: Customize Files
### manifest.json
Replace placeholders:
- `PLUGIN_ID``my-plugin` (lowercase, use hyphens)
- `Plugin Name` → Your plugin's display name
- `PluginClassName``MyPlugin` (PascalCase)
- Update description, author, homepage, etc.
### manager.py
Replace placeholders:
- `PluginClassName``MyPlugin` (must match manifest)
- Implement `_fetch_data()` method
- Implement `_render_content()` method
- Add any custom validation in `validate_config()`
### config_schema.json
Customize:
- Update description
- Add/remove configuration properties
- Set default values
- Add validation rules
### README.md
Replace placeholders:
- `PLUGIN_ID``my-plugin`
- `Plugin Name` → Your plugin's name
- Fill in features, installation, configuration sections
### requirements.txt
Add your plugin's dependencies:
```txt
requests>=2.28.0
pillow>=9.0.0
```
## Step 4: Enable Plugin
Edit `config/config.json`:
```json
{
"my-plugin": {
"enabled": true,
"display_duration": 15
}
}
```
## Step 5: Test Plugin
### Test with Emulator
```bash
cd /path/to/LEDMatrix
python run.py --emulator
```
### Check Plugin Loading
Look for logs like:
```
[INFO] Discovered 1 plugin(s)
[INFO] Loaded plugin: my-plugin v1.0.0
[INFO] Added plugin mode: my-plugin
```
### Test Plugin Display
The plugin should appear in the display rotation. Check logs for any errors.
## Step 6: Develop and Iterate
1. Edit `manager.py` to implement your plugin logic
2. Test with emulator: `python run.py --emulator`
3. Check logs for errors
4. Iterate until working correctly
## Step 7: Test on Hardware (Optional)
When ready, test on Raspberry Pi:
```bash
# Deploy to Pi
rsync -avz plugins/my-plugin/ pi@raspberrypi:/path/to/LEDMatrix/plugins/my-plugin/
# Or if using git
ssh pi@raspberrypi "cd /path/to/LEDMatrix/plugins/my-plugin && git pull"
# Restart service
ssh pi@raspberrypi "sudo systemctl restart ledmatrix"
```
## Common Customizations
### Adding API Integration
1. Add API key to `config_schema.json`:
```json
{
"api_key": {
"type": "string",
"description": "API key for service"
}
}
```
2. Implement API call in `_fetch_data()`:
```python
import requests
def _fetch_data(self):
response = requests.get(
"https://api.example.com/data",
headers={"Authorization": f"Bearer {self.api_key}"}
)
return response.json()
```
3. Store API key in `config/config_secrets.json`:
```json
{
"my-plugin": {
"api_key": "your-secret-key"
}
}
```
### Adding Image Rendering
There is no `draw_image()` helper on `DisplayManager`. To render an
image, paste it directly onto the underlying PIL `Image`
(`display_manager.image`) and then call `update_display()`:
```python
def _render_content(self):
# Load and paste image onto the display canvas
image = Image.open("assets/logo.png").convert("RGB")
self.display_manager.image.paste(image, (0, 0))
# Draw text overlay
self.display_manager.draw_text(
"Text",
x=10, y=20,
color=(255, 255, 255)
)
self.display_manager.update_display()
```
For transparency, paste with a mask:
```python
icon = Image.open("assets/icon.png").convert("RGBA")
self.display_manager.image.paste(icon, (5, 5), icon)
```
### Adding Live Priority
1. Enable in config:
```json
{
"my-plugin": {
"live_priority": true
}
}
```
2. Implement `has_live_content()`:
```python
def has_live_content(self) -> bool:
return self.data and self.data.get("is_live", False)
```
3. Override `get_live_modes()` if needed:
```python
def get_live_modes(self) -> list:
return ["my_plugin_live_mode"]
```
## Troubleshooting
### Plugin Not Loading
- Check `manifest.json` syntax (must be valid JSON)
- Verify `entry_point` file exists
- Ensure `class_name` matches class name in manager.py
- Check for import errors in logs
### Configuration Errors
- Validate config against `config_schema.json`
- Check required fields are present
- Verify data types match schema
### Display Issues
- Check display dimensions: `display_manager.width`, `display_manager.height`
- Verify coordinates are within bounds
- Ensure `update_display()` is called
- Test with emulator first
## Next Steps
- Review existing plugins for patterns:
- `plugins/hockey-scoreboard/` - Sports scoreboard example
- `plugins/ledmatrix-music/` - Real-time data example
- `plugins/ledmatrix-stocks/` - Data display example
- Read full documentation:
- `.cursor/plugins_guide.md` - Comprehensive guide
- `docs/PLUGIN_ARCHITECTURE_SPEC.md` - Architecture details
- `.cursorrules` - Development rules
- Check plugin system code:
- `src/plugin_system/base_plugin.py` - Base class
- `src/plugin_system/plugin_manager.py` - Plugin manager