From 8349443bf575837be4b932e7375f65bf76920203 Mon Sep 17 00:00:00 2001 From: jessikitty Date: Mon, 15 Dec 2025 16:24:07 +1100 Subject: [PATCH] Add comprehensive ESP32 relay integration guide --- docs/ESP32_RELAY_INTEGRATION.md | 560 ++++++++++++++++++++++++++++++++ 1 file changed, 560 insertions(+) create mode 100644 docs/ESP32_RELAY_INTEGRATION.md diff --git a/docs/ESP32_RELAY_INTEGRATION.md b/docs/ESP32_RELAY_INTEGRATION.md new file mode 100644 index 0000000..c5cb637 --- /dev/null +++ b/docs/ESP32_RELAY_INTEGRATION.md @@ -0,0 +1,560 @@ +# ESP32 Bluetooth Relay Integration Guide + +Complete guide for integrating ESP32 8-channel Bluetooth relay controller with the Moonlight Drive-In Theatre system. + +## ๐ŸŽฏ Overview + +This integration allows the theatre software to automatically control: +- **House lights** - Main theatre lighting +- **Screen lights** - Illumination around the screen +- **Marquee lights** - External entrance/sign lighting +- **Speaker power** - Audio system power +- **Projector power** - Video projector control +- **Effect lights** - Special effect lighting +- **Concession lights** - Snack bar area +- **Parking lights** - Parking area illumination + +## ๐Ÿ“ฆ Prerequisites + +### Hardware Required + +1. **ESP32 Development Board** (with Bluetooth) +2. **8-Channel Relay Module** (5V) +3. **Wiring components** (jumper wires, power supply) +4. **Computer with Bluetooth** (for Python script communication) + +### Software Required + +```bash +pip install pyserial +``` + +The ESP32 firmware is in the separate `esp32-bluetooth-relay` repository. + +## ๐Ÿ”ง Hardware Setup + +### Step 1: Build ESP32 Relay Controller + +Follow the complete guide in the `esp32-bluetooth-relay` repository: +- Wire ESP32 to relay module +- Upload firmware to ESP32 +- Test basic relay operation + +### Step 2: Connect Loads to Relays + +Map your theatre equipment to relays (default configuration): + +| Relay | Function | Theatre Equipment | +|-------|----------|-------------------| +| 1 | House Lights | Main overhead lights | +| 2 | Screen Lights | Screen border lighting | +| 3 | Marquee Lights | Entrance sign | +| 4 | Speaker Power | Audio amplifier | +| 5 | Projector Power | Video projector | +| 6 | Effect Lights | RGB/effect lighting | +| 7 | Concession Lights | Snack bar | +| 8 | Parking Lights | Outdoor parking | + +**โš ๏ธ SAFETY:** Only qualified electricians should wire AC-powered equipment. Start with low-voltage DC loads for testing. + +### Step 3: Pair ESP32 with Computer + +**Windows:** +1. Open Bluetooth settings +2. Search for "ESP32-Relay-8CH" +3. Pair the device +4. Note the COM port assigned (e.g., COM4) + +**Linux:** +```bash +# Scan for ESP32 +hcitool scan + +# Pair with ESP32 (replace XX:XX... with actual MAC) +bluetoothctl +> pair XX:XX:XX:XX:XX:XX +> trust XX:XX:XX:XX:XX:XX +> connect XX:XX:XX:XX:XX:XX + +# Bind to serial port +sudo rfcomm bind /dev/rfcomm0 XX:XX:XX:XX:XX:XX +``` + +## ๐Ÿš€ Software Integration + +### Step 1: Install Python Dependencies + +```bash +cd moonlight-drive-in +pip install pyserial +``` + +### Step 2: Configure Theatre Automation + +Edit `config.py` and add the relay configuration section: + +```python +# ESP32 Relay Controller Configuration +RELAY_CONFIG = { + # Enable/disable features + 'enabled': True, + 'auto_theatre_lights': True, # Auto dim lights during movies + 'auto_speaker_power': True, # Auto power speakers + 'light_dim_delay': 5, # Seconds before dimming + + # Serial port (None = auto-detect, or specify like 'COM4' or '/dev/rfcomm0') + 'relay_port': None, + + # Custom relay mapping (optional - override defaults) + 'relay_mapping': { + 'HOUSE_LIGHTS': 1, + 'SCREEN_LIGHTS': 2, + 'MARQUEE_LIGHTS': 3, + 'SPEAKER_POWER': 4, + 'PROJECTOR_POWER': 5, + 'EFFECT_LIGHTS': 6, + 'CONCESSION_LIGHTS': 7, + 'PARKING_LIGHTS': 8, + } +} +``` + +### Step 3: Modify MPV Player Integration + +Edit `mpv_seamless_player.py` to add automation hooks: + +```python +# At top of file, add imports +from theatre_automation import TheatreAutomation, RelayFunction +import config + +# In __init__ method, add: +self.theatre = None +if config.RELAY_CONFIG.get('enabled', False): + try: + self.theatre = TheatreAutomation(config.RELAY_CONFIG) + if self.theatre.connect(): + logger.info("Theatre automation enabled") + else: + logger.warning("Failed to connect to theatre automation") + self.theatre = None + except Exception as e: + logger.error(f"Theatre automation error: {e}") + self.theatre = None + +# Before playing trailer, add: +if self.theatre: + self.theatre.movie_starting(is_trailer=True) + +# After trailer ends, add: +if self.theatre: + self.theatre.movie_ended(is_trailer=True) + +# Before playing main movie, add: +if self.theatre: + self.theatre.movie_starting(is_trailer=False) + +# After movie ends, add: +if self.theatre: + self.theatre.movie_ended(is_trailer=False) + +# On shutdown/cleanup, add: +if self.theatre: + self.theatre.disconnect() +``` + +### Step 4: Add Web Interface Controls + +Edit `web_interface.py` to add relay control routes: + +```python +from theatre_automation import TheatreAutomation, RelayFunction + +# Add global theatre variable +theatre_automation = None + +# Initialize in app startup +if config.RELAY_CONFIG.get('enabled'): + theatre_automation = TheatreAutomation(config.RELAY_CONFIG) + theatre_automation.connect() + +# Add API endpoints +@app.route('/api/relay/status') +def relay_status(): + """Get status of all relays""" + if theatre_automation and theatre_automation.connected: + return jsonify(theatre_automation.get_status()) + return jsonify({'error': 'Theatre automation not connected'}), 503 + +@app.route('/api/relay//') +def relay_control(function_name, state): + """Control a specific relay""" + if not theatre_automation or not theatre_automation.connected: + return jsonify({'error': 'Not connected'}), 503 + + try: + function = RelayFunction[function_name.upper()] + state_bool = state.lower() == 'on' + + if theatre_automation.set_relay(function, state_bool): + return jsonify({'success': True}) + else: + return jsonify({'error': 'Command failed'}), 500 + except KeyError: + return jsonify({'error': 'Invalid function'}), 400 + +@app.route('/api/relay/effect/') +def relay_effect(effect_name): + """Run a lighting effect""" + if theatre_automation and theatre_automation.connected: + theatre_automation.effect_sequence(effect_name) + return jsonify({'success': True}) + return jsonify({'error': 'Not connected'}), 503 +``` + +## ๐Ÿงช Testing + +### Test 1: Basic Connection + +```bash +python esp32_relay_controller.py +``` + +This will: +- List available serial ports +- Connect to ESP32 +- Run interactive test mode + +### Test 2: Theatre Automation + +```bash +python theatre_automation.py +``` + +This will: +- Initialize theatre automation +- Run a demo sequence (trailer โ†’ movie โ†’ closing) +- Test all automation functions + +### Test 3: Integration Test + +1. Start the theatre software normally +2. Watch for log messages: "Theatre automation enabled" +3. Scan an NFC tag to start a movie +4. Observe lights dimming after delay +5. Movie ends and lights come back up + +## ๐ŸŽฎ Manual Control + +### Command Line Control + +```python +from theatre_automation import TheatreAutomation, RelayFunction + +theatre = TheatreAutomation() +theatre.connect() + +# Manual relay control +theatre.set_relay(RelayFunction.HOUSE_LIGHTS, False) # Lights off +theatre.set_relay(RelayFunction.SPEAKER_POWER, True) # Speakers on + +# Run effects +theatre.effect_sequence("flash") +theatre.effect_sequence("pulse") + +# Get status +status = theatre.get_status() +print(status) + +theatre.disconnect() +``` + +### Web Dashboard Control + +Add to `dashboard.html`: + +```html + +
+

