Saturday, April 20, 2013

Connecting to the Polar Personal Trainer Site

Connecting to the Polar Personal Trainer Site

A number of people have requested access to the comms code that I use in the Polar HRM Uploader tool I created.  Because of this, I've decided to write about the software here and offer it free for non-commercial use.  It's not a complete implementation, you will still need to write your own HRM readers and convert that to the Polar format, but the attached code should give you a good starting point.

The communications protocol has been reversed engineered by intercepting the communications between Polar's WebLink and the Polar Personal Trainer Site.  I used an intercepting proxy, called BurpProxy, that does a great job of displaying the content of HTTP traffic.  Luckily, the Polar protocol is in plain text so it makes it relatively straightforward to determine what is required.

Click here to download all the source files in one archive. The code is also on GitHub

The Communications Protocol

Uploading to the Polar Site is a three stage process:
  1. Login.  This stage requires that you authenticate with the Polar site using a basic-auth method.  You can see an example of the login handshake here.
  2. Upload the timestamps of HRM files.  The Polar site will then validate the files and return a response which indicates which files have already been uploaded.  You can see an example of the timestamp handshake here.
  3. Upload the files.  The files are uploaded using a simple XML format.  You can see an example of uploading files here.

XML Marshalling

Since we need to convert from Java to XML, we use an XML data binding library called Castor.  Java has come along way since I originally wrote this code and you can now use Java's JAXB reference implementation to do something similar.

There's a number of good examples on the Castor site that shows how to use the libraries.

Click the link to get the Castor mapping file that I've used.

The code below shows a snippet of the XML format used by Polar.

 <wristunit-data>  
     <prop name="subModel">166</prop>  
     <prop name="version">2</prop>  
     <object name="userSettings">  
         <prop name="maxhr">186</prop>  
         <prop name="resthr">50</prop>  
     </object>  
     <collection name="Exercises">  
         <item type="Exercise">  
             <prop name="origin">1</prop>  
             <prop name="time">2011-08-22 17:39:52.000</prop>  
             <prop name="save">True</prop>  
             <object name="mode">  
                 <prop name="speed">True</prop>  
                 <prop name="cadence">True</prop>  
             </object>  
 ...              
   

We represent each element with a Java object:
  • Property.  These are the core elements on the Polar message that describe a name and value.  They have an optional type.
  • Item. An Item is a collection of Polar objects and it has a Type and an optional Index.
  • Collection.  A named list of Items, e.g. exercises.
  • Polar Object.  A named collection of Properties.
  • Wrist Unit Data. A wrapper object for the message.
  • Webservice.  A wrapper object for the Polar response.
You can download these files by clicking on the links or view them on GitHub.

Communications Code

The communications code is based upon standard Java HTTPUrlConnection and is contained in the class PolarSiteConnection.  This contains simple methods for connecting to the Polar site, sending data and parsing the response.

It encapsulates the Castor data binding too, which is adequate for my project but not generic enough as there's no easy means of implementing an alternative library without some refactoring of the code.

Here's a simple example of how to use the code to login:

 private void processLogin() {  
         // Update the status on the main dialog.  
         controlledFrame.setStatusMessage("Logging into Polar website...");  
         // Get the dialog credentials and try to connect.  
         String username = loginDialog.getUsername();  
         String password = loginDialog.getPassword();  
         System.out.println("Site connection is: " + siteConn);  
         // Pass these to the connection class.  
 ****  
         Webservice ws = siteConn.intiateConnection(username, password);  
 ****  
         if (ws == null) {  
             controlledFrame.setStatusMessage("Cannot connect to Polar site");  
         } else {  
             Status s = ws.getStatus();  
             if (s.isOK()) {  
                 userPreferences = ws.getUserPreferences();  
                 controlledFrame  
                         .setStatusMessage("Logged into Polar website as user "  
                                 + userPreferences.getFirstName() + " "  
                                 + userPreferences.getLastName());  
                 setAppState(AppState.LOGGED_IN);  
             } else {  
                 controlledFrame  
                         .setStatusMessage("Cannot log into the Polar website.");  
             }  
         }  
     }  

Note that the variable siteConn is an instance of PolarSiteConnection. The lines wrapped in **** are the interesting bits that send data to Polar.

PolarSiteConnection also uses a library to convert the password to Base64 as part of the Basic-Auth authentication.  You'll need to source your own copy of this as the licensing around the one I use prevents me from distributing it.





Thursday, November 03, 2011

Uploading Old Polar HRM Data to the Polar Personal Trainer Website

(Update 22nd April 2014: Newer version of the HRMUploader jar fixes an issue with HRZones if there are more than five defined in the HRM file)

I'm a keen cyclist and have used a Heart Rate Monitor of various descriptions for a number of years. I've religiously downloaded this data onto the PC and stored it in the various applications that come with the monitor. Not that I do anything with it, though I did get part way through writing an application to store the data in a relational database and then display multiple rides overlaid on one another for visual comparison. Anyway, I digress.

More recently I've bought Polar HRMs, they are great products with useful features for cycling. Years ago I wrote a Java application that converted the 'other' HRM files to the Polar format, so that all rides and associated HRM data could be shown in the latest Polar application on the PC.

