filoor 1983a215cb feat(settings): voeg Pi HDMI volume controle toe aan UI en API
Deze commit introduceert de mogelijkheid om het HDMI volume van de Raspberry Pi in te stellen via de webapplicatie.

Belangrijkste wijzigingen:
- Toevoeging van een nieuwe invoercontrole (slider) in de instellingenpagina voor het aanpassen van het Pi HDMI volume.
- Implementatie van een backend API endpoint dat het volume instelt via amixer, met validatie en foutafhandeling.
- Testfunctie toegevoegd waarmee gebruikers onmiddellijk het ingestelde volume kunnen testen.
- Automatische HDMI audio configuratie toegevoegd in pi-setup-desktop.sh script.

Dit verbetert de gebruiksvriendelijkheid, doordat gebruikers eenvoudig het audio-uitgangsvolume kunnen beheren en testen zonder directe toegang tot de hardware.
2025-05-28 20:02:51 +02:00

789 lines
30 KiB
Python

from flask import Flask, render_template, request, redirect, send_from_directory, jsonify, request as flask_request
import requests, json, os, random
from datetime import datetime
from config import *
from hijridate import Gregorian
app = Flask(__name__)
# Voeg cache-control headers toe voor statische bestanden
@app.after_request
def add_header(response):
if 'Cache-Control' not in response.headers:
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
return response
# Specifieke route voor statische bestanden met cache-control
@app.route('/static/<path:filename>')
def serve_static(filename):
return send_from_directory('static', filename, cache_timeout=0)
SETTINGS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settings.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'
CLIPS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'clips')
# SONOS_API_IP wordt nu geïmporteerd uit config.py
# 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"""
try:
params = {
'q': WEATHER_LOCATION,
'appid': OPENWEATHER_API_KEY,
'units': 'metric',
'lang': 'nl'
}
response = requests.get('https://api.openweathermap.org/data/2.5/weather', params=params, timeout=5)
response.raise_for_status()
data = response.json()
weather_info = {
'temperature': round(data['main']['temp']),
'feels_like': round(data['main']['feels_like']),
'description': data['weather'][0]['description'].capitalize(),
'humidity': data['main']['humidity'],
'wind_speed': round(data['wind']['speed'] * 3.6), # m/s naar km/h
'icon': data['weather'][0]['icon']
}
return weather_info
except Exception as e:
print(f"⚠️ Fout bij ophalen weerdata: {e}")
return {
'temperature': '--',
'feels_like': '--',
'description': 'Weer niet beschikbaar',
'humidity': '--',
'wind_speed': '--',
'icon': '01d'
}
def load_hadith():
try:
with open(HADITHS_PATH) as f:
hadiths = json.load(f)['hadiths']
return random.choice(hadiths)
except Exception as e:
print(f"⚠️ Fout bij laden van hadith: {e}")
return {"text": "De daden die Allah het meest liefheeft zijn degenen die regelmatig worden verricht, zelfs als ze klein zijn.", "bron": "Sahih al-Bukhari"}
def load_settings():
try:
if os.path.exists(SETTINGS_PATH) and os.path.getsize(SETTINGS_PATH) > 0:
with open(SETTINGS_PATH) as f:
return json.load(f)
except Exception as e:
print(f"⚠️ Fout bij laden van settings: {e}")
return {"volume": 30, "zones": ["Woonkamer"], "audio_clip": "adhan1.mp3"}
def get_current_volume(settings):
"""Bepaal het juiste volume op basis van de huidige tijd"""
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)
# 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')
# 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)
print(f"🌙 Avond volume gebruikt: {volume} (tijd: {current_time})")
return volume
else:
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"""
from datetime import datetime, timedelta
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:
print(f"📅 {prayer}: {original_time}{adjusted_times[prayer]} ({offset_minutes:+d} min)")
except Exception as e:
print(f"⚠️ Fout bij aanpassen {prayer} tijd: {e}")
adjusted_times[prayer] = original_time
return adjusted_times
def fetch_sonos_zones():
try:
res = requests.get(f'http://{SONOS_API_IP}:5005/zones', timeout=5)
res.raise_for_status()
data = res.json()
zones = []
for group in data:
for player in group['members']:
zones.append(player['roomName'])
return sorted(set(zones))
except Exception as e:
print(f'Fout bij ophalen Sonos-zones: {e}')
return ['Woonkamer', 'Slaapkamer', 'Keuken']
def get_date_info():
"""Genereert zowel Gregoriaanse als Hijri datum informatie"""
now = datetime.now()
# Gregoriaanse datum
gregorian_date = now.strftime('%A %d %B %Y')
gregorian_short = now.strftime('%d-%m-%Y')
# Nederlandse maandnamen
dutch_months = {
'January': 'januari', 'February': 'februari', 'March': 'maart',
'April': 'april', 'May': 'mei', 'June': 'juni',
'July': 'juli', 'August': 'augustus', 'September': 'september',
'October': 'oktober', 'November': 'november', 'December': 'december'
}
# Nederlandse dagnamen
dutch_days = {
'Monday': 'maandag', 'Tuesday': 'dinsdag', 'Wednesday': 'woensdag',
'Thursday': 'donderdag', 'Friday': 'vrijdag', 'Saturday': 'zaterdag', 'Sunday': 'zondag'
}
# Vervang Engelse namen door Nederlandse
for eng, nl in dutch_months.items():
gregorian_date = gregorian_date.replace(eng, nl)
for eng, nl in dutch_days.items():
gregorian_date = gregorian_date.replace(eng, nl)
try:
# Converteer naar Hijri datum
hijri_date = Gregorian(now.year, now.month, now.day).to_hijri()
# Arabische maandnamen
hijri_months = [
'محرم', 'صفر', 'ربيع الأول', 'ربيع الثاني', 'جمادى الأولى', 'جمادى الثانية',
'رجب', 'شعبان', 'رمضان', 'شوال', 'ذو القعدة', 'ذو الحجة'
]
# Nederlandse maandnamen voor Hijri
hijri_months_nl = [
'Muharram', 'Safar', 'Rabi al-Awwal', 'Rabi al-Thani', 'Jumada al-Awwal', 'Jumada al-Thani',
'Rajab', 'Sha\'ban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'
]
hijri_arabic = f"{hijri_date.day} {hijri_months[hijri_date.month - 1]} {hijri_date.year} هـ"
hijri_dutch = f"{hijri_date.day} {hijri_months_nl[hijri_date.month - 1]} {hijri_date.year} AH"
except Exception as e:
print(f"⚠️ Fout bij Hijri conversie: {e}")
hijri_arabic = "التاريخ الهجري غير متاح"
hijri_dutch = "Hijri datum niet beschikbaar"
return {
'gregorian_full': gregorian_date,
'gregorian_short': gregorian_short,
'hijri_arabic': hijri_arabic,
'hijri_dutch': hijri_dutch,
'current_time': now.strftime('%H:%M')
}
@app.route('/')
def index():
settings = load_settings()
next_time = "Onbekend"
next_name = "Onbekend"
debug_data = {}
gebedstijden = {}
hadith = load_hadith()
weather = fetch_weather_data()
date_info = get_date_info()
try:
res = requests.get(VUMG_API)
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
}
# Pas offsets toe op gebedstijden
gebedstijden = apply_prayer_offsets(gebedstijden, settings)
now = datetime.now().strftime('%H:%M')
for naam, tijd in gebedstijden.items():
if tijd > now:
next_time = tijd
next_name = naam
break
else:
next_time = list(gebedstijden.values())[0]
next_name = list(gebedstijden.keys())[0]
debug_data = {
"api_response": data,
"gebedstijden": gebedstijden,
"now": now,
"next_time": next_time,
"next_name": next_name
}
except Exception as e:
print("❌ Fout bij ophalen/verwerken van gebedstijden:", e)
dua = "اللّهُمَّ اجْعَلْ صَلاتِي نُورًا"
return render_template('index.html',
next_time=next_time,
next_name=next_name,
dua=dua,
hadith=hadith,
gebedstijden=gebedstijden,
debug=debug_data,
settings=settings,
weather=weather,
date_info=date_info)
@app.route('/instellingen', methods=['GET', 'POST'])
def instellingen():
settings = load_settings()
clips = [f for f in os.listdir(CLIPS_PATH) if f.endswith('.mp3') or f.endswith('.wav')]
alle_zones = fetch_sonos_zones()
if request.method == 'POST':
# Nieuwe volume instellingen
if 'volume_day' in request.form and 'volume_night' in request.form:
settings['volume_day'] = int(request.form['volume_day'])
settings['volume_night'] = int(request.form['volume_night'])
settings['night_start'] = request.form['night_start']
settings['day_start'] = request.form['day_start']
# Update oude volume voor backward compatibility
settings['volume'] = settings['volume_day']
else:
# Fallback: gebruik default waarden als velden ontbreken
settings['volume_day'] = settings.get('volume_day', 15)
settings['volume_night'] = settings.get('volume_night', 8)
settings['night_start'] = settings.get('night_start', '20:00')
settings['day_start'] = settings.get('day_start', '07:00')
settings['volume'] = settings['volume_day']
# Gebedstijd offsets
settings['fajr_offset'] = int(request.form.get('fajr_offset', 0))
settings['zuhr_offset'] = int(request.form.get('zuhr_offset', 0))
settings['asr_offset'] = int(request.form.get('asr_offset', 0))
settings['maghrib_offset'] = int(request.form.get('maghrib_offset', 0))
settings['isha_offset'] = int(request.form.get('isha_offset', 0))
# Adzkaar instellingen
settings['adzkaar_enabled'] = 'adzkaar_enabled' in request.form
settings['adzkaar_duration'] = int(request.form.get('adzkaar_duration', 5))
# Hadith instellingen
settings['hadith_interval_seconds'] = int(request.form.get('hadith_interval_seconds', 30))
# Pi HDMI volume instelling
if 'pi_hdmi_volume' in request.form:
pi_volume = int(request.form.get('pi_hdmi_volume', 70))
settings['pi_hdmi_volume'] = pi_volume
# Stel Pi volume direct in via amixer
import subprocess
try:
subprocess.run(['amixer', 'set', 'PCM', f'{pi_volume}%'],
check=True, capture_output=True, text=True)
print(f"🔊 Pi HDMI volume ingesteld op {pi_volume}%")
except subprocess.CalledProcessError as e:
print(f"❌ Kon Pi volume niet instellen: {e}")
settings['zones'] = request.form.getlist('zones')
settings['audio_clip'] = request.form['audio_clip']
with open(SETTINGS_PATH, 'w') as f:
json.dump(settings, f, indent=2)
if 'test_clip' in request.form:
# Gebruik het juiste volume voor de test
test_volume = get_current_volume(settings)
for zone in settings['zones']:
url = f"http://{SONOS_API_IP}:5005/{zone}/clip/{settings['audio_clip']}/{test_volume}"
try:
r = requests.get(url, timeout=3)
print(f"🎵 Test clip verzonden naar {zone}, status: {r.status_code}")
except Exception as e:
print(f"❌ Fout bij afspelen op zone {zone}: {e}")
return redirect('/instellingen')
return render_template('settings.html',
settings=settings,
alle_zones=alle_zones,
clips=clips)
@app.route('/api/hadith')
def api_hadith():
hadith = load_hadith()
return jsonify(hadith)
@app.route('/api/mute', methods=['POST'])
def toggle_mute():
try:
data = flask_request.get_json()
mute = data.get('mute', False)
with open(SETTINGS_PATH, 'r+') as f:
settings = json.load(f)
settings['mute'] = mute
f.seek(0)
json.dump(settings, f, indent=2)
f.truncate()
return jsonify({'success': True, 'mute': mute})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/weather')
def api_weather():
"""API endpoint voor het ophalen van actuele weerdata"""
weather = fetch_weather_data()
return jsonify(weather)
@app.route('/api/date-info')
def api_date_info():
"""API endpoint voor het ophalen van actuele datum informatie"""
date_info = get_date_info()
return jsonify(date_info)
@app.route('/api/test-audio', methods=['POST'])
def test_audio():
"""Test een audio bestand lokaal in de browser"""
try:
data = flask_request.get_json()
audio_file = data.get('audio_file', 'adhan1.mp3')
# Controleer of het bestand bestaat
audio_path = os.path.join(CLIPS_PATH, audio_file)
if not os.path.exists(audio_path):
return jsonify({'success': False, 'error': 'Audio bestand niet gevonden'}), 404
return jsonify({
'success': True,
'message': f'Audio bestand {audio_file} is beschikbaar',
'url': f'/static/clips/{audio_file}'
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/debug')
def debug():
"""Debug pagina voor het testen van adhaan functionaliteit"""
settings = load_settings()
# Check of debug mode is ingeschakeld
if not settings.get('debug_mode', False):
return redirect('/')
gebedstijden = {}
try:
res = requests.get(VUMG_API)
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
}
# Pas offsets toe op gebedstijden
gebedstijden = apply_prayer_offsets(gebedstijden, settings)
except Exception as e:
print("❌ Fout bij ophalen gebedstijden voor debug:", e)
# Fallback tijden voor testing
gebedstijden = {
"Fajr": "06:00",
"Zuhr": "12:30",
"Asr": "15:00",
"Maghrib": "17:30",
"Isha": "19:00"
}
# Pas ook offsets toe op fallback tijden
gebedstijden = apply_prayer_offsets(gebedstijden, settings)
return render_template('debug.html',
gebedstijden=gebedstijden,
settings=settings)
@app.route('/api/debug-adhaan', methods=['POST'])
def debug_adhaan():
"""API endpoint voor debug adhaan testing"""
import time
# Check of debug mode is ingeschakeld
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()
prayer_name = data.get('prayer', 'Test')
test_time = data.get('time', 'Onbekend')
# Check mute status
if settings.get('mute', False):
return jsonify({
'success': False,
'error': 'Adhaan niet afgespeeld: mute staat aan',
'muted': True
})
# Verbeterde Sonos afspeling
success_count = 0
error_messages = []
zones = settings.get('zones', ['Woonkamer'])
audio_clip = settings.get('audio_clip', 'adhan1.mp3')
volume = get_current_volume(settings)
for zone in zones:
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:
success_count += 1
print(f"🔧 DEBUG: Adhaan afgespeeld op {zone} voor {prayer_name} om {test_time}")
else:
error_messages.append(f"{zone}: HTTP {response.status_code}")
except requests.exceptions.Timeout:
error_messages.append(f"{zone}: Timeout")
except Exception as e:
error_messages.append(f"{zone}: {str(e)}")
# Pauze tussen zones
if len(zones) > 1:
time.sleep(1)
if success_count > 0:
return jsonify({
'success': True,
'message': f'Adhaan afgespeeld op {success_count}/{len(zones)} zone(s)',
'errors': error_messages if error_messages else None
})
else:
return jsonify({
'success': False,
'error': f'Geen zones bereikbaar: {", ".join(error_messages)}'
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/sonos-status')
def sonos_status():
"""API endpoint voor Sonos status controle"""
try:
settings = load_settings()
zones = settings.get('zones', ['Woonkamer'])
status_info = {}
for zone in zones:
try:
# Haal zone status op
status_url = f"http://{SONOS_API_IP}:5005/{zone}/state"
response = requests.get(status_url, timeout=3)
if response.status_code == 200:
zone_data = response.json()
status_info[zone] = {
'status': 'online',
'playbackState': zone_data.get('playbackState', 'unknown'),
'currentTrack': zone_data.get('currentTrack', {}).get('title', 'Geen track'),
'volume': zone_data.get('volume', 0)
}
else:
status_info[zone] = {'status': 'error', 'error': f'HTTP {response.status_code}'}
except Exception as e:
status_info[zone] = {'status': 'offline', 'error': str(e)}
return jsonify({
'success': True,
'zones': status_info,
'api_ip': SONOS_API_IP
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/sonos-stop', methods=['POST'])
def sonos_stop():
"""API endpoint om alle Sonos zones te stoppen"""
try:
settings = load_settings()
zones = settings.get('zones', ['Woonkamer'])
stopped_zones = []
for zone in zones:
try:
stop_url = f"http://{SONOS_API_IP}:5005/{zone}/pause"
response = requests.get(stop_url, timeout=3)
if response.status_code == 200:
stopped_zones.append(zone)
except Exception as e:
print(f"Fout bij stoppen {zone}: {e}")
return jsonify({
'success': True,
'message': f'Audio gestopt op {len(stopped_zones)} zone(s)',
'stopped_zones': stopped_zones
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/quran')
def quran():
"""Quran speler pagina"""
settings = load_settings()
gebedstijden = {}
try:
res = requests.get(VUMG_API)
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
}
# Pas offsets toe op gebedstijden
gebedstijden = apply_prayer_offsets(gebedstijden, settings)
except Exception as e:
print("❌ Fout bij ophalen gebedstijden voor quran pagina:", e)
# Fallback tijden
gebedstijden = {
"Fajr": "06:00",
"Zuhr": "12:30",
"Asr": "15:00",
"Maghrib": "17:30",
"Isha": "19:00"
}
# Pas ook offsets toe op fallback tijden
gebedstijden = apply_prayer_offsets(gebedstijden, settings)
return render_template('quran.html',
gebedstijden=gebedstijden,
settings=settings)
@app.route('/adzkaar')
def adzkaar():
"""Adzkaar pagina na gebed"""
settings = load_settings()
duration_minutes = settings.get('adzkaar_duration', 5) # Default 5 minuten
return render_template('adzkaar.html',
duration_minutes=duration_minutes,
settings=settings)
@app.route('/api/trigger-adzkaar', methods=['POST'])
def trigger_adzkaar():
"""API endpoint om Adzkaar scherm te triggeren (voor debug)"""
try:
settings = load_settings()
# Check of Adzkaar is ingeschakeld
if not settings.get('adzkaar_enabled', True):
return jsonify({
'success': False,
'error': 'Adzkaar is uitgeschakeld in instellingen'
})
duration = settings.get('adzkaar_duration', 5)
return jsonify({
'success': True,
'message': f'Adzkaar scherm wordt getoond voor {duration} minuten',
'duration': duration,
'url': '/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')
})
@app.route('/api/set-pi-volume', methods=['POST'])
def set_pi_volume():
"""API endpoint om Pi HDMI volume in te stellen"""
try:
data = flask_request.get_json()
volume = data.get('volume', 70)
# Valideer volume (0-100)
if not isinstance(volume, int) or volume < 0 or volume > 100:
return jsonify({'success': False, 'error': 'Volume moet tussen 0 en 100 zijn'}), 400
# Stel Pi volume in via amixer
import subprocess
try:
# Stel PCM volume in (HDMI audio)
subprocess.run(['amixer', 'set', 'PCM', f'{volume}%'],
check=True, capture_output=True, text=True)
# Sla volume op in settings voor persistentie
settings = load_settings()
settings['pi_hdmi_volume'] = volume
with open(SETTINGS_PATH, 'w') as f:
json.dump(settings, f, indent=2)
print(f"🔊 Pi HDMI volume ingesteld op {volume}%")
return jsonify({
'success': True,
'message': f'Pi HDMI volume ingesteld op {volume}%',
'volume': volume
})
except subprocess.CalledProcessError as e:
print(f"❌ Amixer fout: {e}")
return jsonify({
'success': False,
'error': f'Kon volume niet instellen: {e.stderr if e.stderr else str(e)}'
}), 500
except Exception as e:
print(f"❌ Volume API fout: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)