Click here to Skip to main content
Click here to Skip to main content

Blood Pressure Tracker, Win 8 Phone Based HealthVault App

, 2 Jun 2014
Rate this:
Please Sign up or sign in to vote.
Blood Pressure Tracker is a Win 8 Phone application for tracking the blood pressure , interacts with HealthVault for storing and fetching the blood pressure information

Disclaimer

This application interacts with HealthVault. One has to create a HealthVault application and make use of the Application Id in Blood Pressure Tracker App.

For now you can run the sample application without creating a new application in HealthVault. However it can be used only for testing and not for production. In reality all your blood pressure information will be stored in HealthVault. You are responsible for your own data. Please make sure to keep them secret and not to disclose to unauthorized persons. 

Please note : This article does not deal with how to move test HealthVault application to production.  Also no part of the concept , code is related to my current or previous organizations.  

Introduction  

This article is all about blood pressure and it's tracking. Blood Pressure Tracker, A Windows 8 Phone application developed for tracking the day to day blood pressure states. Before jumping into the technical details about the application , we will try to understand about blood pressure and related terminologies.  

Domain knowledge is very important for a technical person so that one can understand and contribute better. Many a times programmers don't understand what they do, they just try to complete their work items. They don't bother to understand the business. Things may work fine for few , however it's very important for us to understand the domain so that one can meet the expectations of business analyst or product managers and deliver the right product to customer. 

The blood pressure tracker application stores all the information in Microsoft HealthVault. The same is being fetched. We will not go in detail about the HealthVault integration but to an extent we will see how to communicate with it.  

Let us now start with the basic understanding of blood pressure.

What is Blood Pressure ?

Blood pressure is the force exerted by circulating blood on the walls of blood vessels. The Blood pressure is typically recorded as two numbers, written in a ration like - 115/75 which is read as "115 over 75 millimeters of mercury".

Systolic

The top number (115 as per the above sample) , measures the pressure in the arteries when the heart beats (when the heart muscle contracts).

Diastolic

The bottom number (75 as per the above sample), measures the pressure in the arteries between heartbeats (when the heart muscle is resting between beats and refilling with blood). 

The blood pressure readings are categorized and considered to be normal , high or low based on the below readings.

Normal Blood Pressure - Blood pressure reading is below 120/80 is considered to be normal.

High Blood Pressure - Blood pressure of 140/90 or higher is considered to be high blood pressure. If either of the numbers are usually high, you have high blood pressure. 

Low Blood Pressure - Blood pressure that is too low is known as hypotension. Some experts define low blood pressure as readings lower than 90 systolic or 60 diastolic 

Below is what the American Health Association recommends about the blood pressure  


What is High Blood Pressure ? 

First of all, I recommend all my readers to watch this small youtube video to understand the same http://www.youtube.com/watch?v=tAmLbclSucQ 

Blood pressure is determined by the amount of blood our heart pumps and the amount of resistance to blood flow in our arteries. The more blood our heart pumps , the narrower our arteries, the higher is our blood pressure.

Below are the causes for high blood pressure.  

The exact causes of high blood pressure are not known, However several factors and conditions may play a role in its development, including: 

  • Smoking
     
  • Being overweight or obese
     
  • Lack of physical activity
     
  • Too much salt in the diet
     
  • Too much alcohol consumption (more than 1 to 2 drinks per day)
     
  • Stress
     
  • Older age
     
  • Genetics
     
  • Family history of high blood pressure
     
  • Chronic kidney disease
     
  • Adrenal and thyroid disorders 

Usecase of Blood Pressure Tracker

1. The user should be able to manage and track his/her blood pressure information.

2. Create a HealthVault Application for storing and fetching the blood pressure information.

3. Show a line graph for Systolic and Diastolic numbers by date range vs Millimeters of Mercury (mm Hg). 

4. Integrate Blood Pressure Tracker (Win Phone App) with HealthVault Application so that it authenticates the user for managing his blood pressure information in HealthVault. 

Prototype

The Blood Pressure Tracker application is prototyped with the help of a tool named Pencil Project. It is opensource tool , You can have a look into http://pencil.evolus.vn/ 

The below prototype shows at high level how the application would be. Note per prototype it looks like an iPhone App. However our application is Win 8 Phone App.

 

 

Creating a New HealthVault Application 

