// Only initialize if not already done if (!window.relayControlInitialized) { class RelayControl { constructor() { this.currentState = 'off'; this.relayPin = ''; this.init(); } init() { this.createComponent(); this.loadRelayStatus(); this.setupEventListeners(); // Refresh status every 2 seconds setInterval(() => this.loadRelayStatus(), 2000); } createComponent() { // Create the main container const container = document.createElement('div'); container.className = 'relay-component'; container.innerHTML = `

🔌 Relay Control

OFF
Relay is OFF
Pin: Loading...
`; // Append to component div const componentDiv = document.getElementById('component'); if (componentDiv) { componentDiv.appendChild(container); } else { // Fallback to body if component div not found document.body.appendChild(container); } } setupEventListeners() { document.getElementById('turnOnBtn').addEventListener('click', () => this.controlRelay('on')); document.getElementById('turnOffBtn').addEventListener('click', () => this.controlRelay('off')); document.getElementById('toggleBtn').addEventListener('click', () => this.controlRelay('toggle')); } // Load initial relay status async loadRelayStatus() { try { const response = await fetch('/api/relay/status'); if (!response.ok) { throw new Error('Failed to fetch relay status'); } const data = await response.json(); this.currentState = data.state; this.relayPin = data.pin; this.updateUI(); this.updateUptime(data.uptime); } catch (error) { console.error('Error loading relay status:', error); this.showMessage('Error loading relay status: ' + error.message, 'error'); } } // Control relay async controlRelay(action) { const buttons = document.querySelectorAll('.btn'); buttons.forEach(btn => btn.classList.add('loading')); try { const response = await fetch('/api/relay', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `state=${action}` }); const data = await response.json(); if (data.success) { this.currentState = data.state; this.updateUI(); this.showMessage(`Relay turned ${data.state.toUpperCase()}`, 'success'); } else { this.showMessage(data.message || 'Failed to control relay', 'error'); } } catch (error) { console.error('Error controlling relay:', error); this.showMessage('Error controlling relay: ' + error.message, 'error'); } finally { buttons.forEach(btn => btn.classList.remove('loading')); } } // Update UI based on current state updateUI() { const statusIndicator = document.getElementById('statusIndicator'); const statusText = document.getElementById('statusText'); const pinInfo = document.getElementById('pinInfo'); if (this.currentState === 'on') { statusIndicator.className = 'status-indicator on'; statusIndicator.textContent = 'ON'; statusText.textContent = 'Relay is ON'; } else { statusIndicator.className = 'status-indicator off'; statusIndicator.textContent = 'OFF'; statusText.textContent = 'Relay is OFF'; } if (this.relayPin) { pinInfo.textContent = `Pin: ${this.relayPin}`; } } // Update uptime display updateUptime(uptime) { const uptimeElement = document.getElementById('uptime'); if (uptime) { const seconds = Math.floor(uptime / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); let uptimeText = `Uptime: ${seconds}s`; if (hours > 0) { uptimeText = `Uptime: ${hours}h ${minutes % 60}m ${seconds % 60}s`; } else if (minutes > 0) { uptimeText = `Uptime: ${minutes}m ${seconds % 60}s`; } uptimeElement.textContent = uptimeText; } } // Show message to user showMessage(message, type) { const messageElement = document.getElementById('message'); messageElement.textContent = message; messageElement.className = type; // Clear message after 3 seconds setTimeout(() => { messageElement.textContent = ''; messageElement.className = ''; }, 3000); } } // Initialize the relay control when the page loads document.addEventListener('DOMContentLoaded', () => { new RelayControl(); }); window.relayControlInitialized = true; }