Theatre Automation

+ +
+
+ House Lights + + +
+ +
+ Speaker Power + + +
+ + +
+ +
+ + + +
+
+ + +``` + +## ๐Ÿ“‹ Automation Sequences + +### Movie Starting +1. Wait for light_dim_delay (default 5 seconds) +2. Turn off house lights +3. Turn off screen lights (main movie only) +4. Turn on speaker power + +### Movie Ending +1. Turn on house lights +2. Turn on screen lights +3. Turn off speaker power (if no other content playing) + +### Intermission +1. Turn on house lights +2. Turn on concession lights +3. Keep speakers powered + +### Closing +1. Turn off speakers +2. Turn off screen lights +3. Turn off effect lights +4. Keep parking and marquee lights on + +### Emergency +1. Turn ALL lights ON immediately + +## โš™๏ธ Customization + +### Change Relay Assignments + +Edit `config.py`: + +```python +'relay_mapping': { + 'HOUSE_LIGHTS': 2, # Changed from 1 to 2 + 'SCREEN_LIGHTS': 1, # Swapped with house lights + # ... etc +} +``` + +### Adjust Timing + +```python +'light_dim_delay': 10, # Wait 10 seconds before dimming +``` + +### Disable Auto-Features + +```python +'auto_theatre_lights': False, # Manual light control only +'auto_speaker_power': False, # Manual speaker control +``` + +### Add Custom Functions + +Edit `theatre_automation.py`: + +```python +class RelayFunction(Enum): + # Add new function + FOG_MACHINE = 5 # Use relay 5 for fog machine + +# Add method to control it +def activate_fog(self, duration=5): + self.set_relay(RelayFunction.FOG_MACHINE, True) + time.sleep(duration) + self.set_relay(RelayFunction.FOG_MACHINE, False) +``` + +## ๐Ÿ› Troubleshooting + +### ESP32 Not Found + +**Problem:** "No serial ports found" + +**Solutions:** +1. Ensure ESP32 is powered on +2. Verify Bluetooth pairing +3. Check Bluetooth COM port in Device Manager (Windows) +4. Run `hcitool scan` to verify device (Linux) + +### Connection Fails + +**Problem:** "Failed to connect to relay controller" + +**Solutions:** +1. Check COM port in config matches actual port +2. Verify no other program is using the port +3. Try manual port specification: `relay_port: 'COM4'` +4. Test with standalone script: `python esp32_relay_controller.py` + +### Relays Don't Respond + +**Problem:** Commands sent but relays don't switch + +**Solutions:** +1. Test ESP32 with Serial Bluetooth Terminal app +2. Check ESP32 is running and Bluetooth is active +3. Verify relay module has power +4. Check wiring between ESP32 and relay module + +### Lights Don't Dim + +**Problem:** Automation enabled but lights stay on + +**Solutions:** +1. Check `auto_theatre_lights: True` in config +2. Verify relay wiring to light switch/relay +3. Check relay polarity (active HIGH vs LOW) +4. Test manual control: `theatre.set_relay(RelayFunction.HOUSE_LIGHTS, False)` + +## ๐Ÿ“š API Reference + +### ESP32RelayController + +```python +controller = ESP32RelayController() + +# Connection +controller.connect(port='COM4') +controller.disconnect() + +# Basic Control +controller.turn_on(1) # Turn on relay 1 +controller.turn_off(1) # Turn off relay 1 +controller.toggle(1) # Toggle relay 1 +controller.all_on() # All relays on +controller.all_off() # All relays off + +# Status +controller.get_status() # Request status update +controller.get_relay_state(1) # Get cached state of relay 1 +controller.get_all_states() # Get all cached states + +# Callbacks +controller.register_callback('connect', on_connect_func) +controller.register_callback('disconnect', on_disconnect_func) +controller.register_callback('status_update', on_status_func) +``` + +### TheatreAutomation + +```python +theatre = TheatreAutomation(config) + +# Connection +theatre.connect(port='COM4') +theatre.disconnect() + +# Automation Sequences +theatre.movie_starting(is_trailer=True) +theatre.movie_ended(is_trailer=False) +theatre.intermission() +theatre.closing_sequence() +theatre.emergency_lights_on() + +# Manual Control +theatre.set_relay(RelayFunction.HOUSE_LIGHTS, True) +theatre.toggle_relay(RelayFunction.EFFECT_LIGHTS) +theatre.effect_sequence("flash") + +# Status +status = theatre.get_status() +``` + +## ๐ŸŽฌ Example Workflows + +### Unattended Mode Integration + +```python +# In unattend mode cycle handler +def cycle_content(): + if theatre: + # Starting trailer + theatre.movie_starting(is_trailer=True) + + play_trailer() + + if theatre: + theatre.movie_ended(is_trailer=True) + time.sleep(2) # Brief pause + theatre.movie_starting(is_trailer=False) + + play_movie() + + if theatre: + theatre.movie_ended(is_trailer=False) +``` + +### NFC Tag Triggered Effects + +```python +# Map NFC tags to lighting effects +NFC_EFFECTS = { + 'AAAAAAAA': 'flash', + 'BBBBBBBB': 'pulse', + 'CCCCCCCC': 'marquee', +} + +def handle_nfc(tag_id): + if tag_id in NFC_EFFECTS and theatre: + theatre.effect_sequence(NFC_EFFECTS[tag_id]) +``` + +## ๐Ÿ” Safety Notes + +1. **AC Power:** Only qualified electricians should work with mains voltage +2. **Fusing:** Use appropriate fuses for all loads +3. **Ratings:** Don't exceed relay current/voltage ratings +4. **Failsafe:** Ensure system fails to a safe state (lights ON) +5. **Testing:** Test thoroughly with low-voltage loads first + +## ๐Ÿ“– Additional Resources + +- **ESP32 Relay Repository:** `esp32-bluetooth-relay` +- **ESP32 Documentation:** Full wiring and setup guide +- **Python Serial:** https://pyserial.readthedocs.io/ +- **Bluetooth Serial:** https://learn.adafruit.com/android-bluetooth-serial + +--- + +**Version:** 1.0 +**Last Updated:** December 2025 +**Integration Status:** Ready for testing