Hacking Polar Watch WebSync Software

I recently purchased a Polar FT-40 watch to monitor my fitness level and track my workouts better. I like the watch so far although I’m not ready to give a thorough review on it just yet. Today, I received the Polar FlowLink data transfer unit that allows me to transfer the data on my watch to Polar’s website. It allows you to chart your progress and do all sorts of interesting things with the data. I was surprised how easy and smoothly the software worked. However, I wanted the data on my desktop so I could do more with it. I wanted to provide my own charts and data views in Excel. I wanted to be able to post it to my blog easily or write a WordPress widget to display my data. That said, I decided to look at what the WebSync software was written in. I had a sneaking suspicion that it might be .NET — I was right!

So, I decided to look under the hood and see if I could tackle writing my own front end to their devices. What I found should horrify anyone who has ever read past Chapter 1 of a reasonable “C#” book.

I started by pulling in the obvious assemblies to see what was built. The project looked reasonably well built. There was enough evidence ot see that there was at least SOME design put into the application. I even found some tests in tone assembly — at least there were some tests (checked that off on their requirements eh?). When I took a look at the EXE, however, what I saw shocked me. So I started drilling down into WebSync.exe. I found a Polar.WebSync.Program class with a static Main() method. Bingo – my entry point. I immediately saw some minor concerns. For instance, they were using a Mutex to provide the functionality of a Singleton pattern. Worse yet, they were calling GC.KeepAlive() on the Mutex. Interesting. They did, however, have what looked like an external exception reporting framework, so that at least gave me SOME hope.

I found Application.Run that was starting a new WebSyncTrayForm() so I naturally followed to the form constructor. In a big Try/Catch block (with no code executing in the “catch” portion), I found a TextBox-style TraceListener was added to the form — mmkay. That’s a decent idea I suppose, but let’s look at the form’s Load event. Oh my! I closed my eyes and looked again. I closed then and then looked one more time. Oh, these folks must have written some VB code with “DoEvents” called more than a few times in their past history. Tell me what you see wrong with this:

WARNING: Not good example code!!

private void WebSyncTrayForm_Load(object sender, EventArgs e)
{
    base.Visible = false;
    this.notifyIcon.Tag = this.notifyIcon.Icon;
    this.toolTip = this.notifyIcon.Text;
    this.notifyIcon.Text = this.toolTip + "n" +
        Resources.StatusInitializing;
    this.timerDaemon = new Timer();
    this.timerDaemon.Interval = 0x2710;
    this.timerDaemon.Tick += new EventHandler(this.timerDaemon_Tick);
    this.timerDaemon.Start();
    this.timerDaemon_Tick(this.timerDaemon, EventArgs.Empty);
}

Seriously? These guys set up a timer, and then start it, and then MANUALLY call the Tick function they just set up! (how do they know it hasn’t been executed already between the start call and a thread interuption that might have caused the Tick event to get executed next.

Then I looked at the tick event and I couldn’t believe what I was seeing.

WARNING: Not good example code!!

private void timerDaemon_Tick(object sender, EventArgs e)
{
    this.retryCount++;
    try
    {
        if (this.retryCount == 6)
        {
            this.timerDaemon.Interval = 0xea60;
        }
        this.mounter = new WristUnitListener();
        this.mounter.WristUnitMounted +=
                new WristUnitConnectionEventHandler(this.WristUnitMounted);
        this.mounter.WristUnitUnmounted +=
                new WristUnitConnectionEventHandler(this.WristUnitUnmounted);
        this.mounter.Start();
        this.DoInitialConfig(null);
        this.timerDaemon.Stop();
        this.timerDaemon.Dispose();
        this.timerDaemon = null;
        this.notifyIcon.Icon = this.notifyIcon.Tag as Icon;
        this.notifyIcon.Text = this.toolTip + "n"
                + Resources.StatusRunning;
        Trace.WriteLine("Connected to Polar Daemon.", "WebSync");
    }
    catch (ConnectionException exception)
    {
        if (this.retryCount < 6)
        {
            Trace.WriteLine(
               string.Format("Couldn't connect to Polar Daemon ({0})",
                              exception.CodeString),
                             "WebSync");
        }
        if (this.retryCount == 6)
        {
            Trace.WriteLine(
               string.Format("Couldn't connect to Polar Daemon ({0})",
                             exception.CodeString),
                             "WebSync");
            Trace.WriteLine(
               string.Format("WebSync couldn't initialize properly." +
                             "Please check that Polar Daemon service is running.",
                              new object[0]), "WebSync");
            this.notifyIcon.Icon = Resources.IconExclamation;
            this.notifyIcon.Text = this.toolTip + "n" + Resources.StatusInitError;
            this.notifyIcon.ShowBalloonTip(0x2710, Resources.ToolTipProblemTitle,
                              Resources.ToolTipInitError, ToolTipIcon.Warning);
            this.notifyIcon.BalloonTipClicked +=
                new EventHandler(this.notifyIcon_BalloonTipClicked);
        }
    }
}

OK. These guys are on crack! They have a retry counter that apparently will never be more than 1. Because the tick event will go away and there is no loop in this code, the retryCount will always be 1 (taking note that they decided to start with a 1-based counting system rather than zero because n-1 is a bit complex). That at didn’t stop them from checking to see if it was equal to 6, and if so, changing the interval.

In the tick event, they create a new instance of a WristUnitListener and hook up events to it EACH time. They call start on the WristUnitListener instance and then STOP the timer and dispose of it! Never mind the fact that this timer execution is owned by the main thread rather than the timer tick function — when a timer stops itself, disposes of itself, and then nulls itself, it’s time to reevaluate your understanding of background-thread polling. This is insane! I have no idea how this even works. I can only hope that, as I dig in further WristUnitListener actually works the way it is supposed to and the only thing that sucks is the WebForms code.

Update January 13th, 2010 1:15AM PST:

I was able to successfully hack around with the API and get data off the watch with little effort. The trick was to working around some wonky and non-working APIs. To their defense 1) this API and software has to work with multiple watches 2) wasn’t intended to be consumed by other devs 3) was written with interop for the native libraries accessing the hardware, 4) does show signs of some intelligent thinking (although does need considerable amounts of re-work). As you can see by the image, I can even pull the bitmap logo off of the watch and, if I so desire, set it.

