Files
Claude-Test-App/ESP32-Code-Analyse.md

6.9 KiB
Raw Permalink Blame History

ESP32 iBeacon Code-Analyse

Analyse des ESP32-Codes (ESP32_iBeacon/ESP32_iBeacon.ino) auf mögliche Ursachen für instabile RSSI-Messwerte in der Android-App.

Datum: 2026-02-09


Quelle: Gemini-Analyse

Die folgenden Probleme wurden von Google Gemini identifiziert:

1. KRITISCH: Advertising-Konflikt zwischen Service und iBeacon

Gemini-Befund: init_service() und init_beacon() überschreiben sich gegenseitig das Advertising-Paket. init_service() startet Advertising mit Service-UUID, dann stoppt init_beacon() alles und überschreibt es mit iBeacon-Daten. Das Service-Advertising geht verloren. Beim Reconnect nach Disconnect wird pAdvertising->start() aufgerufen, aber es ist unklar, welche Advertising-Daten dann aktiv sind.

Gemini-Empfehlung: Kombinierte Funktion nutzen, die iBeacon-Daten ins Haupt-Paket und die Service-UUID ins Scan-Response-Paket legt.

Eigene Einschätzung: Bestätigt. Im Code wird in Zeile 78 (init_service) Advertising gestartet, in Zeile 85 (init_beacon) sofort wieder gestoppt und neu konfiguriert. Das ist zwar für den reinen iBeacon-Betrieb kein Problem (das letzte Paket gewinnt), aber der onDisconnect-Callback (Zeile 29) startet Advertising erneut, ohne die iBeacon-Daten neu zu setzen. Nach einer Verbindung könnten also fehlerhafte Advertising-Pakete gesendet werden.

2. HOCH: Kein explizites Advertising-Intervall gesetzt

Gemini-Befund: Ohne explizites Intervall nutzt der ESP32 den BLE-Stack-Default. Unregelmäßige Pakete führen zu variierenden Abtastraten auf der Android-Seite und damit zu instabilen RSSI-Werten.

Gemini-Empfehlung: Festes Intervall von 100ms setzen:

pAdvertising->setMinInterval(0xA0); // 160 * 0.625ms = 100ms
pAdvertising->setMaxInterval(0xA0);

Eigene Einschätzung: Bestätigt und sehr relevant. Der Default-Intervall liegt typischerweise bei 100-1280ms, was für Indoor-Positioning zu unregelmäßig ist. Ein festes, kurzes Intervall (100ms) sorgt für konsistente Datenrate auf der Android-Seite. Die Android-App scannt bereits mit SCAN_MODE_LOW_LATENCY (BleScanner.kt:165), profitiert aber nur davon, wenn der ESP32 auch regelmäßig sendet.

3. HOCH: TX-Power nicht explizit konfiguriert

Gemini-Befund: Die Sendeleistung wird nicht festgelegt, was zu variierender Ausgangsleistung führen kann.

Gemini-Empfehlung:

BLEDevice::setPower(ESP_PWR_LVL_P9); // +9 dBm

Eigene Einschätzung: Bestätigt. Ohne fixe TX-Power kann der ESP32 die Leistung dynamisch anpassen. Für RSSI-basierte Distanzschätzung ist eine konstante Sendeleistung zwingend notwendig, da die gesamte Berechnung auf dem Log-Distance Path Loss Model basiert. Hinweis: Der Seeed XIAO ESP32-C3 unterstützt bis zu +21 dBm – der korrekte Enum-Wert muss ggf. angepasst werden.

4. MITTEL: setSignalPower nicht kalibriert

Gemini-Befund: Der Wert 0xc5 (-59 dBm) im iBeacon-Paket ist ein Standardwert und nicht für die verwendete Hardware kalibriert.

Gemini-Empfehlung: RSSI bei exakt 1m Abstand messen (60s Durchschnitt) und den gemessenen Wert als Signed Byte in Hex setzen.

Eigene Einschätzung: Teilweise relevant. Der signalPower-Wert wird in der Android-App aktuell nicht für die Distanzberechnung verwendet – stattdessen wird BeaconData.RSSI_AT_ONE_METER = -65.0 in Kotlin hardcoded (BeaconData.kt:37). Die App liest zwar txPower aus dem Paket (BleScanner.kt:145), nutzt ihn aber nicht im PositionCalculator. Trotzdem sollte der Wert korrekt sein, falls er zukünftig genutzt wird.

