android-buschauffeurswekker/README.md

5.5 KiB
Raw Blame History

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 → Instellingen → vul 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. Opslaan, terug op het hoofdscherm Nu controleren om te testen.
  5. Verleen de meldingenmachtiging bij de eerste start (systeemdialoog).

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            hoofdscherm: klok + geplande wekkers + "Nu controleren" + link naar instellingen
SettingsActivity        instellingen: CalDAV-url, gebruiker, app-wachtwoord (+ uitleg)
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)

Hoofdscherm en instellingen zijn bewust gescheiden; installatiehulp via launch-intent-extra's (--es url/user/pass) slaat de config op en draait direct een controle, zonder UI-interactie.

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