AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung Bluetooth LE unter Windows 11 funktioniert nicht mehr
Thema durchsuchen
Ansicht
Themen-Optionen

Bluetooth LE unter Windows 11 funktioniert nicht mehr

Ein Thema von elmar.faber · begonnen am 13. Aug 2023 · letzter Beitrag vom 3. Jan 2025
 
rabatscher

Registriert seit: 13. Dez 2007
Ort: Bruck an der Mur
69 Beiträge
 
#5

AW: Bluetooth LE unter Windows 11 funktioniert nicht mehr

  Alt 16. Aug 2023, 11:40
Nur kurz zur Info - es scheint, dass das Enumerieren der Characteristiken in Win11 IN einem Thread sein sollt - nicht im Haupthread...
(Message loop und BTLE stehen sowieso auf "Kriegsfuß". Manche Dinge müssen im Haupthread gemacht werden, manche eben nicht).

Der Fix ist im Endefekt in der Datei System.Win.BluetoothWinRT.pas in den Routinen "DoDiscoverServices" und
"DoGetCharacteristics" und "DoGetIncludedServices" einzubauen (Ich habe auch noch eine Art "Timeout" hinzugefügt...):

Hier mein Code:


Code:
function TWinRTBluetoothLEDevice.DoDiscoverServices: Boolean;
var
  I: Integer;
  LGattService: GenericAttributeProfile_IGattDeviceService;
  dev3 : IBluetoothLEDevice3;
  res3 : IAsyncOperation_1__GenericAttributeProfile_IGattDeviceServicesResult;
  serviceRes : GenericAttributeProfile_IGattDeviceServicesResult;
  LGattServices: IVectorView_1__GenericAttributeProfile_IGattDeviceService;
begin
  Result := True;
  FServices.Clear;
  CheckInitialized;
  if FID = 0 then
  begin
       if not Supports(FBluetoothLEDevice, IBluetoothLEDevice3, dev3) then
          raise EBluetoothDeviceException.CreateRes(@SBluetoothLEDeviceNotPaired);

       if TAsyncOperation<IAsyncOperation_1__GenericAttributeProfile_IGattDeviceServicesResult>.Wait(
          dev3.GetGattServicesAsync(BluetoothCacheMode.Uncached), res3 ) = AsyncStatus.Completed then
       begin
            serviceRes := res3.GetResults;

            LGattServices := serviceRes.Services;

            if LGattServices.Size > 0 then
            begin
                 for I := 0 to LGattServices.Size - 1 do
                 begin
                      LGattService := LGattServices.GetAt(I);
                      FServices.Add(TWinRTBluetoothGattService.Create(Self, LGattService, TBluetoothServiceType.Primary));
                 end;
            end;
       end;
  end
  else
  begin
  if FBluetoothLEDevice.GattServices.Size > 0 then
    for I := 0 to FBluetoothLEDevice.GattServices.Size - 1 do
    begin
      LGattService := FBluetoothLEDevice.GattServices.GetAt(I);
      FServices.Add(TWinRTBluetoothGattService.Create(Self, LGattService, TBluetoothServiceType.Primary));
    end;
  end;

  // ###########################################
  // #### enumerate the characteristics at once: note on windows 11 it seems
  // that the enumeration of characteristics NEED to be in a thread and
  // we trigger the characteristics fetch
  for i := 0 to fServices.Count - 1 do
  begin
       TWinRTBluetoothGattService(fServices[i]).FTimeout := fOperationTimeout;
       TWinRTBluetoothGattService(fServices[i]).DoGetCharacteristics;
  end;

  DoOnServicesDiscovered(Self, FServices);
end;

tion TWinRTBluetoothGattService.DoGetCharacteristics: TBluetoothGattCharacteristicList;
var I: Integer;
    service3 : GenericAttributeProfile_IGattDeviceService3;
    LGattCharacteristics: IVectorView_1__GenericAttributeProfile_IGattCharacteristic;
    res3 : IAsyncOperation_1__GenericAttributeProfile_IGattCharacteristicsResult;
    status1 : IAsyncOperation_1__GenericAttributeProfile_GattOpenStatus;
    charactersRes : GenericAttributeProfile_IGattCharacteristicsResult;
    characteristic : GenericAttributeProfile_IGattCharacteristic;
