locked
What's the best (easiest) way to get a real-time heart-rate into a Xamarin application? RRS feed

  • Question

  • User172704 posted

    This is a very general and vague question but I am really struggling to gain any traction onf it. The problem is that I don't have the money to go out buying random fitness devices, to see if I can get them to connect. And I am struggling to see how much overlap (if any) there is between Apple's Health Kit stuff, which seems to be aimed mainly at the Apple Watch, and Google's Fit API.

    A bunch of questions spring to mind:

    1. I am assuming that Apple being Apple, I can access an Apple Watch only on an iPhone?
    2. Does Google have a similar restriction, or is there a way - perhaps leveraging the power of Xamarin - to get an iOS app to talk to a Google Fit device?
    3. Do I really have to pay the extortionate £1500 just to experiment with the ANT+ protocol (as used by Garmin)?

    I looked at a device that was advertised as being dual Bluetooth BLE / ANT+, but does this simply mean that it uses the ANT+ protocol over Bluetooth? In other words, is there likely to be a way to go in below the ANT+ protocol and just grab raw data over Bluetooth?

    Wearables are an exploding market and so I am surprised how difficult it is to find a trustworthy path into this field. Indeed, I can imagine there might be huge obstacles, but I might have expected Xamarin to be making inroads into making this stuff easier to work with.

    Any help at all would be like water to a man adrift in the Pacific for a month!

    Kind wishes - Patrick

    Friday, August 7, 2020 7:03 AM

