Autor Téma: Android BluetoothLE - CallbackGattTimeout  (Přečteno 337 krát)

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 129
  • Karma: 0
Android BluetoothLE - CallbackGattTimeout
« kdy: 28-05-2019, 20:36:10 »
Vážená komunito,

pokouším se vytvořit stabilní komunikaci přes BluetoothLE s ESP32 modulem (jako server). Bluetooth zařízení je vidět, spojí se, jedna charakteristika pro čtení a druhá pro zápis. Příjem paketů z ESP32 čipu funguje dobře a spojení vydrží i mnoho hodin bez přerušení.

Problém nastává při odesílání paketů do ESP32 čipu pomocí AndroidBluetoothLEDevice.DoWriteCharacteristic. Paket úspěšně dorazí, problém je v tom, že každé odeslání je doprovázeno 5-ti sekundovým zamrznutím kódu. V originálním kódu je totiž jeden řádek, který je dle mého názoru nesmyslný: System.Android.Bluetooth -> FCallbackGattEvents.WaitFor(CallbackGattTimeout);

CallbackGattTimeout je konstanta rovná 5000 definovaná v třídě AndroidBluetoothLEDevice. Rozum by mi velel ji odstranit, vrtá mi hlavou, proč by si Embarcadero vkládalo takovýto nesmyslný "škodič" do kódu? Jakákoliv jiná aplikace (např. stažená z Google Play) je schopná odesílat pakety do ESP32 čipu bez prodlev. Je za tím něco, co nevidím? Jaký to má smysl?

Níže je kompletní funkce pro odesílání charakteristiky z System.Android.Bluetooth. Významu procedury WaitFor prostě nerozumím...
Kód: Delphi [Vybrat]
  1. function TAndroidBluetoothLEDevice.DoWriteCharacteristic(const ACharacteristic: TBluetoothGattCharacteristic): Boolean;
  2. begin
  3.   internalGetGattClient;
  4.   FCallbackGattResult := False;
  5.   if GetIsConnected then
  6.   begin
  7.     if FReconnected then
  8.       UpdateServicesList;
  9.     FCallbackGattEvents.ResetEvent;
  10.     if FJGatt.writeCharacteristic(TAndroidBluetoothGattCharacteristic(ACharacteristic).FJCharacteristic) then
  11.       FCallbackGattEvents.WaitFor(CallbackGattTimeout);
  12.   end;
  13.   Result := FCallbackGattResult;
  14. end;
  15.  

Děkuji za případné rady.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2579
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Re:Android BluetoothLE - CallbackGattTimeout
« Odpověď #1 kdy: 29-05-2019, 07:58:30 »
Významu procedury WaitFor prostě nerozumím...
Ja o te komunikaci jako duchodce cekatel nic nevim a ani vedet nechci, ale podle vseho jde o klasickou synchronizaci pomoci event: nejprve ji vynuluje resetem, pak spusti nejakou operaci, ktera by mela tu event nastavit do stavu signaled a tim WaitFor() ceka nejakou dobu, jestli se tak stane. Pokud se tak nestane, tak by to teroeticky nejak melo reportovat neuspech. A tobe se to zrejme nestasne, kdyz ti to tam visi. Neplest se Sleep().

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 129
  • Karma: 0
Re:Android BluetoothLE - CallbackGattTimeout
« Odpověď #2 kdy: 29-05-2019, 20:08:51 »
Když jsem si prošel kód funkce WaitFor, tak skutečně se čeká na nějaký event, avšak v kódu u DoWriteCharacteristic je to zbytečné. O něčem podobném se na Embarcadero ani nikde jinde nic nepíše. Buď je to něco nedodělaného, nebo hloupé řešení čehosi. Už jen to, že jiné aplikace tímto 5-ti sekundovým zamrznutím netrpí, jedná se čistě o Embarcadeří neplechu.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2579
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Re:Android BluetoothLE - CallbackGattTimeout
« Odpověď #3 kdy: 30-05-2019, 06:38:46 »
avšak v kódu u DoWriteCharacteristic je to zbytečné.
Hmmm.  Zbytecne to rozhodne nebude, protoze nejak musi zjistit, ze BLE zarizeni odpovedelo...

