feat(debug): debug mode tijdsynchronisatie toegevoegd

De commit introduceert een debug tijdsynchronisatie tussen de cron script, de hoofdpagina en de Flask API. Deze functies maken het mogelijk om de huidige tijd te simuleren met een instelbare offset voor testdoeleinden. Het volume en de gebedstijden passen zich nu aan op basis van deze debug tijd indien actief. Debugger gebruikers kunnen via de nieuwe '/api/debug-time' endpoint de tijd aanpassen. De wijzigingen verbeteren de testbaarheid van de applicatie en zorgen ervoor dat gebedsafroepen en volumebepaling correct functioneren onder simulatieomstandigheden.
This commit is contained in:
filoor 2025-05-28 18:59:15 +02:00
parent f3cbd6e910
commit c212ec4987
8 changed files with 806 additions and 120 deletions

View File

@ -4,9 +4,10 @@ import time
SETTINGS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settings.json')
VUMG_API = 'https://www.vumg.nl/?rest_route=/dpt/v1/prayertime&filter=today'
SONOS_API_IP = '192.168.0.114' # Pas aan indien nodig
SONOS_API_IP = '192.168.0.114' # IP van Raspberry Pi waar Sonos API draait
LOG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'adhan_cron.log')
LAST_PLAYED_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'last_played.json')
FLASK_API_URL = 'http://localhost:80' # Flask app URL
def logregel(message):
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
@ -15,13 +16,32 @@ def logregel(message):
with open(LOG_PATH, 'a') as log:
log.write(log_message + '\n')
def get_current_time():
"""Haal de huidige tijd op, gebruik debug tijd als actief"""
try:
# Probeer debug tijd API
response = requests.get(f'{FLASK_API_URL}/api/debug-time', timeout=3)
if response.status_code == 200:
data = response.json()
if data.get('success') and data.get('debug_active'):
debug_time = data.get('current_time_display', '')
logregel(f"🔧 CRON gebruikt debug tijd: {debug_time}")
return debug_time
except Exception as e:
logregel(f"Debug tijd API niet beschikbaar: {e}")
# Fallback naar normale tijd
normal_time = datetime.now().strftime('%H:%M')
return normal_time
def get_current_volume(settings):
"""Bepaal het juiste volume op basis van de huidige tijd"""
# Fallback naar oude volume als nieuwe instellingen niet bestaan
if 'volume_day' not in settings or 'volume_night' not in settings:
return settings.get('volume', 30)
current_time = datetime.now().strftime('%H:%M')
# Gebruik debug tijd als beschikbaar
current_time = get_current_time()
night_start = settings.get('night_start', '20:00')
day_start = settings.get('day_start', '07:00')
@ -38,11 +58,11 @@ def get_current_volume(settings):
if is_night:
volume = settings.get('volume_night', settings.get('volume', 30) // 2)
logregel(f"🌙 Avond volume gebruikt: {volume}")
logregel(f"🌙 Avond volume gebruikt: {volume} (tijd: {current_time})")
return volume
else:
volume = settings.get('volume_day', settings.get('volume', 30))
logregel(f"☀️ Dag volume gebruikt: {volume}")
logregel(f"☀️ Dag volume gebruikt: {volume} (tijd: {current_time})")
return volume
def apply_prayer_offsets(gebedstijden, settings):
@ -145,7 +165,8 @@ def play_sonos_clip(zone, audio_clip, volume, prayer_name):
logregel(f"❌ FOUT Sonos {zone} {prayer_name}: {e}")
return False
now = datetime.now().strftime('%H:%M')
# Gebruik debug tijd als beschikbaar
now = get_current_time()
logregel(f"CRON gestart, huidige tijd: {now}")
# Laad settings

View File

@ -22,7 +22,11 @@ SETTINGS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settin
HADITHS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'hadiths.json')
VUMG_API = 'https://www.vumg.nl/?rest_route=/dpt/v1/prayertime&filter=today'
CLIPS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'clips')
SONOS_API_IP = '192.168.0.114' # IP van host waar Sonos API draait
SONOS_API_IP = '192.168.0.114' # IP van Raspberry Pi waar Sonos API draait
# Globale variabelen
debug_time_offset = 0 # Offset in seconden voor debug mode
debug_mode_active = False
def fetch_weather_data():
"""Haalt weersinformatie op voor de geconfigureerde locatie"""
@ -77,13 +81,20 @@ def load_settings():
def get_current_volume(settings):
"""Bepaal het juiste volume op basis van de huidige tijd"""
from datetime import datetime
from datetime import datetime, timedelta
# Fallback naar oude volume als nieuwe instellingen niet bestaan
if 'volume_day' not in settings or 'volume_night' not in settings:
return settings.get('volume', 30)
current_time = datetime.now().strftime('%H:%M')
# Gebruik debug tijd als actief
global debug_mode_active, debug_time_offset
if debug_mode_active:
current_time = (datetime.now() + timedelta(seconds=debug_time_offset)).strftime('%H:%M')
print(f"🔧 Volume bepaling gebruikt debug tijd: {current_time}")
else:
current_time = datetime.now().strftime('%H:%M')
night_start = settings.get('night_start', '20:00')
day_start = settings.get('day_start', '07:00')
@ -99,9 +110,13 @@ def get_current_volume(settings):
is_night = current_minutes >= night_minutes and current_minutes < day_minutes
if is_night:
return settings.get('volume_night', settings.get('volume', 30) // 2)
volume = settings.get('volume_night', settings.get('volume', 30) // 2)
print(f"🌙 Avond volume gebruikt: {volume} (tijd: {current_time})")
return volume
else:
return settings.get('volume_day', settings.get('volume', 30))
volume = settings.get('volume_day', settings.get('volume', 30))
print(f"☀️ Dag volume gebruikt: {volume} (tijd: {current_time})")
return volume
def apply_prayer_offsets(gebedstijden, settings):
"""Pas offsets toe op gebedstijden"""
@ -644,5 +659,73 @@ def trigger_adzkaar():
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/debug-time', methods=['GET', 'POST'])
def debug_time():
"""API endpoint voor debug tijd beheer"""
global debug_time_offset, debug_mode_active
if flask_request.method == 'POST':
# Check of debug mode is ingeschakeld voor POST requests
settings = load_settings()
if not settings.get('debug_mode', False):
return jsonify({'success': False, 'error': 'Debug mode is niet ingeschakeld'}), 403
try:
data = flask_request.get_json()
action = data.get('action')
if action == 'set_offset':
debug_time_offset = data.get('offset', 0)
debug_mode_active = True
return jsonify({
'success': True,
'message': f'Debug tijd offset ingesteld op {debug_time_offset} seconden',
'offset': debug_time_offset,
'debug_active': debug_mode_active
})
elif action == 'reset':
debug_time_offset = 0
debug_mode_active = False
return jsonify({
'success': True,
'message': 'Debug tijd gereset naar echte tijd',
'offset': debug_time_offset,
'debug_active': debug_mode_active
})
elif action == 'adjust':
adjustment = data.get('seconds', 0)
debug_time_offset += adjustment
debug_mode_active = True
return jsonify({
'success': True,
'message': f'Debug tijd aangepast met {adjustment} seconden',
'offset': debug_time_offset,
'debug_active': debug_mode_active
})
else:
return jsonify({'success': False, 'error': 'Onbekende actie'}), 400
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
else: # GET request - altijd beschikbaar voor cron script
from datetime import datetime, timedelta
current_time = datetime.now()
if debug_mode_active:
current_time += timedelta(seconds=debug_time_offset)
return jsonify({
'success': True,
'current_time': current_time.strftime('%H:%M:%S'),
'current_time_display': current_time.strftime('%H:%M'),
'offset': debug_time_offset,
'debug_active': debug_mode_active,
'real_time': datetime.now().strftime('%H:%M:%S')
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)

View File

@ -12,3 +12,4 @@ Mon May 26 18:17:57 CEST 2025: Tijdzone probleem opgelost - Container gebruikt n
2025-05-28 03:37:57 - Light theme kleuren gerepareerd: teksten nu zichtbaar in light mode, accent kleuren aangepast voor betere contrast
2025-05-28 03:49:24 - Adzkaar fullscreen functionaliteit geïmplementeerd: nieuwe /adzkaar route, instellingen, debug knoppen, automatische trigger na gebedstijden, Nederlandse/Arabische dhikr content
2025-05-28 03:55:38 - Adzkaar scherm verbeterd naar kaart-voor-kaart weergave met navigatie knoppen en toetsenbord besturing
Wed May 28 14:09:12 CEST 2025: Sonos debug tijd synchronisatie geïmplementeerd - get_current_volume functie en cron script gebruiken nu debug tijd API, volume bepaling werkt correct in debug mode

View File

@ -1,10 +1,31 @@
function updateCurrentTime() {
const now = new Date();
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById("current-time").textContent = timeStr;
// Check eerst of debug mode actief is
fetch('/api/debug-time')
.then(response => response.json())
.then(data => {
if (data.success && data.debug_active) {
// Gebruik debug tijd
document.getElementById("current-time").textContent = data.current_time_display;
console.log(`🔧 Debug tijd actief: ${data.current_time_display} (offset: ${data.offset}s)`);
} else {
// Gebruik normale tijd
const now = new Date();
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById("current-time").textContent = timeStr;
}
// Update datum informatie elke minuut
updateDateInfo();
// Update datum informatie elke minuut
updateDateInfo();
})
.catch(error => {
// Fallback naar normale tijd bij fout
const now = new Date();
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById("current-time").textContent = timeStr;
// Update datum informatie elke minuut
updateDateInfo();
});
}
function updateDateInfo() {
@ -33,28 +54,69 @@ let isNextDayPrayer = false;
function startCountdowns(times, names) {
prayerTimes = times;
prayerNames = names;
const nextPrayer = getNextPrayer();
currentPrayerIndex = nextPrayer.index;
isNextDayPrayer = nextPrayer.isNextDay;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
getNextPrayer().then(nextPrayer => {
currentPrayerIndex = nextPrayer.index;
isNextDayPrayer = nextPrayer.isNextDay;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
}).catch(error => {
console.log('Fout bij bepalen volgende gebed:', error);
// Fallback
currentPrayerIndex = 0;
isNextDayPrayer = false;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
});
}
function getNextPrayer() {
const now = new Date();
const currentTime = now.getHours() * 60 + now.getMinutes(); // Huidige tijd in minuten
// Gebruik debug tijd als actief
return fetch('/api/debug-time')
.then(response => response.json())
.then(data => {
let currentTime;
// Zoek naar volgende gebed vandaag
for (let i = 0; i < prayerTimes.length; i++) {
const [h, m] = prayerTimes[i].split(":");
const prayerTimeMinutes = parseInt(h) * 60 + parseInt(m);
if (data.success && data.debug_active) {
// Gebruik debug tijd
const debugTime = data.current_time_display;
const [h, m] = debugTime.split(":");
currentTime = parseInt(h) * 60 + parseInt(m);
console.log(`🔧 Debug tijd gebruikt voor countdown: ${debugTime}`);
} else {
// Gebruik normale tijd
const now = new Date();
currentTime = now.getHours() * 60 + now.getMinutes();
}
if (prayerTimeMinutes > currentTime) {
return { index: i, isNextDay: false };
}
}
// Zoek naar volgende gebed vandaag
for (let i = 0; i < prayerTimes.length; i++) {
const [h, m] = prayerTimes[i].split(":");
const prayerTimeMinutes = parseInt(h) * 60 + parseInt(m);
// Alle gebeden van vandaag zijn voorbij, volgende is eerste gebed van morgen
return { index: 0, isNextDay: true };
if (prayerTimeMinutes > currentTime) {
return { index: i, isNextDay: false };
}
}
// Alle gebeden van vandaag zijn voorbij, volgende is eerste gebed van morgen
return { index: 0, isNextDay: true };
})
.catch(error => {
console.log('Fout bij ophalen debug tijd, gebruik normale tijd:', error);
// Fallback naar normale tijd
const now = new Date();
const currentTime = now.getHours() * 60 + now.getMinutes();
for (let i = 0; i < prayerTimes.length; i++) {
const [h, m] = prayerTimes[i].split(":");
const prayerTimeMinutes = parseInt(h) * 60 + parseInt(m);
if (prayerTimeMinutes > currentTime) {
return { index: i, isNextDay: false };
}
}
return { index: 0, isNextDay: true };
});
}
function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
@ -74,55 +136,119 @@ function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
document.querySelector('.huidig-gebed-bottom .naam').textContent = displayName;
function update() {
const now = new Date();
let diff = Math.floor((target - now) / 1000);
// Gebruik debug tijd als actief
fetch('/api/debug-time')
.then(response => response.json())
.then(data => {
let now;
if (diff <= 0) {
// Speel adhaan af via browser
const audio = document.getElementById('adhanAudio');
if (audio) audio.play();
// Trigger Adzkaar scherm na 3 seconden (geef adhaan tijd om te starten)
setTimeout(() => {
triggerAdzkaarScreen(displayName);
}, 3000);
// Ga naar volgende gebed
if (isNextDayPrayer) {
// We waren aan het wachten op het eerste gebed van de nieuwe dag
// Nu gaan we naar het tweede gebed van vandaag (nieuwe dag)
currentPrayerIndex = 1;
isNextDayPrayer = false;
if (currentPrayerIndex < prayerTimes.length) {
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], false);
if (data.success && data.debug_active) {
// Gebruik debug tijd
const debugTime = data.current_time;
const [h, m, s] = debugTime.split(":");
now = new Date();
now.setHours(parseInt(h), parseInt(m), parseInt(s), 0);
} else {
// Dit zou niet moeten gebeuren, maar veiligheidshalve
currentPrayerIndex = 0;
isNextDayPrayer = true;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], true);
}
} else {
// Normaal doorgang naar volgende gebed
currentPrayerIndex++;
if (currentPrayerIndex >= prayerTimes.length) {
// Alle gebeden van vandaag zijn klaar, ga naar eerste gebed van morgen
currentPrayerIndex = 0;
isNextDayPrayer = true;
// Gebruik normale tijd
now = new Date();
}
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
}
return;
}
let diff = Math.floor((target - now) / 1000);
// Toon countdown
const h = String(Math.floor(diff / 3600)).padStart(2, '0');
const m = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
const s = String(diff % 60).padStart(2, '0');
if (diff <= 0) {
// Speel adhaan af via browser
const audio = document.getElementById('adhanAudio');
if (audio) audio.play();
document.getElementById("countdown").textContent = `${h}:${m}:${s}`;
// Trigger Adzkaar scherm na 3 seconden (geef adhaan tijd om te starten)
setTimeout(() => {
triggerAdzkaarScreen(displayName);
}, 3000);
// Ga naar volgende gebed
if (isNextDayPrayer) {
// We waren aan het wachten op het eerste gebed van de nieuwe dag
// Nu gaan we naar het tweede gebed van vandaag (nieuwe dag)
currentPrayerIndex = 1;
isNextDayPrayer = false;
if (currentPrayerIndex < prayerTimes.length) {
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], false);
} else {
// Dit zou niet moeten gebeuren, maar veiligheidshalve
currentPrayerIndex = 0;
isNextDayPrayer = true;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], true);
}
} else {
// Normaal doorgang naar volgende gebed
currentPrayerIndex++;
if (currentPrayerIndex >= prayerTimes.length) {
// Alle gebeden van vandaag zijn klaar, ga naar eerste gebed van morgen
currentPrayerIndex = 0;
isNextDayPrayer = true;
}
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
}
return;
}
// Toon countdown
const h = String(Math.floor(diff / 3600)).padStart(2, '0');
const m = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
const s = String(diff % 60).padStart(2, '0');
document.getElementById("countdown").textContent = `${h}:${m}:${s}`;
})
.catch(error => {
// Fallback naar normale tijd
const now = new Date();
let diff = Math.floor((target - now) / 1000);
if (diff <= 0) {
// Speel adhaan af via browser
const audio = document.getElementById('adhanAudio');
if (audio) audio.play();
// Trigger Adzkaar scherm na 3 seconden (geef adhaan tijd om te starten)
setTimeout(() => {
triggerAdzkaarScreen(displayName);
}, 3000);
// Ga naar volgende gebed
if (isNextDayPrayer) {
currentPrayerIndex = 1;
isNextDayPrayer = false;
if (currentPrayerIndex < prayerTimes.length) {
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], false);
} else {
currentPrayerIndex = 0;
isNextDayPrayer = true;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], true);
}
} else {
currentPrayerIndex++;
if (currentPrayerIndex >= prayerTimes.length) {
currentPrayerIndex = 0;
isNextDayPrayer = true;
}
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
}
return;
}
// Toon countdown
const h = String(Math.floor(diff / 3600)).padStart(2, '0');
const m = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
const s = String(diff % 60).padStart(2, '0');
document.getElementById("countdown").textContent = `${h}:${m}:${s}`;
});
}
update();
@ -159,18 +285,13 @@ function triggerAdzkaarScreen(prayerName) {
if (data.success) {
console.log(`📿 Adzkaar scherm wordt getoond na ${prayerName}`);
// Open Adzkaar scherm in fullscreen
// In kiosk mode proberen we een nieuw venster te openen
const adzkaarWindow = window.open(
data.url,
'adzkaar',
'fullscreen=yes,scrollbars=no,resizable=no,toolbar=no,menubar=no,status=no'
);
// Als window.open niet werkt (bijv. popup blocker), navigeer naar de pagina
if (!adzkaarWindow) {
console.log('📿 Popup geblokkeerd, navigeren naar Adzkaar pagina...');
window.location.href = data.url;
// Toon Adzkaar modal in plaats van nieuwe pagina
if (window.showAdzkaarModal) {
// Gebruik de duur uit de API response of standaard 5 minuten
const durationMinutes = data.duration_minutes || 5;
window.showAdzkaarModal(durationMinutes);
} else {
console.log('📿 Adzkaar modal functie niet beschikbaar');
}
} else {
console.log(`📿 Adzkaar niet getoond: ${data.error}`);

View File

@ -1400,3 +1400,211 @@ html.dark .hadith-center {
max-width: 300px;
}
}
/* Adzkaar Modal Styles */
.adzkaar-modal {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.95);
z-index: 10000;
display: flex;
justify-content: center;
align-items: center;
}
.adzkaar-container {
position: relative;
width: 100vw;
height: 100vh;
background: var(--primary-gradient);
color: var(--white);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 2rem;
box-sizing: border-box;
overflow-y: auto;
}
.adzkaar-header {
text-align: center;
margin-bottom: 3rem;
}
.adzkaar-title {
font-family: 'Cairo', sans-serif;
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
text-shadow: var(--text-shadow);
}
.adzkaar-subtitle {
font-family: 'Lato', sans-serif;
font-size: 1.5rem;
opacity: 0.9;
font-weight: 300;
}
.adzkaar-content {
max-width: 900px;
width: 100%;
text-align: center;
}
.dhikr-container {
position: relative;
min-height: 400px;
display: flex;
justify-content: center;
align-items: center;
}
.dhikr-item {
display: none;
background: var(--white-10);
border-radius: 15px;
padding: 2rem;
backdrop-filter: blur(10px);
border: 1px solid var(--white-20);
transition: all 0.3s ease;
max-width: 800px;
width: 100%;
text-align: center;
}
.dhikr-item.active {
display: block;
background: var(--white-15);
border: 1px solid var(--white-30);
transform: scale(1.02);
}
.dhikr-arabic {
font-family: 'Cairo', sans-serif;
font-size: 2.2rem;
font-weight: 600;
margin-bottom: 1rem;
direction: rtl;
line-height: 1.6;
color: var(--white);
}
.dhikr-transliteration {
font-family: 'Lato', sans-serif;
font-size: 1.3rem;
font-style: italic;
margin-bottom: 1rem;
opacity: 0.8;
color: var(--text-muted-dark);
}
.dhikr-translation {
font-family: 'Lato', sans-serif;
font-size: 1.2rem;
color: var(--text-muted-dark);
line-height: 1.5;
}
.dhikr-count {
display: inline-block;
background: var(--white-20);
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.9rem;
margin-top: 1rem;
font-weight: 600;
}
.countdown-timer {
position: fixed;
top: 2rem;
right: 2rem;
background: var(--black-50);
padding: 1rem 1.5rem;
border-radius: 10px;
font-family: 'Cairo', sans-serif;
font-size: 1.2rem;
font-weight: 600;
}
.close-button {
position: fixed;
top: 2rem;
left: 2rem;
background: var(--white-20);
border: none;
color: var(--white);
padding: 0.8rem;
border-radius: 50%;
cursor: pointer;
font-size: 1.5rem;
transition: background 0.3s ease;
}
.close-button:hover {
background: var(--white-30);
}
.dhikr-navigation {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 2rem;
}
.nav-btn {
background: var(--white-20);
border: none;
color: var(--white);
font-size: 2rem;
cursor: pointer;
margin: 0 2rem;
padding: 1rem;
border-radius: 50%;
transition: all 0.3s ease;
}
.nav-btn:hover:not(:disabled) {
background: var(--white-30);
transform: scale(1.1);
}
.nav-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.dhikr-counter {
font-size: 1.3rem;
font-weight: 600;
background: var(--black-30);
padding: 0.5rem 1rem;
border-radius: 20px;
}
@media (max-width: 768px) {
.adzkaar-title {
font-size: 2.5rem;
}
.dhikr-arabic {
font-size: 1.8rem;
}
.dhikr-transliteration {
font-size: 1.1rem;
}
.dhikr-translation {
font-size: 1rem;
}
.dhikr-item {
padding: 1.5rem;
}
}

View File

@ -302,17 +302,29 @@
}
function updateDebugDisplay() {
const debugTime = getDebugTime();
const timeStr = debugTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById('currentDebugTime').textContent = timeStr;
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 = isDebugMode ? 'Debug Mode Actief' : 'Normaal';
statusElement.style.color = isDebugMode ? '#ff6b6b' : '#00ff00';
// 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(timeStr);
// 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) {
@ -384,20 +396,41 @@
const targetTime = new Date();
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
debugTimeOffset = Math.floor((targetTime - now) / 1000);
isDebugMode = true;
const offsetSeconds = Math.floor((targetTime - now) / 1000);
log(`⏰ Tijd handmatig ingesteld op ${timeInput.value}`);
updateDebugDisplay();
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) {
debugTimeOffset += seconds;
isDebugMode = true;
const sign = seconds > 0 ? '+' : '';
log(`⏰ Tijd aangepast: ${sign}${seconds} seconden`);
updateDebugDisplay();
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) {
@ -407,12 +440,24 @@
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
targetTime.setTime(targetTime.getTime() + (offsetMinutes * 60 * 1000));
debugTimeOffset = Math.floor((targetTime - now) / 1000);
isDebugMode = true;
const offsetSeconds = Math.floor((targetTime - now) / 1000);
const offsetText = offsetMinutes === 0 ? 'exact' : `${offsetMinutes} min ervoor`;
log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`);
updateDebugDisplay();
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) {
@ -433,10 +478,21 @@
}
function resetTime() {
debugTimeOffset = 0;
isDebugMode = false;
log(`🔄 Tijd gereset naar echte tijd`);
updateDebugDisplay();
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() {

View File

@ -85,6 +85,84 @@
<audio id="adhanAudio" src="/static/clips/{{ settings['audio_clip'] }}" preload="auto"></audio>
<!-- Adzkaar Modal -->
<div id="adzkaarModal" class="adzkaar-modal" style="display: none;">
<div class="adzkaar-container">
<button class="close-button" onclick="closeAdzkaar()" title="Sluiten">
<span class="material-icons">close</span>
</button>
<div class="countdown-timer" id="countdownTimer">
5:00
</div>
<div class="adzkaar-header">
<h1 class="adzkaar-title">أذكار بعد الصلاة</h1>
<p class="adzkaar-subtitle">Adzkaar na het Gebed</p>
</div>
<div class="adzkaar-content">
<div class="dhikr-navigation">
<button class="nav-btn" id="prevBtn" onclick="previousDhikr()" disabled>
<span class="material-icons">arrow_back</span>
</button>
<div class="dhikr-counter">
<span id="currentDhikr">1</span> / <span id="totalDhikr">6</span>
</div>
<button class="nav-btn" id="nextBtn" onclick="nextDhikr()">
<span class="material-icons">arrow_forward</span>
</button>
</div>
<div class="dhikr-container" id="dhikrContainer">
<div class="dhikr-item active" data-index="0">
<div class="dhikr-arabic">أَسْتَغْفِرُ اللَّهَ</div>
<div class="dhikr-transliteration">Astaghfirullah</div>
<div class="dhikr-translation">Ik vraag Allah om vergeving</div>
<div class="dhikr-count">3x</div>
</div>
<div class="dhikr-item" data-index="1">
<div class="dhikr-arabic">اللَّهُمَّ أَنْتَ السَّلاَمُ وَمِنْكَ السَّلاَمُ تَبَارَكْتَ يَا ذَا الْجَلاَلِ وَالإِكْرَامِ</div>
<div class="dhikr-transliteration">Allahumma anta as-salamu wa minka as-salamu, tabarakta ya dhal-jalali wal-ikram</div>
<div class="dhikr-translation">O Allah, U bent de Vrede en van U komt de vrede. Gezegend bent U, O Bezitter van Majesteit en Eer</div>
<div class="dhikr-count">1x</div>
</div>
<div class="dhikr-item" data-index="2">
<div class="dhikr-arabic">سُبْحَانَ اللَّهِ</div>
<div class="dhikr-transliteration">Subhan Allah</div>
<div class="dhikr-translation">Glorie zij Allah</div>
<div class="dhikr-count">33x</div>
</div>
<div class="dhikr-item" data-index="3">
<div class="dhikr-arabic">الْحَمْدُ لِلَّهِ</div>
<div class="dhikr-transliteration">Alhamdulillah</div>
<div class="dhikr-translation">Alle lof zij Allah</div>
<div class="dhikr-count">33x</div>
</div>
<div class="dhikr-item" data-index="4">
<div class="dhikr-arabic">اللَّهُ أَكْبَرُ</div>
<div class="dhikr-transliteration">Allahu Akbar</div>
<div class="dhikr-translation">Allah is de Grootste</div>
<div class="dhikr-count">34x</div>
</div>
<div class="dhikr-item" data-index="5">
<div class="dhikr-arabic">لاَ إِلَهَ إِلاَّ اللَّهُ وَحْدَهُ لاَ شَرِيكَ لَهُ لَهُ الْمُلْكُ وَلَهُ الْحَمْدُ وَهُوَ عَلَى كُلِّ شَيْءٍ قَدِيرٌ</div>
<div class="dhikr-transliteration">La ilaha illa Allah wahdahu la sharika lah, lahu al-mulku wa lahu al-hamdu wa huwa 'ala kulli shay'in qadir</div>
<div class="dhikr-translation">Er is geen god behalve Allah alleen, Hij heeft geen partner. Aan Hem behoort de heerschappij en aan Hem behoort alle lof, en Hij heeft macht over alle dingen</div>
<div class="dhikr-count">1x</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Prayer times data from server
window.prayerTimes = [
@ -181,6 +259,121 @@
}
document.getElementById('muteBtn').addEventListener('click', toggleMute);
setMuteIcon();
// Adzkaar Modal Functionaliteit
let countdownSeconds = 5 * 60; // 5 minuten standaard
let countdownInterval;
let currentDhikrIndex = 0;
const totalDhikrs = 6;
let autoSwitchInterval;
function showAdzkaarModal(durationMinutes = 5) {
countdownSeconds = durationMinutes * 60;
currentDhikrIndex = 0;
// Toon modal
document.getElementById('adzkaarModal').style.display = 'flex';
// Reset dhikr display
showDhikr(0);
// Start countdown
countdownInterval = setInterval(updateAdzkaarCountdown, 1000);
updateAdzkaarCountdown();
// Start automatische wissel elke 30 seconden
autoSwitchInterval = setInterval(autoSwitchDhikr, 30000);
// Auto-close na ingestelde tijd
setTimeout(closeAdzkaar, countdownSeconds * 1000);
}
function updateAdzkaarCountdown() {
const minutes = Math.floor(countdownSeconds / 60);
const seconds = countdownSeconds % 60;
const display = `${minutes}:${seconds.toString().padStart(2, '0')}`;
document.getElementById('countdownTimer').textContent = display;
if (countdownSeconds <= 0) {
closeAdzkaar();
return;
}
countdownSeconds--;
}
function closeAdzkaar() {
clearInterval(countdownInterval);
clearInterval(autoSwitchInterval);
document.getElementById('adzkaarModal').style.display = 'none';
}
function showDhikr(index) {
// Verberg alle dhikr items
document.querySelectorAll('.dhikr-item').forEach(item => {
item.classList.remove('active');
});
// Toon de geselecteerde dhikr
const targetDhikr = document.querySelector(`[data-index="${index}"]`);
if (targetDhikr) {
targetDhikr.classList.add('active');
}
// Update counter
document.getElementById('currentDhikr').textContent = index + 1;
// Update navigation buttons
document.getElementById('prevBtn').disabled = index === 0;
document.getElementById('nextBtn').disabled = index === totalDhikrs - 1;
}
function nextDhikr() {
if (currentDhikrIndex < totalDhikrs - 1) {
currentDhikrIndex++;
showDhikr(currentDhikrIndex);
}
}
function previousDhikr() {
if (currentDhikrIndex > 0) {
currentDhikrIndex--;
showDhikr(currentDhikrIndex);
}
}
function autoSwitchDhikr() {
if (currentDhikrIndex < totalDhikrs - 1) {
currentDhikrIndex++;
showDhikr(currentDhikrIndex);
} else {
// Als we bij de laatste dhikr zijn, begin opnieuw
currentDhikrIndex = 0;
showDhikr(currentDhikrIndex);
}
}
// Keyboard navigation voor modal
document.addEventListener('keydown', function(event) {
const modal = document.getElementById('adzkaarModal');
if (modal.style.display === 'flex') {
if (event.key === 'ArrowRight' || event.key === ' ') {
event.preventDefault();
nextDhikr();
} else if (event.key === 'ArrowLeft') {
event.preventDefault();
previousDhikr();
} else if (event.key === 'Escape') {
closeAdzkaar();
}
}
});
// Maak functies globaal beschikbaar
window.showAdzkaarModal = showAdzkaarModal;
window.closeAdzkaar = closeAdzkaar;
window.nextDhikr = nextDhikr;
window.previousDhikr = previousDhikr;
</script>
</body>
</html>

3
done
View File

@ -62,3 +62,6 @@ Wed May 28 08:02:50 CEST 2025: Countdown gerepareerd - JavaScript aangepast om h
Wed May 28 08:35:42 CEST 2025: Hadith auto-update gerepareerd - JavaScript selector aangepast van .hadith-section naar .hadith-center voor nieuwe layout
Wed May 28 08:37:45 CEST 2025: Hadith interval instelbaar gemaakt - nieuwe setting hadith_interval_seconds toegevoegd aan settings.json, settings.html en app.py, JavaScript gebruikt nu variabele interval
Wed May 28 08:39:34 CEST 2025: Settings pagina georganiseerd in tabbladen - 4 tabs: Audio & Volume, Gebedstijden, Functies, Systeem. Inclusief CSS styling en JavaScript functionaliteit met localStorage voor actieve tab
Wed May 28 13:43:52 CEST 2025: Bevestigd dat Adzkaar scherm wordt geopend in nieuwe pagina bij gebedstijd
Wed May 28 13:46:26 CEST 2025: Adzkaar aangepast van nieuwe pagina naar fullscreen modal in hoofdpagina
Wed May 28 14:02:31 CEST 2025: Debug tijd synchronisatie toegevoegd tussen debug pagina en hoofdpagina