119 lines
6.8 KiB
Markdown
119 lines
6.8 KiB
Markdown
# 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.
|