class: center, middle, inverse # Tracker a self hosted activity tracker with full privacy control --- # The story behind 3 Schweinehunde * [Ganzohr 2017](https://www.uibk.ac.at/congress/ganzohr2017/) * [3 Schweinehunde Podcast](https://3-schweinehun.de/) * [Strava](https://www.strava.com/clubs/3schweinehunde) * Talk at Vienna-rb [Horor Vacui](https://www.informatom.com/presentations/vacuum/#1) * was more on GDPR and log file analysis --- # 2018 * lost weight and good progress in winter and spring * not much progress during summer (actual regression) * [Ganzohr 2018](https://wissenschaftspodcasts.de/blog/wisspod/ganzohr2018-programm-online/) * In preperation: * Started with interval training * Increased training frequency to 4 times a week * Started a running log for discussions with the trainer * I'm quite a privacy nerd and I love static sites, so I developed my own fitness tracker What is it? --- # The Plan * Wanted to play with [Open Streetmap](https://www.openstreetmap.org) * ... and [Leaflet](https://leafletjs.com/) for a long time * found the nice water color [tiles](http://maps.stamen.com/#watercolor/12/37.7706/-122.3782) by Stamen * Wanted to try out a new plotting library: [Taucharts](https://www.taucharts.com/) * Using [Jekyll](https://jekyllrb.com/) as a base * Data comes from a [Garmin Forerunner 235](https://buy.garmin.com/de-AT/AT/p/529988) --- # Code! * Fit file format: [Fit SDK](https://www.thisisant.com/resources/fit/) * Gem [fit-parser](https://github.com/zhublik/fit_parser) * Not a lot of code necessary to create posts from fit files: [Activity Parser](https://github.com/haslinger/tracker/blob/master/activity-parser.rb) * creating the Map and the Plots from the posts yaml files: [Map Layout](https://github.com/haslinger/tracker/blob/master/_layouts/map.html) * Code on [Github](https://github.com/haslinger/tracker/) * Working [Demo Site](https://haslinger.github.io/tracker/) --- # Activity parser ```ruby require "fit" require 'yaml' require 'pry' Dir.foreach("ACTIVITY") do |in_file| next if in_file == '.' or in_file == '..' fit_file = Fit.load_file("ACTIVITY/" + in_file) records = fit_file.records .select{ |r| r.content.record_type != :definition } .map{ |r| r.content } .select{ |r| r[:raw_position_lat]} ``` --- ```ruby points = records.map{ |r| {"datetime" => Time.at(r.raw_timestamp + 631065600), "time" => r.raw_timestamp - records[0].raw_timestamp, "lat" => r.raw_position_lat * 180.0 / 2**31, "long" => r.raw_position_long * 180.0 / 2**31, "distance" => r.raw_distance / 100, "altitude" => (r.raw_altitude / 5.0 - 500).round(1), "speed" => (r.raw_speed * 3.6 / 1000).round(1), "heart_rate" => r[:raw_heart_rate] ? r.raw_heart_rate.to_i : 0, "cadence" => r[:raw_cadence] ? r.raw_cadence * 2 : 0}} front_matter = {"layout" => "map", "title" => "Aktivität am " + datetime.strftime("%d.%m.%Y") + " um " + datetime.strftime("%k:%M"), "date" => datetime, "points" => points} ``` --- ```ruby File.open("_posts/" + datetime.strftime("%Y-%m-%d-%H-%M") + ".md", 'w') do |out_file| out_file.puts(front_matter.to_yaml) out_file.puts("---") out_file.puts("Any comments on the run follow here.") end end ``` --- # Map and Plots ```html
``` --- ```html
``` --- ```html ``` # Demo! * Code on [Github](https://github.com/haslinger/tracker/) * Working [Demo Site](https://haslinger.github.io/tracker/) --- # Future * 10k advent run in December 2nd in Mödling * 15k at the relay run in April 7th (but we are only 2 so far ...) * 1/2 marthon in October in Munich # Call to action * Who wants to get in better shape? * Start running regularly and join in for the 6km or the 9km distance! --- class: center, middle # Thanks! [@informatom](https://twitter.com/informatom) Slides: http://informatom.com/presentations/tracker Keep on running! 😃