453 lines
11 KiB
Markdown
453 lines
11 KiB
Markdown
# 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`:
|
|
1. Current pattern's parameters are **automatically saved**
|
|
2. New pattern's **saved parameters are loaded**
|
|
3. Parameters are sent to LED bars with the pattern
|
|
|
|
### Parameter Updates
|
|
When you update parameters via `POST /api/parameters`:
|
|
1. Parameters update immediately
|
|
2. **Saved for the current pattern only**
|
|
3. 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:**
|
|
```json
|
|
{
|
|
"pattern": "alternating"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"n1": 20,
|
|
"delay": 150
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```javascript
|
|
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
|
|
|
|
```javascript
|
|
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
|
|
|
|
```jsx
|
|
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`:
|
|
|
|
```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 segment
|
|
- `n2`: Number of LEDs OFF in each segment
|
|
- `delay`: Speed of pattern
|
|
- `n3`, `n4`: Not used
|
|
|
|
**Typical values:** n1=10, n2=10, delay=100
|
|
|
|
---
|
|
|
|
### Segmented Movement
|
|
- `n1`: Length of each segment
|
|
- `n2`: Spacing between segments
|
|
- `n3`: Forward movement steps per beat
|
|
- `n4`: Backward movement steps per beat
|
|
- `delay`: Speed of pattern
|
|
|
|
**Typical values:** n1=5, n2=20, n3=10, n4=7, delay=50
|
|
|
|
---
|
|
|
|
### Rainbow
|
|
- `delay`: Speed of color cycling
|
|
- `n1`, `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
|
|
|
|
1. **Show Current Parameters:** When pattern changes, update UI sliders with the loaded parameters
|
|
2. **Label Appropriately:** Show which parameters each pattern uses
|
|
3. **Provide Presets:** Let users save/load parameter sets
|
|
4. **Visual Feedback:** Indicate when parameters are auto-loaded vs user-changed
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
# 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!
|
|
|