diff --git a/InTheHand.BluetoothLE/Platforms/Windows/GattCharacteristic.windows.cs b/InTheHand.BluetoothLE/Platforms/Windows/GattCharacteristic.windows.cs index 3987338..c5bc710 100644 --- a/InTheHand.BluetoothLE/Platforms/Windows/GattCharacteristic.windows.cs +++ b/InTheHand.BluetoothLE/Platforms/Windows/GattCharacteristic.windows.cs @@ -9,6 +9,8 @@ using System.Collections.Generic; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; +using Windows.Devices.Bluetooth; +using Windows.Devices.Enumeration; using Uap = Windows.Devices.Bluetooth.GenericAttributeProfile; namespace InTheHand.Bluetooth @@ -90,17 +92,71 @@ private byte[] PlatformGetValue() } private async Task PlatformReadValue() - { - var result = await _characteristic.ReadValueAsync(Windows.Devices.Bluetooth.BluetoothCacheMode.Uncached).AsTask().ConfigureAwait(false); + { + async Task<(Uap.GattCommunicationStatus Status, byte[]? Data)> ReadCharacteristicAsync() + { + var result = await _characteristic.ReadValueAsync(Windows.Devices.Bluetooth.BluetoothCacheMode.Uncached).AsTask().ConfigureAwait(false); + + if (result.Status == Uap.GattCommunicationStatus.Success) + { + return (result.Status, result.Value.ToArray()); + } + return (result.Status, null); + } - if(result.Status == Uap.GattCommunicationStatus.Success) + var result = await ReadCharacteristicAsync(); + + if (result.Status == Uap.GattCommunicationStatus.AccessDenied || result.Status == Uap.GattCommunicationStatus.ProtocolError) + { + if (!Service.Device.NativeDevice.DeviceInformation.Pairing.IsPaired && + Service.Device.NativeDevice.DeviceInformation.Pairing.CanPair) + { + // Issue a pairing request, to mimic the mobile platforms behavior. + // When a characteristic is access-protected, iOS and Android automatically prompt for a pairing procedure + Service.Device.NativeDevice.DeviceInformation.Pairing.Custom.PairingRequested += Custom_PairingRequested; + try + { + var pairingResult = await Service.Device.NativeDevice.DeviceInformation.Pairing.Custom.PairAsync(DevicePairingKinds.ConfirmOnly); + if (pairingResult.Status == DevicePairingResultStatus.Paired) + { + result = await ReadCharacteristicAsync(); + } + } + finally + { + Service.Device.NativeDevice.DeviceInformation.Pairing.Custom.PairingRequested -= Custom_PairingRequested; + } + } + } + + if (result.Status == Uap.GattCommunicationStatus.Success) { - return result.Value.ToArray(); + return result.Data!; } - - return null; - } - + return null!; + } + + private void Custom_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) + { + switch (args.PairingKind) + { + case DevicePairingKinds.None: + args.Accept(); + break; + case DevicePairingKinds.ConfirmOnly: + args.Accept(); + break; + case DevicePairingKinds.DisplayPin: + break; + case DevicePairingKinds.ProvidePin: + break; + case DevicePairingKinds.ConfirmPinMatch: + break; + case DevicePairingKinds.ProvidePasswordCredential: + break; + } + } + private async Task PlatformWriteValue(byte[] value, bool requireResponse) { await _characteristic.WriteValueAsync(value.AsBuffer(), requireResponse ? Uap.GattWriteOption.WriteWithResponse : Uap.GattWriteOption.WriteWithoutResponse);