Files

6.8 KiB
Raw Permalink Blame History

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):

#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, Nordic DevZone BLE Invisibility

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.