For now we will work on development enviroment of HealthVault. First of all we need a Healthvault Application Id in order for our application to communicate with the HealthVault. Below is the link for creating a new HealthVault
Application. You need a windows live Id, click on the below link and log into the site.

https://config.healthvault-ppe.com/default.aspx

Create a new application by clicking on the button 

Key in the Application name then select the application type as SODA. At last read the terms and condition.

What is a Software on Device Authentication (SODA) Application ? 

Software on Device Authentication (SODA) applications are client applications that run on a desktop or mobile device.  Every time a user installs a SODA application, the user must authorize that installation of the application to access their HealthVault record.  For instance, if the user is running the same application on both their laptop and desktop, they will need to authorize both installations to access their HealthVault record.

SODA applications are offline applications, and the user is sent to HealthVault only once to authorize the application instance.  After the user has authorized the application instance, they then return to the application. 

Assigning the appropriate data-type for storing and fetching the Blood Pressure Information 

Ones the application Id is created successfully , you will have to click on the Application Id link , takes you to a page where we can sit the data-type for our application. 

Click on "SODA app rules" tab and then create a new offline auth rule as below.

Please make a note on Application Id, we will be using it in our Blood Pressure Tracker to communicate with the HealthVault.

Background

Basic understanding of Windows Phone development, XAML etc. Knowing healthcare terminologies and working with it is a plus.

Using the code

The Blood Pressure Tracker App uses some of the HealthVault libraries to integrate with HealthVault for authenticating the user and then storing and fetching of blood pressure information.

Below is the code snippet of App.cs

Create an instance of HealthVaultService , based on the heatlhvault application id, platform url and shell url. We will be using this instance in other PhoneApplication pages. Note - The applicaiton Id used here is what I had created one in Healthvault. You will have to replace the same with your application Id by following the above mentioned steps. 

public partial class App : Application
{
        public static string SettingsFilename = "Settings";
        public static HealthVaultService HealthVaultService { get; set; }
        public static string HealthVaultShellUrl { get; set; }
 
 
        static string platformUrl = @"https://platform.healthvault-ppe.com/platform/wildcat.ashx";
        static string shellUrl = @"https://account.healthvault-ppe.com";
        static string masterAppId = "47246711-2a98-4beb-bd42-4f6ebf2564d9";
 
        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
            HealthVaultService = new HealthVaultService(platformUrl, shellUrl, new Guid(masterAppId));
        }
 
        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
            HealthVaultService = new HealthVaultService(platformUrl, shellUrl, new Guid(masterAppId));
        }
}

Authentication

We are using a PhoneApplicationPage , with WebBrowserControl in it. On Load , we will set the HealthVaultShellUrl and navigate to the same URL. The user will be requested to provide his/her username, password to authenticate a user with HealthVault. On success , this page navigates to MyBloodPressure.xaml.

    public partial class HostedBrowser : PhoneApplicationPage
    {
        public HostedBrowser()
        {
            InitializeComponent();
            c_webBrowser.IsScriptEnabled = true;
 
            Loaded += new RoutedEventHandler(HealthVaultWebPage_Loaded);
            c_webBrowser.Navigated += new EventHandler<system.windows.navigation.navigationeventargs>(c_webBrowser_Navigated);
            c_webBrowser.Navigating += new EventHandler<navigatingeventargs>(c_webBrowser_Navigating);
        }
 
        void c_webBrowser_Navigating(object sender, NavigatingEventArgs e)
        {
            c_CurrentUrl.Text = e.Uri.AbsoluteUri;
        }
 
        void c_webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            if (e.Uri.OriginalString.Contains("target=AppAuthSuccess"))
            {
                Uri pageUri = new Uri("/MyBloodPressure.xaml", UriKind.RelativeOrAbsolute);
 
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    NavigationService.Navigate(pageUri);
                });
            }
        }
 
        void HealthVaultWebPage_Loaded(object sender, RoutedEventArgs e)
        {
            string url = App.HealthVaultShellUrl;
 
            c_webBrowser.Navigate(new Uri(url));
        }
    }

     

All the interactions happening with the HealthVault is XML based request and response.  Internally the HealthVault framework makes a HTTP Post request as below.

        public virtual void BeginSendRequest(HealthVaultRequest request)
        {
            string requestXml = GenerateRequestXml(request);
 
            WebTransport transport = new WebTransport();
            transport.BeginSendPostRequest(HealthServiceUrl, requestXml, SendRequestCallback, request);
        } 