Polar have caught onto the web, and have launched a site that allows you to transfer your data from the HRM to the web. Great for current stuff, but what about all those old files I have? In their wisdom, Polar have not released a tool that allows me to upload the data I've got on my PC.

There are a few people around who would, like me, prefer to have all their data on the web, and want to upload their old data. Being a professional Java developer, I thought it would be a doddle to create a Java Application that interfaced with the Polar web site and allowed me to transfer my data. And, in general, it was. So here is a Java application that does this. It's a little crude, but does the job.

Just run it with:

java -jar HRMUploader.jar


Enter your Polar Personal Trainer userid and password. If you log in successfully, then you will see your name in the lower status pane.

Browse to your polar .hrm files and select one or more (try it with one first :) ) The application will check the site to see if it's already uploaded a file for this date. If it has, it will put a check mark against the file, if it hasn't then use the upload button to upload the file. It won't upload a file that is already on the site, you will have to delete it from the site if you want to resend it.

There are no guarantees that this will work for you. Might be worth opening another 'test' account on the Polar site and trying it out there first. Whilst you can select many files to upload at once, it might be worth limiting it to 10 or so at a time - the Polar site might choke on too many. I just tried it with about 70 and it took a while, but seemed to work.

Regarding calories expended.

This value is read from the associated PDD file and needs to be in the same directory as your HRM file.  There's one PDD file for each day, so you could have many HRM files that reference the same PDD if you do multiple exercises per day.  In these cases, you are unlikely to be able to read the PDD as it will not have the same name as the HRM file.  Unfortunately, when I originally wrote the HRMUploader, I didn't realise I needed to read the PDD too.  Ideally I need to change the application to read the PDD first,  since this contains all the HRM file names.  However, I'm not planning to do this any time soon, sorry.

Altitude data

Altitude data is sent to the Polar site in 'feet'.  This means that if you are using meters in your HRM file, then the conversion to and from feet could result in a rounding error.

Furthermore, I seem to recall a bug in the HRM files that stores altitude as feet, even though the file is supposed to be metric.  Send me a HRM file example if you suspect the altitude is being uploaded incorrectly.

Here's the code to interface with the Polar site

At some point I'd like to host this on the Google Java App Server, but they've done some funny stuff with Java and restricted various classes in the default 'JRE'. It means that some stuff which should work under Java's WORA mantra doesn't.

The application uses various libraries from Apache, Google and Castor. All their respective rights are recognised. The software is supplied 'as-is' and you use it at your own risk. You did back that data up, right?

Saturday, February 12, 2011

Tune Announcer - Scrobble Links

Noticed with the latest Songbird release for Android they support multiple Scrobble clients but broadcast them ALL!

Whilst it's probably a bug, as no other player does this, I've modified Tune Announcer to let the user select which ones to receive.  Mainly because I want to use Songbird.

However, it took me a while to find which scrobble broadcasts did what (note to self: Code comments are useful), so here is a list of the scrobble sites:

There's also the default clients (Android and HTC),no info on these other than they broadcast the following:

<action android:name="com.android.music.playstatechanged" />
<action android:name="com.android.music.metachanged" />
<action android:name="com.htc.music.metachanged" />
<action android:name="com.htc.music.playbackcomplete" />
<action android:name="com.htc.music.playstatechanged" />

They are very similar to the others in content.




Sunday, January 30, 2011

Gestures Download File

Users of Contact Lookup can create their own gestures file.  See this blog post for more details.

To get the pre-built file, then click this link.


(Apologies for bouncing you from one blog to another, but this blog has analytics so I can track how much interest there is in gestures).

Tuesday, December 28, 2010

Customising Google Search

Spam Sites in Search

How many times have you clicked on a Google search result only to be presented with a spam site that just wraps other site content with ads?  I find technical searches on Google are littered with this dross.  It's pissed me off enough to look at using Bing and Bing is far better at hiding this crap from the search list.

I tried this chrome extension, and whilst the idea is sound, it doesn't work particularly well with instant search.

However, there is another option.  Use a customised Google Search Site.  You can read more here on how to set this up.  Whilst the screen looks very basic, it does work at removing dross sites, although you do need to manually blacklist each one 'as you find it'.

You can even link this into chrome to be the default search engine.  You'll need to tweak a few things in the URL to get it to work, specifically adding %s to indicate where the search terms need to go.  Want dated searches?  Add &tbs=qdr:y to get results in the last year and add the date select to your searches.

So finally, I have a Google search that can filter out those spastic sites.

Wednesday, December 15, 2010

Moving to WordPress

The Android posts have moved over to WordPress, mainly to keep the development off the personal blog, but also because WordPress is so much better at editing complicated pages with images.  Blogger seems to have been dumbed down :-(

I might see how the Google Sites stuff works, as I need some better control over the CSS - oh, wait, they don't allow that either :-(

Contact Search Updated

Works with OS 1.6 devices

The latest changes to Contact Search have been around the Database access classes to allow 1.6 devices to work.

For OS2.0, Google improved the framework around data access for Contacts and these are not compatible with 1.6.  It was a large piece of work to write the 1.6 data access code and refactor the contact searching to be able to run both.

Coming to the Market near you soon ;-)