Answers

  • User379860 posted

    I think read the heart-rate from the wearables by Bluetooth BLE, then use Xamarin application read the heart-rate from the Bluetooth BLE , it is a simiple way.

    I found a demo about read heart-rate from a Polar H7. https://github.com/nicolgit/demo-xamarin-heartrate-ble

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, August 7, 2020 8:56 AM
  • User172704 posted

    @criapix

    I have very quickly stripped the file down to its bare-bones and pasted it below. See if you can work out what is happening from this. Maybe the Characteristic_ValueUpdated event handler is what you are looking for. If not, we'll have to figure out a way for me to share the full code securely.

    Your device might be the problem. I have tried connecting to cheap BLE devices before and got nowhere. Maybe they have rubbish Bluetooth hardware or maybe they only pay lip-service to implementing a proper interface? If you continue to struggle, I'd get a device like the one I linked to. It wasn't that expensive (maybe £GBP40) and works perfectly.

    • Patrick

    ``` public class BluetoothLE { // Event handler for when the Bluetooth LE connection is lost. private async void BLEAdapter_DeviceConnectionLost( object sender, DeviceErrorEventArgs e ) { if( e.Device.Id == _thisSessionConnectedDeviceGuid ) { // Disconnected device has GUID {e.Device.Id}, which matches GUID of connected heart-rate device, so attempt reconnection. await AttemptReconnectOrDiscoveryAsync( true, CancellationToken.None ); } }

    // Event handler for when a Bluetooth LE device disconnects.
    private async void BLEAdapter_DeviceDisconnected( object sender, DeviceEventArgs e )
    {
        if( e.Device.Id == _thisSessionConnectedDeviceGuid )
        {
            await AttemptReconnectOrDiscoveryAsync( true, CancellationToken.None );
        }
    }
    
    // Handle connection timeout.
    private void BLEAdapter_ScanTimeoutElapsed( object sender, EventArgs e )
    {
    }
    
    
    // Event handler for when a Bluetooth LE device is discovered.
    private void BLEAdapter_DeviceDiscovered( object sender, DeviceEventArgs e )
    {
        _devices.Add( new BluetoothLEDeviceRecord( e.Device ) );
    }
    
    // Event handler for when a new value is read from the connected Bluetooth LE device.
    private void Characteristic_ValueUpdated( object sender, CharacteristicUpdatedEventArgs e )
    {
        byte[] valueHexBytes = e.Characteristic.Value;
        byte t = valueHexBytes[ 1 ];
        valueHexBytes[ 1 ] = valueHexBytes[ 0 ];
        valueHexBytes[ 0 ] = t;
        UInt16 valueInteger = BitConverter.ToUInt16( valueHexBytes, 0 );
        _latestBioSampleValue = (double)valueInteger;
    }
    
    // Helper to attempt reconnection of known device or scan if needed.
    private async Task<bool> AttemptReconnectOrDiscoveryAsync( bool triggeredbyBLEEvent, CancellationToken cancellationToken )
    {
        if( await InternalInitialiseOrReinitialiseAsync() )
        {
            if( Descriptor.TryGetGuid( _BluetoothLEDeviceGUID, out Guid lastBLEDeviceGuid ) )
            {
                await AttemptReconnectionAsync( lastBLEDeviceGuid );
            }
            else
            {
                await ScanForDevices( cancellationToken );
            }
    
            await ExamineDiscoveredDevices( cancellationToken );
    
            if( AllOkay )
            {
                Descriptor.SetOrAddKeyValue( _BluetoothLEDeviceGUID, _connectedBLEDevice.Id.ToString() );
                return true;
            }
            else
            {
                return false;
            }
        }
    
    
        // Attempt reconnection of a known device, bypassing the power-hungry need to do a full scan.
        private async Task AttemptReconnectionAsync( Guid deviceGuid )
        {
            IDevice specificDevice = await ConnectToKnownDeviceAsync( deviceGuid ).ConfigureAwait( false );
            if( specificDevice != null )
            {
                _devices.Add( new BluetoothLEDeviceRecord( specificDevice ) );
            }
            else
            {
                IReadOnlyCollection<IDevice> connectedDevices = App.BLE.Adapter.GetSystemConnectedOrPairedDevices();
                foreach( IDevice device in connectedDevices )
                {
                    _devices.Add( new BluetoothLEDeviceRecord( device ) );
                }
            }
        }
    
    
        // Helper to attempt connection to a known device, which saves power wasted on a full scan.
        private async Task<IDevice> ConnectToKnownDeviceAsync( Guid deviceGuid )
        {
            QA.CodeStackDebug();
            IDevice device;
            try
            {
                device = await App.BLE.Adapter.ConnectToKnownDeviceAsync( deviceGuid ).TimeoutAfter<IDevice>( TimeSpan.FromSeconds( 30.0 ) );
            }
            catch( TimeoutException ex )
            {
            }
            return device;
        }
    
    
        // Search the specified device for a heart-rate service.
        private async Task SearchForHeartRateService( IDevice connectedDevice, CancellationToken cancellationToken )
        {
            IReadOnlyList<IService> services = await connectedDevice.GetServicesAsync( cancellationToken );
            foreach( IService service in services )
            {
                IReadOnlyList<ICharacteristic> characteristics = await service.GetCharacteristicsAsync();
                foreach( ICharacteristic characteristic in characteristics )
                {
                    if( characteristic.Id == _HeartRateGuid )
                    {
                        _connectedBLEDevice = connectedDevice;
                        _selectedBLEService = service;
                        _selectedBLECharacteristic = characteristic;
                        _selectedBLECharacteristic.ValueUpdated += Characteristic_ValueUpdated;
                        _thisSessionConnectedDeviceGuid = _connectedBLEDevice.Id;
                        await characteristic.StartUpdatesAsync();
                        return;
                    }
                }
            }
        }
    
        // Wraps the scanning for Bluetooth LE devices.
        private async Task ScanForDevices( CancellationToken cancellationToken )
        {
            App.BLE.Adapter.ScanMode = ScanMode.LowLatency;
            await App.BLE.Adapter.StartScanningForDevicesAsync( cancellationToken );
        }
    
    
        // Helper to wrap up examining all discovered devices.
        private async Task ExamineDiscoveredDevices( CancellationToken cancellationToken )
        {
            foreach( BluetoothLEDeviceRecord deviceRecord in _devices )
                await ExamineDiscoveredDevice( deviceRecord.Device, cancellationToken );
        }
    
    
        // Helper function that determines if a Bluetooth BLE instance has been set.
        private bool BLESet => App.BLE != null;
    
    
        // Helper function that determines if Bluetooth LE is turned on.
        private bool BLEOn => BLESet && App.BLE.State == BluetoothState.On;
    
    
        // Helper to safely determine if a Bluetooth LE device scan is currently underway.
        private bool IsScanningForDevices => BLEOn && ( App.BLE.Adapter?.IsScanning ?? false );
    
    
        // Helper to wrap up ON/OFF state text from the Bluetooth instance on this platform.
        private string BLEStateString => ( !BLESet ) ? "BLE instance not set!" : ( App.BLE.IsOn ) ? "BLE State = ON" : "BLE State = OFF";
    
    
        // Helper to compose the logic conditions necessary to determine is there is a successful connection.
        private bool AllOkay => BLEOn && _connectedBLEDevice != null && _selectedBLEService != null && _selectedBLECharacteristic != null;
    
        // Helper that does its best to put the code and Bluetooth back into a known state.
        private async Task<bool> InternalInitialiseOrReinitialiseAsync()
        {
            App.BLE.StateChanged -= BLE_StateChanged;
            App.BLE.Adapter.DeviceDiscovered -= BLEAdapter_DeviceDiscovered;
            App.BLE.Adapter.ScanTimeoutElapsed -= BLEAdapter_ScanTimeoutElapsed;
            App.BLE.Adapter.DeviceDisconnected -= BLEAdapter_DeviceDisconnected;
            App.BLE.Adapter.DeviceConnectionLost -= BLEAdapter_DeviceConnectionLost;
            _selectedBLECharacteristic.ValueUpdated -= Characteristic_ValueUpdated;
            _selectedBLECharacteristic = null;
            _connectedBLEDevice = null;
            _selectedBLEService = null;
            foreach( BluetoothLEDeviceRecord device in _devices )
            {
                await App.BLE.Adapter.DisconnectDeviceAsync( device.Device );
            }
            _devices.Clear();
    
            App.BLE.StateChanged += BLE_StateChanged;
            App.BLE.Adapter.DeviceDiscovered += BLEAdapter_DeviceDiscovered;
            App.BLE.Adapter.ScanTimeoutElapsed += BLEAdapter_ScanTimeoutElapsed;
            App.BLE.Adapter.DeviceDisconnected += BLEAdapter_DeviceDisconnected;
            App.BLE.Adapter.DeviceConnectionLost += BLEAdapter_DeviceConnectionLost;
    
            return true;
        }
    
        // State information for the Bluetooth LE connected device.
        private bool _internallyBusy = false;
        private IDevice _connectedBLEDevice = null;
        private IService _selectedBLEService = null;
        private ICharacteristic _selectedBLECharacteristic = null;
        private Guid _thisSessionConnectedDeviceGuid = Guid.Empty;
        private Collection<BluetoothLEDeviceRecord> _devices = new Collection<BluetoothLEDeviceRecord>();
    
        // Latest bio-sample obtained from the connected device.
        private double _latestBioSampleValue = 0.0;
    
        // UUID for heart-rate device (see  https://www.bluetooth.com/specifications/bluetooth-core-specification/).
        private const int _HeartRateUuid = 0x2a37;
        private readonly Guid _HeartRateGuid = _HeartRateUuid.UuidFromPartial();
    
        // How long to attempt reconnection.
        private const double _ReconnectionTimeoutSeconds = 30.0;
    
        // These are kept here simply because they may prove to be useful and it can take some digging to find them online.         
        // Device information 0x180a
        // Battery service: 0x180f
        // Heart-rate: 0x180d
        // Body sensor location: 2a38
        // Manufacturer Name String: 2a29
        // Model Number String: 2a24
        // Hardware Revision String: 2a27
        // Firmware Revision String: 2a26
        // Software Revision String: 2a28
        // BatteryLevelUuid: 0x2a37;
    
        /// <summary>
        /// Holds information about a single Bluetooth LE device.
        /// </summary>
        private struct BluetoothLEDeviceRecord
        {
            public BluetoothLEDeviceRecord( IDevice device )
            {
                Device = device;
            }
    
            public IDevice Device { get; private set; }
            public Guid UniqueId => Device.Id;
            public bool IsConnected => Device.State == DeviceState.Connected;
            public int Rssi => Device.Rssi;
            public string Name => Device.Name;
        }
    }
    

    }

    ```

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, March 12, 2021 8:13 AM

