[英]How do I correctly subscribe to a bluetooth low energy device's GattCharacteristic.ValueChanged notification (indication) in a Windows UWP App?
On my Linux machine I have successfully subscribed to a Timeular/ZEI Bluetooth LE Device using Java, the TinyB Library and BlueZ. 在我的Linux机器上,我已经使用Java, TinyB库和BlueZ成功订阅了Timeular / ZEI蓝牙LE设备。
However I do need the same functionality for Windows 10 (1709). 但是我确实需要Windows 10(1709)的相同功能。 I am using the most recent Windows SDK with Visual Studio 2017. 我在Visual Studio 2017中使用最新的Windows SDK。
My goal is to subscribe to a GattCharacteristic.ValueChanged
event, so whenever someone is "rolling the dice", the BTLE device will send a notification to the Windows App and call my DiceOrientationChangeHandler
. 我的目标是订阅GattCharacteristic.ValueChanged
事件,因此无论何时有人“掷骰子”,BTLE设备都会向Windows应用程序发送通知并调用我的DiceOrientationChangeHandler
。
What I got so far is: 到目前为止,我得到的是:
const string DEVICE_MAC_ADDRESS = "ee:ab:17:be:37:20"; //Timeular's MAC address
const string BLUETOOTH_LE_SERVICE_UUID = "c7e70010-c847-11e6-8175-8c89a55d403c"; //the service which contains Timeular's orientation change characteristic
const string BLUETOOTH_LE_CHARACTERISTIC_UUID = "c7e70012-c847-11e6-8175-8c89a55d403c"; //the characteristic that allows subscription to notification (indication) for orientation change
public async void SubscribeToOrientationChangeNotification()
{
BluetoothLEDevice bluetoothLEDevice = null;
//loop through bluetooth devices until we found our desired device by mac address
DeviceInformationCollection deviceInformationCollection = await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector());
foreach (var deviceInformation in deviceInformationCollection)
{
String deviceInformationId = deviceInformation.Id;
String mac = deviceInformationId.Substring(deviceInformationId.Length - 17);
if (mac.Equals(DEVICE_MAC_ADDRESS))
{
bluetoothLEDevice = await BluetoothLEDevice.FromIdAsync(deviceInformation.Id);
Debug.WriteLine($"Found Bluetooth LE Device [{mac}]: {bluetoothLEDevice.ConnectionStatus}");
break;
}
}
//Subscribe to the connection status change event
bluetoothLEDevice.ConnectionStatusChanged += ConnectionStatusChangeHandler;
//get the desired service
Guid serviceGuid = Guid.Parse(BLUETOOTH_LE_SERVICE_UUID);
GattDeviceServicesResult serviceResult = await bluetoothLEDevice.GetGattServicesForUuidAsync(serviceGuid);
if (serviceResult.Status == GattCommunicationStatus.Success)
{
GattDeviceService service = serviceResult.Services[0];
Debug.WriteLine($"Service @ {service.Uuid}, found and accessed!");
//get the desired characteristic
Guid characteristicGuid = Guid.Parse(BLUETOOTH_LE_CHARACTERISTIC_UUID);
GattCharacteristicsResult characteristicResult = await service.GetCharacteristicsForUuidAsync(characteristicGuid);
if (characteristicResult.Status == GattCommunicationStatus.Success)
{
GattCharacteristic characteristic = characteristicResult.Characteristics[0];
Debug.WriteLine($"Characteristic @ {characteristic.Uuid} found and accessed!");
//check access to the characteristic
Debug.Write("We have the following access to the characteristic: ");
GattCharacteristicProperties properties = characteristic.CharacteristicProperties;
foreach (GattCharacteristicProperties property in Enum.GetValues(typeof(GattCharacteristicProperties)))
{
if (properties.HasFlag(property))
{
Debug.Write($"{property} ");
}
}
Debug.WriteLine("");
//subscribe to the GATT characteristic's notification
GattCommunicationStatus status = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
if (status == GattCommunicationStatus.Success)
{
Debug.WriteLine("Subscribing to the Indication/Notification");
characteristic.ValueChanged += DiceOrientationChangeHandler;
}
else
{
Debug.WriteLine($"ERR1: {status}");
}
} else
{
Debug.WriteLine($"ERR2: {characteristicResult.Status}");
}
} else
{
Debug.WriteLine($"ERR3: {serviceResult.Status}");
}
}
public void DiceOrientationChangeHandler(GattCharacteristic sender, GattValueChangedEventArgs eventArgs)
{
Debug.WriteLine($"Dice rolled...");
}
public void ConnectionStatusChangeHandler(BluetoothLEDevice bluetoothLEDevice, Object o)
{
Debug.WriteLine($"The device is now: {bluetoothLEDevice.ConnectionStatus}");
}
The output looks like: 输出如下:
Found Bluetooth LE Device [ee:ab:17:be:37:20]: Connected 找到了蓝牙LE设备[ee:ab:17:be:37:20]:已连接
Service @ c7e70010-c847-11e6-8175-8c89a55d403c, found and accessed! 找到并访问了服务@ c7e70010-c847-11e6-8175-8c89a55d403c!
Characteristic @ c7e70012-c847-11e6-8175-8c89a55d403c found and accessed! 找到并访问了@ c7e70012-c847-11e6-8175-8c89a55d403c特征!
We have the following access to the characteristic: None Read Indicate 我们可以通过以下方式访问该特征:无阅读指示
Subscribing to the Indication/Notification 订阅指示/通知
The device is now: Disconnected 设备现已:断开连接
But whenever I change the device's orientation, nothing happens. 但是,每当我更改设备的方向时,都不会发生任何事情。 The service uuid and characteristic uuid are the same that I am using in the Linux program, where the orientation change handler is working. 服务uuid和特征uuid与我在Linux程序中使用的相同,方向更改处理程序正在其中工作。
After a short while, one last message will be printed to the console: 片刻之后,最后一条消息将被打印到控制台:
The Thread 0x2b40 has exited with code 0 (0x0). 线程0x2b40已退出,代码为0(0x0)。
What am I doing wrong subscribing to the Bluetooth LE device's notification? 订阅Bluetooth LE设备的通知时我做错了什么?
I finally found the issue: 我终于找到了问题:
Using the linux library, it somehow automatically determined what type of notification the GATT Service is using. 使用linux库,它将以某种方式自动确定GATT服务正在使用哪种通知类型。
Using the Windows SDK I had to explicitly specify that the type of notification is an indication by using GattClientCharacteristicConfigurationDescriptorValue.Indicate
. 使用Windows SDK,我必须通过使用GattClientCharacteristicConfigurationDescriptorValue.Indicate
明确指定通知的类型是一种指示。
Now the event is fired once I "roll the dice". 现在,一旦我“掷骰子”,便会触发该事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.