filoor cc8972cadc feat(debug): voeg audiotestfunctionaliteit toe aan debugpagina
Een nieuwe sectie voor audiotests is toegevoegd aan de debugpagina om browser (HDMI) en Sonos audio te testen. Drie nieuwe knoppen activeren respectievelijk tests voor browseraudio, Sonosaudio of beide. Bijbehorende JavaScript-functies zijn geïmplementeerd om de tests uit te voeren en statusupdates weer te geven. In pi-setup-desktop.sh worden nu HDMI audio-uitvoer, volume instellingen, en kiosk browseropstartparameters geconfigureerd ter ondersteuning van automatische audiotests en weergave-optimalisaties.
2025-05-28 19:31:47 +02:00

662 lines
21 KiB
HTML

<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<title>Debug - Gebedstijden Tester</title>
<link rel="stylesheet" href="/static/style.css">
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
body {
margin: 0;
padding: 0;
min-height: 100vh;
overflow-x: hidden;
overflow-y: auto;
}
.debug-container {
max-width: 1200px;
margin: 2rem auto;
padding: 2rem;
background: var(--panel-bg);
border-radius: 15px;
border: 1px solid var(--panel-border);
color: var(--text-color);
min-height: calc(100vh - 4rem);
}
.debug-header {
text-align: center;
margin-bottom: 2rem;
}
.debug-header h1 {
color: var(--accent);
font-family: 'Cairo', sans-serif;
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.debug-header p {
color: var(--text-secondary);
font-size: 1.1rem;
}
.debug-grid {
display: flex;
flex-direction: column;
gap: 2rem;
margin-bottom: 2rem;
}
.debug-panel {
background: var(--card-bg);
padding: 1.5rem;
border-radius: 10px;
border: 1px solid var(--border-color);
color: var(--text-color);
}
.debug-panel h3 {
color: var(--accent);
margin-bottom: 1rem;
font-family: 'Cairo', sans-serif;
font-size: 1.3rem;
}
.time-controls {
display: flex;
flex-direction: column;
gap: 1rem;
}
.time-input {
display: flex;
align-items: center;
gap: 1rem;
}
.time-input label {
color: var(--text-color);
font-weight: 600;
}
.time-input input {
padding: 0.5rem;
border: 1px solid var(--border-color);
border-radius: 5px;
background: var(--input-bg);
color: var(--text-color);
font-size: 1.1rem;
width: 120px;
}
.btn {
padding: 0.7rem 1.5rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
margin: 0.2rem;
font-size: 0.9rem;
}
.btn-primary {
background: var(--accent);
color: var(--bg-color);
}
.btn-secondary {
background: var(--text-secondary);
color: var(--bg-color);
}
.btn-danger {
background: #dc3545;
color: white;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
opacity: 0.9;
}
.prayer-times-list {
list-style: none;
padding: 0;
margin: 0;
}
.prayer-times-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.7rem;
margin-bottom: 0.5rem;
background: var(--input-bg);
border-radius: 5px;
border: 1px solid var(--border-color);
color: var(--text-color);
}
.prayer-times-list li.active {
background: rgba(234, 179, 8, 0.2);
border-color: var(--accent);
}
.status-display {
background: var(--input-bg);
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
color: var(--text-color);
border: 1px solid var(--border-color);
}
.quick-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 1rem;
}
.back-link {
display: inline-block;
margin-bottom: 1rem;
color: var(--accent);
text-decoration: none;
font-weight: 600;
}
.back-link:hover {
color: var(--text-color);
}
@media (max-width: 768px) {
.debug-container {
margin: 1rem;
padding: 1rem;
}
.btn {
font-size: 0.8rem;
padding: 0.5rem 1rem;
}
}
</style>
</head>
<body>
<div class="debug-container">
<a href="/" class="back-link">← Terug naar hoofdpagina</a>
<div class="debug-header">
<h1>🔧 Debug Mode</h1>
<p>Test de adhaan functionaliteit door de tijd aan te passen</p>
</div>
<div class="debug-grid">
<div class="debug-panel">
<h3>⏰ Tijd Controles</h3>
<div class="status-display" id="statusDisplay">
Huidige tijd: <span id="currentDebugTime">--:--</span><br>
Volgende gebed: <span id="nextPrayerDebug">--</span><br>
Status: <span id="debugStatus">Normaal</span>
</div>
<div class="time-controls">
<div class="time-input">
<label>Stel tijd in:</label>
<input type="time" id="manualTime" />
<button class="btn btn-primary" onclick="setManualTime()">Zet Tijd</button>
</div>
<div class="quick-actions">
<button class="btn btn-secondary" onclick="adjustTime(-60)">-1 min</button>
<button class="btn btn-secondary" onclick="adjustTime(-10)">-10 sec</button>
<button class="btn btn-secondary" onclick="adjustTime(10)">+10 sec</button>
<button class="btn btn-secondary" onclick="adjustTime(60)">+1 min</button>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="setTimeToNextPrayer(-1)">1 min voor gebed</button>
<button class="btn btn-primary" onclick="setTimeToNextPrayer(0)">Exact gebedstijd</button>
<button class="btn btn-danger" onclick="resetTime()">Reset naar echte tijd</button>
</div>
</div>
</div>
<div class="debug-panel">
<h3>🕌 Gebedstijden Vandaag</h3>
<ul class="prayer-times-list" id="prayerTimesList">
{% for naam, tijd in gebedstijden.items() %}
<li data-prayer="{{ naam }}" data-time="{{ tijd[:5] }}">
<span>{{ naam }}</span>
<span>{{ tijd[:5] }}</span>
<button class="btn btn-secondary" onclick="setTimeToPrayer('{{ tijd[:5] }}', -1)">-1 min</button>
<button class="btn btn-primary" onclick="setTimeToPrayer('{{ tijd[:5] }}', 0)">Nu</button>
</li>
{% endfor %}
</ul>
</div>
</div>
<div class="debug-panel">
<h3>📊 Debug Log</h3>
<div class="status-display" id="debugLog" style="height: 200px; overflow-y: auto;">
Debug log wordt hier weergegeven...<br>
</div>
<button class="btn btn-secondary" onclick="clearLog()">Wis Log</button>
</div>
<div class="debug-panel">
<h3>🔊 Sonos Status</h3>
<div class="status-display" id="sonosStatus" style="height: 150px; overflow-y: auto;">
Sonos status wordt geladen...<br>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="checkSonosStatus()">🔄 Ververs Status</button>
<button class="btn btn-danger" onclick="stopAllSonos()">⏹️ Stop Alle Audio</button>
</div>
</div>
<div class="debug-panel">
<h3>📿 Adzkaar Testing</h3>
<div class="status-display" id="adzkaarStatus" style="height: 100px; overflow-y: auto;">
Status: {% if settings.adzkaar_enabled %}Ingeschakeld{% else %}Uitgeschakeld{% endif %}<br>
Duur: {{ settings.adzkaar_duration or 5 }} minuten<br>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="testAdzkaar()">📿 Test Adzkaar Scherm</button>
<button class="btn btn-secondary" onclick="openAdzkaarDirect()">🔗 Open Adzkaar Direct</button>
</div>
</div>
<div class="debug-panel">
<h3>🎵 Audio Test</h3>
<div class="status-display" id="audioTestStatus" style="height: 100px; overflow-y: auto;">
Test browser audio (HDMI) en Sonos...<br>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="testBrowserAudio()">🔊 Test Browser Audio (HDMI)</button>
<button class="btn btn-secondary" onclick="testSonosAudio()">📻 Test Sonos Audio</button>
<button class="btn btn-success" onclick="testBothAudio()">🎵 Test Beide</button>
</div>
</div>
</div>
<script>
let debugTimeOffset = 0; // Offset in seconden
let isDebugMode = false;
function log(message) {
const logElement = document.getElementById('debugLog');
const timestamp = new Date().toLocaleTimeString();
logElement.innerHTML += `[${timestamp}] ${message}<br>`;
logElement.scrollTop = logElement.scrollHeight;
}
function clearLog() {
document.getElementById('debugLog').innerHTML = 'Debug log gewist...<br>';
}
function getDebugTime() {
const now = new Date();
if (isDebugMode) {
now.setTime(now.getTime() + (debugTimeOffset * 1000));
}
return now;
}
function updateDebugDisplay() {
fetch('/api/debug-time')
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('currentDebugTime').textContent = data.current_time_display;
// Update status
const statusElement = document.getElementById('debugStatus');
statusElement.textContent = data.debug_active ? 'Debug Mode Actief' : 'Normaal';
statusElement.style.color = data.debug_active ? '#ff6b6b' : '#00ff00';
// Check voor gebedstijd
checkPrayerTime(data.current_time_display);
}
})
.catch(error => {
console.log('Fout bij ophalen debug tijd:', error);
// Fallback naar normale tijd
const now = new Date();
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById('currentDebugTime').textContent = timeStr;
document.getElementById('debugStatus').textContent = 'Normaal';
});
}
function checkPrayerTime(currentTime) {
const prayerTimes = {{ gebedstijden | tojson }};
let nextPrayer = null;
let isExactTime = false;
for (const [name, time] of Object.entries(prayerTimes)) {
const prayerTime = time.substring(0, 5);
if (prayerTime === currentTime) {
isExactTime = true;
log(`🕌 ADHAAN TIJD! ${name} (${prayerTime})`);
// Trigger adhaan
triggerAdhaan(name);
}
if (prayerTime > currentTime && !nextPrayer) {
nextPrayer = `${name} (${prayerTime})`;
}
}
if (!nextPrayer) {
// Volgende dag
const firstPrayer = Object.entries(prayerTimes)[0];
nextPrayer = `${firstPrayer[0]} (${firstPrayer[1].substring(0, 5)}) - morgen`;
}
document.getElementById('nextPrayerDebug').textContent = nextPrayer;
// Update active prayer in list
document.querySelectorAll('.prayer-times-list li').forEach(li => {
li.classList.remove('active');
if (li.dataset.time === currentTime) {
li.classList.add('active');
}
});
}
function triggerAdhaan(prayerName) {
// Speel adhaan af
const audio = document.getElementById('adhanAudio');
if (audio) {
audio.play().catch(e => log(`Fout bij afspelen audio: ${e.message}`));
}
// Verstuur naar Sonos (als niet gemute)
fetch('/api/debug-adhaan', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prayer: prayerName, time: getDebugTime().toLocaleTimeString() })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`✅ Adhaan verzonden naar Sonos voor ${prayerName}`);
} else {
log(`❌ Fout bij Sonos: ${data.error}`);
}
})
.catch(e => log(`❌ Netwerk fout: ${e.message}`));
}
function setManualTime() {
const timeInput = document.getElementById('manualTime');
if (!timeInput.value) return;
const [hours, minutes] = timeInput.value.split(':');
const now = new Date();
const targetTime = new Date();
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
const offsetSeconds = Math.floor((targetTime - now) / 1000);
fetch('/api/debug-time', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'set_offset', offset: offsetSeconds })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`${data.message}`);
updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
}
function adjustTime(seconds) {
fetch('/api/debug-time', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'adjust', seconds: seconds })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`${data.message}`);
updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
}
function setTimeToPrayer(prayerTime, offsetMinutes) {
const [hours, minutes] = prayerTime.split(':');
const now = new Date();
const targetTime = new Date();
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
targetTime.setTime(targetTime.getTime() + (offsetMinutes * 60 * 1000));
const offsetSeconds = Math.floor((targetTime - now) / 1000);
fetch('/api/debug-time', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'set_offset', offset: offsetSeconds })
})
.then(response => response.json())
.then(data => {
if (data.success) {
const offsetText = offsetMinutes === 0 ? 'exact' : `${offsetMinutes} min ervoor`;
log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`);
updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
}
function setTimeToNextPrayer(offsetMinutes) {
const prayerTimes = {{ gebedstijden | tojson }};
const currentTime = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
for (const [name, time] of Object.entries(prayerTimes)) {
const prayerTime = time.substring(0, 5);
if (prayerTime > currentTime) {
setTimeToPrayer(prayerTime, offsetMinutes);
return;
}
}
// Als geen gebed meer vandaag, neem eerste van morgen
const firstPrayer = Object.entries(prayerTimes)[0];
setTimeToPrayer(firstPrayer[1].substring(0, 5), offsetMinutes);
}
function resetTime() {
fetch('/api/debug-time', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'reset' })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`🔄 ${data.message}`);
updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
}
function checkSonosStatus() {
log('🔄 Sonos status controleren...');
fetch('/api/sonos-status')
.then(response => response.json())
.then(data => {
const statusElement = document.getElementById('sonosStatus');
if (data.success) {
let statusHtml = `Sonos API: ${data.api_ip}<br><br>`;
for (const [zone, info] of Object.entries(data.zones)) {
const statusColor = info.status === 'online' ? '#00ff00' : '#ff6b6b';
statusHtml += `<span style="color: ${statusColor}">● ${zone}</span><br>`;
statusHtml += ` Status: ${info.status}<br>`;
if (info.status === 'online') {
statusHtml += ` Afspelen: ${info.playbackState}<br>`;
statusHtml += ` Track: ${info.currentTrack}<br>`;
statusHtml += ` Volume: ${info.volume}%<br>`;
} else if (info.error) {
statusHtml += ` Fout: ${info.error}<br>`;
}
statusHtml += '<br>';
}
statusElement.innerHTML = statusHtml;
log('✅ Sonos status bijgewerkt');
} else {
statusElement.innerHTML = `❌ Fout: ${data.error}`;
log(`❌ Sonos status fout: ${data.error}`);
}
})
.catch(error => {
log(`❌ Netwerk fout bij Sonos status: ${error.message}`);
document.getElementById('sonosStatus').innerHTML = `❌ Netwerk fout: ${error.message}`;
});
}
function stopAllSonos() {
log('⏹️ Alle Sonos audio stoppen...');
fetch('/api/sonos-stop', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`${data.message}`);
// Ververs status na stoppen
setTimeout(checkSonosStatus, 1000);
} else {
log(`❌ Fout bij stoppen: ${data.error}`);
}
})
.catch(error => {
log(`❌ Netwerk fout bij stoppen: ${error.message}`);
});
}
function testAdzkaar() {
log('📿 Adzkaar scherm testen...');
fetch('/api/trigger-adzkaar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`${data.message}`);
// Open Adzkaar scherm in nieuw venster/tab
window.open(data.url, '_blank', 'fullscreen=yes,scrollbars=no,resizable=no');
} else {
log(`❌ Adzkaar fout: ${data.error}`);
document.getElementById('adzkaarStatus').innerHTML += `❌ Fout: ${data.error}<br>`;
}
})
.catch(error => {
log(`❌ Netwerk fout bij Adzkaar test: ${error.message}`);
});
}
function openAdzkaarDirect() {
log('🔗 Adzkaar scherm direct openen...');
window.open('/adzkaar', '_blank', 'fullscreen=yes,scrollbars=no,resizable=no');
}
function testBrowserAudio() {
log('🔊 Test browser audio (HDMI)...');
const audio = document.getElementById('adhanAudio');
if (audio) {
audio.play()
.then(() => {
log('✅ Browser audio gestart (HDMI)');
document.getElementById('audioTestStatus').innerHTML += '✅ Browser audio werkt<br>';
})
.catch(error => {
log(`❌ Browser audio fout: ${error.message}`);
document.getElementById('audioTestStatus').innerHTML += `❌ Browser audio fout: ${error.message}<br>`;
});
} else {
log('❌ Audio element niet gevonden');
document.getElementById('audioTestStatus').innerHTML += '❌ Audio element niet gevonden<br>';
}
}
function testSonosAudio() {
log('📻 Test Sonos audio...');
fetch('/api/debug-adhaan', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prayer: 'Test', time: 'Nu' })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`✅ Sonos audio test: ${data.message}`);
document.getElementById('audioTestStatus').innerHTML += `✅ Sonos: ${data.message}<br>`;
} else {
log(`❌ Sonos audio fout: ${data.error}`);
document.getElementById('audioTestStatus').innerHTML += `❌ Sonos: ${data.error}<br>`;
}
})
.catch(error => {
log(`❌ Sonos test netwerk fout: ${error.message}`);
document.getElementById('audioTestStatus').innerHTML += `❌ Sonos netwerk fout: ${error.message}<br>`;
});
}
function testBothAudio() {
log('🎵 Test beide audio systemen...');
document.getElementById('audioTestStatus').innerHTML = 'Test beide audio systemen...<br>';
// Test browser audio eerst
testBrowserAudio();
// Test Sonos audio na 2 seconden
setTimeout(() => {
testSonosAudio();
}, 2000);
}
// Update elke seconde
setInterval(updateDebugDisplay, 1000);
// Initiële updates
updateDebugDisplay();
checkSonosStatus();
log('🔧 Debug mode gestart');
</script>
<!-- Hidden audio element for testing -->
<audio id="adhanAudio" src="/static/clips/{{ settings['audio_clip'] }}" preload="auto"></audio>
</body>
</html>