diff --git a/.cursor/README.md b/.cursor/README.md index 5dace9eb..0d62e0e1 100644 --- a/.cursor/README.md +++ b/.cursor/README.md @@ -43,39 +43,46 @@ cp ../../.cursor/plugin_templates/*.template . 2. **Using dev_plugin_setup.sh**: ```bash # Link from GitHub -./dev_plugin_setup.sh link-github my-plugin +./scripts/dev/dev_plugin_setup.sh link-github my-plugin # Link local repo -./dev_plugin_setup.sh link my-plugin /path/to/repo +./scripts/dev/dev_plugin_setup.sh link my-plugin /path/to/repo ``` -### Running Plugins +### Running the Display ```bash -# Emulator (development) -python run.py --emulator +# Emulator mode (development, no hardware required) +EMULATOR=true python3 run.py -# Hardware (production) -python run.py +# Hardware (production, requires the rpi-rgb-led-matrix submodule built) +python3 run.py -# As service +# As a systemd service sudo systemctl start ledmatrix + +# Dev preview server (renders plugins to a browser without running run.py) +python3 scripts/dev_server.py # then open http://localhost:5001 ``` +There is no `--emulator` flag — the emulator is selected via the +`EMULATOR=true` environment variable, which `src/display_manager.py:2` +checks at import time. + ### Managing Plugins ```bash # List plugins -./dev_plugin_setup.sh list +./scripts/dev/dev_plugin_setup.sh list # Check status -./dev_plugin_setup.sh status +./scripts/dev/dev_plugin_setup.sh status # Update plugin(s) -./dev_plugin_setup.sh update [plugin-name] +./scripts/dev/dev_plugin_setup.sh update [plugin-name] # Unlink plugin -./dev_plugin_setup.sh unlink +./scripts/dev/dev_plugin_setup.sh unlink ``` ## Using These Files with Cursor @@ -118,9 +125,13 @@ Refer to `plugins_guide.md` for: - **Plugin System**: `src/plugin_system/` - **Base Plugin**: `src/plugin_system/base_plugin.py` - **Plugin Manager**: `src/plugin_system/plugin_manager.py` -- **Example Plugins**: `plugins/hockey-scoreboard/`, `plugins/football-scoreboard/` +- **Example Plugins**: see the + [`ledmatrix-plugins`](https://github.com/ChuckBuilds/ledmatrix-plugins) + repo for canonical sources (e.g. `plugins/hockey-scoreboard/`, + `plugins/football-scoreboard/`). Installed plugins land in + `plugin-repos/` (default) or `plugins/` (dev fallback). - **Architecture Docs**: `docs/PLUGIN_ARCHITECTURE_SPEC.md` -- **Development Setup**: `dev_plugin_setup.sh` +- **Development Setup**: `scripts/dev/dev_plugin_setup.sh` ## Getting Help diff --git a/.cursor/plugin_templates/QUICK_START.md b/.cursor/plugin_templates/QUICK_START.md index b212f748..9a9f9591 100644 --- a/.cursor/plugin_templates/QUICK_START.md +++ b/.cursor/plugin_templates/QUICK_START.md @@ -156,20 +156,34 @@ def _fetch_data(self): ### 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 render image - image = Image.open("assets/logo.png") - self.display_manager.draw_image(image, x=0, y=0) - + # 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: diff --git a/.cursor/plugins_guide.md b/.cursor/plugins_guide.md index 898a1091..4b989c38 100644 --- a/.cursor/plugins_guide.md +++ b/.cursor/plugins_guide.md @@ -53,13 +53,13 @@ This method is best for plugins stored in separate Git repositories. ```bash # Link a plugin from GitHub (auto-detects URL) -./dev_plugin_setup.sh link-github +./scripts/dev/dev_plugin_setup.sh link-github # Example: Link hockey-scoreboard plugin -./dev_plugin_setup.sh link-github hockey-scoreboard +./scripts/dev/dev_plugin_setup.sh link-github hockey-scoreboard # With custom URL -./dev_plugin_setup.sh link-github https://github.com/user/repo.git +./scripts/dev/dev_plugin_setup.sh link-github https://github.com/user/repo.git ``` The script will: @@ -71,10 +71,10 @@ The script will: ```bash # Link a local plugin repository -./dev_plugin_setup.sh link +./scripts/dev/dev_plugin_setup.sh link # Example: Link a local plugin -./dev_plugin_setup.sh link my-plugin ../ledmatrix-my-plugin +./scripts/dev/dev_plugin_setup.sh link my-plugin ../ledmatrix-my-plugin ``` ### Method 2: Manual Plugin Creation @@ -321,7 +321,8 @@ Each plugin has its own section in `config/config.json`: ### Secrets Management -Store sensitive data (API keys, tokens) in `config/config_secrets.json`: +Store sensitive data (API keys, tokens) in `config/config_secrets.json` +under the same plugin id you use in `config/config.json`: ```json { @@ -331,19 +332,21 @@ Store sensitive data (API keys, tokens) in `config/config_secrets.json`: } ``` -Reference secrets in main config: +At load time, the config manager deep-merges `config_secrets.json` into +the main config (verified at `src/config_manager.py:162-172`). So in +your plugin's code: -```json -{ - "my-plugin": { - "enabled": true, - "config_secrets": { - "api_key": "my-plugin.api_key" - } - } -} +```python +class MyPlugin(BasePlugin): + def __init__(self, plugin_id, config, display_manager, cache_manager, plugin_manager): + super().__init__(plugin_id, config, display_manager, cache_manager, plugin_manager) + self.api_key = config.get("api_key") # already merged from secrets ``` +There is no separate `config_secrets` reference field — just put the +secret value under the same plugin namespace and read it from the +merged config. + ### Plugin Discovery Plugins are automatically discovered when: @@ -355,7 +358,7 @@ Check discovered plugins: ```bash # Using dev_plugin_setup.sh -./dev_plugin_setup.sh list +./scripts/dev/dev_plugin_setup.sh list # Output shows: # ✓ plugin-name (symlink) @@ -368,7 +371,7 @@ Check discovered plugins: Check plugin status and git information: ```bash -./dev_plugin_setup.sh status +./scripts/dev/dev_plugin_setup.sh status # Output shows: # ✓ plugin-name @@ -391,13 +394,16 @@ cd ledmatrix-my-plugin # Link to LEDMatrix project cd /path/to/LEDMatrix -./dev_plugin_setup.sh link my-plugin ../ledmatrix-my-plugin +./scripts/dev/dev_plugin_setup.sh link my-plugin ../ledmatrix-my-plugin ``` ### 2. Development Cycle 1. **Edit plugin code** in linked repository -2. **Test with emulator**: `python run.py --emulator` +2. **Test with the dev preview server**: + `python3 scripts/dev_server.py` (then open `http://localhost:5001`). + Or run the full display in emulator mode with + `EMULATOR=true python3 run.py`. There is no `--emulator` flag. 3. **Check logs** for errors or warnings 4. **Update configuration** in `config/config.json` if needed 5. **Iterate** until plugin works correctly @@ -406,30 +412,30 @@ cd /path/to/LEDMatrix ```bash # Deploy to Raspberry Pi -rsync -avz plugins/my-plugin/ pi@raspberrypi:/path/to/LEDMatrix/plugins/my-plugin/ +rsync -avz plugins/my-plugin/ ledpi@your-pi-ip:/path/to/LEDMatrix/plugins/my-plugin/ # Or if using git, pull on Pi -ssh pi@raspberrypi "cd /path/to/LEDMatrix/plugins/my-plugin && git pull" +ssh ledpi@your-pi-ip "cd /path/to/LEDMatrix/plugins/my-plugin && git pull" # Restart service -ssh pi@raspberrypi "sudo systemctl restart ledmatrix" +ssh ledpi@your-pi-ip "sudo systemctl restart ledmatrix" ``` ### 4. Updating Plugins ```bash # Update single plugin from git -./dev_plugin_setup.sh update my-plugin +./scripts/dev/dev_plugin_setup.sh update my-plugin # Update all linked plugins -./dev_plugin_setup.sh update +./scripts/dev/dev_plugin_setup.sh update ``` ### 5. Unlinking Plugins ```bash # Remove symlink (preserves repository) -./dev_plugin_setup.sh unlink my-plugin +./scripts/dev/dev_plugin_setup.sh unlink my-plugin ``` --- @@ -625,8 +631,8 @@ python run.py --emulator **Solutions**: 1. Check symlink: `ls -la plugins/my-plugin` 2. Verify target exists: `readlink -f plugins/my-plugin` -3. Update plugin: `./dev_plugin_setup.sh update my-plugin` -4. Re-link plugin if needed: `./dev_plugin_setup.sh unlink my-plugin && ./dev_plugin_setup.sh link my-plugin ` +3. Update plugin: `./scripts/dev/dev_plugin_setup.sh update my-plugin` +4. Re-link plugin if needed: `./scripts/dev/dev_plugin_setup.sh unlink my-plugin && ./scripts/dev/dev_plugin_setup.sh link my-plugin ` 5. Check git status: `cd plugins/my-plugin && git status` --- @@ -697,22 +703,22 @@ python run.py --emulator ```bash # Link plugin from GitHub -./dev_plugin_setup.sh link-github +./scripts/dev/dev_plugin_setup.sh link-github # Link local plugin -./dev_plugin_setup.sh link +./scripts/dev/dev_plugin_setup.sh link # List all plugins -./dev_plugin_setup.sh list +./scripts/dev/dev_plugin_setup.sh list # Check plugin status -./dev_plugin_setup.sh status +./scripts/dev/dev_plugin_setup.sh status # Update plugin(s) -./dev_plugin_setup.sh update [name] +./scripts/dev/dev_plugin_setup.sh update [name] # Unlink plugin -./dev_plugin_setup.sh unlink +./scripts/dev/dev_plugin_setup.sh unlink # Run with emulator python run.py --emulator