The Blood Pressure Tracker App needs to create/construct a xml request for blood pressure type. Also it should have logic for parsing the HealthVault response when we are fetching the blood pressure information.

Below is the code snipper which is responsible for constructing the xml i.e GetXml() and for parsing. 

    /// <summary>
    ///  Data Model for BloodPressure.
    ///  This model should enable - 
    ///     1. Loading an bloodpressure state from existing HealthVault XML
    ///     2. Creating an bloodpressure state object to be store in HealthVault
    ///     3. Expose the important properties of bloodpressure state available in HealthVault SDK
    /// </summary>
    public class BloodPressureModel : HealthRecordItemModel
    {
        public readonly static string TypeId = "ca3c57f4-f4c1-4e15-be67-0a3caf5414ed";
                
        public void Parse(XElement thingXml)
        {
            XElement bloodPressureState = thingXml.Descendants("data-xml").Descendants("blood-pressure").First();
 
            this.When = Convert.ToDateTime(thingXml.Element("eff-date").Value);
 
            if (thingXml.Descendants("common") != null &&
                    (thingXml.Descendants("common").Descendants("note").Count() != 0))
            {
                this.Note = thingXml.Descendants("common").Descendants("note").First().Value;
            }
 
            if (bloodPressureState.Element("systolic") != null)
            {
                try
                {
                    this.Systolic = int.Parse(bloodPressureState.Element("systolic").Value);
                }
                catch (Exception) { }
            }
            if (bloodPressureState.Element("diastolic") != null)
            {
                try
                {
                    this.Diastolic = int.Parse(bloodPressureState.Element("diastolic").Value);
                }
                catch (Exception) { }
            }
            if (bloodPressureState.Element("pulse") != null)
            {
                try
                {
                    this.Pulse = int.Parse(bloodPressureState.Element("pulse").Value);
                }
                catch (Exception) { }
            }
            if (bloodPressureState.Element("irregular-heartbeat") != null)
            {
                try
                {
                    this.IrregularHeartbeat = bool.Parse(bloodPressureState.Element("irregular-heartbeat").Value);
                }
                catch (Exception) { }
            }
            else
                this.IrregularHeartbeat = false;
        }
 
        /// <summary>
        /// Get the Xml representing this type
        /// </summary>
        /// <returns>
        public override string GetXml()
        {
            int irregularHeartbeat = 0;
            if (IrregularHeartbeat)
                irregularHeartbeat = 1;
 
            return string.Format(
                thingXml,
                When.Year,
                When.Month,
                When.Day,
                When.Hour,
                When.Minute,
                When.Second,
                When.Millisecond,
                (this.Systolic).ToString(),
                (this.Diastolic).ToString(),
                (this.Pulse).ToString(),
                irregularHeartbeat,
                this.Note);
        }
 
        public String FormattedWhen
        {
            get{
                return String.Format("{0:dd/MM}",When);
            }
        }
        public DateTime When { get; set; }       
        public string Note { get; set; }
        public int Systolic { get; set; }
        public int Diastolic { get; set; }
        public int Pulse { get; set; }
        public bool IrregularHeartbeat { get; set; }
    }  

Fetching the Blood Pressure Readings

Below is the code snippet which makes a request to HealthVault and gets the last blood pressure readings. The GetThingsCompleted is a call back method which will be called after the execution of GetThings. The response will be either the blood pressure information or error messages. 

Note: The Last reading may be null in case if we are trying this for first time, there won't be any last readings. In such cases we are updating the UI with 'No readings..'

     if (App.HealthVaultService.CurrentRecord != null)
     {
           SetRecordName(App.HealthVaultService.CurrentRecord.RecordName
           // We are only interested in the last item
           HealthVaultMethods.GetThings(BloodPressureModel.TypeId, null, null, null, GetThingsCompleted);
           SetProgressBarVisibility(true);
     }
 
     void GetThingsCompleted(object sender, HealthVaultResponseEventArgs e)
     {
            SetProgressBarVisibility(false);
 
            if (e.ErrorText == null)
            {
                XElement responseNode = XElement.Parse(e.ResponseXml);
                // using LINQ to get the latest reading of blood pressure state
                XElement latestReading = (from thingNode in responseNode.Descendants("thing")
                                          orderby Convert.ToDateTime(thingNode.Element("eff-date").Value) descending
                                          select thingNode).FirstOrDefault<xelement>();
 
                if (latestReading != null)
                {
                    BloodPressureModel bloodPressureState = new BloodPressureModel();
                    bloodPressureState.Parse(latestReading);
 
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        txtLastUpdated.Text = string.Format("When - {0}, Systolic - {1}, Diastolic - {2}",
                                                            bloodPressureState.When.ToString("MMM dd, yyyy"),
                                                            bloodPressureState.Systolic,
                                                            bloodPressureState.Diastolic);
                    });
                }
                else
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        txtLastUpdated.Text = "No readings! Time to track blood pressure.";
                    });
                }
            }
      } 