All replies

  • User379860 posted

    I think read the heart-rate from the wearables by Bluetooth BLE, then use Xamarin application read the heart-rate from the Bluetooth BLE , it is a simiple way.

    I found a demo about read heart-rate from a Polar H7. https://github.com/nicolgit/demo-xamarin-heartrate-ble

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, August 7, 2020 8:56 AM
  • User172704 posted

    @LeonLu

    That looks excellent! I will definitely make sure I can build it okay then buy a Polar H7.

    But most interesting for me is the Microsoft Band code. I initially spent three months trying to get a reliable connection to a Band 2. (The delay was in part caused by a bug or at least an undesirable 'feature' in Microsoft's code.) Anyway, I still have a Microsoft Band sitting in my drawer and I still have my code in source control. I removed it from the project because Microsoft pulled the nuget package required to talk to it. I've just checked nuget in VS now and it seems to be available again. So my existing code may just work!

    You may just have saved me a month or two of work and a ton of wasted cash. Thank you! Fingers crossed...

    • Patrick
    Friday, August 7, 2020 10:25 AM
  • User89714 posted

    @EasyGoingPat said: But most interesting for me is the Microsoft Band code. I initially spent three months trying to get a reliable connection to a Band 2. (The delay was in part caused by a bug or at least an undesirable 'feature' in Microsoft's code.) Anyway, I still have a Microsoft Band sitting in my drawer and I still have my code in source control. I removed it from the project because Microsoft pulled the nuget package required to talk to it. I've just checked nuget in VS now and it seems to be available again. So my existing code may just work!

    If you still have a working Microsoft Band, that's great (I liked the Band and still have two kicking around). However, they are no longer sold, and some of the related online services are no longer available. I wouldn't recommend investing time in developing software for them, unless it's just for your own use for as long as your own Band keeps working.

    Friday, August 7, 2020 11:37 AM
  • User366729 posted

    @EasyGoingPat , were you able to connect your Xamarin application to the BLE ANT+ device? I'm having the same difficulty.

    Thursday, March 11, 2021 1:30 AM
  • User172704 posted

    @criapix

    I gave up with ANT+ because, as far as I could tell, you do indeed have to pay the extortionate licence fee even just to experiment with it. Fortunately, most ANT+ devices are also BLE devices, and indeed there are many BLE devices out there that don't use ANT+ at all.

    So, my solution was to buy one of these: Fitness Tracker

    And then I used this excellent nuget package to talk to it over BLE: Xamarin Bluetooth LE

    Works a treat! Totally reliable connection. In fact, while trying to test loss of connection, I had to go outside and walk thirty metres just to get it to disconnect from the iPhone.

    The example code is fairly easy to find a way into. If you get stuck, I'm happy to share information or code fragments.

    • Patrick
    Thursday, March 11, 2021 8:08 AM
  • User366729 posted

    Hi @EasyGoingPat

    I'm having exactly the same problem: connecting to a BLE-compliant Chinese heart rate monitor I'm using the Xamarin Bluetooth LE library, but I can't find the heart rate monitor in the list of devices found. I don't know if it appears as an unnamed device.

    After identifying the device, I must connect to it and get data. But I still don't know how to read this data.

    Thanks,

    Patrick (me too)

    Thursday, March 11, 2021 3:35 PM
  • User172704 posted

    @criapix

    I have very quickly stripped the file down to its bare-bones and pasted it below. See if you can work out what is happening from this. Maybe the Characteristic_ValueUpdated event handler is what you are looking for. If not, we'll have to figure out a way for me to share the full code securely.

    Your device might be the problem. I have tried connecting to cheap BLE devices before and got nowhere. Maybe they have rubbish Bluetooth hardware or maybe they only pay lip-service to implementing a proper interface? If you continue to struggle, I'd get a device like the one I linked to. It wasn't that expensive (maybe £GBP40) and works perfectly.

    • Patrick

    ``` public class BluetoothLE { // Event handler for when the Bluetooth LE connection is lost. private async void BLEAdapter_DeviceConnectionLost( object sender, DeviceErrorEventArgs e ) { if( e.Device.Id == _thisSessionConnectedDeviceGuid ) { // Disconnected device has GUID {e.Device.Id}, which matches GUID of connected heart-rate device, so attempt reconnection. await AttemptReconnectOrDiscoveryAsync( true, CancellationToken.None ); } }

    // Event handler for when a Bluetooth LE device disconnects.
    private async void BLEAdapter_DeviceDisconnected( object sender, DeviceEventArgs e )
    {
        if( e.Device.Id == _thisSessionConnectedDeviceGuid )
        {
            await AttemptReconnectOrDiscoveryAsync( true, CancellationToken.None );
        }
    }
    
    // Handle connection timeout.
    private void BLEAdapter_ScanTimeoutElapsed( object sender, EventArgs e )
    {
    }
    
    
    // Event handler for when a Bluetooth LE device is discovered.
    private void BLEAdapter_DeviceDiscovered( object sender, DeviceEventArgs e )
    {
        _devices.Add( new BluetoothLEDeviceRecord( e.Device ) );
    }
    
    // Event handler for when a new value is read from the connected Bluetooth LE device.
    private void Characteristic_ValueUpdated( object sender, CharacteristicUpdatedEventArgs e )
    {
        byte[] valueHexBytes = e.Characteristic.Value;
        byte t = valueHexBytes[ 1 ];
        valueHexBytes[ 1 ] = valueHexBytes[ 0 ];
        valueHexBytes[ 0 ] = t;
        UInt16 valueInteger = BitConverter.ToUInt16( valueHexBytes, 0 );
        _latestBioSampleValue = (double)valueInteger;
    }
    
    // Helper to attempt reconnection of known device or scan if needed.
    private async Task<bool> AttemptReconnectOrDiscoveryAsync( bool triggeredbyBLEEvent, CancellationToken cancellationToken )
    {
        if( await InternalInitialiseOrReinitialiseAsync() )
        {
            if( Descriptor.TryGetGuid( _BluetoothLEDeviceGUID, out Guid lastBLEDeviceGuid ) )
            {
                await AttemptReconnectionAsync( lastBLEDeviceGuid );
            }
            else
            {
                await ScanForDevices( cancellationToken );
            }
    
            await ExamineDiscoveredDevices( cancellationToken );
    
            if( AllOkay )
            {
                Descriptor.SetOrAddKeyValue( _BluetoothLEDeviceGUID, _connectedBLEDevice.Id.ToString() );
                return true;
            }
            else
            {
                return false;
            }
        }
    
    
        // Attempt reconnection of a known device, bypassing the power-hungry need to do a full scan.
        private async Task AttemptReconnectionAsync( Guid deviceGuid )
        {
            IDevice specificDevice = await ConnectToKnownDeviceAsync( deviceGuid ).ConfigureAwait( false );
            if( specificDevice != null )
            {
                _devices.Add( new BluetoothLEDeviceRecord( specificDevice ) );
            }
            else
            {
                IReadOnlyCollection<IDevice> connectedDevices = App.BLE.Adapter.GetSystemConnectedOrPairedDevices();
                foreach( IDevice device in connectedDevices )
                {
                    _devices.Add( new BluetoothLEDeviceRecord( device ) );
                }
            }
        }
    
    
        // Helper to attempt connection to a known device, which saves power wasted on a full scan.
        private async Task<IDevice> ConnectToKnownDeviceAsync( Guid deviceGuid )
        {
            QA.CodeStackDebug();
            IDevice device;
            try
            {
                device = await App.BLE.Adapter.ConnectToKnownDeviceAsync( deviceGuid ).TimeoutAfter<IDevice>( TimeSpan.FromSeconds( 30.0 ) );
            }
            catch( TimeoutException ex )
            {
            }
            return device;
        }
    
    
        // Search the specified device for a heart-rate service.
        private async Task SearchForHeartRateService( IDevice connectedDevice, CancellationToken cancellationToken )
        {
            IReadOnlyList<IService> services = await connectedDevice.GetServicesAsync( cancellationToken );
            foreach( IService service in services )
            {
                IReadOnlyList<ICharacteristic> characteristics = await service.GetCharacteristicsAsync();
                foreach( ICharacteristic characteristic in characteristics )
                {
                    if( characteristic.Id == _HeartRateGuid )
                    {
                        _connectedBLEDevice = connectedDevice;
                        _selectedBLEService = service;
                        _selectedBLECharacteristic = characteristic;
                        _selectedBLECharacteristic.ValueUpdated += Characteristic_ValueUpdated;
                        _thisSessionConnectedDeviceGuid = _connectedBLEDevice.Id;
                        await characteristic.StartUpdatesAsync();
                        return;
                    }
                }
            }
        }
    
        // Wraps the scanning for Bluetooth LE devices.
        private async Task ScanForDevices( CancellationToken cancellationToken )
        {
            App.BLE.Adapter.ScanMode = ScanMode.LowLatency;
            await App.BLE.Adapter.StartScanningForDevicesAsync( cancellationToken );
        }
    
    
        // Helper to wrap up examining all discovered devices.
        private async Task ExamineDiscoveredDevices( CancellationToken cancellationToken )
        {
            foreach( BluetoothLEDeviceRecord deviceRecord in _devices )
                await ExamineDiscoveredDevice( deviceRecord.Device, cancellationToken );
        }
    
    
        // Helper function that determines if a Bluetooth BLE instance has been set.
        private bool BLESet => App.BLE != null;
    
    
        // Helper function that determines if Bluetooth LE is turned on.
        private bool BLEOn => BLESet && App.BLE.State == BluetoothState.On;
    
    
        // Helper to safely determine if a Bluetooth LE device scan is currently underway.
        private bool IsScanningForDevices => BLEOn && ( App.BLE.Adapter?.IsScanning ?? false );
    
    
        // Helper to wrap up ON/OFF state text from the Bluetooth instance on this platform.
        private string BLEStateString => ( !BLESet ) ? "BLE instance not set!" : ( App.BLE.IsOn ) ? "BLE State = ON" : "BLE State = OFF";
    
    
        // Helper to compose the logic conditions necessary to determine is there is a successful connection.
        private bool AllOkay => BLEOn && _connectedBLEDevice != null && _selectedBLEService != null && _selectedBLECharacteristic != null;
    
        // Helper that does its best to put the code and Bluetooth back into a known state.
        private async Task<bool> InternalInitialiseOrReinitialiseAsync()
        {
            App.BLE.StateChanged -= BLE_StateChanged;
            App.BLE.Adapter.DeviceDiscovered -= BLEAdapter_DeviceDiscovered;
            App.BLE.Adapter.ScanTimeoutElapsed -= BLEAdapter_ScanTimeoutElapsed;
            App.BLE.Adapter.DeviceDisconnected -= BLEAdapter_DeviceDisconnected;
            App.BLE.Adapter.DeviceConnectionLost -= BLEAdapter_DeviceConnectionLost;
            _selectedBLECharacteristic.ValueUpdated -= Characteristic_ValueUpdated;
            _selectedBLECharacteristic = null;
            _connectedBLEDevice = null;
            _selectedBLEService = null;
            foreach( BluetoothLEDeviceRecord device in _devices )
            {
                await App.BLE.Adapter.DisconnectDeviceAsync( device.Device );
            }
            _devices.Clear();
    
            App.BLE.StateChanged += BLE_StateChanged;
            App.BLE.Adapter.DeviceDiscovered += BLEAdapter_DeviceDiscovered;
            App.BLE.Adapter.ScanTimeoutElapsed += BLEAdapter_ScanTimeoutElapsed;
            App.BLE.Adapter.DeviceDisconnected += BLEAdapter_DeviceDisconnected;
            App.BLE.Adapter.DeviceConnectionLost += BLEAdapter_DeviceConnectionLost;
    
            return true;
        }
    
        // State information for the Bluetooth LE connected device.
        private bool _internallyBusy = false;
        private IDevice _connectedBLEDevice = null;
        private IService _selectedBLEService = null;
        private ICharacteristic _selectedBLECharacteristic = null;
        private Guid _thisSessionConnectedDeviceGuid = Guid.Empty;
        private Collection<BluetoothLEDeviceRecord> _devices = new Collection<BluetoothLEDeviceRecord>();
    
        // Latest bio-sample obtained from the connected device.
        private double _latestBioSampleValue = 0.0;
    
        // UUID for heart-rate device (see  https://www.bluetooth.com/specifications/bluetooth-core-specification/).
        private const int _HeartRateUuid = 0x2a37;
        private readonly Guid _HeartRateGuid = _HeartRateUuid.UuidFromPartial();
    
        // How long to attempt reconnection.
        private const double _ReconnectionTimeoutSeconds = 30.0;
    
        // These are kept here simply because they may prove to be useful and it can take some digging to find them online.         
        // Device information 0x180a
        // Battery service: 0x180f
        // Heart-rate: 0x180d
        // Body sensor location: 2a38
        // Manufacturer Name String: 2a29
        // Model Number String: 2a24
        // Hardware Revision String: 2a27
        // Firmware Revision String: 2a26
        // Software Revision String: 2a28
        // BatteryLevelUuid: 0x2a37;
    
        /// <summary>
        /// Holds information about a single Bluetooth LE device.
        /// </summary>
        private struct BluetoothLEDeviceRecord
        {
            public BluetoothLEDeviceRecord( IDevice device )
            {
                Device = device;
            }
    
            public IDevice Device { get; private set; }
            public Guid UniqueId => Device.Id;
            public bool IsConnected => Device.State == DeviceState.Connected;
            public int Rssi => Device.Rssi;
            public string Name => Device.Name;
        }
    }
    

    }

    ```

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, March 12, 2021 8:13 AM
  • User366729 posted

    @EasyGoingPat Oh... It will help a lot. In next days I will try to use some solutions from this snippet. I return telling about the results.

    Very very thanks. Patrick Coelho

    Friday, March 12, 2021 12:53 PM
  • User366729 posted

    @EasyGoingPat Thanks so much. The SearchForHeartRateService method was perfect to me. Now I can continue with my project.

    Saturday, March 13, 2021 3:20 PM
  • User172704 posted

    @criapix

    Glad I could help. Good luck!

    • Patrick
    Monday, March 15, 2021 7:43 AM