# Lighting Controller - Separated Architecture This version of the lighting controller separates the UI and control logic, communicating via WebSocket. The MIDI controller is now integrated with the UI client. ## Architecture Overview ``` ┌─────────────────┐ WebSocket ┌─────────────────┐ WebSocket ┌─────────────────┐ │ UI Client │◄─────────────────►│ Control Server │◄─────────────────►│ LED Server │ │ │ │ │ │ │ │ - MIDI Input │ │ - Lighting Logic│ │ - LED Bars │ │ - User Interface│ │ - Pattern Logic │ │ - ESP-NOW │ │ - Status Display│ │ - Beat Handling │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ TCP │ ▼ │ ┌─────────────────┐ │ │ Sound Detector │ │ │ │ │ │ - Audio Input │ │ │ - Beat Detection│ │ │ - BPM Analysis │ │ └─────────────────┘ │ │ MIDI ▼ ┌─────────────────┐ │ MIDI Controller │ │ │ │ - Knobs/Dials │ │ - Buttons │ │ - Pattern Select│ └─────────────────┘ ``` ## Components ### 1. UI Client (`src/ui_client.py`) - **Purpose**: User interface and MIDI controller integration - **Features**: - MIDI controller input handling - Real-time status display - Pattern selection visualization - Connection status monitoring - **Communication**: WebSocket client to control server ### 2. Control Server (`src/control_server.py`) - **Purpose**: Core lighting control logic - **Features**: - Pattern execution - Beat synchronization - Parameter management - LED bar communication - **Communication**: - WebSocket server for UI clients - TCP server for sound detector - WebSocket client to LED server ### 3. Sound Detector (`src/sound.py`) - **Purpose**: Audio beat detection and BPM analysis - **Features**: - Real-time audio processing - Beat detection - BPM calculation - Tempo reset functionality - **Communication**: TCP client to control server ## WebSocket Protocol ### UI Client → Control Server Messages ```json { "type": "pattern_change", "data": { "pattern": "pulse" } } ``` ```json { "type": "color_change", "data": { "r": 255, "g": 0, "b": 0 } } ``` ```json { "type": "brightness_change", "data": { "brightness": 80 } } ``` ```json { "type": "parameter_change", "data": { "n1": 15, "n2": 20 } } ``` ```json { "type": "delay_change", "data": { "delay": 150 } } ``` ```json { "type": "beat_toggle", "data": { "enabled": true } } ``` ```json { "type": "reset_tempo", "data": {} } ``` ## Running the System ### Option 1: Use the startup script (Recommended) ```bash python start_lighting_controller.py ``` ### Option 2: Start components individually 1. **Start Control Server**: ```bash pipenv run control # or python src/control_server.py ``` 2. **Start Sound Detector** (in another terminal): ```bash pipenv run sound # or python src/sound.py ``` 3. **Start UI Client** (in another terminal): ```bash pipenv run ui # or python src/ui_client.py ``` ### Option 3: Development mode with auto-reload ```bash # Terminal 1 - Control Server pipenv run dev-control # Terminal 2 - Sound Detector pipenv run sound # Terminal 3 - UI Client pipenv run dev-ui ``` ## Configuration ### MIDI Controller - MIDI device preferences are saved in `config.json` - The UI client automatically detects and connects to MIDI devices - Use the dropdown to select different MIDI ports ### Network Settings - **Control Server**: `localhost:8765` (WebSocket) - **Sound Detector**: `127.0.0.1:65432` (TCP) - **LED Server**: `192.168.4.1:80/ws` (WebSocket) ### Audio Settings - Audio input device index: 7 (modify in `src/sound.py`) - Buffer size: 512 samples - Sample rate: Auto-detected from device ## MIDI Controller Mapping ### Buttons (Notes 36-51) - **Row 1**: Pulse, Sequential Pulse - **Row 2**: Alternating, Alternating Phase - **Row 3**: N Chase, Rainbow - **Row 4**: Flicker, Radiate ### Dials (CC30-37) - **CC30**: Red (0-255) - **CC31**: Green (0-255) - **CC32**: Blue (0-255) - **CC33**: Brightness (0-100) - **CC34**: N1 parameter - **CC35**: N2 parameter - **CC36**: N3 parameter - **CC37**: Delay (0-508ms) ### Additional Knobs (CC38-45) - **CC38**: Pulse N1 - **CC39**: Pulse N2 - **CC40**: Alternating N1 - **CC41**: Alternating N2 - **CC42**: Radiate N1 - **CC43**: Radiate Delay - **CC44**: Knob 7 - **CC45**: Knob 8 ### Control Buttons - **CC27**: Beat sending toggle (127=on, 0=off) - **CC29**: Reset tempo detection ## Troubleshooting ### Connection Issues 1. **UI Client can't connect to Control Server**: - Ensure control server is running first - Check firewall settings - Verify port 8765 is available 2. **Control Server can't connect to LED Server**: - Check LED server IP address (192.168.4.1) - Verify LED server is running - Check network connectivity 3. **Sound Detector can't connect to Control Server**: - Ensure control server is running - Check TCP port 65432 is available ### MIDI Issues 1. **No MIDI devices detected**: - Check MIDI controller connection - Install MIDI drivers if needed - Use "Refresh MIDI Ports" button 2. **MIDI input not working**: - Verify correct MIDI port is selected - Check MIDI controller is sending data - Look for error messages in console ### Performance Issues 1. **High CPU usage**: - Reduce audio buffer size in sound.py - Increase parameter update interval - Check for network latency 2. **Audio dropouts**: - Increase audio buffer size - Check audio device settings - Reduce system load ## Development ### Adding New Patterns 1. Add pattern name to `PATTERN_NAMES` in `control_server.py` 2. Implement pattern logic in `LightingController` class 3. Add pattern to MIDI button mapping in `ui_client.py` ### Adding New MIDI Controls 1. Add control change handler in `MidiController.handle_midi_message()` 2. Add corresponding WebSocket message type 3. Implement handler in `LightingController.handle_ui_command()` ### Modifying UI - Edit `src/ui_client.py` for UI changes - Use `pipenv run dev-ui` for auto-reload during development - UI uses tkinter with dark theme ## Migration from Monolithic Version The separated architecture maintains compatibility with: - Existing MIDI controller mappings - LED bar communication protocol - Sound detection functionality - Configuration files Key differences: - MIDI controller is now part of UI client - Control logic is isolated in control server - Communication via WebSocket instead of direct function calls - Better separation of concerns and modularity