Marco's Blog

All content strictly personal opinions.
en eo

Linux and the Polar F6 Heart Rate Monitor (2)

2008-09-05 3 min read Utilities marco

In the first post in the matter, I introduced you to a quick way of getting your Polar data into a Linux computer. I found that the transfer of data using sound is a nifty way of doing things, and the utilities written work pretty well.

There is one thing, though, that totally annoyed me about the process of transferring data: once you get the FRD files out of the watch, you have to manually add each exercise into SportsTracker – which is a tedious task at best, especially because it’s obvious SportsTracker is meant to track distances more than anything else. I mean, after all it was born as a way to track cycling and running workouts.

The oddest thing is that the FRD files are binary, while the final output of SportsTracker is XML. It was just a matter of looking at the file format and figuring out how to write the corresponding XML, which I did in the following.

Please note: I have used Tcl for this task, not because it’s particularly suited, but because it was there and I knew it. I could have just as well used Python, Java, or any other language, but for now it’s Tcl. From your perspective, you may have to install Tcl on your Linux box if you want to use the utility – not a big deal. apt-get install tcl will do the trick (or emerge tcl, or whatever you use).

You invoke the utility with the files you want to convert to XML as parameters. The utility will then:

  1. decode the files
  2. check whether a workout at exactly that time is already in the exercises file
  3. spit out useful XML

Not much error checking, so far, and the utility doesn’t store back to the exercises file. I have an improved version that takes my workout schedule and assigns workout types accordingly (for instance, on Wednesday nights at 6p I always spin), but the logic is just mine, so there is no need to discuss it here.

``` #!/usr/bin/tclsh set exercise_file [glob ~/.sportstracker/exercises.xml] set template {            %id%         %sport%         1         %date%         %duration%         NORMAL         0.0         0.0         %hrm%         %cal%         %file%     } proc parse data {         global template parsed         binary scan $data cx7cccH2H2H2H2H2H2ccsH2H2H2H6 marker d m y S M H dS dM  dH avgHR maxHR energy totS totM totH totE         foreach v {d m} {                 if {[subst $$v] < 10} {                         set $v 0[subst $$v]                 }         }         set date “[expr 2000 + $y]-$m-${d}T$H:$M:00”         if {[lsearch $parsed $date] > -1} {                 puts stderr “already parsed $date”                 return {}         }         regsub %date% $template $date template         regsub %duration% $template [expr $dS + 60 * ($dM + 60 * $dH)] template         regsub %hrm% $template $avgHR template         regsub %cal% $template $energy template         return $template } # read the exercise file and get the highest id used set f [open $exercise_file r] set data [split [read $f] \n] close $f set max 0 set parsed [list] foreach line $data {         if {[regexp {([0-9]+)} $line dummy id]} {                 if {$id > $max} {                         set max $id                 }         }         if {[regexp {(.*)} $line dummy date]} {                 lappend parsed $date         } } set id $max foreach file $argv {         set f [open $file r]         set data [read $f]         close $f         set xml [parse $data]         if {$xml != “”} {                 regsub %file% $xml [file normalize $file] xml                 regsub %id% $xml [incr id] xml                 puts $xml         } }