Ta event na kterou to ceka bude soucasti implementace asynchronniho callbacku https://developer.android.com/reference/android/bluetooth/BluetoothGattCallback.html tj. na odezvu zarizeni a chyba u tebe neni v tom, ze se na ni ceka, ale ze nejspis neprijde.

Takze hledas na spatnem konci.



[/quote]

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 129
  • Karma: 0
Re:Android BluetoothLE - CallbackGattTimeout
« Odpověď #4 kdy: 30-05-2019, 07:01:22 »
Pokoušel jsem se zjistit jak Bluetooth LE řeší vzájemnou komunikaci a při vytvoření charakteristiky se určí atribut - čtení / zápis / zápis bez odpovědi atd. Když pak provedete zápis pomocí write, bluetooth by se měl "interně" postarat o jakýsi ACK potvrzení, které již neobsluhujete vy v rámci aplikace. Nikde v příkladech jsem nenašel kód, který by něco podobného prováděl.

Momentálně mám dva konce:
1) Delphi aplikace
2) ESP32 modul

Pokus č.1:
Odeslání paketu z Delphi aplikace do ESP32 modulu je zatíženo 5 sekundovým zamrznutím. Při čekání na dokončení WaitFor se mi dokonce "nabuferují" příchozí pakety z ESP32. Z toho usuzuji, že ESP32 pracuje normálně a problém je pouze v Delphi.

Pokus č.2: 
Nainstaloval jsem si Bluetooth terminál a simuloval odeslání paketu do ESP32. Žádné zamrznutí se nekonalo a příchozí pakety z ESP32 se plynule zpracovaly. ESP32 je tedy "nastaveno" správně.

S ohledem na výše provedené testování je problém pouze v Delphi. Bude fungovat, když vykomentuji WaitFor v původních zdrojových kódech a překompiluji je?

Děkuji.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2579
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Re:Android BluetoothLE - CallbackGattTimeout
« Odpověď #5 kdy: 30-05-2019, 10:42:28 »
Nikde v příkladech jsem nenašel kód, který by něco podobného prováděl.
No vzdyt ted priklad sam posilas: zapisujes atributy a vysledkem by melo by true/false podle toho, jak to dopadlo. Ale abys to mohl vratit, musis vedet, ze operace skoncila a nekde lezi vysledek. A to se podle vseho zajistuje pres tu synchronizacni event, coz byva prostredek OS, ktery moznuje na ni treba povesit thread, ktery se vzbudi, az bude ve stavu signaled apod.

Ty bys nemel zakomentovat WaitFor, ale mel bys v kodu najit neco jako FCallbackGattEvents.SetEvent(...), kde by to melo neco nastavit a tobe se to nedeje. Treba jen nekde v inicializaci nastavit, aby to ty event pouzivalo apod.  Nevim. O teto konkretni komunikaci nic nevim a jako duchodce-cekatel ani vedet nechci.

Je samozrejme mozne, ze tam maji bug, delat chyby je normalni a pustit se do neprobadanych oblastni, se kterymi ma zkusenost jen hrstka programatoru, to je na nejaky dost dobry duvod  ;).

Ja treba vcera stravil nekolik hodin hledanim AV, ktera se mi po mesicich prace vcera odpoledne zniceho nic objevila pri praci s TClientDataSet. Tam maji taky chybu v pripade, ze jim spadne pokus o vytvoreni DSBase (a je nil) ho jdou pouzivat k reportovani chyby. A to je to znacne stara zalezitost a jak jsem zjistil, tak nekteri o te chybe vedi (a nikdo s ni nic nedela).  Ovsem to je chyba indukovana, ta prapricina, ze cele ty mesice a vcera pul dne Delphi nekde nejak lovil MIDASlib.dll a po restartu pocitace, aniz bych se nejak hrabal v PATH & spol nebo neco instaloval, zacal pracovat s nespravnou verzi teto DLL od jine instalace Delphi a vubec netusim proc. Samozrejme pridanim MIDASLib do uses to spravilo.