android-buschauffeurswekker/README.md

7 KiB
Raw Permalink Blame History

Buschauffeurswekker

Android-wekker-app die wekkers automatisch zet op basis van het EBS-dienstrooster in de Nextcloud CalDAV-agenda EBS-Diensten. De wekker wekt zoals elke normale wekker-app (geluid, trillen, volledig scherm, snooze) — maar het wanneer wordt zelf bepaald uit de dienst van morgen.

Werking

Elke dag om 12:00 haalt de app de agenda van morgen op en zet daaruit de dienstaanvang. Die wordt naar beneden afgerond op een heel kwartier:

Aanvang dienst Aangenomen aanvang
05:00 – 05:14 05:00
05:15 – 05:29 05:15
05:30 – 05:44 05:30
05:45 – 05:59 05:45

Technisch: minuut = (minuut / 15) * 15 (floor op kwartier). Rond middernacht kan de wekker op de vorige dag vallen (dienst 00:10 → Opstaan de dag ervoor 22:00).

Daarna worden drie wekkers gezet, elk voor de afgeronde aanvang:

Wekker Tijd vóór aanvang Voorbeeld (06:15)
Opstaan 2 uur 04:15
Wally 1,5 uur 04:45
Vertrek 0,5 uur 05:45

Geen dienst morgen → geen wekkers.

Kenmerken

  • Donkere wekker-UI in de stijl van de systeemwekker: kop "Wekkers", één kaart per wekker met grote tijd + naam, acties achter het ⋮-menu.
  • Aan/uit per wekker — schakelaar op elke kaart; een uitgezette wekker blijft uit (ook de dagelijkse 12:00-controle plant hem niet opnieuw) tot je hem weer aanzet. Uitgeschakelde kaart is grijs, aangezette blauw.
  • Eigen geluid per wekker via Instellingen → Wekkergeluiden (systeem-ringtone- kiezer). Standaard is het systeem-alarmgeluid; valt terug op die toon als het gekozen bestand verdwenen is.
  • Volwaardige wekker: geluid (herhalend) + trillen, volledig scherm óók bovenop het vergrendelscherm, snooze 10 min, "wekker uit".
  • Werkt op de achtergrond: exacte alarmen (ook in Doze), herstel na herstart, mobiele data toegestaan.
  • Statusmelding om 12:00 met de wekkers van morgen; tikken opent de app.

Schermen

  • Hoofdscherm — "Wekkers": de drie wekkerkaarten (met aan/uit) van morgen; onderaan de diensttijd ("Dienst om 06:18"). Het ⋮-menu bevat Nu controleren en Instellingen.
  • Instellingen — CalDAV-gegevens (agenda-URL, gebruiker, app-wachtwoord + Opslaan) en Wekkergeluiden (per wekker een geluid).
  • Afgaande wekker — full-screen: naam, lopende klok, Snooze (10 min) / Wekker uit.

Installatie

  1. Bouw: ./gradlew :app:assembleDebug → app/build/outputs/apk/debug/app-debug.apk
  2. APK op de telefoon zetten en installeren (sideload).
  3. App openen → ⋮ → Instellingen → invullen:
    • 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). Niet in de app hardcoden; zie de Obsidian-vault.
  4. Opslaan → terug → ⋮ → Nu controleren om te testen.
  5. Meldingenmachtiging: systeemdialoog bij de eerste start.

Config is ook zonder UI te zetten (installatiehulp):

adb shell am start -n nl.eddydevink.buschauffeurswekker/.MainActivity \
  --es url 'https://nextcloud.eddydevink.nl/remote.php/dav/calendars/eddy/ebs_diensten-1/' \
  --es user 'eddy' --es pass '<app-wachtwoord>'

Machtigingen

Machtiging Doel
Internet / netwerk Agenda ophalen over wifi én mobiele data
Meldingen (POST_NOTIFICATIONS) Afgaande wekker + status 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 + 12:00-controle na herstart herstellen

Architectuur

App                  kanalen + 12:00-controle bij opstart

dagelijks 12:00
  AlarmScheduler.scheduleNoonCheck (exact, allowWhileIdle)
    → DailyCheckReceiver → ShiftCheck.run
        CalDavClient  REPORT calendar-query (time-range, basic auth)
        Ical          iCal-parse: DTSTART (TZID/UTC), vroegste aanvang
        ShiftPlanner  kwartier-afronding + Opstaan/Wally/Vertrek
        AlarmScheduler  plan de aangezette wekkers

afgaan
  AlarmScheduler.scheduleAlarm (exact, allowWhileIdle)
    → AlarmRingReceiver → full-screen intent + start → AlarmActivity
        Ringer      geluid (loop; eigen keuze met fallback) + trillen
        snooze 10 min / dismiss

MainActivity / SettingsActivity  UI (kaarten, menu, instellingen, geluidskeuze)
BootReceiver     na reboot: wekkers + 12:00-controle herstellen
Prefs            instellingen/status/plan, versleuteld (EncryptedSharedPreferences)

Modules

  • core/ShiftPlanner.kt — pure logica: kwartier-afronding + wekkerplanning (JVM-tests).
  • 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 (recept uit de scrapedienst).
  • core/ShiftCheck.kt — orchestrator: ophalen → filteren op morgen → vroegste aanvang → plannen (aangezette) of annuleren; gedeeld door receiver, menu-knop en setup-intent.
  • core/AlarmScheduler.kt — exacte alarmen, 12:00-controle, snooze, per-naam aanv/uit.
  • core/Notifier.kt — kanalen "wekkers"/"status"; statusmelding tikt de app open.
  • core/Ringer.kt — wekkergeluid (loop) gekozen per wekker + vibratie; fallback naar de standaard alarmtoon als het gekozen bestand weg is.
  • receivers/DailyCheckReceiver.kt, AlarmRingReceiver.kt, BootReceiver.kt.
  • AlarmActivity.kt — full-screen wekker (geluid, trillen, snooze/dismiss).
  • SettingsActivity.kt — CalDAV-gegevens + per-wekker geluidskeuze.

Keuzes

  • 12:00-controle = exact AlarmManager-alarm, niet WorkManager: precies om 12:00 (WorkManager-periodiek is minimaal 15 min en onnauwkeurig).
  • Meerdere events op één dag → vroegste aanvang telt als dienstaanvang.
  • All-day-events ("vrij") tellen niet; alleen getimede diensten.
  • Na een fout (bv. offline) blijven eerder geplande wekkers staan + statusmelding.
  • Wachtwoord versleuteld op het toestel (EncryptedSharedPreferences AES256-GCM; bij falen plain fallback in de app-sandbox). Nooit hardcoded.
  • UI volgt Material 3: donker thema, standaard MaterialSwitch en systeemcomponenten.

Build & test

  • Gradle wrapper 8.13 · AGP 8.7.3 · Kotlin 2.0.21
  • compileSdk/targetSdk 34, minSdk 27 (Android 8.1+)
  • ./gradlew :app:assembleDebug en ./gradlew :app:testDebugUnitTest
  • Unit tests dekken de afrondingsvoorbeelden (incl. de vier óf), wekkerplanning, iCal-parse en een snapshot van een echte serverresponse door de pipeline.

Gerelateerd

  • Scrapedienst — vult de ebs_diensten-agenda (dagelijks 17:05): ~/src/scrapedienst + vault-notitie Homelab/Software ontwikkeling/scrapedienst.md
  • CalDAV-referentieclient: ~/src/caldav-mcp
  • Meldingen/wekkers staan uit; zie de Obsidian-vault-notitie Homelab/Software ontwikkeling/Buschauffeurswekker.md