# Buschauffeurswekker Android-app die de functie van de normale wekker-app vervult, maar de wekkers automatisch zet op basis van de Nextcloud CalDAV-agenda **EBS-Diensten**. ## Werking - Elke dag om **12:00** leest de app de agenda van de **volgende dag**. - De dienstbegintijd wordt **naar beneden afgerond op een heel kwartier**: - 05:00–05:14 → 05:00 - 05:15–05:29 → 05:15 - 05:30–05:44 → 05:30 - 05:45–05:59 → 05:45 - Er worden drie wekkers gezet, alle drie vóór de afgeronde aanvangstijd: - **Opstaan** — 2 uur vóór aanvang - **Wally** — 1,5 uur vóór aanvang - **Vertrek** — 0,5 uur vóór aanvang - Staat er **geen dienst** in de agenda voor morgen, dan worden **geen wekkers** gezet. - De wekker gaat volwaardig af (geluid + trillen, volledig scherm) **ook bij een vergrendeld scherm**, met snooze (10 min) en "wekker uit". - Het toestel mag daarvoor **mobiele data** verbruiken en taken op de **achtergrond** uitvoeren. ## Installatie 1. Bouw de APK: `./gradlew :app:assembleDebug` → `app/build/outputs/apk/debug/app-debug.apk` 2. Zet de APK op de telefoon en installeer (sideload). 3. Open de app en vul bij **Instellingen** in: - Agenda-URL: `https://nextcloud.eddydevink.nl/remote.php/dav/calendars/eddy/ebs_diensten-1/` - Gebruikersnaam: `eddy` - App-wachtwoord: een Nextcloud-app-wachtwoord (Nextcloud → Beveiliging → App-wachtwoorden; zie de Obsidian-vault voor de bestaande app-wachtwoorden — niet in de app hardcoden) 4. Druk op **Opslaan** en daarna op **Nu controleren** om te testen. 5. Verleen de gevraagde machtigingen via de knoppen onder **Machtigingen**: meldingen, exacte alarmen, batterijoptimalisatie uitzonderen en (Android 14+) volledig scherm. ## Machtigingen | Machtiging | Doel | |---|---| | Internet / netwerk | Agenda ophalen over wifi én mobiele data | | Meldingen (POST_NOTIFICATIONS) | Afgaande wekker tonen | | Exacte alarmen (USE_EXACT_ALARM / SCHEDULE_EXACT_ALARM) | Wekker óp tijd, ook in Doze | | Volledig scherm (USE_FULL_SCREEN_INTENT) | Wekker bovenop het vergrendelscherm | | Wakelock + trillen | Scherm aanhouden en trillen tijdens afgaan | | Boot (RECEIVE_BOOT_COMPLETED) | Wekkers na herstart opnieuw inplannen | | Batterijoptimalisatie uitzonderen | Achtergrondtaken betrouwbaar | ## Architectuur ``` MainActivity status + instellingen, knop "Nu controleren" AlarmActivity volledig-scherm wekker (geluid, trillen, snooze/dismiss) App kanalen + dagelijkse 12:00-controle bij opstart daily check: AlarmScheduler.scheduleNoonCheck → DailyCheckReceiver (12:00, exact, allowWhileIdle) → ShiftCheck.run agenda morgen ophalen → afronden → wekkers plannen → CalDavClient REPORT calendar-query (time-range, basic auth) → Ical iCal-parse: DTSTART (TZID/UTC), vroegste aanvang → ShiftPlanner afronding op kwartier + Opstaan/Wally/Vertrek ring: AlarmScheduler.scheduleAlarm → AlarmRingReceiver (exact, allowWhileIdle) → full-screen intent + directe start → AlarmActivity → Ringer wekkergeluid (loop) + vibratiepatroon BootReceiver na reboot: 12:00-controle + geplande wekkers herstellen Prefs instellingen/status, versleuteld (EncryptedSharedPreferences) ``` Details per bestand: - `core/ShiftPlanner.kt` — pure logica: kwartier-afronding en wekkerplanning (JVM-unit-tests, geen Android-afhankelijkheden). - `caldav/Ical.kt` — minimale RFC 5545-parser (VEVENT, DTSTART met TZID/UTC, all-day en geannuleerde events worden overgeslagen). - `caldav/CalDavClient.kt` — REPORT calendar-query volgens het recept van de scrapedienst (zie vault-notitie `Homelab/Software ontwikkeling/scrapedienst.md`). - `core/ShiftCheck.kt` — orchestrator: ophalen → filteren op morgen → vroegste aanvang → plannen of annuleren; gedeeld door receiver en knop. - `core/AlarmScheduler.kt` — exacte alarmen + 12:00-controle + snooze + testwekker. - `receivers/DailyCheckReceiver.kt` — 12:00; plant zichzelf via AlarmScheduler steeds opnieuw. - `receivers/AlarmRingReceiver.kt` — afgaande wekker: wakelock, full-screen intent (ook vergrendeld scherm), directe activity-start. - `receivers/BootReceiver.kt` — herstart-herstel (BOOT_COMPLETED, TIME_SET, TIMEZONE_CHANGED, MY_PACKAGE_REPLACED). - `core/Notifier.kt`, `core/Ringer.kt` — meldingen (kanalen "wekkers"/"status") en geluid/trillen. ## Keuzes - **12:00-controle via exact AlarmManager-alarm**, niet WorkManager: precies om 12:00 (WorkManager periodiek is minimaal 15 min en onnauwkeurig). - Bij **meerdere events** op één dag geldt de **vroegste aanvang** als dienstbegintijd. - **All-day-events** (bijv. "vrij") worden genegeerd; alleen getimede diensten tellen. - Na een fout (bv. offline) blijven eerder geplande wekkers staan en verschijnt een statusmelding. - Wachtwoord staat **versleuteld** op het toestel (EncryptedSharedPreferences, AES256-GCM; bij falen plain fallback in de app-sandbox). ## Build - Gradle wrapper 8.13, AGP 8.7.3, Kotlin 2.0.21 - compileSdk/targetSdk 34, minSdk 27 (Android 8.1+) - Tests: `./gradlew :app:testDebugUnitTest` ## Gerelateerd - Scrapedienst die de EBS-Diensten-agenda vult: `~/src/scrapedienst` + vault-notitie `scrapedienst.md` - CalDAV-referentieclient: `~/src/caldav-mcp`