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);
        }
Exemple #2
0
 public Task <string> ReadCharacteristicValueAsync(CancellationToken cancellationToken)
 {
     return(BluetoothDeviceProximityProbe.CompleteReadAsync(_readCompletionSource, cancellationToken));
 }