UWP BLE not working for authenticated attributes
I can't write to the CCCD on a BLE device that has the authentication flag enabled on the CCCD
Universal Windows Platform (UWP)
-
Corby Wilson • 0 Reputation points
2024-07-31T00:32:20.31+00:00 Ok, now the post works.
I have a BLE device where one of the characteristics has[NOTIFY|AUTHENTICATE]
flags enabled.
I want to write to the CCCD but I get a GattProtocolError.InsufficientAuthentication error when writing.
Pairing doesn't workCustom Pairing doesn't work.
How do I get the OS to recognize that it needs to enable authentication when talking to the CHAR?
Sample Code:
def example(addr: int): device = await BluetoothLEDevice.from_bluetooth_address_async(int(self.info.addr)) svc_token = device.add_gatt_services_changed(self._on_services_changed) with await GattSession.from_device_id_async(device.bluetooth_device_id) as session: session_status_changed_token = session.add_session_status_changed(self._on_session_status_changed) mtu_changed_token = session.add_max_pdu_size_changed(self._on_mtu_changed) await self._discover_services(device) await asyncio.sleep(1) # Find my custom char with NOTIFY chars = [char for cid, char in self._chars.items() if cid < 0x100 and char.characteristic_properties & GattCharacteristicProperties.NOTIFY] char = chars[0] #char.protection_level = GattProtectionLevel.AUTHENTICATION_REQUIRED <-- does NOT work! desc = self._handles[char.attribute_handle + 2] #desc.protection_level = GattProtectionLevel.AUTHENTICATION_REQUIRED <-- ditto pe = await self._desc_write(desc, b'\x01\x00') if pe == GattProtocolError.insufficient_authentication: di = await self.pair(device.device_id) await asyncio.sleep(1) del di pe = await self._desc_write(desc, b'\x01\x00') session.remove_max_pdu_size_changed(mtu_changed_token) session.remove_session_status_changed(session_status_changed_token) device.remove_gatt_services_changed(svc_token)
-
Junjie Zhu - MSFT • 20,441 Reputation points • Microsoft Vendor
2024-07-31T03:29:45.1033333+00:00 Hi @Anonymous ,
Welcome to Microsoft Q&A!
Sorry, we currently only support issues related to using the BLE API in UWP. Your project is written in Python, and it's not a UWP project.
Thank you.
-
Corby Wilson • 0 Reputation points
2024-08-01T03:19:32.3933333+00:00 Pardon me. Let me change the color of the paint in my bucket:
using System; using Windows.Devices.Bluetooth; using Windows.Devices.Enumeration; using Windows.Devices.Bluetooth.GenericAttributeProfile; using System.Reflection.PortableExecutable; class Program { static async Task Main(string[] args) { string address = "D2:12:E2:18:78:32"; BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(ulong.Parse(address.Replace(":", ""), System.Globalization.NumberStyles.HexNumber)); bleDevice.GattServicesChanged += (sender, args) => Console.WriteLine($"GattServicesChanged: {args}"); GattSession gattSession = await GattSession.FromDeviceIdAsync(bleDevice.BluetoothDeviceId); gattSession.SessionStatusChanged += (sender, args) => Console.WriteLine($"SessionStatusChanged: {args}"); gattSession.MaxPduSizeChanged += (sender, args) => Console.WriteLine($"MaxPduSizeChanged: {args}"); Dictionary<int, Object> handles = await Device_DiscoverServices(bleDevice); var characteristicsWithNotify = handles.Values .Where(obj => obj is GattCharacteristic characteristic && characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify)) .Cast<GattCharacteristic>() .ToList(); bleDevice.DeviceInformation.Pairing.Custom.PairingRequested += (sender, args) => args.Accept(); DevicePairingResult pairingResult = await bleDevice.DeviceInformation.Pairing.Custom.PairAsync(DevicePairingKinds.ConfirmOnly); if (pairingResult.Status == DevicePairingResultStatus.Paired) { Console.WriteLine("Device paired successfully"); } else { Console.WriteLine($"Failed to pair with device: {pairingResult.Status}"); } foreach (var characteristic in characteristicsWithNotify) { ushort uuid16 = (ushort)(characteristic.Uuid.ToByteArray()[0] | (characteristic.Uuid.ToByteArray()[1] << 8)); string uuid16String = uuid16.ToString("X4"); Console.WriteLine($"Characteristic with notify property: {characteristic.Uuid}:{uuid16String}"); if (uuid16 < 100) { try { GattCommunicationStatus ret = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify); if (ret != GattCommunicationStatus.Success) { Console.WriteLine($"Failed to write client characteristic configuration descriptor: {ret}"); } else { Console.WriteLine("Successfully wrote client characteristic configuration descriptor"); } } catch (Exception e) { Console.WriteLine($"Failed to write client characteristic configuration descriptor: {e}"); } } } } private static async Task<Dictionary<int, Object>> Device_DiscoverServices(BluetoothLEDevice bleDevice) { Dictionary<int, Object> handles = new Dictionary<int, Object>(); GattDeviceServicesResult result = await bleDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached); if (result.Status != GattCommunicationStatus.Success) { Console.WriteLine($"Failed to get GATT services: {result.Status}"); return handles; } foreach (GattDeviceService service in result.Services) { Console.WriteLine($"Service: {service.Uuid}"); handles.Add(service.AttributeHandle, service); GattCharacteristicsResult characteristicsResult = await service.GetCharacteristicsAsync(BluetoothCacheMode.Uncached); if (characteristicsResult.Status != GattCommunicationStatus.Success) { Console.WriteLine($"Failed to get characteristics for service {service.Uuid}"); continue; } foreach (GattCharacteristic characteristic in characteristicsResult.Characteristics) { Console.WriteLine($" Characteristic: {characteristic.Uuid}"); handles.Add(characteristic.AttributeHandle, characteristic); GattDescriptorsResult descriptorsResult = await characteristic.GetDescriptorsAsync(BluetoothCacheMode.Uncached); if (descriptorsResult.Status != GattCommunicationStatus.Success) { Console.WriteLine($"Failed to get descriptors for characteristic {characteristic.Uuid}"); continue; } foreach (GattDescriptor descriptor in descriptorsResult.Descriptors) { Console.WriteLine($" Descriptor: {descriptor.Uuid}"); handles.Add(descriptor.AttributeHandle, descriptor); } } } return handles; } }
-
Junjie Zhu - MSFT • 20,441 Reputation points • Microsoft Vendor
2024-08-01T06:35:50.0266667+00:00 Hi @Corby Wilson ,
Thank you for the code. What results did you get when running this code? How is it different from what you expected?
-
Rafael Pontes • 0 Reputation points
2025-02-10T23:31:12.75+00:00 I'm facing this same issue. Do we have any update on this? @Anonymous , were you able to fix that?
-
Corby Wilson • 0 Reputation points
2025-02-11T19:31:10.8566667+00:00 No, we were forced to abandon the use of the Windows OS BT subsystem because it's not compliant with the Bluetooth spec when it comes to per characteristic encryption.
We switched to using an H4 HCI dongle with direct control of the Bluetooth interface.
It works fine on MacOS and Linux tho.
Sign in to comment