# LED Driver ESPNow API Documentation

This document describes the ESPNow message format for controlling LED driver devices.

## Message Format

All messages are JSON objects sent via ESPNow with the following structure:

```json
{
  "v": "1",
  "presets": { ... },
  "select": { ... }
}
```

### Version Field

- **`v`** (required): Message version, must be `"1"`. Messages with other versions are ignored.

## Presets

Presets define LED patterns with their configuration. Each preset has a name and contains pattern-specific settings.

### Preset Structure

```json
{
  "presets": {
    "preset_name": {
      "pattern": "pattern_type",
      "colors": ["#RRGGBB", ...],
      "delay": 100,
      "brightness": 127,
      "auto": true,
      "n1": 0,
      "n2": 0,
      "n3": 0,
      "n4": 0,
      "n5": 0,
      "n6": 0
    }
  }
}
```

### Preset Fields

- **`pattern`** (required): Pattern type. Options:
  - `"off"` - Turn off all LEDs
  - `"on"` - Solid color
  - `"blink"` - Blinking pattern
  - `"rainbow"` - Rainbow color cycle
  - `"pulse"` - Pulse/fade pattern
  - `"transition"` - Color transition
  - `"chase"` - Chasing pattern
  - `"circle"` - Circle loading pattern

- **`colors`** (optional): Array of hex color strings (e.g., `"#FF0000"` for red). Default: `["#FFFFFF"]`
  - Colors are automatically converted from hex to RGB and reordered based on device color order setting
  - Supports multiple colors for patterns that use them

- **`delay`** (optional): Delay in milliseconds between pattern updates. Default: `100`

- **`brightness`** (optional): Brightness level (0-255). Default: `127`

- **`auto`** (optional): Auto mode flag. Default: `true`
  - `true`: Pattern runs continuously
  - `false`: Pattern advances one step per beat (manual mode)

- **`n1` through `n6`** (optional): Pattern-specific numeric parameters. Default: `0`
  - See pattern-specific documentation below

### Pattern-Specific Parameters

#### Rainbow
- **`n1`**: Step increment (how many color wheel positions to advance per update). Default: `1`

#### Pulse
- **`n1`**: Attack time in milliseconds (fade in)
- **`n2`**: Hold time in milliseconds (full brightness)
- **`n3`**: Decay time in milliseconds (fade out)
- **`delay`**: Delay time in milliseconds (off between pulses)

#### Transition
- **`delay`**: Transition duration in milliseconds

#### Chase
- **`n1`**: Number of LEDs with first color
- **`n2`**: Number of LEDs with second color
- **`n3`**: Movement amount on even steps (can be negative)
- **`n4`**: Movement amount on odd steps (can be negative)

#### Circle
- **`n1`**: Head movement rate (LEDs per second)
- **`n2`**: Maximum length
- **`n3`**: Tail movement rate (LEDs per second)
- **`n4`**: Minimum length

## Select Messages

Select messages control which preset is active on which device. The format uses a list to support step synchronization.

### Select Format

```json
{
  "select": {
    "device_name": ["preset_name"],
    "device_name2": ["preset_name2", step_value]
  }
}
```

### Select Fields

- **`select`**: Object mapping device names to selection lists
  - **Key**: Device name (as configured in device settings)
  - **Value**: List with one or two elements:
    - `["preset_name"]` - Select preset (uses default step behavior)
    - `["preset_name", step]` - Select preset with explicit step value (for synchronization)

### Step Synchronization

The step value allows precise synchronization across multiple devices:

- **Without step**: `["preset_name"]`
  - If switching to different preset: step resets to 0
  - If selecting "off" pattern: step resets to 0
  - If selecting same preset (beat): step is preserved, pattern restarts

- **With step**: `["preset_name", 10]`
  - Explicitly sets step to the specified value
  - Useful for synchronizing multiple devices to the same step

### Beat Functionality

Calling `select()` again with the same preset name acts as a "beat" - it restarts the pattern generator:

- **Single-tick patterns** (rainbow, chase in manual mode): Advance one step per beat
- **Multi-tick patterns** (pulse in manual mode): Run through full cycle per beat

Example beat sequence:
```json
// Beat 1
{"select": {"device1": ["rainbow_preset"]}}

// Beat 2 (same preset = beat)
{"select": {"device1": ["rainbow_preset"]}}

// Beat 3
{"select": {"device1": ["rainbow_preset"]}}
```

## Synchronization

### Using "off" Pattern

Selecting the "off" pattern resets the step counter to 0, providing a synchronization point:

```json
{
  "select": {
    "device1": ["off"],
    "device2": ["off"]
  }
}
```

After all devices are "off", switching to a pattern ensures they all start from step 0:

```json
{
  "select": {
    "device1": ["rainbow_preset"],
    "device2": ["rainbow_preset"]
  }
}
```

### Using Step Parameter

For precise synchronization, use the step parameter:

```json
{
  "select": {
    "device1": ["rainbow_preset", 10],
    "device2": ["rainbow_preset", 10],
    "device3": ["rainbow_preset", 10]
  }
}
```

All devices will start at step 10 and advance together on subsequent beats.

## Complete Example

```json
{
  "v": "1",
  "presets": {
    "red_blink": {
      "pattern": "blink",
      "colors": ["#FF0000"],
      "delay": 200,
      "brightness": 255,
      "auto": true
    },
    "rainbow_manual": {
      "pattern": "rainbow",
      "delay": 100,
      "n1": 2,
      "auto": false
    },
    "pulse_slow": {
      "pattern": "pulse",
      "colors": ["#00FF00"],
      "delay": 500,
      "n1": 1000,
      "n2": 500,
      "n3": 1000,
      "auto": false
    }
  },
  "select": {
    "device1": ["red_blink"],
    "device2": ["rainbow_manual", 0],
    "device3": ["pulse_slow"]
  }
}
```

## Message Processing

1. **Version Check**: Messages with `v != "1"` are rejected
2. **Preset Processing**: Presets are created or updated (upsert behavior)
3. **Color Conversion**: Hex colors are converted to RGB tuples and reordered based on device color order
4. **Selection**: Devices select their assigned preset, optionally with step value

## Best Practices

1. **Always include version**: Set `"v": "1"` in all messages
2. **Use "off" for sync**: Select "off" pattern to synchronize devices before starting patterns
3. **Beats for manual mode**: Send select messages repeatedly with same preset name to advance manual patterns
4. **Step for precision**: Use step parameter when exact synchronization is required
5. **Color format**: Always use hex strings (`"#RRGGBB"`), conversion is automatic

## Error Handling

- Invalid version: Message is ignored
- Missing preset: Selection fails, device keeps current preset
- Invalid pattern: Selection fails, device keeps current preset
- Missing colors: Pattern uses default white color
- Invalid step: Step value is used as-is (may cause unexpected behavior)

## Notes

- Colors are automatically converted from hex strings to RGB tuples
- Color order reordering happens automatically based on device settings
- Step counter wraps around (0-255 for rainbow, unbounded for others)
- Manual mode patterns stop after one step/cycle, waiting for next beat
- Auto mode patterns run continuously until changed
