BLE (Heart Rate) readings to a file

FilipeSantos

Member
Joined
May 27, 2019
Messages
12
Programming Experience
1-3
Hello,
Am new here!
Need help on building a windows app to read a Polar H10 HR measure band.
Am starting by using this code; Bluetooth Generic Attribute Profile - Heart Rate Service.zip
Sample app reads HR and presents values to a window as bar chart and listbox.
I need to export the readings to a TXT file or even a virtual com port.
Anyways, not even a text file creation/appending am being successful :D
My knowledge about C# is very low...
My code below. Can anyone help out?
All and any ideas would be greatly appreciated.
Thank you!

async void Instance_ValueChangeCompleted:
private async void Instance_ValueChangeCompleted(HeartRateMeasurement heartRateMeasurementValue)

        {

            // Serialize UI update to the the main UI thread.

            await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>

            {

                statusTextBlock.Text = "Latest received heart rate measurement: " +

                    heartRateMeasurementValue.HeartRateValue;


#if WINDOWS_APP

                outputDataChart.PlotChart(HeartRateService.Instance.DataPoints);

#endif


                outputListBox.Items.Insert(0, heartRateMeasurementValue);



                string path = @"C:\Users\eliseu.santos\Documents\file.txt";


                // convert string to stream

                byte[] byteArray = Encoding.UTF8.GetBytes(path);

                MemoryStream stream = new MemoryStream(byteArray);


                using (TextWriter tw = new StreamWriter(stream))

                {

                    tw.WriteLine("The next line!");

                    tw.WriteLine(heartRateMeasurementValue.HeartRateValue);

                    //tw.Dispose();

                }


            });

        }
 
Last edited:
Hey Skydiver, thank you very much for your help.

I tried all sorts of examples out there and always get error: CS1503 Argument 1: cannot convert from 'string' to 'System.IO.Stream'

C#:
private async void Instance_ValueChangeCompleted(HeartRateMeasurement heartRateMeasurementValue)
        {
            // Serialize UI update to the the main UI thread.
            await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                statusTextBlock.Text = "Latest received heart rate measurement: " +
                    heartRateMeasurementValue.HeartRateValue;

#if WINDOWS_APP
                outputDataChart.PlotChart(HeartRateService.Instance.DataPoints);
#endif

                outputListBox.Items.Insert(0, heartRateMeasurementValue);




                string docpath = @"C:\Users\eliseu.santos\Documents\";

                

                // Append text to an existing file named "WriteLines.txt".
                using (StreamWriter outputFile = new StreamWriter(Path.Combine(docpath, "file.txt")))
                {
                    outputFile.WriteLine("The next line!");
                    outputFile.WriteLine(heartRateMeasurementValue.HeartRateValue);
                }


            });
        }

Can you help here about this error?

Code above in the 1st post didn't show any errors, but it don't creat any file nor write to an existing one.
All code sample is from GitHub, here.

Thank you.
 
You shouldn't be writing the path manually, that is what Environment.SpecialFolder is for. You will notice where this line is :: sWriter.WriteLine(arrText); - you can remove the loop and only write in your heart rate measurements if you want. Code is tested and working, edit to your own liking. Post back if you get stuck or have any questions. Code has inline comments, but is pretty self explanatory.

Write a text file:
using System;
using System.IO;
using System.Windows.Forms;

namespace TestCSharpApp
{
    public partial class Form1 : Form
    {
        private readonly string pathOfAddress = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); //Use special folders instead of manually writing the file path
        private readonly string fileName = "VisualStudioFile";
        private readonly string extAttribute = ".txt";
        private readonly string[] arrOfstuff = { "Sheepings wrote this for me", "Because my dog eat my homework" };

        public Form1()
        {
            InitializeComponent();
            var fullPath = Path.Combine(pathOfAddress, string.Concat(fileName, extAttribute)); //Combine the path and concatenate the path with its file extension
            runArgs(fullPath, arrOfstuff); //Call runArgs by passing in our path and variables to write
        }

        private void runArgs(string path, string[] arrText) //This method takes two parameters, which are fullPath, and arrOfStuff
        {
            try
            {
                using (StreamWriter sWriter = new StreamWriter(path)) //Use using blocks as they are self disposing as well as the resources used within. Pass in your path to the writer
                {
                    for (int i = 0; i < 2; i++) //Loop the strings in arrText
                    {
                        sWriter.WriteLine(arrText[i]);
                    }
                }
            }
            catch (Exception x)
            {
                //Handle any errors if any
            }
            finally
            {
                //Finnish up any work here
            }
        }
    }
}