Saving Blood Pressure Information

Below is the code snippet which is responsible for initiating the PutThings. It may succeed or fail. In either case we will notify the user with the error message.

Note - Upon the completion of PutThings , the PutThingsCompleted will be called. Ideally there won't be any errors unless otherwise some validation failure happens in PutThings.

    void SaveApplicationBarIconButton_Click(object sender, EventArgs e)
    {
            string formattedTime = "";
 
            if (timeControl.Value.HasValue)
            {
                var timeSpan = TimeSpan.Parse(timeControl.Value.ToString());
                var hours = (Int32)timeSpan.Hours;
                var minutes = (Int32)timeSpan.Minutes;
                var amPmDesignator = "AM";
                if (hours == 0)
                    hours = 12;
                else if (hours == 12)
                    amPmDesignator = "PM";
                else if (hours > 12)
                {
                    hours -= 12;
                    amPmDesignator = "PM";
                }
 
                formattedTime = String.Format("{0}:{1:00} {2}", hours, minutes, amPmDesignator);
            }
            var dateTime = txtWhen.Text + " " + formattedTime;
 
            BloodPressureModel model = new BloodPressureModel();
            model.Systolic = int.Parse(txtSystolic.Text);
            model.Diastolic = int.Parse(txtdiastolic.Text);
            model.Pulse = int.Parse(txtPulse.Text);
            model.When = DateTime.Parse(dateTime);
            if (!string.IsNullOrEmpty(txtNote.Text))
            {
                model.Note = txtNote.Text.Trim();
            }
            HealthVaultMethods.PutThings(model, PutThingsCompleted);
            SetProgressBarVisibility(true);
     }
 
     void PutThingsCompleted(object sender, HealthVaultResponseEventArgs e)
     {
            SetProgressBarVisibility(false);
            if (e.ErrorText != null)
            {
                SetErrorMesasge(e.ErrorText);
            }
            else
            {
                Dispatcher.BeginInvoke(() =>
                {
                    var messagePrompt = new MessagePrompt
                    {
                        Title = "Info",
                        Message = "Blood Pressure information saved successfully."
                    };
                    messagePrompt.Show();
                });
            }
     }

Plotting the Systolic and Diastolic Graphs

This application uses QuickCharts (an opensouce charting library for Win Phone) to render a line graph. Below is the code snippet which gathers all the Systolic values which will be used for drawing the line graph. The code is same for diastolic except we are getting the Diastolic property value.

     public ObservableCollection<graphitem> Data { get { return _data; } }
  
     void GetThingsCompleted(object sender, HealthVaultResponseEventArgs e)
     {
            if (e.ErrorText == null)
            {
                XElement responseNode = XElement.Parse(e.ResponseXml);
                // using LINQ to get the latest reading of blood pressure state
                var readings = (from thingNode in responseNode.Descendants("thing")
                                orderby Convert.ToDateTime(thingNode.Element("eff-date").Value) ascending
                                select thingNode).ToList();
 
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    BloodPressureModel bloodPressureState = new BloodPressureModel();
                    foreach (var item in readings)
                    {
                        bloodPressureState.Parse(item);
                        _data.Add(new GraphItem
                                     {
                                         Name = bloodPressureState.When.ToShortDateString(),
                                         Value = bloodPressureState.Systolic.ToString()
                                     });
                    }
 
                    progressOverlay.Hide();
                });
            }
            else
            {
                Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(e.ErrorText);
                });
            }
      }   




 

References

Below are few links by which I to know more about blood pressure. And other interesting links for HealthVault and Coding4Fun Controls for Win Phone. 

http://msdn.microsoft.com/en-us/library/jj551286.aspx

http://coding4fun.codeplex.com/documentation

http://developer.healthvault.com/

http://www.mayoclinic.com/health/high-blood-pressure/DS00100

