Files
lighting-controller/PER_PATTERN_PARAMETERS.md

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:

  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:

{
  "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 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

# 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!