# Gemini-Delegator Memory ## Bug-Patterns ### State-Initialisierung bei Scan-Start **Problem identifiziert:** In BleScanner wurde `PositionCalculator` nur beim `startScanning()` initialisiert. Config-Änderungen während eines laufenden Scans wurden nicht übernommen. **Lösung:** Extrahiere Initialisierungs-Logik in separate Methode (`initializePositionCalculator()`), biete öffentliche `reloadConfig()` Methode an. UI ruft diese nach Config-Änderung auf. **Pattern:** Bei Langlebigen Objekten (Scanner) die State von kurzlebiger Config abhängt → Reload-Mechanismus vorsehen. ### KeyboardType für negative Zahlen **Problem:** `KeyboardType.Decimal` und `KeyboardType.Number` erlauben in Android Compose **kein Minuszeichen**. **Lösung:** `KeyboardType.Text` für Felder verwenden, die negative Werte akzeptieren müssen (Koordinaten, RSSI). Validierung via `toDoubleOrNull()` bleibt bestehen. **Betroffene Felder:** Beacon-Koordinaten (X/Y), Raum-Positionen (X/Y), RSSI-Werte (immer negativ). ## Hardware-Debugging ### BLE-Unsichtbarkeit (ESP32 + Android) **Problem:** Ein spezifischer ESP32-C3 wird auf einem spezifischen Android-Handy NICHT gefunden (auch nicht mit nRF Connect), auf anderen Handys aber schon. Andere ESP32s funktionieren auf dem problematischen Handy. **Ursache (wahrscheinlich):** MAC-Adress-Kollision oder Android BLE-Controller-Blacklisting auf Hardware-Level. **Diagnose-Schritte:** 1. Original BLE-MAC auslesen (`esp_bt_dev_get_address()` nach `BLEDevice::init()`) 2. Mit MAC auf funktionierendem Handy (nRF Connect) vergleichen 3. Custom-MAC setzen via `esp_base_mac_addr_set()` **VOR** `BLEDevice::init()` **Lösung:** Custom-MAC flashen mit locally administered Address (Byte 0 = `0x02`), eindeutige Werte wählen. **Code-Pattern (ESP32):** ```cpp #include "esp_bt_device.h" // Für MAC-Ausgabe #include "esp_mac.h" // Für MAC-Setzen uint8_t custom_mac[6] = {0x02, 0xAA, 0xBB, 0xCC, 0xDD, 0x05}; esp_base_mac_addr_set(custom_mac); // VOR BLEDevice::init() BLEDevice::init("Name"); const uint8_t* ble_mac = esp_bt_dev_get_address(); // Ausgeben ``` **Quellen:** [Random Nerd Tutorials](https://randomnerdtutorials.com/get-change-esp32-esp8266-mac-address-arduino/), [Nordic DevZone BLE Invisibility](https://devzone.nordicsemi.com/f/nordic-q-a/77366/nrf-ble-android---my-blescannercompat-doesn-t-detect-a-device-but-nrf-connect-does) ## Projekt-Spezifisches ### BLE Indoor Positioning App - **Aktive Version:** `/App v2/` (vorher `/App v1_2/`) - **Config-Persistierung:** SharedPreferences via `ConfigRepository` - **Datenfluss:** ConfigRepository → BleScanner → PositionCalculator → UI - **Keine DI:** Direkte Instanziierung, StateFlow für Reaktivität - **Sprache:** Kotlin, Compose UI, Kommentare auf Deutsch - **Koordinaten:** Beliebige Werte möglich (auch negativ) – Bounding Box wird aus Räumen + Beacons berechnet ### Kritische Klassen - `BleScanner`: Zentrale BLE-Logik, verwaltet Scanner, Filter, Calculator, Smoother - `PositionCalculator`: Trilateration (IDW + Gauss-Newton + Blending) - `ConfigRepository`: Lädt/Speichert AppConfig (Raumgröße + Beacon-Positionen) - `BeaconFilterManager`: Verwaltet RSSI-Filter pro Beacon (Kalman/EMA/MA) ### Häufige Fehlerquellen - Config-Änderungen während laufender Operationen - Initialisierung nur bei Start ohne Reload-Mechanismus - Fehlende Synchronisation zwischen UI-State und Scanner-State ### Config-Modell Pattern (erweitert) **Gelernt bei:** Individuelle pathLossExponent + rssiAtOneMeter pro Beacon - `@Serializable data class` mit Default-Werten → Abwärtskompatibilität (alte Configs ohne neue Felder laden mit Defaults) - Neue Felder in **beiden** Dialogen: - **AddBeaconDialog:** Neue Beacons (Default-Werte vorbelegen: `mutableStateOf("5.5")`) - **EditBeaconDialog:** Bearbeitung (beacon.field.toString() initialisieren) - Config-Anzeige: LazyColumn erweitern (neue Felder anzeigen) - Beacon-Liste klickbar: `.clickable { showEditBeaconDialog = beacon }` - Berechnungs-Methoden: Per-Beacon-Lookup mit Fallback → `beacons.find { it.minor == beaconMinor }?.field ?: globalDefault` ## Gemini-Interaktion ### Rate Limits Gemini: 429 RESOURCE_EXHAUSTED möglich, liefert oft trotzdem Ergebnisse nach Retries (am Ende der Ausgabe). ### Gemini Prompt Best Practices - Kontext vollständig angeben (relevante Code-Ausschnitte mit Line-Nummern) - Aufgabe strukturiert (nummeriert), Dateipfade explizit - Output-Format: "OUTPUT ONLY unified diff, no explanations" ### Wann selbst fixen vs. Gemini - **Selbst:** Klare Anforderung, minimale Änderung (z.B. KeyboardType-Wechsel) - **Gemini:** Große Refactorings, komplexe Algorithmen - **Nach Gemini:** IMMER fachlich prüfen (Typ, Logik, Patterns) ### Gemini Fehler-Pattern **Problem:** Gemini generiert Diffs mit falschen Annahmen über Datenstrukturen - **Beispiel (2026-02-10):** Negative Koordinaten – Gemini verwendete `.corners` (nicht existent) statt `.x/.y/.width/.height` - **Lösung:** Bei strukturellen Änderungen (Datenmodell, API) relevante Klassen vollständig in Prompt inkludieren - **Warnung:** Gemini erfindet manchmal Pfade (`com.example` statt `com.erik`) → Diff-Pfade immer prüfen ### Color-Parameter in @Composable mit Canvas (2026-02-10) **Problem:** Gemini versuchte `beaconColor: Color = MaterialTheme.colorScheme.primary` als Default-Parameter in Funktionssignatur zu setzen – funktioniert NICHT, da kein @Composable-Context in Parameter-Defaults verfügbar ist. **Lösung:** Color-Parameter MIT Defaults direkt in der @Composable-Funktion deklarieren (wo MaterialTheme verfügbar ist). Bei Helper-Funktionen (z.B. drawRooms) Parameter ohne Defaults durchreichen. **Korrektur:** Nach Gemini-Output selbst gefixt – Color-Parameter in FloorplanView mit MaterialTheme-Defaults versehen, drawRooms()-Signatur manuell erweitert. ### Material Icons Verfügbarkeit (2026-02-10) **Problem:** Gemini generiert oft nicht-existierende Material Icons (z.B. `DarkMode`, `LightMode`, `Brightness4`, `Brightness7`, `Nightlight`, `WbSunny`). **Lösung:** Nach Gemini-Output IMMER Icon-Verfügbarkeit prüfen: - Nur Icons aus `Icons.Default.*` verwenden, die in bestehenden Dateien bereits verwendet werden (z.B. `Settings`, `Place`, `Info`) - Falls spezielle Icons benötigt werden: Im Projekt nach verwendeten Icons greppen (`Icons\.Default\.`) - Fallback: Generische Icons wie `Info`, `Check`, `Star` verwenden **Warnung:** `Icons.Outlined`/`Icons.Filled` sind oft nicht vollständig in älteren Material Icons Versionen verfügbar. ### remember() außerhalb @Composable (2026-02-10) **Problem:** Gemini verwendete `var isDarkMode by remember { mutableStateOf(...) }` in `MainActivity.onCreate()` – `remember` funktioniert NICHT außerhalb von `@Composable` Funktionen. **Lösung:** Direkt `mutableStateOf()` als Property verwenden (`private var isDarkMode by mutableStateOf(false)`) oder `rememberSaveable` INNERHALB `setContent { }` Block nutzen.