11 KiB
Per-Pattern Parameters - Frontend Documentation
Overview
Each pattern now has its own unique set of parameters (n1, n2, n3, n4, delay). When you switch patterns, the system automatically loads that pattern's saved parameters.
This means:
- Alternating can have n1=10, n2=10, delay=100
- Segmented Movement can have n1=5, n2=20, n3=10, n4=7, delay=50
- Each pattern remembers its own settings!
How It Works
Pattern Switching
When you change patterns via POST /api/pattern
:
- Current pattern's parameters are automatically saved
- New pattern's saved parameters are loaded
- Parameters are sent to LED bars with the pattern
Parameter Updates
When you update parameters via POST /api/parameters
:
- Parameters update immediately
- Saved for the current pattern only
- Other patterns keep their own settings
API Changes
POST /api/pattern (Enhanced)
Before: Only returned pattern name
Now: Returns pattern name AND its parameters
Request:
{
"pattern": "alternating"
}
Response:
{
"status": "ok",
"pattern": "alternating",
"parameters": {
"delay": 100,
"n1": 10,
"n2": 10,
"n3": 1,
"n4": 1
}
}
Important: The parameters returned are the loaded parameters for this pattern, not global values.
POST /api/parameters (Unchanged API, Enhanced Behavior)
Parameters are now saved per-pattern automatically.
Request:
{
"n1": 20,
"delay": 150
}
Response:
{
"status": "ok",
"parameters": {
"brightness": 100,
"delay": 150,
"n1": 20,
"n2": 10,
"n3": 1,
"n4": 1
}
}
What happens: These parameters are saved for the currently active pattern only.
GET /api/state (Enhanced)
Now returns parameters for the current pattern.
Response:
{
"pattern": "segmented_movement",
"parameters": {
"brightness": 100,
"delay": 50,
"n1": 5,
"n2": 20,
"n3": 10,
"n4": 7
},
"color_palette": {...},
"beat_index": 42
}
Usage Examples
Example 1: Pattern-Specific Configuration
const api = 'http://10.42.0.1:8765';
// Configure alternating pattern
await fetch(`${api}/api/pattern`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({pattern: 'alternating'})
});
await fetch(`${api}/api/parameters`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({n1: 10, n2: 10, delay: 100})
});
// Configure segmented_movement pattern
await fetch(`${api}/api/pattern`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({pattern: 'segmented_movement'})
});
await fetch(`${api}/api/parameters`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({n1: 5, n2: 20, n3: 10, n4: 7, delay: 50})
});
// Switch back to alternating
await fetch(`${api}/api/pattern`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({pattern: 'alternating'})
});
// Parameters are now back to n1=10, n2=10, delay=100 automatically!
Example 2: UI Pattern Selector with Parameter Memory
class PatternController {
constructor(apiBase = 'http://10.42.0.1:8765') {
this.api = apiBase;
}
async setPattern(patternName) {
const response = await fetch(`${this.api}/api/pattern`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({pattern: patternName})
});
const result = await response.json();
// Update UI with the loaded parameters for this pattern
this.updateParameterSliders(result.parameters);
return result;
}
async updateParameter(paramName, value) {
const response = await fetch(`${this.api}/api/parameters`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({[paramName]: value})
});
return await response.json();
}
updateParameterSliders(parameters) {
// Update UI sliders with pattern's saved parameters
document.getElementById('delay-slider').value = parameters.delay;
document.getElementById('n1-slider').value = parameters.n1;
document.getElementById('n2-slider').value = parameters.n2;
document.getElementById('n3-slider').value = parameters.n3;
document.getElementById('n4-slider').value = parameters.n4;
}
}
// Usage
const patterns = new PatternController();
// Switch to alternating - UI automatically shows its parameters
await patterns.setPattern('alternating');
// Adjust parameters for alternating
await patterns.updateParameter('n1', 15);
// Switch to rainbow - UI automatically shows its parameters
await patterns.setPattern('rainbow');
// Alternating's n1=15 is saved and will reload when you switch back!
Example 3: React Component
import { useState, useEffect } from 'react';
function PatternControl() {
const [pattern, setPattern] = useState('');
const [parameters, setParameters] = useState({});
const API = 'http://10.42.0.1:8765';
// Load initial state
useEffect(() => {
fetch(`${API}/api/state`)
.then(r => r.json())
.then(data => {
setPattern(data.pattern);
setParameters(data.parameters);
});
}, []);
// Change pattern - parameters auto-update
const changePattern = async (newPattern) => {
const response = await fetch(`${API}/api/pattern`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({pattern: newPattern})
});
const result = await response.json();
setPattern(result.pattern);
setParameters(result.parameters); // Auto-loaded for this pattern!
};
// Update parameter - saves for current pattern
const updateParam = async (param, value) => {
await fetch(`${API}/api/parameters`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({[param]: parseInt(value)})
});
setParameters({...parameters, [param]: parseInt(value)});
};
return (
<div>
<h2>Pattern: {pattern}</h2>
<div>
<button onClick={() => changePattern('alternating')}>Alternating</button>
<button onClick={() => changePattern('segmented_movement')}>Segmented</button>
<button onClick={() => changePattern('rainbow')}>Rainbow</button>
</div>
<div>
<label>Delay: {parameters.delay}</label>
<input
type="range" min="10" max="500"
value={parameters.delay || 100}
onChange={(e) => updateParam('delay', e.target.value)}
/>
<label>N1: {parameters.n1}</label>
<input
type="range" min="1" max="50"
value={parameters.n1 || 10}
onChange={(e) => updateParam('n1', e.target.value)}
/>
<label>N2: {parameters.n2}</label>
<input
type="range" min="0" max="50"
value={parameters.n2 || 10}
onChange={(e) => updateParam('n2', e.target.value)}
/>
</div>
<p>
<small>Parameters are saved per-pattern. Switch patterns and come back - your settings are remembered!</small>
</p>
</div>
);
}
Configuration Storage
Parameters are stored in lighting_config.json
:
{
"pattern_parameters": {
"alternating": {
"delay": 100,
"n1": 10,
"n2": 10,
"n3": 1,
"n4": 1
},
"segmented_movement": {
"delay": 50,
"n1": 5,
"n2": 20,
"n3": 10,
"n4": 7
},
"rainbow": {
"delay": 80,
"n1": 10,
"n2": 10,
"n3": 1,
"n4": 1
}
},
"color_palette": [...],
"selected_color_indices": [0, 1]
}
Pattern-Specific Parameter Usage
Different patterns use parameters differently:
Alternating
n1
: Number of LEDs ON in each segmentn2
: Number of LEDs OFF in each segmentdelay
: Speed of patternn3
,n4
: Not used
Typical values: n1=10, n2=10, delay=100
Segmented Movement
n1
: Length of each segmentn2
: Spacing between segmentsn3
: Forward movement steps per beatn4
: Backward movement steps per beatdelay
: Speed of pattern
Typical values: n1=5, n2=20, n3=10, n4=7, delay=50
Rainbow
delay
: Speed of color cyclingn1
,n2
,n3
,n4
: Not typically used
Typical values: delay=80
Migration from Global Parameters
Old behavior: All patterns shared the same parameters
New behavior: Each pattern has its own parameters
For existing apps:
- API is backward compatible
- Parameters will automatically save per-pattern
- First time a pattern is used, it gets default values
- After that, it remembers its settings
No changes needed to existing code! Just be aware that:
- Changing parameters for pattern A doesn't affect pattern B
- When you switch patterns, parameters automatically update
Benefits
✅ Pattern-Specific Settings - Each pattern remembers its configuration
✅ No Manual Switching - Parameters load automatically
✅ Persistent - Saved across server restarts
✅ Intuitive - Configure once, use forever
✅ Backward Compatible - Existing code works unchanged
UI Recommendations
- Show Current Parameters: When pattern changes, update UI sliders with the loaded parameters
- Label Appropriately: Show which parameters each pattern uses
- Provide Presets: Let users save/load parameter sets
- Visual Feedback: Indicate when parameters are auto-loaded vs user-changed
Testing
# Set alternating with specific parameters
curl -X POST http://localhost:8765/api/pattern \
-H "Content-Type: application/json" \
-d '{"pattern": "alternating"}'
curl -X POST http://localhost:8765/api/parameters \
-H "Content-Type: application/json" \
-d '{"n1": 15, "n2": 8}'
# Switch to another pattern
curl -X POST http://localhost:8765/api/pattern \
-H "Content-Type: application/json" \
-d '{"pattern": "rainbow"}'
# Switch back - parameters are restored!
curl -X POST http://localhost:8765/api/pattern \
-H "Content-Type: application/json" \
-d '{"pattern": "alternating"}'
# Response includes: "parameters": {"n1": 15, "n2": 8, ...}
Summary
Key Points:
- Parameters are now per-pattern, not global
- Switching patterns automatically loads that pattern's parameters
- Updating parameters saves for current pattern only
- All automatic - no extra API calls needed
- Fully backward compatible
For Frontend Developers:
- Update your UI to display loaded parameters when pattern changes
- Parameters in
POST /api/pattern
response show what was loaded - Each pattern can have completely different settings
- Users can configure patterns once and they stay configured!