// Configuration const API_BASE_URL = 'http://localhost:80'; const MQTT_BROKER_URL = 'ws://localhost:9001/mqtt'; // WebSocket port for MQTT const WS_URL = 'http://localhost:80'; // State let mqttClient = null; let wsClient = null; let subscribedTopics = new Set(); // Initialize document.addEventListener('DOMContentLoaded', init); function init() { setupTabs(); setupAPI(); setupMQTT(); setupWebSocket(); setupDebug(); setupQuickActions(); } // Tab Management function setupTabs() { const tabButtons = document.querySelectorAll('.tab-button'); const tabContents = document.querySelectorAll('.tab-content'); tabButtons.forEach(button => { button.addEventListener('click', () => { const tabName = button.dataset.tab; // Remove active class from all tabButtons.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); // Add active class to selected button.classList.add('active'); document.getElementById(`${tabName}-tab`).classList.add('active'); }); }); } // API Setup function setupAPI() { const endpointSelect = document.getElementById('api-endpoint'); const paramsTextarea = document.getElementById('api-params'); const sendBtn = document.getElementById('api-send-btn'); const responsePre = document.getElementById('api-response'); sendBtn.addEventListener('click', async () => { const endpoint = endpointSelect.value; const [method, path] = endpoint.split(' '); const params = paramsTextarea.value.trim(); try { let options = { method: method, headers: {} }; if (method === 'POST' && params) { // Try to parse as JSON, otherwise use as form data try { const jsonData = JSON.parse(params); options.headers['Content-Type'] = 'application/json'; options.body = JSON.stringify(jsonData); } catch { // Not JSON, use form data const formData = new URLSearchParams(); const pairs = params.split('&'); pairs.forEach(pair => { const [key, value] = pair.split('='); if (key && value) { formData.append(key, decodeURIComponent(value)); } }); options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; options.body = formData.toString(); } } const response = await fetch(`${API_BASE_URL}${path}`, options); const text = await response.text(); let formatted; try { formatted = JSON.stringify(JSON.parse(text), null, 2); } catch { formatted = text; } responsePre.textContent = formatted; } catch (error) { responsePre.textContent = `Error: ${error.message}`; } }); } // MQTT Setup function setupMQTT() { const topicInput = document.getElementById('mqtt-topic'); const payloadTextarea = document.getElementById('mqtt-payload'); const publishBtn = document.getElementById('mqtt-publish-btn'); const subscribeBtn = document.getElementById('mqtt-subscribe-btn'); const unsubscribeBtn = document.getElementById('mqtt-unsubscribe-btn'); const subscribeTopicInput = document.getElementById('mqtt-subscribe-topic'); const messagesContainer = document.getElementById('mqtt-messages'); const clearMessagesBtn = document.getElementById('clear-messages-btn'); // Connect to MQTT broker try { mqttClient = mqtt.connect(MQTT_BROKER_URL, { clientId: 'debug-ui-' + Math.random().toString(16).substr(2, 8) }); mqttClient.on('connect', () => { console.log('MQTT connected'); updateStatus('mqtt-status', 'MQTT: Connected', true); }); mqttClient.on('error', (error) => { console.error('MQTT error:', error); updateStatus('mqtt-status', 'MQTT: Error', false); }); mqttClient.on('close', () => { console.log('MQTT disconnected'); updateStatus('mqtt-status', 'MQTT: Disconnected', false); }); mqttClient.on('message', (topic, message) => { addMessage(topic, message.toString()); }); } catch (error) { console.error('Failed to connect to MQTT:', error); updateStatus('mqtt-status', 'MQTT: Connection Failed', false); } publishBtn.addEventListener('click', () => { const topic = topicInput.value.trim(); let payload = payloadTextarea.value.trim(); if (!topic) { alert('Please enter a topic'); return; } // Try to parse as JSON, otherwise use as-is try { const jsonData = JSON.parse(payload); payload = JSON.stringify(jsonData); } catch { // Not JSON, use as-is } if (mqttClient && mqttClient.connected) { mqttClient.publish(topic, payload, (err) => { if (err) { console.error('Publish error:', err); alert('Failed to publish: ' + err.message); } else { console.log('Published to', topic); } }); } else { alert('MQTT not connected'); } }); subscribeBtn.addEventListener('click', () => { const topic = subscribeTopicInput.value.trim(); if (!topic) { alert('Please enter a topic pattern'); return; } if (mqttClient && mqttClient.connected) { mqttClient.subscribe(topic, (err) => { if (err) { console.error('Subscribe error:', err); alert('Failed to subscribe: ' + err.message); } else { subscribedTopics.add(topic); console.log('Subscribed to', topic); } }); } else { alert('MQTT not connected'); } }); unsubscribeBtn.addEventListener('click', () => { if (mqttClient && mqttClient.connected) { subscribedTopics.forEach(topic => { mqttClient.unsubscribe(topic); }); subscribedTopics.clear(); console.log('Unsubscribed from all topics'); } }); clearMessagesBtn.addEventListener('click', () => { messagesContainer.innerHTML = ''; }); } function addMessage(topic, payload) { const messagesContainer = document.getElementById('mqtt-messages'); const messageDiv = document.createElement('div'); messageDiv.className = 'message-item'; const timestamp = new Date().toLocaleTimeString(); let formattedPayload = payload; try { formattedPayload = JSON.stringify(JSON.parse(payload), null, 2); } catch {} messageDiv.innerHTML = `