mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 21:03:01 +00:00
* docs: rename FONT_MANAGER_USAGE.md to FONT_MANAGER.md Renamed for clearer naming convention. Part of documentation consolidation effort. * docs: consolidate Plugin Store guides (2→1) Merged: - PLUGIN_STORE_USER_GUIDE.md - PLUGIN_STORE_QUICK_REFERENCE.md Into: PLUGIN_STORE_GUIDE.md - Unified writing style to professional technical - Added Quick Reference section at top for easy access - Removed duplicate content - Added cross-references to related documentation - Updated formatting to match style guidelines * docs: create user-focused Web Interface Guide Created WEB_INTERFACE_GUIDE.md consolidating: - V3_INTERFACE_README.md (technical details) - User-facing interface documentation - Focused on end-user tasks and navigation - Removed technical implementation details - Added common tasks section - Included troubleshooting - Professional technical writing style * docs: consolidate WiFi setup guides (4→1) Merged: - WIFI_SETUP.md - OPTIMAL_WIFI_AP_FAILOVER_SETUP.md - AP_MODE_MANUAL_ENABLE.md - WIFI_ETHERNET_AP_MODE_FIX.md (behavior documentation) Into: WIFI_NETWORK_SETUP.md - Comprehensive coverage of WiFi setup and configuration - Clear explanation of AP mode failover and grace period - Configuration scenarios and best practices - Troubleshooting section combining all sources - Professional technical writing style - Added quick reference table for behavior * docs: consolidate troubleshooting guides (4→1) Merged: - TROUBLESHOOTING_QUICK_START.md - WEB_INTERFACE_TROUBLESHOOTING.md - CAPTIVE_PORTAL_TROUBLESHOOTING.md - WEATHER_TROUBLESHOOTING.md Into: TROUBLESHOOTING.md - Organized by issue category (web, WiFi, plugins) - Comprehensive diagnostic commands reference - Quick diagnosis steps at the top - Service file template preserved - Complete diagnostic script included - Professional technical writing style * docs: create consolidated Advanced Features guide Merged: - VEGAS_SCROLL_MODE.md - ON_DEMAND_DISPLAY_QUICK_START.md - ON_DEMAND_DISPLAY_API.md - ON_DEMAND_CACHE_MANAGEMENT.md - BACKGROUND_SERVICE_README.md - PERMISSION_MANAGEMENT_GUIDE.md Into: ADVANCED_FEATURES.md - Comprehensive guide covering all advanced features - Vegas scroll mode with integration examples - On-demand display with API reference - Cache management troubleshooting - Background service documentation - Permission management patterns - Professional technical writing style * docs: create Getting Started guide for first-time users Created GETTING_STARTED.md: - Quick start guide (5 minutes) - Initial configuration walkthrough - Common first-time issues and solutions - Next steps and quick reference - User-friendly tone for beginners - Links to detailed documentation * docs: archive consolidated source files and ephemeral docs Archived files that have been consolidated: - Plugin Store guides (2 files → PLUGIN_STORE_GUIDE.md) - Web Interface guide (V3_INTERFACE_README.md → WEB_INTERFACE_GUIDE.md) - WiFi Setup guides (4 files → WIFI_NETWORK_SETUP.md) - Troubleshooting guides (4 files → TROUBLESHOOTING.md) - Advanced Features (6 files → ADVANCED_FEATURES.md) Archived ephemeral/debug documentation: - DEBUG_WEB_ISSUE.md - BROWSER_ERRORS_EXPLANATION.md - FORM_VALIDATION_FIXES.md - WEB_UI_RELIABILITY_IMPROVEMENTS.md - CAPTIVE_PORTAL_TESTING.md - NEXT_STEPS_COMMANDS.md - STATIC_IMAGE_MULTI_UPLOAD_PLAN.md - RECONNECT_AFTER_CAPTIVE_PORTAL_TESTING.md Archived implementation summaries: - PLUGIN_CONFIG_TABS_SUMMARY.md - PLUGIN_CONFIG_SYSTEM_VERIFICATION.md - PLUGIN_SCHEMA_AUDIT_SUMMARY.md - STARTUP_OPTIMIZATION_SUMMARY.md - PLUGIN_DISPATCH_IMPLEMENTATION.md - NESTED_SCHEMA_IMPLEMENTATION.md - AP_MODE_MANUAL_ENABLE_CHANGES.md - PLUGIN_CONFIG_SYSTEM_EXPLANATION.md Total archived: 27 files Preserves git history while cleaning up main docs directory * docs: rename API_REFERENCE.md to REST_API_REFERENCE.md Renamed for clarity - this is specifically the REST API reference for the web interface, not a general API reference. * docs: update README.md to reflect consolidated documentation structure Updated documentation index: - Reflects new consolidated guides (51 → 16-17 files) - Updated Quick Start sections with new file names - Added consolidation history (January 2026) - Updated file references (API_REFERENCE → REST_API_REFERENCE) - Documented archival of 33 files - Added benefits of consolidation - Updated statistics and highlights - Removed outdated references - Professional writing style maintained throughout * docs: add Vegas scroll mode system architecture documentation Added comprehensive internal architecture section for Vegas mode: - Component overview with diagram - VegasModeCoordinator responsibilities and main loop - StreamManager buffering strategy and content flow - PluginAdapter integration and fallback behavior - RenderPipeline 125 FPS rendering process - Component interaction flows - Thread safety patterns - Performance characteristics Covers: - How the four components work together - Initialization and render loop flows - Config update handling - Frame rate management and optimization - Memory usage and CPU characteristics --------- Co-authored-by: Chuck <chuck@example.com>
379 lines
11 KiB
Markdown
379 lines
11 KiB
Markdown
# Static Image Plugin - Multi-Image Upload & Rotation Implementation Plan
|
|
|
|
## Overview
|
|
|
|
Enhance the static-image plugin to support:
|
|
1. **Multiple image uploads** via web UI
|
|
2. **Image rotation** (sequential, random, time-based, date-based)
|
|
3. **Robust asset management** (storage, validation, cleanup)
|
|
4. **Future-proof architecture** for advanced rotation logic
|
|
|
|
## Architecture Design
|
|
|
|
### 1. Configuration Schema Enhancement
|
|
|
|
#### Current Schema
|
|
```json
|
|
{
|
|
"image_path": "assets/static_images/default.png"
|
|
}
|
|
```
|
|
|
|
#### Enhanced Schema (Backward Compatible)
|
|
```json
|
|
{
|
|
"image_config": {
|
|
"mode": "single" | "multiple",
|
|
"rotation_mode": "sequential" | "random" | "time_based" | "date_based",
|
|
"images": [
|
|
{
|
|
"id": "uuid-or-hash",
|
|
"path": "assets/plugins/static-image/uploads/image_1234567890.png",
|
|
"uploaded_at": "2025-01-15T10:30:00Z",
|
|
"display_order": 0,
|
|
"schedule": null // Future: {"start_time": "08:00", "end_time": "18:00", "days": [1,2,3,4,5]}
|
|
}
|
|
]
|
|
},
|
|
|
|
// Legacy support - maps to single image mode
|
|
"image_path": "assets/static_images/default.png",
|
|
|
|
// Rotation settings
|
|
"rotation_settings": {
|
|
"sequential_loop": true,
|
|
"random_seed": null, // null = use time, or fixed seed for reproducible rotation
|
|
"time_intervals": {
|
|
"enabled": false,
|
|
"interval_seconds": 3600 // Change image every hour
|
|
},
|
|
"date_ranges": [] // Future: [{"start": "2025-12-01", "end": "2025-12-25", "image_id": "..."}]
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Asset Storage Structure
|
|
|
|
```text
|
|
assets/
|
|
├── plugins/
|
|
│ └── static-image/
|
|
│ └── uploads/
|
|
│ ├── image_1705312200_abc123.png
|
|
│ ├── image_1705312400_def456.jpg
|
|
│ └── .metadata.json // Maps IDs to filenames
|
|
```
|
|
|
|
**Storage Strategy:**
|
|
- Files stored in `assets/plugins/static-image/uploads/`
|
|
- Filenames: `image_{timestamp}_{hash}.{ext}` (prevents collisions)
|
|
- Metadata JSON tracks: ID → filename mapping, upload dates, file sizes
|
|
- Cleanup: Remove files not referenced in config
|
|
|
|
### 3. Backend API Endpoints
|
|
|
|
#### POST `/api/v3/plugins/assets/upload`
|
|
**Purpose:** Upload image files for a specific plugin
|
|
|
|
**Request:**
|
|
- `multipart/form-data`
|
|
- `plugin_id`: string (required)
|
|
- `files`: File[] (multiple files supported)
|
|
- `rotation_mode`: string (optional, default: "sequential")
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"uploaded_files": [
|
|
{
|
|
"id": "uuid-here",
|
|
"filename": "image_1705312200_abc123.png",
|
|
"path": "assets/plugins/static-image/uploads/image_1705312200_abc123.png",
|
|
"size": 45678,
|
|
"uploaded_at": "2025-01-15T10:30:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Validation:**
|
|
- File type: PNG, JPG, JPEG, BMP, GIF
|
|
- Max file size: 5MB per file
|
|
- Max files per upload: 10
|
|
- Total storage limit: 50MB per plugin
|
|
|
|
#### DELETE `/api/v3/plugins/assets/delete`
|
|
**Purpose:** Delete uploaded image
|
|
|
|
**Request:**
|
|
- `plugin_id`: string
|
|
- `image_id`: string (from upload response)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"deleted_file": "image_1705312200_abc123.png"
|
|
}
|
|
```
|
|
|
|
#### GET `/api/v3/plugins/assets/list`
|
|
**Purpose:** List all uploaded images for a plugin
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"images": [
|
|
{
|
|
"id": "uuid-here",
|
|
"filename": "image_1705312200_abc123.png",
|
|
"path": "assets/plugins/static-image/uploads/image_1705312200_abc123.png",
|
|
"size": 45678,
|
|
"uploaded_at": "2025-01-15T10:30:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 4. Frontend Form Generator Enhancement
|
|
|
|
#### Schema Format for File Upload
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"images": {
|
|
"type": "array",
|
|
"x-widget": "file-upload",
|
|
"x-upload-config": {
|
|
"endpoint": "/api/v3/plugins/assets/upload",
|
|
"plugin_id_field": "plugin_id",
|
|
"max_files": 10,
|
|
"allowed_types": ["image/png", "image/jpeg", "image/bmp", "image/gif"],
|
|
"max_size_mb": 5
|
|
},
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {"type": "string"},
|
|
"path": {"type": "string"},
|
|
"uploaded_at": {"type": "string", "format": "date-time"}
|
|
}
|
|
},
|
|
"description": "Upload images to display. Multiple images will rotate based on rotation mode."
|
|
},
|
|
"rotation_mode": {
|
|
"type": "string",
|
|
"enum": ["sequential", "random", "time_based", "date_based"],
|
|
"default": "sequential",
|
|
"description": "How to rotate through images"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### UI Components
|
|
1. **File Upload Widget:**
|
|
- Drag-and-drop zone
|
|
- File list with thumbnails
|
|
- Remove button per file
|
|
- Upload progress indicator
|
|
- Image preview before upload
|
|
|
|
2. **Rotation Mode Selector:**
|
|
- Dropdown with rotation options
|
|
- Settings panel per mode:
|
|
- Sequential: Loop option
|
|
- Random: Seed option
|
|
- Time-based: Interval input
|
|
- Date-based: Calendar picker (future)
|
|
|
|
### 5. Plugin Manager Updates
|
|
|
|
#### Rotation Logic in `manager.py`
|
|
|
|
```python
|
|
class StaticImagePlugin(BasePlugin):
|
|
def __init__(self, ...):
|
|
# ... existing code ...
|
|
|
|
# Enhanced image handling
|
|
self.image_config = config.get('image_config', {})
|
|
self.rotation_mode = self.image_config.get('rotation_mode', 'sequential')
|
|
self.rotation_settings = config.get('rotation_settings', {})
|
|
self.images_list = self.image_config.get('images', [])
|
|
self.current_image_index = 0
|
|
self.last_rotation_time = time.time()
|
|
|
|
# Initialize rotation
|
|
self._setup_rotation()
|
|
|
|
def _setup_rotation(self):
|
|
"""Initialize rotation based on mode"""
|
|
if self.rotation_mode == 'random':
|
|
import random
|
|
seed = self.rotation_settings.get('random_seed')
|
|
if seed:
|
|
random.seed(seed)
|
|
|
|
if not self.images_list:
|
|
# Fallback to legacy image_path
|
|
if self.image_path:
|
|
self.images_list = [{'path': self.image_path}]
|
|
|
|
def _get_next_image(self) -> Optional[str]:
|
|
"""Get next image path based on rotation mode"""
|
|
if not self.images_list:
|
|
return None
|
|
|
|
if self.rotation_mode == 'sequential':
|
|
path = self.images_list[self.current_image_index]['path']
|
|
self.current_image_index = (self.current_image_index + 1) % len(self.images_list)
|
|
return path
|
|
|
|
elif self.rotation_mode == 'random':
|
|
import random
|
|
return random.choice(self.images_list)['path']
|
|
|
|
elif self.rotation_mode == 'time_based':
|
|
interval = self.rotation_settings.get('time_intervals', {}).get('interval_seconds', 3600)
|
|
now = time.time()
|
|
if now - self.last_rotation_time >= interval:
|
|
self.current_image_index = (self.current_image_index + 1) % len(self.images_list)
|
|
self.last_rotation_time = now
|
|
return self.images_list[self.current_image_index]['path']
|
|
|
|
elif self.rotation_mode == 'date_based':
|
|
# Future implementation
|
|
return self._get_date_based_image()
|
|
|
|
return self.images_list[0]['path']
|
|
|
|
def display(self, force_clear: bool = False):
|
|
"""Display current image based on rotation"""
|
|
image_path = self._get_next_image()
|
|
if not image_path or not os.path.exists(image_path):
|
|
self._display_error()
|
|
return
|
|
|
|
self.image_path = image_path # For compatibility
|
|
self._load_image()
|
|
|
|
# ... rest of display logic ...
|
|
```
|
|
|
|
### 6. Asset Management System
|
|
|
|
#### File Operations
|
|
- **Upload:** Save to `assets/plugins/{plugin_id}/uploads/`
|
|
- **Validation:** Check file type, size, dimensions
|
|
- **Metadata:** Track in `.metadata.json`
|
|
- **Cleanup:** Remove orphaned files on config save
|
|
- **Permissions:** Ensure writable by web service
|
|
|
|
#### Security
|
|
- Validate file extensions (whitelist)
|
|
- Check file content (magic bytes, not just extension)
|
|
- Limit file sizes
|
|
- Sanitize filenames
|
|
- Prevent path traversal
|
|
|
|
### 7. Migration Strategy
|
|
|
|
#### Backward Compatibility
|
|
1. **Legacy Support:**
|
|
- If `image_path` exists but no `image_config`, auto-convert
|
|
- Create `image_config` with single image from `image_path`
|
|
|
|
2. **Config Migration:**
|
|
```python
|
|
def _migrate_legacy_config(self, config):
|
|
"""Migrate legacy image_path to new image_config format"""
|
|
if 'image_path' in config and 'image_config' not in config:
|
|
config['image_config'] = {
|
|
'mode': 'single',
|
|
'rotation_mode': 'sequential',
|
|
'images': [{
|
|
'id': str(uuid.uuid4()),
|
|
'path': config['image_path'],
|
|
'uploaded_at': datetime.now().isoformat(),
|
|
'display_order': 0
|
|
}]
|
|
}
|
|
return config
|
|
```
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Core Upload System
|
|
1. ✅ Enhanced config schema
|
|
2. ✅ Backend upload endpoint
|
|
3. ✅ Asset storage structure
|
|
4. ✅ File validation
|
|
|
|
### Phase 2: Frontend Integration
|
|
5. ✅ File upload widget in form generator
|
|
6. ✅ Image preview/management UI
|
|
7. ✅ Rotation mode selector
|
|
|
|
### Phase 3: Plugin Rotation Logic
|
|
8. ✅ Update plugin manager with rotation
|
|
9. ✅ Sequential rotation
|
|
10. ✅ Random rotation
|
|
|
|
### Phase 4: Advanced Features
|
|
11. ✅ Time-based rotation
|
|
12. ✅ Date-based rotation (future)
|
|
13. ✅ Cleanup/orphan removal
|
|
|
|
## File Structure Changes
|
|
|
|
```text
|
|
plugins/static-image/
|
|
├── manager.py # Enhanced with rotation logic
|
|
├── config_schema.json # Updated with upload/rotation fields
|
|
├── manifest.json # No changes
|
|
└── README.md # Update documentation
|
|
|
|
web_interface/
|
|
├── blueprints/
|
|
│ └── api_v3.py # Add upload/delete/list endpoints
|
|
└── templates/v3/
|
|
└── partials/
|
|
└── plugins.html # File upload widget
|
|
|
|
assets/
|
|
└── plugins/
|
|
└── static-image/
|
|
└── uploads/ # NEW - user uploaded images
|
|
└── .metadata.json
|
|
```
|
|
|
|
## Testing Checklist
|
|
|
|
- [ ] Single image upload works
|
|
- [ ] Multiple image upload works
|
|
- [ ] File validation (type, size)
|
|
- [ ] Sequential rotation cycles correctly
|
|
- [ ] Random rotation works
|
|
- [ ] Time-based rotation changes at intervals
|
|
- [ ] Legacy config migration preserves existing images
|
|
- [ ] Orphaned file cleanup on config save
|
|
- [ ] Web UI displays upload widget correctly
|
|
- [ ] Image preview shows before upload
|
|
- [ ] Delete removes file and updates config
|
|
- [ ] Error handling for missing/invalid files
|
|
|
|
## Future Enhancements
|
|
|
|
1. **Date-based rotation:** Display different images on specific dates
|
|
2. **Time-of-day rotation:** Show images based on time ranges
|
|
3. **Transition effects:** Fade between images
|
|
4. **Image filters:** Apply effects (brightness, contrast)
|
|
5. **Bulk operations:** Select multiple images for deletion
|
|
6. **Image organization:** Folders/tags for images
|
|
7. **Remote images:** Support URLs (with caching)
|
|
|