Exemple #1
0
        private async Task <IBleResult <IReadOnlyList <IDevice> > > ExecuteDeviceSearchAsync(IDeviceFilter deviceFilter, bool stopAfterFirstResult, CancellationToken cancellationToken)
        {
            IBleResult <IReadOnlyList <IDevice> > result = null;

            try
            {
                await _searchSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

                try
                {
                    var searchResult = await _bleAdapter.SearchAsync(deviceFilter, stopAfterFirstResult, _executor, _logger, cancellationToken);

                    result = BleResult.Success(searchResult);
                }
                finally
                {
                    _searchSemaphore.Release();
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception e)
            {
                result = BleResult.Failure <IReadOnlyList <IDevice> >(e);
            }

            return(result);
        }
        internal static async Task <IBleResult> ExecuteWithBleAvailabilityCheckAsync(this IBleAvailability bleAvailability, Func <Task <IBleResult> > executionProvider)
        {
            IBleResult result;

            try
            {
                switch (bleAvailability.BleState)
                {
                case BluetoothState.On:
                    result = await executionProvider.Invoke().ConfigureAwait(false);

                    break;

                case BluetoothState.Unavailable:
                    result = BleResult.Failure(BleFailure.BleNotAvailable);
                    break;

                case BluetoothState.Unauthorized:
                    result = BleResult.Failure(BleFailure.NoBluetoothPermissions);
                    break;

                default:
                    result = BleResult.Failure(BleFailure.BluetoothNotEnabled);
                    break;
                }
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
        private async Task <IBleResult> EnsureDeviceIsFoundAsync(CancellationToken cancellationToken)
        {
            IBleResult result;

            if (IsFound)
            {
                result = BleResult.Success();
            }
            else
            {
                var searchResult = await _bleInfrastructure.SearchManager.SearchForFirstDeviceAsync(_deviceSearchFilter, cancellationToken).ConfigureAwait(false);

                if (searchResult.IsOperationCompleted)
                {
                    _device = searchResult.Data;
                    result  = _device != null?BleResult.Success() : BleResult.Failure(BleFailure.DeviceNotFound);
                }
                else
                {
                    result = BleResult.Failure(BleFailure.DeviceNotFound, searchResult);
                }
            }

            return(result);
        }
Exemple #4
0
        public async Task <IBleResult> WriteAsync(IWriterBehavior <TIn> writer, TOut value, CancellationToken cancellationToken)
        {
            IBleResult result = null;

            try
            {
                using (var rawDataSequenceEnumerator = _valueConverter.Invoke(value).GetEnumerator())
                {
                    while (rawDataSequenceEnumerator.MoveNext() && result == null)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        var writeChunkResult = await writer.WriteAsync(rawDataSequenceEnumerator.Current, cancellationToken).ConfigureAwait(false);

                        if (!writeChunkResult.IsOperationCompleted)
                        {
                            result = writeChunkResult;
                        }
                    }
                }

                result = result ?? BleResult.Success();
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
        public async Task <IBleResult <TOut> > ReadAsync(IParametrizedReaderBehavior <TIn, TOut> parametrizedReader, TIn parameter, CancellationToken cancellationToken)
        {
            IBleResult <TOut> result;

            try
            {
                if (_connector.IsConnected)
                {
                    result = await parametrizedReader.ReadAsync(parameter, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    var connectionResult = await _connector.ConnectAsync(cancellationToken);

                    if (connectionResult.IsOperationCompleted)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        result = await parametrizedReader.ReadAsync(parameter, cancellationToken);
                    }
                    else
                    {
                        result = BleResult.Failure <TOut>(BleFailure.DeviceNotConnected, connectionResult);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure <TOut>(BleFailure.OperationCancelled);
            }

            return(result);
        }
        internal static IBleResult <T> ExecuteWithBleAvailabilityCheck <T>(this IBleAvailability bleAvailability, Func <IBleResult <T> > executionProvider)
        {
            IBleResult <T> result;

            try
            {
                switch (bleAvailability.BleState)
                {
                case BluetoothState.On:
                    result = executionProvider.Invoke();
                    break;

                case BluetoothState.Unavailable:
                    result = BleResult.Failure <T>(BleFailure.BleNotAvailable);
                    break;

                case BluetoothState.Unauthorized:
                    result = BleResult.Failure <T>(BleFailure.NoBluetoothPermissions);
                    break;

                default:
                    result = BleResult.Failure <T>(BleFailure.BluetoothNotEnabled);
                    break;
                }
            }
            catch (Exception e)
            {
                result = BleResult.Failure <T>(e);
            }

            return(result);
        }
        public override async Task <IBleResult> StartObservingAsync(IObserverBehavior <T> decoratedObserver, CancellationToken cancellationToken)
        {
            IBleResult result;

            try
            {
                if (_connector.IsConnected)
                {
                    result = await decoratedObserver.StartObservingAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    var connectionResult = await _connector.ConnectAsync(cancellationToken);

                    if (connectionResult.IsOperationCompleted)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        result = await decoratedObserver.StartObservingAsync(cancellationToken);
                    }
                    else
                    {
                        result = BleResult.Failure(BleFailure.DeviceNotConnected, connectionResult);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }

            return(result);
        }
        private async Task <IBleResult <TValue> > ExecuteSequentiallyAsync <TValue>(Func <Task <IBleResult <TValue> > > executionProvider, CancellationToken cancellationToken)
        {
            IBleResult <TValue> result;

            try
            {
                await _operationExecutionSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

                try
                {
                    result = await executionProvider.Invoke();
                }
                finally
                {
                    _operationExecutionSemaphore.Release();
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure <TValue>(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure <TValue>(e);
            }

            return(result);
        }
        public Task <IBleResult> TryConnectToDeviceAsync(IDevice device, bool connectWhenAvailable, CancellationToken cancellationToken)
        {
            _logger?.Log(LogSender, $"Trying to connect to device [DeviceName={device.Name},GUID={device.Id:D}]");

            return(_bleAvailability.ExecuteWithBleAvailabilityCheckAsync(async() =>
            {
                IBleResult result;

                _logger?.Log(LogSender, $"Internal connect to device started");
                try
                {
                    var connectParameters = new ConnectParameters(connectWhenAvailable);
                    await _bleAdapter.ConnectToDeviceAsync(device, connectParameters, cancellationToken);
                    result = device.State == DeviceState.Connected ? BleResult.Success() : BleResult.Failure(BleFailure.ConnectNotCompleted);
                }
                catch (TimeoutException)
                {
                    result = BleResult.Failure(BleFailure.OperationTimeout);
                }
                catch (OperationCanceledException)
                {
                    result = BleResult.Failure(BleFailure.OperationCancelled);
                }
                catch (Exception e)
                {
                    result = BleResult.Failure(e);
                }
                _logger?.Log(LogSender, $"Internal connect to device completed with result: {result}");

                return result;
            }));
        }
        private async Task <IBleResult> InitializeProtocolAsync(CancellationToken cancellationToken)
        {
            IBleResult result;

            try
            {
                var failedResults = new List <IBleResult>();
                foreach (var characteristic in _deviceCharacteristics.Values)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var initializationResult = await characteristic.InitializeAsync(_device, cancellationToken);

                    if (!initializationResult.IsOperationCompleted)
                    {
                        failedResults.Add(initializationResult);
                    }
                }
                result = failedResults.Any() ? BleResult.Failure(failedResults.ToArray()) : BleResult.Success();
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
Exemple #11
0
        public async Task <IBleResult> WriteAsync(IWriterBehavior <T> writer, T value, CancellationToken cancellationToken)
        {
            IBleResult result;

            try
            {
                if (_connector.IsConnected)
                {
                    result = await writer.WriteAsync(value, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    var connectionResult = await _connector.ConnectAsync(cancellationToken);

                    if (connectionResult.IsOperationCompleted)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        result = await writer.WriteAsync(value, cancellationToken);
                    }
                    else
                    {
                        result = BleResult.Failure(BleFailure.DeviceNotConnected, connectionResult);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }

            return(result);
        }
Exemple #12
0
        public Task <IBleResult <IDevice> > SearchForFirstDeviceAsync(IDeviceFilter deviceFilter, CancellationToken cancellationToken)
        {
            var foundDevice = GetConnectedDevices(deviceFilter).FirstOrDefault();

            return(foundDevice != null
                ? Task.FromResult(BleResult.Success(foundDevice))
                : _bleAvailabilityManager.ExecuteWithBleAvailabilityCheckAsync(async() =>
            {
                var result = await ExecuteDeviceSearchAsync(deviceFilter, true, cancellationToken).ConfigureAwait(false);
                return result.Convert(list => list.FirstOrDefault());
            }));
        }
        private async Task <IBleResult> ConnectWithPolicyAsync(bool connectWhenAvailable, CancellationToken cancellationToken)
        {
            IBleResult result;

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            try
            {
                var deviceSearchResult = await EnsureDeviceIsFoundAsync(cancellationToken).ConfigureAwait(false);

                _bleInfrastructure.Logger.Log(LogSender, $"Search completed after {stopwatch.Elapsed}");
                if (deviceSearchResult.IsOperationCompleted)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var deviceConnectedResult = await EnsureDeviceIsConnectedAsync(connectWhenAvailable, cancellationToken);

                    _bleInfrastructure.Logger.Log(LogSender, $"Connection completed after {stopwatch.Elapsed}");
                    if (deviceConnectedResult.IsOperationCompleted)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        var initializationResult = await InitializeProtocolAsync(cancellationToken);

                        _bleInfrastructure.Logger.Log(LogSender, $"Initialization completed after {stopwatch.Elapsed}");
                        result = initializationResult.IsOperationCompleted ? BleResult.Success() : BleResult.Failure(BleFailure.DeviceNotInitialized, initializationResult);
                    }
                    else
                    {
                        result = deviceConnectedResult;
                    }
                }
                else
                {
                    result = deviceSearchResult;
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }
            finally
            {
                stopwatch.Stop();
            }

            return(result);
        }
        public static async Task <IBleResult> WriteAsync <T>(this IWriterBehavior <T> writerBehavior, Func <T> valueProvider, CancellationToken cancellationToken = default)
        {
            IBleResult result;

            try
            {
                result = await writerBehavior.WriteAsync(valueProvider.Invoke(), cancellationToken).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
Exemple #15
0
        public static IBleResult <T> TryParseData <T>(this byte[] rawData, Func <byte[], T> parser)
        {
            IBleResult <T> result;

            try
            {
                result = BleResult.Success(parser.Invoke(rawData));
            }
            catch (Exception e)
            {
                result = BleResult.Failure <T>(BleFailure.DataConversionFailed, e);
            }

            return(result);
        }
        public async Task <IBleResult> TryDisconnectAsync()
        {
            IBleResult result;

            if (IsConnected)
            {
                result = await _bleInfrastructure.ConnectionManager.TryDisconnectFromDeviceAsync(_device).ConfigureAwait(false);
            }
            else
            {
                _connectionCancellation?.Cancel();
                _connectionCancellation = null;
                result = BleResult.Success();
            }

            return(result);
        }
        private async Task <IBleResult> EnsureDeviceIsConnectedAsync(bool connectWhenAvailable, CancellationToken cancellationToken)
        {
            IBleResult result;

            if (IsConnected)
            {
                result = BleResult.Success();
            }
            else
            {
                var connectionResult = await DoConnectToDeviceAsync(connectWhenAvailable, cancellationToken).ConfigureAwait(false);

                result = connectionResult.IsOperationCompleted ? BleResult.Success() : BleResult.Failure(BleFailure.CannotConnect, connectionResult);
            }

            return(result);
        }
Exemple #18
0
        public async Task <IBleResult> InitializeAsync(IDevice device, CancellationToken cancellationToken)
        {
            IBleResult result;

            try
            {
                if (_bleCharacteristic != null)
                {
                    _bleCharacteristic.ValueUpdated -= OnValueUpdated;
                    _bleCharacteristic = null;
                }

                var service = await device.GetServiceAsync(_serviceId, cancellationToken).ConfigureAwait(false);

                if (service != null)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    _bleCharacteristic = await service.GetCharacteristicAsync(_characteristicId);

                    if (_bleCharacteristic != null)
                    {
                        _bleCharacteristic.ValueUpdated += OnValueUpdated;
                        result = BleResult.Success();
                    }
                    else
                    {
                        throw new CharacteristicNotFoundException(_characteristicId);
                    }
                }
                else
                {
                    throw new ServiceNotFoundException(_serviceId);
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
        public async Task <IBleResult> TryDisconnectFromDeviceAsync(IDevice device)
        {
            IBleResult result;

            try
            {
                _logger?.Log(LogSender, $"Trying to disconnect to device [DeviceName={device.Name},GUID={device.Id:D}]");
                await _bleAdapter.DisconnectDeviceAsync(device).ConfigureAwait(false);

                result = device.State != DeviceState.Connected ? BleResult.Success() : BleResult.Failure(BleFailure.DisconnectNotCompleted);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
        private async Task <IBleResult <TValue> > CheckCharacteristicExistsAsync <TValue>(Guid characteristicId, Func <IBleCharacteristic, Task <IBleResult <TValue> > > executionProvider)
        {
            IBleResult <TValue> result;

            try
            {
                var characteristic = GetCharacteristic(characteristicId);
                result = characteristic != null
                    ? await executionProvider.Invoke(characteristic).ConfigureAwait(false)
                    : BleResult.Failure <TValue>(BleFailure.UnknownCharacteristic);
            }
            catch (Exception e)
            {
                result = BleResult.Failure <TValue>(e);
            }

            return(result);
        }
Exemple #21
0
        internal static async Task <IBleResult> TimeoutBleOperationAsync(this IExecutor executor, Func <CancellationToken, Task <IBleResult> > taskProvider,
                                                                         TimeSpan timeout, CancellationToken cancellationToken = default)
        {
            IBleResult result;

            try
            {
                result = await executor.CancelAfterTimeoutAsync(taskProvider, timeout, true, cancellationToken).ConfigureAwait(false);
            }
            catch (TimeoutException ex)
            {
                result = BleResult.Failure(BleFailure.OperationTimeout, ex);
            }
            catch (Exception ex)
            {
                result = BleResult.Failure(ex);
            }

            return(result);
        }
Exemple #22
0
        public Task <IBleResult> BeginSearchForAllDevicesAsync(IObserver <IDevice> observer, IDeviceFilter deviceFilter, CancellationToken cancellationToken)
        {
            return(_bleAvailabilityManager.ExecuteWithBleAvailabilityCheckAsync(async() =>
            {
                await _searchSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
                var searchCompletionObserver = new SearchCompletedObserver(observer, completedSuccessfully => _searchSemaphore.Release());

                try
                {
                    _bleAdapter.Search(searchCompletionObserver, deviceFilter, false, _executor, _logger, cancellationToken);
                }
                catch
                {
                    _searchSemaphore.Release();
                    throw;
                }

                return BleResult.Success();
            }));
        }
        private async Task <IBleResult> DoConnectToDeviceAsync(bool connectWhenAvailable, CancellationToken cancellationToken)
        {
            IBleResult result;

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            try
            {
                await _connectionSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

                _bleInfrastructure.Logger.Log(LogSender, $"Semaphore equired after {stopwatch.Elapsed}");
                try
                {
                    _connectionCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    result = await _bleInfrastructure.ConnectionManager.TryConnectToDeviceAsync(_device, connectWhenAvailable, _connectionCancellation.Token);

                    _bleInfrastructure.Logger.Log(LogSender, $"Connected after {stopwatch.Elapsed}");
                }
                finally
                {
                    _connectionCancellation = null;
                    _connectionSemaphore.Release();
                }
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }
            finally
            {
                stopwatch.Stop();
            }

            return(result);
        }
Exemple #24
0
        public async Task <IBleResult <IReadOnlyList <TBleDevice> > > SearchForDevicesAsync(bool includeConnected, TimeSpan timeout,
                                                                                            CancellationToken cancellationToken)
        {
            var searchResult = await _bleInfrastructure.Executor.CancelAfterTimeoutAsync(
                ct => _bleInfrastructure.SearchManager.SearchForAllDevicesAsync(_generalDeviceFilter, ct), timeout, false, cancellationToken).ConfigureAwait(false);

            if (searchResult.IsOperationCompleted)
            {
                var foundDevices = searchResult.Data.Select(GetBleDevice).ToList();
                if (includeConnected)
                {
                    foundDevices.AddRange(_bleInfrastructure.SearchManager.GetConnectedDevices(_generalDeviceFilter).Select(GetBleDevice).ToList());
                }

                return(BleResult.Success <IReadOnlyList <TBleDevice> >(foundDevices));
            }
            else
            {
                return(searchResult.Convert <IReadOnlyList <TBleDevice> >());
            }
        }
Exemple #25
0
        public async Task <IBleResult> WriteAsync(IWriterBehavior <TIn> writer, TOut value, CancellationToken cancellationToken)
        {
            IBleResult result;

            try
            {
                var convertedValue = _valueConverter.Invoke(value);
                cancellationToken.ThrowIfCancellationRequested();
                result = await writer.WriteAsync(convertedValue, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
Exemple #26
0
        public async Task <IBleResult> StopObservingAsync()
        {
            IBleResult result;

            try
            {
                if (_bleCharacteristic == null)
                {
                    result = BleResult.Failure(BleFailure.DeviceNotInitialized);
                }
                else if (!_bleCharacteristic.CanUpdate)
                {
                    result = BleResult.Failure(BleFailure.UpdateNotSupported);
                }
                else
                {
                    if (IsObserving)
                    {
                        await _bleCharacteristic.StopUpdatesAsync().ConfigureAwait(false);

                        IsObserving = false;
                        NotifyObservationCompleted();
                    }
                    result = BleResult.Success();
                }
            }
            catch (TimeoutException)
            {
                result = BleResult.Failure(BleFailure.OperationTimeout);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
Exemple #27
0
        public async Task <IBleResult <byte[]> > ReadRawAsync(CancellationToken cancellationToken)
        {
            IBleResult <byte[]> result;

            try
            {
                if (_bleCharacteristic == null)
                {
                    result = BleResult.Failure <byte[]>(BleFailure.DeviceNotInitialized);
                }
                else if (!_bleCharacteristic.CanRead)
                {
                    result = BleResult.Failure <byte[]>(BleFailure.ReadNotSupported);
                }
                else
                {
                    var rawData = await _bleCharacteristic.ReadAsync(cancellationToken).ConfigureAwait(false);

                    result = BleResult.Success(rawData);
                }
            }
            catch (TimeoutException)
            {
                result = BleResult.Failure <byte[]>(BleFailure.OperationTimeout);
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure <byte[]>(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure <byte[]>(e);
            }

            return(result);
        }
Exemple #28
0
        public async Task <IBleResult> WriteRawAsync(byte[] data, CancellationToken cancellationToken)
        {
            IBleResult result;

            try
            {
                if (_bleCharacteristic == null)
                {
                    result = BleResult.Failure(BleFailure.DeviceNotInitialized);
                }
                else if (!_bleCharacteristic.CanWrite)
                {
                    result = BleResult.Failure(BleFailure.WriteNotSupported);
                }
                else
                {
                    var completed = await _bleExecutionProvider.ExecuteAsync(() => _bleCharacteristic.WriteAsync(data, cancellationToken)).ConfigureAwait(false);

                    result = completed ? BleResult.Success() : BleResult.Failure(BleFailure.WriteFailed);
                }
            }
            catch (TimeoutException)
            {
                result = BleResult.Failure(BleFailure.OperationTimeout);
            }
            catch (OperationCanceledException)
            {
                result = BleResult.Failure(BleFailure.OperationCancelled);
            }
            catch (Exception e)
            {
                result = BleResult.Failure(e);
            }

            return(result);
        }
 private Task <IBleResult> ExecuteOperationWithPolicyAsync(Func <Task <IBleResult> > executionProvider, CancellationToken cancellationToken)
 {
     return(IsConnected
         ? ExecuteSequentiallyAsync(executionProvider, cancellationToken)
         : Task.FromResult(BleResult.Failure(BleFailure.DeviceNotConnected)));
 }
Exemple #30
0
 public Task <IBleResult> StopObservingAsync(CancellationToken cancellationToken)
 {
     return(IsObserving
         ? _characteristicObserver.StopObservingRawValueAsync(_characteristicId, cancellationToken)
         : Task.FromResult(BleResult.Success()));
 }