begin
  Result := FCharacteristics;
  if fCharacteristicsFetched then
     exit;

  CheckNotClosed;
  FCharacteristics.Clear;

  if Supports(FGattService, GenericAttributeProfile_IGattDeviceService3, service3) then
  begin
       if TAsyncOperation<IAsyncOperation_1__GenericAttributeProfile_GattOpenStatus>.Wait(
              service3.OpenAsync(GenericAttributeProfile_GattSharingMode.SharedReadAndWrite), status1 ) <> AsyncStatus.Completed
       then
           exit(nil);

       if (status1.GetResults = GenericAttributeProfile_GattOpenStatus.Success) or
          (status1.GetResults = GenericAttributeProfile_GattOpenStatus.AlreadyOpened) then
       begin
            if TAsyncOperation<IAsyncOperation_1__GenericAttributeProfile_IGattCharacteristicsResult>.Wait(
                   service3.GetCharacteristicsAsync(BluetoothCacheMode.Uncached), res3, FTimeout ) = AsyncStatus.Completed
            then
            begin
                 charactersRes := res3.GetResults;

                 LGattCharacteristics := charactersRes.Characteristics;

                 if LGattCharacteristics.Size > 0 then
                 begin
                      for I := LGattCharacteristics.Size - 1 downto 0 do
                      begin
                           characteristic := LGattCharacteristics.GetAt(I);
                           FCharacteristics.Add(TWinRTBluetoothGattCharacteristic.Create(Self, characteristic));
                      end;
                 end;
            end;
       end
       else
           OutputDebugString(PChar('RequestAccessAysync failed with code ' + Integer(status1.GetResults).tostring));
  end
  else
  begin
       // does not work any more -> need to do sync
       LGattCharacteristics := (FGattService as GenericAttributeProfile_IGattDeviceService2).GetAllCharacteristics;
       if LGattCharacteristics.Size > 0 then
         for I := 0 to LGattCharacteristics.Size - 1 do
           FCharacteristics.Add(TWinRTBluetoothGattCharacteristic.Create(Self, LGattCharacteristics.GetAt(I)));
  end;

  for i := 0 to FCharacteristics.Count - 1 do
  begin
       TWinRTBluetoothGattCharacteristic(fCharacteristics[i]).FTimeout := FTimeout;
       TWinRTBluetoothGattCharacteristic(fCharacteristics[i]).DoGetDescriptors;
  end;

  fCharacteristicsFetched := True;
  Result := FCharacteristics;
end;

function TWinRTBluetoothGattService.DoGetIncludedServices: TBluetoothGattServiceList;
var
  I: Integer;
  LGattServices: IVectorView_1__GenericAttributeProfile_IGattDeviceService;
  service3 : GenericAttributeProfile_IGattDeviceService3;
  res3 : IAsyncOperation_1__GenericAttributeProfile_IGattDeviceServicesResult;
  serviceRes : GenericAttributeProfile_IGattDeviceServicesResult;
  status1 : IAsyncOperation_1__GenericAttributeProfile_GattOpenStatus;
begin
  CheckNotClosed;
  FIncludedServices.Clear;

  if Supports(FGattService, GenericAttributeProfile_IGattDeviceService3, service3) then
  begin
       if TAsyncOperation<IAsyncOperation_1__GenericAttributeProfile_GattOpenStatus>.Wait(
              service3.OpenAsync(GenericAttributeProfile_GattSharingMode.SharedReadAndWrite), status1 ) <> AsyncStatus.Completed
       then
           exit(nil);

       if (status1.GetResults = GenericAttributeProfile_GattOpenStatus.Success) or
          (status1.GetResults = GenericAttributeProfile_GattOpenStatus.AlreadyOpened) then
       begin
            if TAsyncOperation<IAsyncOperation_1__GenericAttributeProfile_IGattDeviceServicesResult>.Wait(
                   service3.GetIncludedServicesAsync, res3, FTimeout ) = AsyncStatus.Completed
            then
            begin
                 serviceRes := res3.GetResults;

                 LGattServices := serviceRes.Services;

                 if LGattServices.Size > 0 then
                 begin
                      for I := LGattServices.Size - 1 downto 0 do
                          FIncludedServices.Add(TWinRTBluetoothGattService.Create(FDevice, LGattServices.GetAt(I), TBluetoothServiceType.Primary));
                 end;
            end;
       end
       else
           OutputDebugString(PChar('RequestAccessAysync failed with code ' + Integer(status1.GetResults).tostring));
  end
  else
  begin
       LGattServices := (FGattService as GenericAttributeProfile_IGattDeviceService2).GetAllIncludedServices;
       if LGattServices.Size > 0 then
         for I := 0 to LGattServices.Size - 1 do
           FIncludedServices.Add(TWinRTBluetoothGattService.Create(FDevice, LGattServices.GetAt(I), TBluetoothServiceType.Primary));
  end;

  Result := FIncludedServices;
end;
Bitte mal mit dem Snipplets probieren und für fTimeout = 10000 einsetzen. fCharacteristicsFetched ist auch von mir und sollte im TWinRTBluetoothGattService als private variable deklariert werden.

Falls wer noch interesse hat ich kann das File auch schicken - nur nicht ganz öffentlich machen...
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz