简体   繁体   English

如何在Windows UWP App中正确订阅蓝牙低能耗设备的GattCharacteristic.ValueChanged通知(指示)?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM