如何使用Delphi的蓝牙低功耗组件访问支持心率服务(Heart Rate Service)的BLE设备。我们将解决在尝试发现BLE设备的服务时遇到的配对要求异常问题,并确保能够正确地获取服务列表。
问题描述
根据提供的代码示例,当调用DiscoverServices
方法时,程序抛出一个异常,提示需要先配对设备。此外,在不调用该命令的情况下,服务数组为空,只有广告数据列表被填充。然而,对于BLE设备来说,通常不需要进行传统意义上的配对即可读取其服务信息。
解决方案
根据德国Delphi社区的信息,Delphi 10.3版本对于无需配对即查询BLE设备服务的支持存在问题。为了解决这个问题,可以按照以下步骤修改系统单元System.Win.BluetoothWinRT
来适应微软的BLE例子中的C#实现。
修改步骤:
修改TWinRTBluetoothLEDevice.CheckInitialized
方法:
将原有的检查初始化的方法调整为异步从蓝牙地址创建BLE设备实例的方式,避免直接抛出未配对的异常。
if FId = 0 then
begin
// 原来的代码会在这里抛出异常...
if TAsyncOperation<IAsyncOperation_1__IBluetoothLEDevice>.Wait(
TBluetoothLEDevice.Statics.FromBluetoothAddressAsync(FAddress), LBLEDeviceAsyncOp) = AsyncStatus.Completed then
begin
FBluetoothLEDevice := LBLEDeviceAsyncOp.GetResults;
FClosed := False;
if DeviceName = '' then
FDeviceName := FBluetoothLEDevice.Name.ToString;
FConnectionStatusChangeDelegate := TConnectionStatusChangeEventHandler.Create(Self);
FBluetoothLEDevice.add_ConnectionStatusChanged(FConnectionStatusChangeDelegate);
Exit;
end;
end;
部分修改DoDiscoverService
方法:
2、在此方法中,通过异步操作获取设备的服务列表,而无需预先配对。
var
dev3: IBluetoothLEDevice3;
res3: IAsyncOperation_1__GenericAttributeProfile_IGattDeviceServicesResult;
serviceRes: GenericAttributeProfile_IGattDeviceServicesResult;
begin
Result := True;
FServices.Clear;
CheckInitialized;
if FID = 0 then
begin
dev3 := fBluetoothLEDevice as IBluetoothLEDevice3;
if dev3 = nil then
raise EBluetoothDeviceException.Create(SBluetoothLEDeviceNotPaired);
if TAsyncOperation<IAsyncOperation_1__GenericAttributeProfile_IGattDeviceServicesResult>.Wait(
dev3.GetGattServicesAsync(BluetoothCacheMode.Uncached), res3) = AsyncStatus.Completed then
begin
serviceRes := res3.GetResults;
LGattServices := serviceRes.Services;
for I := 0 to LGattServices.Size - 1 do
begin
LGattService := LGattServices.GetAt(I);
AddGattService(LGattService);
end;
end;
end;
end;
上述修改基于微软官方的BLE示例项目,适用于Delphi 10.3版本中蓝牙低功耗组件的限制。通过这种方式,您可以绕过不必要的配对要求,直接查询和访问BLE设备的服务信息。希望未来的Delphi版本能够更好地支持这一功能,减少手动修改的需求。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END