http://www.webmd.com/hypertension-high-blood-pressure/guide/blood-pressure-causes

http://www.heart.org/HEARTORG/Conditions/HighBloodPressure/AboutHighBloodPressure/Understanding-Blood-Pressure-Readings_UCM_301764_Article.jsp

Snapshots

1. Getting Started

2. Blood Pressure Tracker application Main Screen

 

3. Save blood pressure information

Points of Interest

It was really interesting to learn and share something in Healthcare domain. I really found this one very useful to track my day to day blood pressure information in a more secure manner which can be used further for various analysis.  Lot of things I'm having in mind to enhance. For now it's just a basic version.

Your feedback is essential for me to understand how useful the application is , how it can be enhanced further etc. Please feel free to drop your comments or suggestions, We shall together make a wonderful app and make it available in Windows Phone Store for free. 

History 

Version 1.0 - 3/24/2013 - Initial Version of Blood Pressure Tracker connects to HealthVault for storing and fetching the blood pressure information. 

 

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ranjan.D
Web Developer
United States United States
Profile
 
Around 9 years of professional software development experience in analysis, design, development, testing and implementation of enterprise web applications for healthcare domain with good exposure to object-oriented design, software architectures, design patterns, test-driven development and agile practices.
 
In Brief
 
Analyse and create High Level , Detailed Design documents.
Use UML Modelling and create Use Cases , Class Diagram , Component Model , Deployment Diagram, Sequence Diagram in HLD.
 
Area of Working : Dedicated to Microsoft .NET Technologies
Experience with : C# , J2EE , J2ME, Windows Phone 8, Windows Store App
Proficient in: C# , XML , XHTML, XML, HTML5, Javascript, Jquery, CSS, SQL, LINQ, EF
 
Software Development
 
Database: Microsoft SQL Server, FoxPro
Development Frameworks: Microsoft .NET 1.1, 2.0, 3.5, 4.5
UI: Windows Forms, Windows Presentation Foundation, ASP.NET Web Forms and ASP.NET MVC3, MVC4
Coding: WinForm , Web Development, Windows Phone, WinRT Programming, WCF, WebAPI
 
Healthcare Domain Experience
 
CCD, CCR, QRDA, HIE, HL7 V3, Healthcare Interoperability
 
Others:
 
TTD, BDD
 
Education
 
B.E (Computer Science)
 
CodeProject Contest So Far:
 
1. Windows Azure Developer Contest - HealthReunion - A Windows Azure based healthcare product , link - http://www.codeproject.com/Articles/582535/HealthReunion-A-Windows-Azure-based-healthcare-pro
 
2. DnB Developer Contest - DNB Business Lookup and Analytics , link - http://www.codeproject.com/Articles/618344/DNB-Business-Lookup-and-Analytics
 
3. Intel Ultrabook Contest - Journey from development, code signing to publishing my App to Intel AppUp , link - http://www.codeproject.com/Articles/517482/Journey-from-development-code-signing-to-publishin
 
4. Intel App Innovation Contest 2013 - eHealthCare - http://www.codeproject.com/Articles/635815/eHealthCare
 
5. Grand Prize Winner of CodeProject HTML5 &CSS3 Article Content 2014

Comments and Discussions

 
QuestionExcellent introduction to HealthVault integration with Windows Phone PinmemberNji, Klaus3-Jun-14 17:21 
AnswerRe: Excellent introduction to HealthVault integration with Windows Phone PinmvpRanjan.D3-Jun-14 17:23 
QuestionHealthVault Problem. Pinmemberwebwon17-Apr-14 12:43 
AnswerRe: HealthVault Problem. PinmvpRanjan.D12-May-14 17:01 
GeneralMy vote of 5 PinmemberStefan Heesch3-Apr-13 0:45 
Good introduction into MS HealthVault and howto make use of it for your own apps.
GeneralRe: My vote of 5 PinmemberRanjan.D3-Apr-13 15:10 
QuestionAny other storage tech? Pinmembersraoh25-Mar-13 15:21 
AnswerRe: Any other storage tech? PinmemberRanjan.D25-Mar-13 16:48 
GeneralMy vote of 5 Pinmembersraoh25-Mar-13 15:18 
QuestionWhy need separate framework? PingroupGrasshopper.iics24-Mar-13 19:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 2 Jun 2014
Article Copyright 2013 by Ranjan.D
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid