SPORE LEDLab
LEDLab is a tool for streaming animations to LED matrices connected to SPORE nodes. Create visual effects with real-time parameter control and individual node management.
Features
- Multi-Node Management: Control multiple SPORE nodes individually
- Real-Time Preview: See live canvas preview for each node
- Dynamic Presets: Choose from 10+ built-in animation presets
- Visual Preset Editor: Create custom animations with building blocks
- Live Parameter Control: Adjust animation parameters in real-time
- Auto-Discovery: Automatically discovers SPORE nodes on the network
- Modern UI: Clean, responsive interface with dark/light theme support
- Import/Export: Save and share custom presets as JSON files
Architecture
Server
The Node.js server provides the backend for SPORE LEDLab:
- Gateway Integration: Subscribes to spore-gateway WebSocket for real-time cluster updates (requires spore-gateway to be running)
- UDP Frame Streaming: Sends animation frames to SPORE nodes via UDP on port 4210
- WebSocket API: Real-time bidirectional communication with the web UI
- Preset Management: Manages animation presets with configurable parameters
- Multi-Node Streaming: Streams different presets to individual nodes simultaneously
- Frame Generation: Generates animation frames at configurable FPS (1-60)
- Node State Management: Tracks configuration and streaming state per node
Web UI
The web interface provides an intuitive control panel:
- Node Grid View: Visual grid showing all discovered nodes with live canvas previews
- Node Selection: Click any node to open its control panel
- Preset Selection: Choose from available animation presets
- Parameter Controls: Real-time sliders and inputs for preset parameters
- Matrix Configuration: Configurable matrix dimensions (default: 16x16)
- Settings Panel: Test frames and matrix clearing utilities
- Theme Support: Toggle between dark and light themes
Communication Flow
Web UI (Browser) <--WebSocket--> Server <--UDP--> SPORE Nodes
|
Preset Engine
|
Frame Generation (60fps)
Gateway WebSocket (Real-time cluster updates)
Build
Prerequisites
- Node.js (v14 or higher)
- npm (v6 or higher)
- spore-gateway must be running on port 3001
Installation
- Clone the repository or navigate to the
spore-ledlabdirectory:
cd spore-ledlab
- Install dependencies:
npm install
This will install:
express: Web server frameworkws: WebSocket library for real-time communication
Project Structure
spore-ledlab/
├── server/ # Backend server
│ ├── index.js # Main server & WebSocket handling
│ ├── gateway-client.js # Gateway client for node discovery
│ └── udp-discovery.js # UDP sender for frame streaming
├── presets/ # Animation preset implementations
│ ├── preset-registry.js
│ ├── base-preset.js
│ ├── building-blocks.js # Reusable shape/animation components
│ ├── custom-preset.js # Configurable preset engine
│ ├── rainbow-preset.js
│ ├── lava-lamp-preset.js
│ ├── examples/ # Example custom preset JSON files
│ └── ...
├── public/ # Frontend web UI
│ ├── index.html
│ ├── scripts/ # JavaScript modules
│ │ ├── preset-editor.js # Visual preset editor
│ │ └── ...
│ └── styles/ # CSS stylesheets
└── package.json # Project dependencies
Run
Start the Server
npm start
Or use the dev script (same as start):
npm run dev
The server will:
- Start the HTTP server on port 8080 (default)
- Initialize WebSocket server
- Connect to spore-gateway for node discovery
- Initialize UDP sender for frame streaming
- Serve the web UI at http://localhost:8080
Access the Web UI
Open your browser and navigate to:
http://localhost:8080
Configure SPORE Nodes
Ensure your SPORE nodes are:
- Connected to the same network as the LEDLab server
- Running firmware with PixelStreamController support
- Listening on UDP port 4210
- Discovered by spore-gateway
- Labeled with
app: pixelstream(LEDLab only displays nodes with this label)
The nodes will automatically appear in the LEDLab grid view once they are discovered by spore-gateway and have the app: pixelstream label.
Node Labeling
To display nodes in LEDLab, you must set the app: pixelstream label on your SPORE nodes. This can be done via the spore-gateway API or from the SPORE node itself.
From SPORE Node:
Nodes should advertise their labels via the UDP heartbeat. The PixelStreamController firmware automatically sets the app: pixelstream label.
Manual via Gateway: You can also set labels manually using the spore-gateway API or spore-ui interface.
Disabling Filtering
To display all nodes without filtering, set the environment variable:
FILTER_APP_LABEL= npm start
Or leave it empty to show all discovered nodes.
Usage
Basic Workflow
-
Discover Nodes: Wait for SPORE nodes to appear in the grid (auto-discovery runs every 5 seconds)
-
Select a Node: Click on any node in the grid to open the control panel
-
Choose a Preset: Select an animation preset from the dropdown menu
-
Adjust Parameters: Use sliders and inputs to modify animation parameters in real-time
-
Start Streaming: Click "Start Streaming" to begin sending frames to the selected node
-
Stop Streaming: Click "Stop Streaming" to halt the animation
Available Presets
- Rainbow: Classic rainbow cycle effect
- Lava Lamp: Organic flowing blobs
- Aurora Curtains: Northern lights simulation
- Bouncing Ball: Physics-based bouncing ball
- Circuit Pulse: Digital circuit patterns
- Meteor Rain: Falling meteor trails
- Nebula Drift: Cosmic cloud effects
- Ocean Glimmer: Wave-like shimmer
- Spiral Bloom: Rotating spiral patterns
- Voxel Fireflies: 3D particle system
- Wormhole Tunnel: Depth tunnel effect
- Fade Green-Blue: Simple color fade
Matrix Configuration
Default matrix size is 16x16 pixels. To change:
- Click the ⚙️ Settings button
- Navigate to the Settings view
- Adjust Width and Height values
- Click "Apply Changes"
Testing
In the Settings view:
- Send Test Frame: Sends a checkerboard pattern to verify connectivity
- Clear Matrix: Turns off all LEDs on the selected node
Configuration
Server Configuration
Edit server/index.js or use environment variables:
const PORT = 8080; // HTTP/WebSocket port
const UDP_PORT = 4210; // UDP frame streaming port
const GATEWAY_URL = 'http://localhost:3001'; // spore-gateway URL
const FILTER_APP_LABEL = 'pixelstream'; // Filter nodes by app label
const DEFAULT_FPS = 20; // Default frame rate
const MATRIX_WIDTH = 16; // Default matrix width
const MATRIX_HEIGHT = 16; // Default matrix height
Environment variables:
PORT- HTTP server port (default: 8080)UDP_PORT- UDP port for frame streaming (default: 4210)GATEWAY_URL- spore-gateway URL (default: http://localhost:3001)FILTER_APP_LABEL- Filter nodes by app label (default: pixelstream, set to empty string to disable filtering)MATRIX_WIDTH- Default matrix width (default: 16)MATRIX_HEIGHT- Default matrix height (default: 16)
Adding Custom Presets
- Create a new preset file in
presets/:
const BasePreset = require('./base-preset');
class MyCustomPreset extends BasePreset {
constructor(width, height) {
super(width, height);
this.name = 'My Custom Preset';
this.description = 'Description of my preset';
}
defineParameters() {
return {
speed: { type: 'range', min: 0.1, max: 5, step: 0.1, default: 1 },
color: { type: 'color', default: 'ff0000' }
};
}
update(frameCount) {
// Animation logic here
}
}
module.exports = MyCustomPreset;
- Register it in
presets/preset-registry.js:
const MyCustomPreset = require('./my-custom-preset');
registerPreset('my-custom', MyCustomPreset);
Preset Editor
The 🎨 Editor view allows you to create custom animations by combining reusable building blocks without writing code.
Building Blocks
Shapes
- Circle: Round shape with adjustable radius
- Rectangle: Four-sided shape with width and height
- Triangle: Three-sided shape
- Blob: Soft circle with energy field falloff
- Point: Single pixel
- Line: Line between two points
Patterns
- Trail: Fade effect on previous frames
- Radial: Gradient radiating from center
- Spiral: Rotating spiral arms
Colors
- Solid: Single color
- Gradient: Linear blend between two colors
- Palette: Multi-stop gradient with custom colors
- Rainbow: Color wheel effect
Animations
- Move: Linear movement from point A to B
- Rotate: Rotation around center
- Pulse: Scale oscillation (breathing effect)
- Oscillate X/Y: Sine wave movement on X or Y axis
- Fade: Fade in or out
Creating a Custom Preset
- Navigate to the 🎨 Editor view
- Enter a name and description
- Add layers (shapes or patterns):
- Select type and configure properties
- Set position, size, and color
- Add optional animation
- Click ➕ Add Layer
- Edit layers with ✏️, reorder with ▲/▼, or delete with ✕
- Preview with ▶️ Preview (requires a selected node from Stream view)
- 💾 Save to browser localStorage or 📤 Export JSON to file
Example Presets
Import example JSON files from presets/examples/ to learn:
- Pulsing Circle: Rainbow circle with pulse animation
- Bouncing Squares: Multiple colored squares oscillating
- Spiral Rainbow: Rotating spiral with rainbow gradient
- Moving Triangle: Triangle with linear movement
Use 📥 Import JSON to load examples and customize them.
JSON Format
Presets are stored as JSON:
{
"name": "My Preset",
"description": "Custom animation",
"layers": [
{
"type": "shape",
"shape": "circle",
"position": { "x": 8, "y": 8 },
"size": { "radius": 4 },
"color": { "type": "solid", "value": "ff0000" },
"animation": {
"type": "pulse",
"params": { "minScale": 0.5, "maxScale": 1.5, "frequency": 1.0 }
}
}
]
}
See presets/examples/README.md for detailed documentation.
Troubleshooting
Nodes Not Appearing
- Ensure spore-gateway is running on port 3001
- Verify nodes are on the same network
- Check firewall settings allow UDP port 4210
- Ensure nodes are running PixelStreamController firmware
- Verify spore-gateway has discovered the nodes
- IMPORTANT: Nodes must have the
app: pixelstreamlabel set. LEDLab only displays nodes with this label. Check node labels in spore-gateway.
WebSocket Connection Issues
- Check browser console for errors
- Verify server is running on port 8080 (default)
- Try refreshing the browser
Animation Not Streaming
- Select a node first by clicking on it
- Choose a preset from the dropdown
- Verify the node shows "streaming" status
Custom Preset Issues
- No preview: Ensure a node is selected from Stream view first
- Nothing visible: Check layer has valid position/size values
- Errors: Open browser console (F12) for detailed error messages
Technology Stack
Backend:
- Node.js
- Express.js (HTTP server)
- ws (WebSocket server)
- HTTP client (for querying spore-gateway)
- UDP (Frame streaming only)
Frontend:
- Vanilla JavaScript (ES6+)
- Component-based architecture
- CSS3 with CSS variables for theming
- Canvas API for visualization
License
MIT
Credits
Based on the SPORE framework and uses styling/components from spore-ui.