You don't even need a streamwriter, you can do this with File Write All Lines. Hope you found this useful.

Edit :: fixed a typo
 
Last edited:
Hi Sheepings, thank you for your help.

How I should use that code?
Tried making new class file with that code, but get errors...
Specially this;
Environment.GetFolderPath, gives me error CS0117 'environment' doesn't contain a definition for 'GetFolderPath'

I am very basic about C#... much probably am doing something wrong here.

Even tried to use that code partially, inserted in that Async Void;

(Get almost same errors...)

C#:
private async void Instance_ValueChangeCompleted(HeartRateMeasurement heartRateMeasurementValue)
        {
            // Serialize UI update to the the main UI thread.
            await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                statusTextBlock.Text = "Latest received heart rate measurement: " +
                    heartRateMeasurementValue.HeartRateValue;

#if WINDOWS_APP
                outputDataChart.PlotChart(HeartRateService.Instance.DataPoints);
#endif

                outputListBox.Items.Insert(0, heartRateMeasurementValue);
            });
        }

I just need this Class to put in a text file the heart rate measures.... Damn, this should be easy. :D
 
Last edited:
The reason is because the sample code you cribbed is targeted for Windows Runtime, but the code presented by Sheepings is for Windows Forms.
 
Hmm you say :: Need help on building a windows app - Can you clarify? Is this for UWP/Windows Store? Or what? I assumed a desktop app and sorry I should have asked.

Irrespective @FilipeSantos, yes you can still use my code, tweak it to suit your needs. If you're building a store app or cross platform app, some things won't be available that are available in a standard desktop environment app such as winforms.
 
Oh, yes, am also sorry for that lack of clarification.
I need if for a stand alone desktop app indeed.
Been trying alot of code samples from many websites I found while looking for a BLE HR reader, and so far this sample was the only one that my little knowledge at coding (other than VB) manage to make working and see some results... :D

Thanks to both, anyway, for sharing your code/ help, but it seems that now things are tougher on my side, right?
So now, what are my chances of getting those readings exported to a text file, or to a com port, or any other mean of grabbing them from another app that am doing in VB6 ?
 
If your primary app is in VB6? Why not simply add code to you app to read form the virtual comm port that most Bluetooth devices expose? If you're already modifying your VB6 program to read from some either a text file, why not just go straight to the source?

I vaguely recall that to read from Bluetooth in VB6 you needed the MSCOMM.OCX, but it's really long ago and I tried my best to flush all my memories of VB6.
 
:D
Hey Skydiver, wish I could do that... flush my memories of VB6. But dont have much time to learn deeply other languages and new development techniques/ syntaxes/ etc.
Anyways, AFAIK, BLE devices don't build virtual comm ports, that would be another big wish from here. But will confirm those chances.
Now, back to my old path, don't mind to have a second app running to collect those HR measurments.
What chances to have it working?
 
See this question in StackOverflow about how to get access to the UWP Bluetooth APIs without having to go full blown UWP.
 
Hi Skydiver, thank you very much.
Development platform options are so many now, that I get lost on them.
Need to learn about that... :D
I can't post in that forum. So many rules and limitations to newbies.
Anyways, am thinking on building a desktop form app from scratch, using all info gathered so far.
Maybe will migrate primary app from VB6 to C# while learning how to code here...
From your experience, do you think it will be possible to work (meaning BLE - heart rate measurements reading) in the end?
 
Last edited:
Yes it is possible. The fact that the demo app provided my Microsoft shows that it is possible to get the data from the device.

The main issue is that you have only two obvious routes to go to get the data. Option 1 is the easiest which is to write a UWP app because the BLE APIs are nicely exposed by the UWP framework. Option 2 is at the medium level of difficulty which is to write a C++ COM app because the BLE APIs are also exposed by Windows as part of the Windows SDK/DDK.

Unfortunately, I've not yet found a middle ground where the BLE APIs are nicely wrapped for a regular .NET Framework application. Hence my link above about how to get to the UWP BLE APIs from a regular .NET Framework application.

Conceivably, since the BLE APIs are exposed as COM objects, it would be possible to create an Interop assembly to access them from the .NET Framework and/or use P/Invoke. I don't really have the time or inclination to explore that right now, but perhaps somebody has already done it. Just need the right keywords to search for.
 
Hey Skydiver, thank you for your input.
So, if I understood correctly, best approach would be the one I posted in first post, right?
About the link you posted, that Console option seems promising... I get my device listed by its address and name, but having an hard time to get anything else, mainly because the lack of the needed knowledge to extract the values of HR.
 
Back
Top Bottom