Bluetooth Funktionalität #8
Labels
No labels
blocked
claude
in-progress
needs-review
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
aiways/AiwaysApp#8
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Wir hatten in folgendem Repo (Link) bereits einen ersten funktionierenden Prototypen gebaut, der die Steuerbefehle per BLE an das Auto sendet .
Können wir diese Funktion in dieser App integrieren? Aktuell schicken wir die Befehle ans Backend und sie landen dort in einer Queue. Könnte man den Mechanismus bei behalten, aber die Logik so ändern, dass er auch eine lokale Queue in der App hält und erstmal versucht das Command per BLE abzuschicken ? (Scan der Umgebung, wird AICHI_* gefunden? Falls ja versuch execute, falls nein, ab ans Backend). Sollte der BLE gefunden werden, aber ein Fehler auftreten, ebenfalls als Backup das Command ans Backend schicken
Umgesetzt (Release
v1.0.28, Commit82ce396). CI + Deploy grün.Der Weg eines Befehls ist jetzt genau der aus Deinem Issue:
AICHI_*. Gefunden → A001-Auth → B001-Befehl →resCode 0. Damit ist der Befehl sofort ausgeführt, ganz ohne Netz.resCode != 0) → ebenfalls ans Backend, genau wie von Dir gewünscht.Eine Entscheidung, die Du kennen solltest: Was per Bluetooth ausgeführt wurde, geht nicht zusätzlich ans Backend. Sonst würde das Auto denselben Befehl später ein zweites Mal ausführen, sobald es wieder online ist. Nebenwirkung: per BLE ausgeführte Befehle tauchen nicht in der Backend-Historie („Letzte Befehle") auf. Wenn Du die Historie vollständig haben willst, wäre der saubere Weg ein Backend-Endpunkt „bereits am Auto ausgeführt" — sag Bescheid, dann lege ich dafür ein Issue im Backend an.
Zur Portierung: Krypto und Protokoll sind aus
aiways/BLEAndroidAppnach Dart übertragen (AES-128-CBC, RSA-1024 PKCS#1, MD5, V1-Frames). Ich habe aus Deinem Java-Prototyp mit festentid/dateReferenzvektoren erzeugt und teste die Dart-Seite byte-genau dagegen — A001- und B001-Frames sind identisch zu dem, was am Auto nachweislich funktioniert. Transport überflutter_blue_plus: Scan, 20-Byte-Chunks mit Response, Frame-Reassembly, pro Befehl eine frische Verbindung — wie im Prototyp.Befehls-Zuordnung: entriegeln/verriegeln/Heckklappe/Fenster auf+zu/Schiebedach kippen/Blinken/Hupe/Klima an+aus (mit Zieltemperatur, ×10 wie in der TBox). Nicht zugeordnet sind
sunroof_open(Prototyp kennt nur „kippen" und „zu") undcharge_port_open— dafür kenne ich keinen verifizierten Code, und am Fahrzeug rate ich nicht. Die beiden gehen weiterhin direkt ans Backend.Sicherheit — bitte kurz gegenlesen: Der Community-Key liegt jetzt auch in diesem Repo. Er wird nur für Android/iOS kompiliert (bedingter Import); im Web-Bundle ist er nicht enthalten — ich habe das im ausgelieferten
main.dart.jsauf http://192.168.1.85/ gegengeprüft (weder Key nochOPENAIWAYS/AICHIkommen darin vor). Das war mir wichtig, weil das Web-Bundle unauthentifiziert im LAN liegt.Was Du noch tun musst: Bluetooth wirkt nur in der Android-App, und die CI baut derzeit kein APK (
BUILD_APK=false). Zum Testen am Auto bitte die Repo-Variable auftruesetzen und einmal neu releasen — dann hängt das APK am Release.Verifiziert: 37 Tests grün (Protokoll gegen die Java-Vektoren, Queue-Weichen inkl. Offline-Fall und Persistenz),
flutter analyzesauber, Web- und Android-Release-Build lokal gebaut, Permissions im fertigen APK geprüft. Am echten Fahrzeug konnte ich nicht testen — das geht nur mit Handy in BLE-Reichweite.Ich habe den BUILD_APK enabled, um das mit BLE zu testen, kannst du noch ein mal den Build triggern?
Build ist durch — Release
v1.0.31(Commitc42cb64), CI + Deploy grün.Mit dem jetzt gesetzten
BUILD_APK=truehängen die APKs am Release:Der Commit ist bewusst leer — am Code hat sich nichts geändert, er stößt nur den Release-Job erneut an, damit er diesmal die APKs baut. Der BLE-Stand aus
82ce396ist unverändert drin, dazu die zwischenzeitlichen Releases zu #6 und #3.Gegengeprüft am fertigen APK (heruntergeladen vom Release, nicht lokal gebaut):
BLUETOOTH_SCAN(neverForLocation),BLUETOOTH_CONNECT, für Android ≤ 11 zusätzlichBLUETOOTH/BLUETOOTH_ADMIN/ACCESS_FINE_LOCATION, dazuINTERNET. Web läuft weiter unter http://192.168.1.85/ (HTTP 200).Für den Test am Auto: Beim ersten Befehl fragt Android nach der Bluetooth-Berechtigung — die braucht es, sonst findet der Scan nichts. Wenn ein Befehl per BLE durchgeht, siehst Du ihn nicht in der Backend-Historie „Letzte Befehle"; das ist so gewollt (sonst führt das Auto ihn später ein zweites Mal aus). Nicht per BLE belegt sind weiterhin
sunroof_openundcharge_port_open— die laufen über das Backend.Falls am Fahrzeug etwas hakt: sag mir bitte, welcher Befehl und was die App anzeigt (Timeout, Auth abgelehnt, oder „ans Backend geschickt"), dann kann ich das gezielt eingrenzen.
Das scheint noch nicht zu funktionieren. Es kommt keine Fehlermeldung, aber er sagt mehr oder weniger direkt "übergeben ans Backend" als würde er BLE gar nicht erst versuchen.
Gefunden — und es lag nicht am Protokoll, sondern an einer Berechtigung, die gar nicht zu erfüllen war. Behoben in Release
v1.0.32(Commitbbcaa01), CI + Deploy grün.Was wirklich passiert ist: Die App hat den Scan mit der Option „Standort mitbenutzen" gestartet. Auf Android 12 und neuer verlangt das Bluetooth-Plugin dann zusätzlich die Standort-Berechtigung — die meldet unser Manifest aber bewusst nur bis Android 11 an, weil wir bei
BLUETOOTH_SCANdas Kennzeichen „wird nicht für Standortbestimmung genutzt" setzen. Eine Berechtigung, die für die laufende Android-Version gar nicht im Manifest steht, lehnt Android sofort und ohne Dialog ab. Das Plugin bricht daraufhin den Scan mit einem Fehler ab. Deshalb kam nach Bruchteilen einer Sekunde „ans Backend übergeben" — der Scan hat nie stattgefunden. Für Android ≤ 11 fordert das Plugin den Standort ohnehin von selbst an; die Option war schlicht falsch und ist raus.Warum Du davon nichts gesehen hast: Die Meldung „ans Backend übergeben" war die einzige Rückmeldung — den Grund hat die App verschluckt. Das war der eigentlich ärgerliche Teil, und den habe ich gleich mit erledigt:
AICHI_*. Darunter läuft eine Mitschrift des BLE-Verkehrs mit Zeitstempeln (Scan, Verbindung, A001, B001, Fehler), die Du mit einem Tipp kopieren kannst. Du testest am Auto mit dem Handy in der Hand, da gibt es keine Konsole — und wenn doch noch etwas hakt, kann ich mit dieser Mitschrift gezielt weitersuchen, statt zu raten.Zum Testen: aiways-app-v1.0.32-arm64-v8a.apk (19,5 MB, das richtige für praktisch jedes aktuelle Handy) oder armeabi-v7a für ältere 32-Bit-Geräte. Beim ersten Scan fragt Android nach der Bluetooth-Berechtigung — diesmal ist es eine, die es auch geben kann. Ich würde zuerst „Mehr → Bluetooth → Umgebung scannen" aufmachen: steht das Auto als
AICHI_…in der Liste, ist der Weg frei; steht es nicht drin, siehst Du wenigstens, dass der Scan überhaupt Geräte findet.Web ist unberührt: Der Menüpunkt erscheint dort nicht, und im ausgelieferten Web-Bundle ist weiterhin weder der Schlüssel noch überhaupt eine Spur von
AICHI/OPENAIWAYS— nachgeprüft am heruntergeladenen Release-Bundle, nicht lokal.Verifiziert:
flutter analyzesauber, 47 Tests grün (die neuen decken ab, dass der Grund beim Backend-Weg mitkommt und dass die Web-Version deswegen nicht bei jedem Befehl eine Meldung zeigt), Web- und Android-Release-Build lokal gebaut, Berechtigungen im heruntergeladenen Release-APK gegengeprüft (BLUETOOTH_SCAN neverForLocation,BLUETOOTH_CONNECT, Standort nur bis Android 11), Web live unter http://192.168.1.85/ (HTTP 200).Am Fahrzeug konnte ich weiterhin nicht testen — das geht nur mit Handy in BLE-Reichweite. Falls es immer noch hakt: bitte einmal „Mehr → Bluetooth" öffnen, scannen, das Protokoll kopieren und hier reinsetzen. Damit sehe ich genau, an welcher Stelle es abbricht.
Okay, Bluetooth scheint zu funktionieren, habe noch nicht alle commands getestet, aber schon einen Verbesserungsvorschlag:
Kann in der App nicht ein Hintergrundprozess laufen, der den Bluetooth Connect schon erledigt und die Verbindung automatisch herstellt?
Aktuell wird für jedes command neu:
Suchen>Verbinden>Authentifizieren>Commands
Das Suchen muss ja nur einmal gemacht werden, danach speichert die App den Client. Hintergrund Prozeß macht > find Client? Connect : wait and try again.
Wenn Connect existiert, direkt commands feuern, sollte die Performance deutlich besser machen.
Außerdem: Es scheint einen blöden Bug zu geben, wo Bluetooth am Telefon aus und wieder angemacht werden muss, bevor es funktioniert, kann man das noch fixen?
Beides umgesetzt — Release
v1.0.33(Commitb2f6c10), CI + Deploy grün.Die Verbindung wird jetzt gehalten
Genau der Ablauf, den Du vorgeschlagen hast: einmal suchen, Adresse merken, verbunden bleiben. Solange die App vorn ist, hält sie die Verbindung samt Anmeldung offen — ein Befehl ist dann nur noch ein einziger B001-Frame, ohne Scan, ohne Verbindungsaufbau, ohne A001. Fällt die Verbindung weg (weggefahren, TBox legt auf), baut sie sich von selbst wieder auf: erst nach 2 Sekunden, dann 4, 8, 15, höchstens 30 — ein Handy, das minutenlang im Sekundentakt nach einem Auto sucht, das nicht da ist, kostet nur Akku.
Der Scan entfällt ab dem zweiten Mal komplett. Die App merkt sich die Bluetooth-Adresse des Fahrzeugs und verbindet direkt dorthin. Das ist nicht nur schneller, es ist auch der eigentliche Grund, warum Dein zweiter Fehler auftrat — dazu gleich mehr.
Neu auf „Mehr → Bluetooth": der Verbindungszustand in Klartext (verbunden / sucht / verbindet / kein Fahrzeug erreichbar), welches Fahrzeug gemerkt ist, ein Schalter „Verbindung halten", Knöpfe zum Verbinden und Trennen von Hand und einer zum Vergessen des gemerkten Fahrzeugs.
Nebenbei: liegengebliebene Befehle aus der lokalen Warteschlange gehen jetzt von selbst raus, sobald das Fahrzeug erreichbar wird — dafür ist die gehaltene Verbindung ja da.
Der „erst nach Bluetooth aus/an"-Fehler
Ich konnte ihn hier nicht nachstellen — dazu bräuchte ich das Auto. Ich habe deshalb die drei bekannten Ursachen angegangen, die genau dieses Verhalten erzeugen, statt eine davon zu raten:
Zusätzlich: geht Bluetooth am Handy wieder an, verbindet die App sofort neu, statt im Wartetakt zu hängen.
Zwei Entscheidungen, die Du kennen solltest
Die Verbindung wird nur gehalten, solange die App offen ist — kein Dienst im Hintergrund. Grund: eine gehaltene Verbindung lässt die TBox aufhören zu werben, solange die App sie hält findet also auch die Original-App das Auto nicht. Solange Du die App gerade offen hast, ist das genau richtig; rund um die Uhr wäre es unhöflich dem Auto gegenüber und kostet Akku auf beiden Seiten. Beim Zurückwechseln in die App steht die Verbindung mit der gemerkten Adresse in ein bis zwei Sekunden wieder.
Mehrere Befehle über eine Anmeldung sind nicht am Fahrzeug verifiziert. Dein Java-Prototyp macht pro Befehl eine frische Verbindung; ob die TBox eine Session über mehrere B001 hinweg akzeptiert, weiß ich schlicht nicht. Deshalb der Rückfall: antwortet die stehende Verbindung nicht oder unlesbar, wird einmal frisch verbunden und derselbe Befehl wiederholt, bevor das Backend übernimmt — im schlimmsten Fall ist es also genau das bisherige, am Auto bewährte Verhalten, nur mit etwas Verzögerung. Ein abgelehnter Befehl (
resCode != 0) wird dagegen nicht wiederholt: das Auto hat ihn verstanden und Nein gesagt, ein zweiter Anlauf wäre nur ein zweites Nein.Falls die TBox eine Session tatsächlich nur für einen Befehl gelten lässt, siehst Du das daran, dass ab dem zweiten Befehl jedes Mal „neu aufbauen" im Protokoll steht. Dann sag Bescheid — dann halte ich die Verbindung, baue aber die Anmeldung pro Befehl neu auf. Das wäre immer noch deutlich schneller als heute, weil Scan und Verbindungsaufbau entfallen.
Zum Testen
aiways-app-v1.0.33-arm64-v8a.apk (19,6 MB, das richtige für praktisch jedes aktuelle Handy) oder armeabi-v7a.
Der erste Befehl am Auto sucht noch einmal (die Adresse ist ja neu zu merken), ab dann sollte es sofort gehen. Auf „Mehr → Bluetooth" kannst Du live mitlesen, ob die Verbindung steht. Wenn doch noch etwas hakt: dort das Protokoll kopieren und hier reinsetzen — darin steht jetzt jeder Schritt mit Zeitstempel, inklusive ob direkt verbunden oder gesucht wurde.
Verifiziert:
flutter analyzesauber, 57 Tests grün (neu: Wiederholabstände, das Scan-Gatter gegen Androids Limit, wann ein zweiter Anlauf sinnvoll ist, und dass die stehende Verbindung liegengebliebene Befehle anstößt), Web- und Android-Release-Build lokal gebaut, Berechtigungen im heruntergeladenen Release-APK gegengeprüft (unverändert, keine neuen — der Verbindungshalter braucht keine), Web live unter http://192.168.1.85/ (HTTP 200) und im ausgelieferten Bundle weiterhin keine Spur von Schlüssel,AICHIoderOPENAIWAYS.Am Fahrzeug konnte ich nicht testen — das geht nur mit Handy in BLE-Reichweite.