From 9bfbcfd8a8b47a251b39f2080755c3a1fcce4a8e Mon Sep 17 00:00:00 2001 From: sirmrak Date: Thu, 21 May 2026 19:56:51 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20Web=20Client=20=E2=80=94=20=D1=83=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=BD=D0=BE=D0=B5=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA?= =?UTF-8?q?=20WebSocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Изменения: 1. Поле для ввода WebSocket адреса (вместо prompt) - wsUrlInput с значением по умолчанию - Сохраняется между перезагрузками 2. Кнопка CONNECT/DISCONNECT - Меняет текст и цвет при подключении - DISCONNECT красная кнопка - Работают обе кнопки (в шапке и в карточке) 3. Auto-connect - Чекбокс 'Auto-connect on load' - Автоматическое подключение при загрузке - Можно отключить 4. updateConnectButton() - Обновляет обе кнопки синхронно - 🔌 CONNECT / 🔌 DISCONNECT --- web-client/client.html | 105 +++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 15 deletions(-) diff --git a/web-client/client.html b/web-client/client.html index c67aa06..6898154 100644 --- a/web-client/client.html +++ b/web-client/client.html @@ -279,7 +279,7 @@
-
+
⚡ Wyoming Droid Assistant ⚡
@@ -290,6 +290,25 @@
+ +
+
+ 🔌 WebSocket Connection +
+
+ + + +
+
+
@@ -643,29 +662,49 @@ drawSatelliteVisualization(); - // Подключение микрофона для визуализации (опционально) — УДАЛЕНО - // Теперь используем RMS от satellite вместо локального микрофона - - // WebSocket подключение - function connectWebSocket() { - const hostInput = prompt("Введите адрес LVA WebSocket (по умолчанию ws://192.168.200.111:8675):", "ws://192.168.200.111:8675"); - if(!hostInput) return; - if(ws && ws.readyState === WebSocket.OPEN) ws.close(); - ws = new WebSocket(hostInput); + // WebSocket подключение/отключение + function toggleConnection() { + const wsUrl = document.getElementById('wsUrlInput').value.trim(); + + if(!wsUrl) { + addEventToLog('❌ Введите WebSocket URL'); + return; + } + + // Если уже подключены — отключаемся + if(ws && ws.readyState === WebSocket.OPEN) { + ws.close(); + return; + } + + // Подключаемся + if(ws && ws.readyState === WebSocket.CONNECTING) { + ws.close(); + return; + } + + ws = new WebSocket(wsUrl); + ws.onopen = () => { isConnected = true; + updateConnectButton(); statusLed.classList.add('connected'); statusLabel.innerText = 'connected'; - addEventToLog(`✅ Соединение установлено с ${hostInput}`); + addEventToLog(`✅ Соединение установлено с ${wsUrl}`); stateText.innerText = 'ONLINE'; orb.style.animation = 'pulse-glow 0.8s'; setTimeout(()=> orb.style.animation='',700); - // initMicVisualizer() — удалено, используем satellite RMS }; + ws.onmessage = handleIncomingMessage; - ws.onerror = (err) => { addEventToLog(`⚠️ WebSocket ошибка`); }; + + ws.onerror = (err) => { + addEventToLog(`⚠️ WebSocket ошибка`); + }; + ws.onclose = () => { isConnected = false; + updateConnectButton(); statusLed.classList.remove('connected'); statusLabel.innerText = 'disconnected'; addEventToLog(`🔌 Отключено`); @@ -673,9 +712,45 @@ document.body.classList.remove('listening-active'); }; } + + // Обновление кнопки подключения + function updateConnectButton() { + const btn = document.getElementById('connectBtn'); + const btnCard = document.getElementById('connectBtnCard'); + + if(ws && ws.readyState === WebSocket.OPEN) { + if(btn) { btn.innerHTML = '🔌 DISCONNECT'; btn.classList.add('danger-btn'); } + if(btnCard) { btnCard.innerHTML = '🔌 DISCONNECT'; btnCard.classList.add('danger-btn'); } + } else { + if(btn) { btn.innerHTML = '⟳ CONNECT'; btn.classList.remove('danger-btn'); } + if(btnCard) { btnCard.innerHTML = '⟳ CONNECT'; btnCard.classList.remove('danger-btn'); } + } + } - // Кнопки управления - document.getElementById('connectBtn').addEventListener('click', connectWebSocket); + // Кнопки подключения + document.getElementById('connectBtn').addEventListener('click', toggleConnection); + document.getElementById('connectBtnCard').addEventListener('click', toggleConnection); + + // Auto-connect при загрузке + window.addEventListener('load', () => { + addEventToLog('🤖 Wyoming Droid Assistant • готов к подключению'); + + // Инициализация RMS элементов после загрузки DOM + const rmsFillEl = document.getElementById('rmsFill'); + const rmsValueEl = document.getElementById('rmsValue'); + if (rmsFillEl && rmsValueEl) { + console.log('RMS meter initialized'); + } + + // Auto-connect если включена опция + const autoConnect = document.getElementById('autoConnect'); + if(autoConnect && autoConnect.checked) { + setTimeout(() => { + addEventToLog('📡 Auto-connect...'); + toggleConnection(); + }, 500); + } + }); // Volume control document.getElementById('startListeningBtn').addEventListener('click', () => sendCommand('set_volume', { level: 1.0 }));