简体   繁体   中英

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.

However I do need the same functionality for Windows 10 (1709). I am using the most recent Windows SDK with Visual Studio 2017.

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 .

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

Service @ c7e70010-c847-11e6-8175-8c89a55d403c, found and accessed!

Characteristic @ c7e70012-c847-11e6-8175-8c89a55d403c found and accessed!

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.

After a short while, one last message will be printed to the console:

The Thread 0x2b40 has exited with code 0 (0x0).

What am I doing wrong subscribing to the Bluetooth LE device's notification?

I finally found the issue:

Using the linux library, it somehow automatically determined what type of notification the GATT Service is using.

Using the Windows SDK I had to explicitly specify that the type of notification is an indication by using GattClientCharacteristicConfigurationDescriptorValue.Indicate .

Now the event is fired once I "roll the dice".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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