public async Task <List <Tuple <string, DateTimeOffset> > > ReadPeripheralCharacteristicValuesAsync(CancellationToken cancellationToken) { List <Tuple <string, DateTimeOffset> > characteristicValueTimestamps = new List <Tuple <string, DateTimeOffset> >(); // copy list of peripherals to read. note that the same device may be reported more than once. read each once. List <Tuple <CBPeripheral, CBCentralManager, DateTimeOffset> > peripheralCentralTimestamps; lock (_peripheralCentralTimestamps) { peripheralCentralTimestamps = _peripheralCentralTimestamps.GroupBy(peripheralCentralTimestamp => peripheralCentralTimestamp.Item1.Identifier).Select(group => group.First()).ToList(); } _probe.ReadAttemptCount += peripheralCentralTimestamps.Count; // read characteristic from each peripheral foreach (Tuple <CBPeripheral, CBCentralManager, DateTimeOffset> peripheralCentralTimestamp in peripheralCentralTimestamps) { if (cancellationToken.IsCancellationRequested) { break; } TaskCompletionSource <string> readCompletionSource = new TaskCompletionSource <string>(); CBPeripheral peripheral = peripheralCentralTimestamp.Item1; CBCentralManager central = peripheralCentralTimestamp.Item2; DateTimeOffset timestamp = peripheralCentralTimestamp.Item3; #region discover services peripheral.DiscoveredService += (sender, e) => { try { if (e.Error == null) { SensusServiceHelper.Get().Logger.Log("Discovered services. Discovering characteristics...", LoggingLevel.Normal, GetType()); // discover characteristics for newly discovered services that match the one we're looking for foreach (CBService service in peripheral.Services) { if (service.UUID.Equals(_service.UUID)) { peripheral.DiscoverCharacteristics(new CBUUID[] { _characteristic.UUID }, service); } } } else { throw new Exception("Error while discovering services: " + e.Error); } } catch (Exception ex) { SensusServiceHelper.Get().Logger.Log("Exception while discovering characteristics: " + ex.Message, LoggingLevel.Normal, GetType()); } }; #endregion #region discover characteristics peripheral.DiscoveredCharacteristic += (sender, e) => { try { if (e.Error == null) { SensusServiceHelper.Get().Logger.Log("Discovered characteristics. Reading value...", LoggingLevel.Normal, GetType()); // read characteristic value for newly discovered characteristics that match the one we're looking for foreach (CBCharacteristic characteristic in e.Service.Characteristics) { if (characteristic.UUID.Equals(_characteristic.UUID)) { peripheral.ReadValue(characteristic); } } } else { throw new Exception("Error while discovering characteristics: " + e.Error); } } catch (Exception ex) { SensusServiceHelper.Get().Logger.Log("Exception while reading characteristic values from peripheral: " + ex.Message, LoggingLevel.Normal, GetType()); } }; #endregion #region update characteristic value peripheral.UpdatedCharacterteristicValue += (sender, e) => { try { if (e.Error == null) { // characteristic should have a non-null value if (e.Characteristic.Value == null) { throw new Exception("Null updated value for characteristic."); } else { SensusServiceHelper.Get().Logger.Log("Value read.", LoggingLevel.Normal, GetType()); string characteristicValue = Encoding.UTF8.GetString(e.Characteristic.Value.ToArray()); readCompletionSource.SetResult(characteristicValue); } } else { throw new Exception("Error while updating characteristic value: " + e.Error); } } catch (Exception ex) { SensusServiceHelper.Get().Logger.Log("Exception while reporting characteristic value: " + ex.Message, LoggingLevel.Normal, GetType()); } }; #endregion try { SensusServiceHelper.Get().Logger.Log("Connecting to peripheral...", LoggingLevel.Normal, GetType()); central.ConnectPeripheral(peripheral); string characteristicValue = await BluetoothDeviceProximityProbe.CompleteReadAsync(readCompletionSource, cancellationToken); if (characteristicValue != null) { characteristicValueTimestamps.Add(new Tuple <string, DateTimeOffset>(characteristicValue, timestamp)); _probe.ReadSuccessCount++; } } catch (Exception ex) { SensusServiceHelper.Get().Logger.Log("Exception while reading peripheral: " + ex, LoggingLevel.Normal, GetType()); } finally { DisconnectPeripheral(central, peripheral); } } return(characteristicValueTimestamps); }
public Task <string> ReadCharacteristicValueAsync(CancellationToken cancellationToken) { return(BluetoothDeviceProximityProbe.CompleteReadAsync(_readCompletionSource, cancellationToken)); }