Analogue_Hyperlapse_Camera/CraterLab_camera/include/interface.html
2025-03-13 18:26:32 +01:00

593 lines
18 KiB
HTML

// 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";