Adhaan/adhan-webapp/adhan_cron.py
filoor c212ec4987 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.
2025-05-28 18:59:15 +02:00

234 lines
8.8 KiB
Python

import requests, json, os
from datetime import datetime, date, timedelta
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' # 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')
log_message = f"[{timestamp}] {message}"
print(log_message) # Voor Docker logs
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)
# 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')
# Converteer tijden naar vergelijkbare format
current_minutes = int(current_time[:2]) * 60 + int(current_time[3:5])
night_minutes = int(night_start[:2]) * 60 + int(night_start[3:5])
day_minutes = int(day_start[:2]) * 60 + int(day_start[3:5])
# Bepaal of het avond is
if night_minutes > day_minutes: # Normale dag/nacht cyclus (bijv. dag 07:00-20:00)
is_night = current_minutes >= night_minutes or current_minutes < day_minutes
else: # Avond gaat over middernacht (bijv. avond 20:00-07:00)
is_night = current_minutes >= night_minutes and current_minutes < day_minutes
if is_night:
volume = settings.get('volume_night', settings.get('volume', 30) // 2)
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} (tijd: {current_time})")
return volume
def apply_prayer_offsets(gebedstijden, settings):
"""Pas offsets toe op gebedstijden"""
offsets = {
'Fajr': settings.get('fajr_offset', 0),
'Zuhr': settings.get('zuhr_offset', 0),
'Asr': settings.get('asr_offset', 0),
'Maghrib': settings.get('maghrib_offset', 0),
'Isha': settings.get('isha_offset', 0)
}
adjusted_times = {}
for prayer, original_time in gebedstijden.items():
offset_minutes = offsets.get(prayer, 0)
if offset_minutes == 0:
adjusted_times[prayer] = original_time
continue
try:
# Parse de originele tijd
time_obj = datetime.strptime(original_time, '%H:%M')
# Voeg offset toe
adjusted_time = time_obj + timedelta(minutes=offset_minutes)
# Converteer terug naar string
adjusted_times[prayer] = adjusted_time.strftime('%H:%M')
if offset_minutes != 0:
logregel(f"📅 {prayer}: {original_time}{adjusted_times[prayer]} ({offset_minutes:+d} min)")
except Exception as e:
logregel(f"⚠️ Fout bij aanpassen {prayer} tijd: {e}")
adjusted_times[prayer] = original_time
return adjusted_times
def check_recent_play(prayer_name):
"""Controleer of deze adhaan recent is afgespeeld (binnen 2 minuten)"""
try:
if os.path.exists(LAST_PLAYED_PATH):
with open(LAST_PLAYED_PATH, 'r') as f:
last_played = json.load(f)
last_time = last_played.get(prayer_name)
if last_time:
last_datetime = datetime.fromisoformat(last_time)
time_diff = (datetime.now() - last_datetime).total_seconds()
if time_diff < 120: # 2 minuten
logregel(f"⏭️ {prayer_name} recent afgespeeld ({int(time_diff)}s geleden), overslaan")
return True
except Exception as e:
logregel(f"Fout bij controleren recent play: {e}")
return False
def mark_as_played(prayer_name):
"""Markeer deze adhaan als afgespeeld"""
try:
last_played = {}
if os.path.exists(LAST_PLAYED_PATH):
with open(LAST_PLAYED_PATH, 'r') as f:
last_played = json.load(f)
last_played[prayer_name] = datetime.now().isoformat()
with open(LAST_PLAYED_PATH, 'w') as f:
json.dump(last_played, f)
except Exception as e:
logregel(f"Fout bij markeren als afgespeeld: {e}")
def play_sonos_clip(zone, audio_clip, volume, prayer_name):
"""Speel een clip af op een specifieke Sonos zone met error handling"""
try:
# Stop eerst alle audio op deze zone
stop_url = f"http://{SONOS_API_IP}:5005/{zone}/pause"
requests.get(stop_url, timeout=2)
time.sleep(0.5) # Korte pauze
# Speel de clip af
clip_url = f"http://{SONOS_API_IP}:5005/{zone}/clip/{audio_clip}/{volume}"
response = requests.get(clip_url, timeout=10)
if response.status_code == 200:
logregel(f"✅ AFGESPEELD {prayer_name} op {zone} ({audio_clip}, volume {volume})")
return True
else:
logregel(f"❌ HTTP {response.status_code} voor {zone}: {response.text[:100]}")
return False
except requests.exceptions.Timeout:
logregel(f"⏱️ TIMEOUT bij {zone} voor {prayer_name}")
return False
except Exception as e:
logregel(f"❌ FOUT Sonos {zone} {prayer_name}: {e}")
return False
# Gebruik debug tijd als beschikbaar
now = get_current_time()
logregel(f"CRON gestart, huidige tijd: {now}")
# Laad settings
try:
with open(SETTINGS_PATH) as f:
settings = json.load(f)
except Exception as e:
logregel(f"Fout bij laden settings: {e}")
exit(1)
# Controleer mute-status
if settings.get('mute', False):
logregel("Adhaan niet afgespeeld: mute staat aan.")
exit(0)
# Haal gebedstijden op
try:
res = requests.get(VUMG_API, timeout=10)
res.raise_for_status()
data = res.json()[0]
gebedstijden = {
"Fajr": data.get("fajr_jamah", "00:00")[:5], # Haal seconden weg
"Zuhr": data.get("zuhr_jamah", "00:00")[:5], # Haal seconden weg
"Asr": data.get("asr_jamah", "00:00")[:5], # Haal seconden weg
"Maghrib": data.get("maghrib_jamah", "00:00")[:5], # Haal seconden weg
"Isha": data.get("isha_jamah", "00:00")[:5] # Haal seconden weg
}
except Exception as e:
logregel(f"Fout bij ophalen gebedstijden: {e}")
exit(1)
# Pas offsets toe op gebedstijden
gebedstijden = apply_prayer_offsets(gebedstijden, settings)
# Check voor gebedstijd
for naam, tijd in gebedstijden.items():
if tijd[:5] == now: # Alleen uren:minuten vergelijken
# Controleer of recent afgespeeld
if check_recent_play(naam):
continue
logregel(f"🕌 GEBEDSTIJD GEDETECTEERD: {naam} om {tijd}")
# Markeer als afgespeeld VOOR het afspelen
mark_as_played(naam)
# Speel af op alle zones
success_count = 0
zones = settings.get('zones', ['Woonkamer'])
audio_clip = settings.get('audio_clip', 'adhan1.mp3')
volume = get_current_volume(settings)
for zone in zones:
if play_sonos_clip(zone, audio_clip, volume, naam):
success_count += 1
time.sleep(1) # Pauze tussen zones
if success_count > 0:
logregel(f"🎵 Adhaan succesvol afgespeeld op {success_count}/{len(zones)} zones")
else:
logregel(f"❌ Adhaan kon niet worden afgespeeld op geen enkele zone")
break # Stop na eerste match
logregel(f"CRON voltooid om {datetime.now().strftime('%H:%M:%S')}")