蓝牙 LE 播发
本主题概述了 通用 Windows 平台 (UWP) 应用的蓝牙低功耗 (LE) 播发信标。
重要
必须在 Package.appxmanifest 中声明“蓝牙”功能才能使用此功能。
<Capabilities> <DeviceCapability Name="bluetooth" /> </Capabilities>
重要的 API
受支持的功能
LE 播发 API 支持两大功能:
示例
有关蓝牙 LE 播发的完整功能示例,请参阅 GitHub 上的蓝牙播发示例。
基本设置
若要在通用 Windows 平台应用中使用基本蓝牙 LE 功能,则须在 Package.appxmanifest 中检查蓝牙功能。
- 打开 Package.appxmanifest
- 转到“功能”选项卡
- 在左侧列表中查找“蓝牙”,然后选中它旁边的框。
发布播发
蓝牙 LE 播发允许设备不断标出特定有效负载(称为一次播发)。 如果已设置支持 LE 的任意附近蓝牙设备以侦听是否存在此特定播发,则此类设备均可发现此播发。
注意
为保护用户隐私,播发的生命周期与应用的生命周期相关。 可创建 BluetoothLEAdvertisementPublisher,并在后台任务中调用 Start 以进行播发。 有关后台任务的详细信息,请参阅启动、恢复和后台任务。
可通过多种方式将数据添加到播发。 此示例演示了创建特定于公司的播发的常见方法。
首先,创建播发发布程序,它可控制设备是否正在标出特定播发。
BluetoothLEAdvertisementPublisher publisher = new BluetoothLEAdvertisementPublisher();
然后,创建自定义数据部分。 此示例使用未分配的 CompanyId 值 0xFFFE 并将文本 Hello World 添加到播发中。
// Add custom data to the advertisement
var manufacturerData = new BluetoothLEManufacturerData();
manufacturerData.CompanyId = 0xFFFE;
var writer = new DataWriter();
writer.WriteString("Hello World");
// Make sure that the buffer length can fit within an advertisement payload (~20 bytes).
// Otherwise you will get an exception.
manufacturerData.Data = writer.DetachBuffer();
// Add the manufacturer data to the advertisement publisher:
publisher.Advertisement.ManufacturerData.Add(manufacturerData);
现在,已创建和设置了发布者,你可以调用“开始”来开始发布广告。
publisher.Start();
监视是否存在播发
以下代码演示如何创建蓝牙 LE 播发观察程序、设置回调并开始监视是否存在 LE 播发。
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += OnAdvertisementReceived;
watcher.Start();
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
// Do whatever you want with the advertisement
}
主动扫描
若要同时接收扫描响应播发,则应在创建观察程序后设置以下内容。 请注意,此操作将导致更大的耗用功率,且在后台模式下不可用。
watcher.ScanningMode = BluetoothLEScanningMode.Active;
监视是否存在特定播发模式
有时,你想侦听是否存在特定播发。 在本例中,我们会侦听是否存在包含虚构公司(标识为 0xFFFE)有效负载且在播发中包含字符串 Hello World 的播发。 它可与“基本发布”示例配对,以便有一个 Windows 计算机用于播发,而另一个计算机会用于监视。 在启动观察程序之前,请务必设置此播发筛选器!
var manufacturerData = new BluetoothLEManufacturerData();
manufacturerData.CompanyId = 0xFFFE;
// Make sure that the buffer length can fit within an advertisement payload (~20 bytes).
// Otherwise you will get an exception.
var writer = new DataWriter();
writer.WriteString("Hello World");
manufacturerData.Data = writer.DetachBuffer();
watcher.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData);
监视是否存在附近的播发
有时,仅当设备播发已进入范围时,你才想触发观察程序。 可定义自己的范围,但需注意值会剪切为 0 到 -128 之间。
// Set the in-range threshold to -70dBm. This means advertisements with RSSI >= -70dBm
// will start to be considered "in-range" (callbacks will start in this range).
watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;
// Set the out-of-range threshold to -75dBm (give some buffer). Used in conjunction
// with OutOfRangeTimeout to determine when an advertisement is no longer
// considered "in-range".
watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75;
// Set the out-of-range timeout to be 2 seconds. Used in conjunction with
// OutOfRangeThresholdInDBm to determine when an advertisement is no longer
// considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
测量距离
触发蓝牙 LE 观察程序的回调时,eventArgs 将包含一个 RSSI 值,从而告知接收到的信号强度(蓝牙信号的强度)。
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
// The received signal strength indicator (RSSI)
Int16 rssi = eventArgs.RawSignalStrengthInDBm;
}
该值可大致转换为距离,但不应用于测量真实距离,因为每条无线电均各不相同。 不同的环境因素可能会使距离难以测量(如墙壁、无线电周围的情况,甚至还有空气湿度)。
判断纯距离的替代方法是定义“存储桶”。 无线电往往会在非常接近时报告 0 到 -50 DBm,处于中距离时报告 -50 到 -90 DBm,距离很远时则报告 -90 DBm 以下。 试错法最适合用于确定适用于你的应用的存储桶。