5. MITTEL: Advertising-Flags

Gemini-Befund: Flags 0x1A statt Standard-iBeacon 0x06.

Gemini-Empfehlung: 0x06 verwenden (LE General Discoverable + BR/EDR Not Supported).

Eigene Einschätzung: Geringes Risiko. 0x1A setzt zusätzlich das Bit für "Simultaneous LE and BR/EDR (Controller)" – bei einem reinen BLE-Beacon unnötig, aber in der Praxis unproblematisch. 0x06 wäre sauberer.

6. NIEDRIG: Manufacturer ID Byte-Order

Gemini-Befund: ESP32 sendet 0x004C (Little-Endian, korrekt laut BLE-Spec). Android-App parst mit 0x4C00.

Gemini-Empfehlung: Android-App prüfen.

Eigene Einschätzung: Kein Problem. Android's getManufacturerSpecificData() erwartet den Company Identifier in Host-Byte-Order. Der Wert 0x4C00 in der Android-App (BeaconData.kt:12) ist korrekt für Apple's Company ID und funktioniert nachweislich (die App empfängt ja Beacons). Die ESP32-Bibliothek übernimmt die Konvertierung intern.


Eigene Zusatzanalyse (Claude)

Über die Gemini-Analyse hinaus sind folgende Punkte aufgefallen:

7. HOCH: loop() sendet Notifications alle 2 Sekunden

In loop() (Zeile 114-123) wird bei bestehender Verbindung alle 2 Sekunden eine Notification gesendet. Das ist für den iBeacon-Betrieb irrelevant, aber: Wenn sich ein Gerät verbindet, könnte das Advertising unterbrochen oder verlangsamt werden. Der ESP32 BLE-Stack kann nicht gleichzeitig eine aktive Verbindung bedienen und mit voller Rate advertisen.

Empfehlung: Für reinen Beacon-Betrieb den gesamten Service-Teil entfernen (init_service, MyCallbacks, MyServerCallbacks, Notification-Code in loop). Der ESP32 soll nur advertisen, keine Verbindungen annehmen.

8. MITTEL: Kein Deep-Sleep / Light-Sleep zwischen Advertisements

Für Akkubetrieb fehlt jegliche Energiespar-Logik. Der ESP32 läuft permanent im aktiven Modus, auch zwischen den Advertising-Events.

Empfehlung: Für den Seeed XIAO ESP32-C3 im Akkubetrieb Light-Sleep aktivieren oder den ESP32 zwischen Advertisements in den Deep-Sleep schicken und per Timer aufwecken.

9. NIEDRIG: PositionSmoother Alpha-Wert Diskrepanz

In der CLAUDE.md und im PositionSmoother-Defaultwert steht alpha=0.25, aber in BleScanner.kt:52 wird PositionSmoother(alpha = 0.15) instanziiert. Der tatsächlich verwendete Wert ist 0.15 (reaktiver als dokumentiert).


Zusammenfassung: Prioritäten

# Priorität Problem Quelle
1 KRITISCH Advertising-Konflikt Service/iBeacon Gemini
2 HOCH Kein Advertising-Intervall gesetzt Gemini
3 HOCH TX-Power nicht fixiert Gemini
7 HOCH Verbindungen stören Advertising Claude
4 MITTEL SignalPower nicht kalibriert Gemini
5 MITTEL Advertising-Flags suboptimal Gemini
8 MITTEL Kein Energiesparmodus Claude
9 NIEDRIG Alpha-Wert Diskrepanz Doku vs Code Claude
6 NIEDRIG Manufacturer ID Byte-Order Gemini

Empfohlene Maßnahmen (Reihenfolge)

  1. Service-Teil komplett entfernen (nur iBeacon-Advertising, keine Verbindungen)
  2. Festes Advertising-Intervall setzen (100ms)
  3. TX-Power explizit auf Maximum fixieren
  4. SignalPower im iBeacon-Paket kalibrieren (RSSI @ 1m messen)
  5. Flags auf 0x06 ändern
  6. Light-Sleep für Akkubetrieb implementieren
  7. Alpha-Wert in CLAUDE.md korrigieren (0.15 statt 0.25)