You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Delphi 10.3 BTLE心率服务发现异常:需配对及设备发现事件未触发咨询

Delphi BLE Heart Rate Service Troubleshooting: Core Misunderstandings & Fixes

Let's break down your core misunderstandings first, then walk through practical fixes for your code:

1. Misconception: BLE Never Requires Pairing

You’re correct that most standard BLE services (like Heart Rate) are designed for open access, but Windows (and Delphi’s BLE implementation) may still trigger implicit pairing/bonding when accessing services with underlying security requirements. Even if your device doesn’t show a manual pairing prompt, the OS might initiate a background pairing process when you attempt to discover services—this is what’s throwing your exception. You don’t need pre-pair manually, but you do need to let the OS handle automatic pairing requests.

2. Misconception: OnEndDiscoverDevices Only Triggers When Cancelled

The OnEndDiscoverDevices event should fire both when the scan interval expires naturally AND when you call CancelDiscovery. The reason it only fires on cancel is your timCancel timer cuts the scan short before the 18-second interval finishes. If you let the scan run to completion without cancelling, the event will trigger automatically.

Also, BTLE.DiscoverDevices() handles the timeout internally—you don’t need a manual timer to cancel it. Your current timer overrides the natural scan completion flow.

3. Misconception: You Can Discover Services Without Connecting First

In your tvDevicesClick handler, you’re calling aDev.DiscoverServices() directly without establishing a connection to the device first. For BLE, you must connect to the device before you can discover its services. The DiscoverServices method tries to connect implicitly, but if that connection triggers an unhandled pairing request, it throws an exception.


Code Fixes to Resolve These Issues

Fix 1: Let Scans Complete Naturally (Fix OnEndDiscoverDevices)

Remove the timCancel timer logic from Button1Click—let DiscoverDevices handle the timeout on its own:

procedure TForm1.Button1Click(Sender: TObject);
begin
  tvDevices.Items.Clear;
  // Let DiscoverDevices manage the 18-second timeout internally
  if BTLE.DiscoverDevices(18000, [HRSERVICE]) then
    memLog.Lines.Add('Scan started successfully');
end;

You can delete the timCancelTimer procedure and remove the timer from your form entirely, or add a dedicated "Stop Scan" button if you need manual cancellation.

Fix 2: Connect Before Discovering Services

Modify your tvDevicesClick handler to first connect to the selected device, then discover services once connected. Add an OnConnected event to your TBluetoothLE component:

// Add this event to your BTLE component via the form designer
procedure TForm1.BTLEConnected(const Sender: TObject; const ADevice: TBluetoothLEDevice);
begin
  memLog.Lines.Add('Connected to ' + ADevice.DeviceName);
  // Discover services only after successful connection
  ADevice.DiscoverServices;
end;

procedure TForm1.tvDevicesClick(Sender: TObject);
var
  SelectedDeviceName: string;
  aDev : TBluetoothLEDevice;
begin
  if tvDevices.Selected = nil then Exit;
  SelectedDeviceName := tvDevices.Selected.Text;

  for aDev in btle.CurrentManager.AllDiscoveredDevices do
  begin
    if (aDev.DeviceName = SelectedDeviceName) or (aDev.Identifier = SelectedDeviceName) then
    begin
      memLog.Lines.Add('Attempting to connect to ' + SelectedDeviceName);
      // Initiate connection to the device
      aDev.Connect;
      Break;
    end;
  end;
end;

Fix 3: Handle Pairing Requests (If Needed)

If the OS prompts for pairing, auto-accept requests for your device by adding an OnPairingRequest event to TBluetoothLE:

// Add this event to your BTLE component via the form designer
procedure TForm1.BTLEPairingRequest(const Sender: TObject; const ADevice: TBluetoothLEDevice; var PairingAccepted: Boolean);
begin
  // Auto-accept pairing for your heart rate device
  PairingAccepted := True;
  memLog.Lines.Add('Accepting pairing request for ' + ADevice.DeviceName);
end;

Quick Bug Fix

Your bytesToStr function has an off-by-one error—change:

for i := 0 to Length(aval) do

to:

for i := 0 to Length(aval) - 1 do

This prevents accessing an index beyond the array’s bounds.


内容的提问来源于stack exchange,提问作者mrabat

火山引擎 最新活动