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') 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' 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') 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') 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): def logregel(message):
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
@ -15,13 +16,32 @@ def logregel(message):
with open(LOG_PATH, 'a') as log: with open(LOG_PATH, 'a') as log:
log.write(log_message + '\n') 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): def get_current_volume(settings):
"""Bepaal het juiste volume op basis van de huidige tijd""" """Bepaal het juiste volume op basis van de huidige tijd"""
# Fallback naar oude volume als nieuwe instellingen niet bestaan # Fallback naar oude volume als nieuwe instellingen niet bestaan
if 'volume_day' not in settings or 'volume_night' not in settings: if 'volume_day' not in settings or 'volume_night' not in settings:
return settings.get('volume', 30) 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') night_start = settings.get('night_start', '20:00')
day_start = settings.get('day_start', '07:00') day_start = settings.get('day_start', '07:00')
@ -38,11 +58,11 @@ def get_current_volume(settings):
if is_night: if is_night:
volume = settings.get('volume_night', settings.get('volume', 30) // 2) 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 return volume
else: else:
volume = settings.get('volume_day', settings.get('volume', 30)) 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 return volume
def apply_prayer_offsets(gebedstijden, settings): 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}") logregel(f"❌ FOUT Sonos {zone} {prayer_name}: {e}")
return False return False
now = datetime.now().strftime('%H:%M') # Gebruik debug tijd als beschikbaar
now = get_current_time()
logregel(f"CRON gestart, huidige tijd: {now}") logregel(f"CRON gestart, huidige tijd: {now}")
# Laad settings # 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') 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' 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') 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(): def fetch_weather_data():
"""Haalt weersinformatie op voor de geconfigureerde locatie""" """Haalt weersinformatie op voor de geconfigureerde locatie"""
@ -77,13 +81,20 @@ def load_settings():
def get_current_volume(settings): def get_current_volume(settings):
"""Bepaal het juiste volume op basis van de huidige tijd""" """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 # Fallback naar oude volume als nieuwe instellingen niet bestaan
if 'volume_day' not in settings or 'volume_night' not in settings: if 'volume_day' not in settings or 'volume_night' not in settings:
return settings.get('volume', 30) return settings.get('volume', 30)
# 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') current_time = datetime.now().strftime('%H:%M')
night_start = settings.get('night_start', '20:00') night_start = settings.get('night_start', '20:00')
day_start = settings.get('day_start', '07: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 is_night = current_minutes >= night_minutes and current_minutes < day_minutes
if is_night: 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: 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): def apply_prayer_offsets(gebedstijden, settings):
"""Pas offsets toe op gebedstijden""" """Pas offsets toe op gebedstijden"""
@ -644,5 +659,73 @@ def trigger_adzkaar():
except Exception as e: except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500 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__': if __name__ == '__main__':
app.run(host='0.0.0.0', port=80) 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: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: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 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() { function updateCurrentTime() {
// 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();
})
.catch(error => {
// Fallback naar normale tijd bij fout
const now = new Date(); const now = new Date();
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById("current-time").textContent = timeStr; document.getElementById("current-time").textContent = timeStr;
// Update datum informatie elke minuut // Update datum informatie elke minuut
updateDateInfo(); updateDateInfo();
});
} }
function updateDateInfo() { function updateDateInfo() {
@ -33,15 +54,38 @@ let isNextDayPrayer = false;
function startCountdowns(times, names) { function startCountdowns(times, names) {
prayerTimes = times; prayerTimes = times;
prayerNames = names; prayerNames = names;
const nextPrayer = getNextPrayer();
getNextPrayer().then(nextPrayer => {
currentPrayerIndex = nextPrayer.index; currentPrayerIndex = nextPrayer.index;
isNextDayPrayer = nextPrayer.isNextDay; isNextDayPrayer = nextPrayer.isNextDay;
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer); 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() { function getNextPrayer() {
// Gebruik debug tijd als actief
return fetch('/api/debug-time')
.then(response => response.json())
.then(data => {
let currentTime;
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(); const now = new Date();
const currentTime = now.getHours() * 60 + now.getMinutes(); // Huidige tijd in minuten currentTime = now.getHours() * 60 + now.getMinutes();
}
// Zoek naar volgende gebed vandaag // Zoek naar volgende gebed vandaag
for (let i = 0; i < prayerTimes.length; i++) { for (let i = 0; i < prayerTimes.length; i++) {
@ -55,6 +99,24 @@ function getNextPrayer() {
// Alle gebeden van vandaag zijn voorbij, volgende is eerste gebed van morgen // Alle gebeden van vandaag zijn voorbij, volgende is eerste gebed van morgen
return { index: 0, isNextDay: true }; 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) { function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
@ -74,7 +136,23 @@ function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
document.querySelector('.huidig-gebed-bottom .naam').textContent = displayName; document.querySelector('.huidig-gebed-bottom .naam').textContent = displayName;
function update() { function update() {
const now = new Date(); // Gebruik debug tijd als actief
fetch('/api/debug-time')
.then(response => response.json())
.then(data => {
let now;
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 {
// Gebruik normale tijd
now = new Date();
}
let diff = Math.floor((target - now) / 1000); let diff = Math.floor((target - now) / 1000);
if (diff <= 0) { if (diff <= 0) {
@ -123,6 +201,54 @@ function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
const s = String(diff % 60).padStart(2, '0'); const s = String(diff % 60).padStart(2, '0');
document.getElementById("countdown").textContent = `${h}:${m}:${s}`; 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(); update();
@ -159,18 +285,13 @@ function triggerAdzkaarScreen(prayerName) {
if (data.success) { if (data.success) {
console.log(`📿 Adzkaar scherm wordt getoond na ${prayerName}`); console.log(`📿 Adzkaar scherm wordt getoond na ${prayerName}`);
// Open Adzkaar scherm in fullscreen // Toon Adzkaar modal in plaats van nieuwe pagina
// In kiosk mode proberen we een nieuw venster te openen if (window.showAdzkaarModal) {
const adzkaarWindow = window.open( // Gebruik de duur uit de API response of standaard 5 minuten
data.url, const durationMinutes = data.duration_minutes || 5;
'adzkaar', window.showAdzkaarModal(durationMinutes);
'fullscreen=yes,scrollbars=no,resizable=no,toolbar=no,menubar=no,status=no' } else {
); console.log('📿 Adzkaar modal functie niet beschikbaar');
// 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;
} }
} else { } else {
console.log(`📿 Adzkaar niet getoond: ${data.error}`); console.log(`📿 Adzkaar niet getoond: ${data.error}`);

View File

@ -1400,3 +1400,211 @@ html.dark .hadith-center {
max-width: 300px; 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() { function updateDebugDisplay() {
const debugTime = getDebugTime(); fetch('/api/debug-time')
const timeStr = debugTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); .then(response => response.json())
document.getElementById('currentDebugTime').textContent = timeStr; .then(data => {
if (data.success) {
document.getElementById('currentDebugTime').textContent = data.current_time_display;
// Update status // Update status
const statusElement = document.getElementById('debugStatus'); const statusElement = document.getElementById('debugStatus');
statusElement.textContent = isDebugMode ? 'Debug Mode Actief' : 'Normaal'; statusElement.textContent = data.debug_active ? 'Debug Mode Actief' : 'Normaal';
statusElement.style.color = isDebugMode ? '#ff6b6b' : '#00ff00'; statusElement.style.color = data.debug_active ? '#ff6b6b' : '#00ff00';
// Check voor gebedstijd // Check voor gebedstijd
checkPrayerTime(timeStr); 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) { function checkPrayerTime(currentTime) {
@ -384,20 +396,41 @@
const targetTime = new Date(); const targetTime = new Date();
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0); targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
debugTimeOffset = Math.floor((targetTime - now) / 1000); const offsetSeconds = Math.floor((targetTime - now) / 1000);
isDebugMode = true;
log(`⏰ Tijd handmatig ingesteld op ${timeInput.value}`); 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(); updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
} }
function adjustTime(seconds) { function adjustTime(seconds) {
debugTimeOffset += seconds; fetch('/api/debug-time', {
isDebugMode = true; method: 'POST',
headers: { 'Content-Type': 'application/json' },
const sign = seconds > 0 ? '+' : ''; body: JSON.stringify({ action: 'adjust', seconds: seconds })
log(`⏰ Tijd aangepast: ${sign}${seconds} seconden`); })
.then(response => response.json())
.then(data => {
if (data.success) {
log(`⏰ ${data.message}`);
updateDebugDisplay(); updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
} }
function setTimeToPrayer(prayerTime, offsetMinutes) { function setTimeToPrayer(prayerTime, offsetMinutes) {
@ -407,12 +440,24 @@
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0); targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
targetTime.setTime(targetTime.getTime() + (offsetMinutes * 60 * 1000)); targetTime.setTime(targetTime.getTime() + (offsetMinutes * 60 * 1000));
debugTimeOffset = Math.floor((targetTime - now) / 1000); const offsetSeconds = Math.floor((targetTime - now) / 1000);
isDebugMode = true;
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`; const offsetText = offsetMinutes === 0 ? 'exact' : `${offsetMinutes} min ervoor`;
log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`); log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`);
updateDebugDisplay(); updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
} }
function setTimeToNextPrayer(offsetMinutes) { function setTimeToNextPrayer(offsetMinutes) {
@ -433,10 +478,21 @@
} }
function resetTime() { function resetTime() {
debugTimeOffset = 0; fetch('/api/debug-time', {
isDebugMode = false; method: 'POST',
log(`🔄 Tijd gereset naar echte tijd`); headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'reset' })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`🔄 ${data.message}`);
updateDebugDisplay(); updateDebugDisplay();
} else {
log(`❌ Fout: ${data.error}`);
}
})
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
} }
function checkSonosStatus() { function checkSonosStatus() {

View File

@ -85,6 +85,84 @@
<audio id="adhanAudio" src="/static/clips/{{ settings['audio_clip'] }}" preload="auto"></audio> <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> <script>
// Prayer times data from server // Prayer times data from server
window.prayerTimes = [ window.prayerTimes = [
@ -181,6 +259,121 @@
} }
document.getElementById('muteBtn').addEventListener('click', toggleMute); document.getElementById('muteBtn').addEventListener('click', toggleMute);
setMuteIcon(); 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> </script>
</body> </body>
</html> </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: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: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 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