This is far from complete but I will work it over some this week and this weekend before publishing the source on Codeplex. Let me know if there is something in particular that you’d like to see.

 

Update July 7th, 2010 12:01AM PST:

I have posted this code to codeplex as-is. You can find it here: http://polarsync.codeplex.com/

If you would like to contribute source code or improve the project for others in the community, please send me a request and I’ll approve you. I don’t intend to maintain the code or improve it.

Be Sociable, Share!

    21 Thoughts on “Hacking Polar Watch WebSync Software

    1. Is there anywhere in the code for the upload settings – trying to get the software working via a proxy server is a nightmare as there is nowhere to set username and password for the proxy to use.

      Is there somewhere in the code to hack out a config file for this do you reckon ?

    2. Kirstin Juhl on April 6, 2010 at 10:35 am said:

      Tobin,
      You are my hero. That was awesome. I’ve never even thought of hacking my watch.

    3. Peter on April 6, 2010 at 12:14 pm said:

      Hi
      where can I find your version – I’m very interested in it?

      THX

    4. Melle on April 10, 2010 at 4:06 am said:

      You rock!
      I was looking into it as well… and I’m also trying to find a way to make it work on a mac.
      I might write my own driver and get rid off de Polar SW altogether. Being it .NET makes that a little easier ;o)
      Thanks, man.

    5. There are a lot of people screaming for a way of getting access to their raw polar hrm data… Great to see someone doing some work in this area…

      If there is anything I can do to help I’d be happy to do so 🙂

    6. Thanks everyone. Seems to have been a lot of sudden interest in this topic this week. I will post my code tonight on codeplex and try to get something better out soon. I haven’t touched the code since January however so I’m not certain if it is useful for anyone else. It will provide at least a starting point, I think.

    7. ajitaM on April 29, 2010 at 9:19 am said:

      Hi!

      Did you put it on CodeP? I can’t wait. 🙂 I’m going to use it with my RS300X and 3rd party software becouse I don’t like idea to put my personal data on their servers nor to use their web apps.

      You’re great!

      Cheers,

      Matija

    8. Mattias on May 15, 2010 at 12:27 am said:

      Hi

      I’m thinking of buying a Polar heart rate monitor and was looking around if I will be able to get the data to my computer instead of their website. I’m glad that I found your site but unfortunately I couldn’t find the code on codeplex. Would you mind providing us with a link?

    9. rwallace on May 17, 2010 at 6:57 pm said:

      Hi,
      This looks good, but I’m not a coder and don’t understand all the jargon.
      I need some way of getting my data off my Polar RS300X when I’m offline.

      Can you help?

    10. Juan Pablo Casas on December 29, 2010 at 7:29 am said:

      Just Excelent!!

    11. Finally a “Polar Saviour”… looking foward to the software…

    12. Pingback: FlowLink, WebSync, Log Files and Polar RS300X | runningitis

    13. Brender on January 19, 2011 at 10:10 am said:

      Hi,

      i have the RS300X too. do you continue to?

    14. how can we download your source code ?

      thanks

      jean

    15. Andre A on April 14, 2011 at 1:21 pm said:

      I’ve used your code successfully only with the installation of WebSync 1.3.5. It doesn’t work with the latest version, 2.1.

      I’ve tried to disassemble the 2.1 version with Reflector without success.

      Which disassembler did you use?

      My goal is to translate the RS300X data into HRM files so I can upload them to RunKeeper.

      Great work!

      • So I worked at this a little today and realized I just don’t have the experience for this yet. I’m going to dig a bit but imagine this won’t be out in a useful time for you or anyone else. It’s more a curiosity for me and not necessarily tied to anything in my world.

    16. Andre. It would appear that version 2.1 is not written in .NET. I had a conversation with a polar representative some time after writing this post and they have apparently opted to rewrite the new software in something other than .NET to prevent easy disassembly rather than addresssing the real problem — that people don’t want to push this data up to their website. I’ll address this shortly as I don’t need .NET in order to fix their issues. I’ll work on a bit of code to fix the 2.1 software. I’ll report progress once I have some for you.

    17. Miguel from LATAM on January 29, 2013 at 2:07 pm said:

      Thanks for your publication. Furthermore I am seeking “to hack” the monitor signal to the watch…. Do you have some link or información a put this?? Thanks ones moré

    18. mgkurilla on March 4, 2014 at 7:59 pm said:

      I’m wondering if you can offer any advice. I purchased Flowlink, but can’t get it ti synchronize with my FT60. WebSync installs correctly and the Polar Daemon is running. when Flowlink is plugged in, my computer (Win7) recognizes it as an “unspecified device” although the HID entry in device manager appears correct. When I attempt to synchronize, WebSync simply tells me to plug in Flowlink and won’t go any further. Polar is clueless and wants me to return both Flowlink and the FT60, although I doubt either of them is defective. I suspect that something in my computer is preventing Websync from seeing Flowlink, but Polar can’t help. Any thoughts?

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Post Navigation