// Plantilla HTML const char *htmlTemplate = R"rawliteral( <html> <head> <meta charset='UTF-8'> <style> /* Tema oscuro básico */ body { background-color: #121212; color: #ffffff; font-family: Arial, sans-serif; margin: 20px; font-size: 12px } h2 { color: #cccccc; /* Gris claro */ font-size: 32px; border-bottom: 2px solid #555555; /* Un borde gris medio */ padding-bottom: 5px; margin-bottom: 20px; } h3 { color: #bbbbbb; /* Gris medio-claro */ font-size: 20px; margin-top: 30px; padding-bottom: 5px; border-bottom: 1px solid #444444; /* Un borde gris oscuro */ } h4 { color: #dddddd; /* Blanco roto o gris muy claro */ font-size: 18px; margin-top: 20px; } .button-bar { display: flex; justify-content: space-between; background-color: #333; padding: 10px; border-radius: 5px; margin-bottom: 20px; } .button-bar button { background-color: #1e88e5; border: none; color: white; padding: 10px 20px; text-align: center; font-size: 16px; cursor: pointer; border-radius: 5px; transition: background-color 0.3s ease; } /* Botones */ button { background-color: #1e88e5; border: none; color: white; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 10px 2px; cursor: pointer; border-radius: 5px; transition: background-color 0.3s ease; } button:hover { background-color: #1565c0; } .button-bar button:hover { background-color: #1565c0; } .columns-container { display: flex; justify-content: space-between; width: 100%; } .section:nth-child(1) { flex: 22%; /* Primera columna */ } .section:nth-child(2) { flex: 15%; /* Segunda columna */ } .section:nth-child(3) { flex: 15%; /* Tercera columna */ } .section:nth-child(4) { flex: 45%; /* Cuarta columna */ } .section { background-color: #1e1e1e; padding: 20px; border-radius: 10px; margin-bottom: 20px; margin: 5px; } /* Estilos de los inputs */ input[type="text"], input[type="number"], select { width: 100%; padding: 5px; margin: 5px 0; background-color: #333; border: 1px solid #555; color: #fff; border-radius: 5px; } /* Estilos del checkbox y radio */ input[type="checkbox"], input[type="radio"] { margin: 10px; vertical-align: middle; margin-right: 5px; /* Ajusta el espacio entre el input y el texto */ } /* Estilo de los sliders */ /*input[type="range"] { writing-mode: bt-lr; transform: rotate(270deg); width: auto; height: 150px; display: block; }*/ input[type="range"] { width: 100%; margin: 10px 0; } /* Estilos de la capa flotante */ #monitorLayer { display: none; position: fixed; top: 10%; left: 50%; transform: translate(-50%, 0); background: rgba(0, 0, 0, 0.9); padding: 20px; border-radius: 10px; z-index: 1000; width: 80%; max-width: 800px; } #monitorLayer iframe { width: 100%; height: 400px; border: none; } #closeMonitor { background: red; border: none; color: white; padding: 10px; font-size: 16px; cursor: pointer; margin-top: 10px; } .motor-camera { display: flex; flex-direction: column; align-items: center; } .motor-columns { display: flex; justify-content: space-between; width: 100%; } .motor-column { flex: 1; padding: 10px; } .motor-buttons { text-align: center; margin-top: 20px; } .speed-container { display: flex; flex-direction: column; align-items: center; text-align: center; margin-bottom: 10px; } .speed-value { display: flex; align-items: center; gap: 5px; } #iframe360 { width: 100%; height: 100%; min-height: 400px; /* Ajusta la altura mínima según sea necesario */ border: none; } </style> </head> <body> <div class="button-bar"> <button onclick="accion()">REC</button> <button onclick="corten()">STOP</button> <button onclick="toggleMonitor()">SCREEN</button> </div> <div id="monitorLayer"> <iframe src="http://192.168.8.5:8000"></iframe> <button id="closeMonitor" onclick="toggleMonitor()">Cerrar</button> </div> <div class="columns-container"> <div class="section"> <h3>Motor Cámara</h3> <div class="motor-columns"> <!-- Columna 1: Counter y Speed --> <div class="motor-column"> <h4>Counter</h4> <input type='number' id='frames'> <h4>Speed</h4> <label for='fps'>FPS:</label> <div class="speed-container"> <input type='range' min='0' max='48' value='24' id='speedSlider'> <div class="speed-value"> <span id='speedValueDisplay'>24</span> <span>fps</span> </div> </div> <input type='number' id='fps'><br><br> <input type='checkbox' id='speedCheckbox'>Speed </div> <!-- Columna 2: Intervalómetro y Dirección --> <div class="motor-column"> <h4>Intervalómetro:</h4> <label for='intervalFrames'>Frames:</label> <input type='number' id='intervalFrames' value='10' min='1'><br><br> <label for='intervalSeconds'>Segundos:</label> <input type='number' id='intervalSeconds' value='1' min='1'><br><br> <input type='checkbox' id='intervalCheckbox'> Intervalómetro <h4>Dirección:</h4> <input type='radio' id='forward' name='direction' value='forward' checked> Forward<br> <input type='radio' id='backward' name='direction' value='backward'> Backward </div> </div> <!-- Botones centrados abajo --> <div class="motor-buttons"> <button onclick="sendMotorCameraData('test_motor')">Test</button> <button onclick="sendMotorCameraData('save_motor')">Save</button> <button onclick="stop()">Stop</button> <span id="motorCameraMessage" style="color: green; display: none;">Datos enviados correctamente</span> </div> </div> <div class="section"> <h3>Shutter</h3> <h4>Fade In/Out Frames:</h4> <p>% apertura inicial: <span id='fadePercentDisplay'>0</span></p> <input type='range' min='0' max='100' value='0' id='fadePercentSlider'> <input type='number' id='fade'> <p>Número de frames: <span id='fadeFramesDisplay'>10</span></p> <input type='range' min='0' max='100' value='10' id='fadeFramesSlider'> <h4>Fade Activación:</h4> <input type='checkbox' id='fadeInCheckbox'> Fade In <input type='checkbox' id='fadeOutCheckbox'> Fade Out <br><br> <input type='checkbox' id='syncWithIntervalCheckbox'> Sincronizar con Intervalómetro <br><br><br> <button onclick="sendShutterData('save_shutter')">Save</button> <span id="shutterMessage" style="color: green; display: none;">Datos enviados correctamente</span> </div> <div class="section"> <!-- Sección Óptica --> <h3>Óptica</h3> <h4>Zoom:</h4> <p>Valor de zoom: <span id='zoomValueDisplay'>50</span></p> <input type='range' min='0' max='100' value='50' id='zoomSlider'> <h4>Foco:</h4> <p>Valor de foco: <span id='focusValueDisplay'>50</span></p> <input type='range' min='0' max='100' value='50' id='focusSlider'> <h4>Diafragma:</h4> <select id='diaphragmSelect'> <option value='1.9'>1.9</option> <option value='2.2'>2.2</option> <option value='4'>4</option> <option value='5.6'>5.6</option> <option value='8'>8</option> <option value='11'>11</option> <option value='16'>16</option> <option value='22'>22</option> </select> <br><br> <input type='checkbox' id='syncWithIntervalOptics'> Sincronizar con Intervalómetro <br><br> <button onclick="sendOpticsData('test_optics')">Test</button> <button onclick="sendOpticsData('save_optics')">Save</button> <span id="opticsMessage" style="color: green; display: none;">Datos enviados correctamente</span> </div> <div class="section"> <h3>Dispositivo 360</h3> <iframe id="iframe360" src="http://192.168.8.3"></iframe> </div> </div> <!-- Script para manejar las interacciones y enviar el JSON --> <script> function toggleMonitor() { let monitorLayer = document.getElementById('monitorLayer'); monitorLayer.style.display = (monitorLayer.style.display === 'none' || monitorLayer.style.display === '') ? 'block' : 'none'; } window.addEventListener("message", function (event) { console.log("Mensaje recibido:", event.data); // Depuración // Seleccionar el iframe específico por su ID const targetIframe = document.getElementById("iframe360"); // Verificar que el mensaje contiene un número válido (altura) if (targetIframe && typeof event.data === "number" && event.data > 0) { targetIframe.style.height = event.data + "px"; console.log("Altura ajustada del iframe a:", event.data + "px"); // Depuración } }); function updateDisplay() { document.getElementById('speedValueDisplay').innerText = document.getElementById('speedSlider').value; document.getElementById('fadePercentDisplay').innerText = document.getElementById('fadePercentSlider').value; document.getElementById('fadeFramesDisplay').innerText = document.getElementById('fadeFramesSlider').value; document.getElementById('zoomValueDisplay').innerText = document.getElementById('zoomSlider').value; document.getElementById('focusValueDisplay').innerText = document.getElementById('focusSlider').value; } function showMessage(elementId) { const messageElement = document.getElementById(elementId); if (messageElement) { messageElement.style.display = 'inline'; setTimeout(() => { messageElement.style.display = 'none'; }, 3000); // Mostrar el mensaje durante 3 segundos } } function sendMotorCameraData(type_mode) { const motorData = { type: type_mode, /*speedValue: document.getElementById('speedSlider').value, isSpeedActive: document.getElementById('speedCheckbox').checked, intervalFrames: document.getElementById('intervalFrames').value, intervalSeconds: document.getElementById('intervalSeconds').value, isIntervalActive: document.getElementById('intervalCheckbox').checked, direction: document.querySelector('input[name="direction"]:checked').value*/ 0: document.getElementById('speedSlider').value, 1: document.getElementById('speedCheckbox').checked, 2: document.getElementById('intervalFrames').value, 3: document.getElementById('intervalSeconds').value, 4: document.getElementById('intervalCheckbox').checked, 5: document.querySelector('input[name="direction"]:checked').value }; fetch('/updateMotorCamera', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(motorData), }) .then(response => response.text()) .then(() => showMessage('motorCameraMessage')) .catch(error => console.error('Motor Camera Error:', error)); } function stop() { const accionData = { type: 'stop', }; fetch('/stop', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(accionData), }) .then(response => response.text()) .then(() => showMessage('motorCameraMessage')) .catch(error => console.error('Stop Error:', error)); } function sendShutterData(type_mode) { const shutterData = { type: type_mode, /*fadePercent: document.getElementById('fadePercentSlider').value, fadeFrames: document.getElementById('fadeFramesSlider').value, syncWithInterval: document.getElementById('syncWithIntervalCheckbox').checked, fadeInActive: document.getElementById('fadeInCheckbox').checked, fadeOutActive: document.getElementById('fadeOutCheckbox').checked*/ 0: document.getElementById('fadePercentSlider').value, 1: document.getElementById('fadeFramesSlider').value, 2: document.getElementById('syncWithIntervalCheckbox').checked, 3: document.getElementById('fadeInCheckbox').checked, 4: document.getElementById('fadeOutCheckbox').checked }; fetch('/updateShutter', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(shutterData), }) .then(response => response.text()) .then(() => showMessage('shutterMessage')) .catch(error => console.error('Shutter Error:', error)); } function sendOpticsData(type_mode) { const opticsData = { type: type_mode, zoomValue: document.getElementById('zoomSlider').value, focusValue: document.getElementById('focusSlider').value, diaphragmValue: document.getElementById('diaphragmSelect').value, syncWithInterval: document.getElementById('syncWithIntervalOptics').checked }; fetch('/updateOptics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(opticsData), }) .then(response => response.text()) .then(() => showMessage('opticsMessage')) .catch(error => console.error('Optics Error:', error)); } function moveMotor(type_mode, motor) { const degrees = document.getElementById(`${motor}Degrees`).value; const duration = document.getElementById(`${motor}Duration`).value; const syncWithInterval = document.getElementById('syncWithInterval360').checked; const motorData = { type: type_mode, motor: motor, degrees: degrees, duration: duration, syncWithInterval: syncWithInterval }; fetch('/moveMotor360', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(motorData), }) .then(response => response.text()) .then(() => showMessage(`${motor}Message`)) .catch(error => console.error('Motor Error:', error)); } function accion() { const accionData = { type: 'accion', }; fetch('/accion', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(accionData), }) .then(response => response.text()) .then(() => showMessage('accionMessage')) .catch(error => console.error('Accion Error:', error)); } function corten() { const accionData = { type: 'corten', }; fetch('/corten', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(accionData), }) .then(response => response.text()) .then(() => showMessage('accionMessage')) .catch(error => console.error('Corten Error:', error)); } // Actualizar la interfaz al cambiar los sliders document.getElementById('speedSlider').addEventListener('input', updateDisplay); document.getElementById('fadePercentSlider').addEventListener('input', updateDisplay); document.getElementById('fadeFramesSlider').addEventListener('input', updateDisplay); document.getElementById('zoomSlider').addEventListener('input', updateDisplay); document.getElementById('focusSlider').addEventListener('input', updateDisplay); //pide motorSpeed al M7 function updateMotorSpeed() { fetch('/motorSpeed') .then(response => response.json()) .then(data => { document.getElementById('fps').value = data.motorSpeedRead; }) .catch(error => console.error('Error al obtener motorSpeed:', error)); } function updateFramesCount() { fetch('/framesCount') .then(response => response.json()) .then(data => { document.getElementById('frames').value = data.framesCountRead; }) .catch(error => console.error('Error al obtener numero de frames:', error)); } function updatefadePosition() { fetch('/fadePercent') .then(response => response.json()) .then(data => { document.getElementById('fade').value = data.FadePercentRead; }) .catch(error => console.error('Error al obtener fadePercent:', error)); } function updateSensors() { fetch('/sensors') .then(response => response.json()) // Parsear la respuesta como JSON .then(data => { if (data.sensors && Array.isArray(data.sensors)) { const sensorValues = data.sensors; // Asignar los valores a los elementos de la interfaz if (sensorValues.length >= 1) { document.getElementById('fps').value = sensorValues[0]; } if (sensorValues.length >= 2) { document.getElementById('fade').value = sensorValues[1]; } if (sensorValues.length >= 3) { document.getElementById('frames').value = sensorValues[2]; } } else { console.error('Estructura inesperada:', data); } }) .catch(error => console.error('Error al obtener sensores:', error)); } // Llama a updateSensors cada 500ms setInterval(updateSensors, 500); </script> </body> </html> )rawliteral";