fitnio_export 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +31 -0
- data/bin/fitnio_export +27 -0
- data/lib/fitnio_export.rb +120 -0
- metadata +83 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Jakub Suder
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Fitnio export
|
2
|
+
|
3
|
+
This tool downloads your activity data from the sports tracking webapp [Fitnio.com](http://fitnio.com). You can use this if you want to back up your data or move it elsewhere (e.g. to [RunKeeper](http://runkeeper.com)). It exports the activity data in [GPX format](https://en.wikipedia.org/wiki/GPS_eXchange_Format), a standard format for representing GPS routes.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
You need to have Ruby installed on your machine (any recent version will do).
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Just install the gem:
|
12
|
+
|
13
|
+
gem install fitnio_export
|
14
|
+
|
15
|
+
## Running
|
16
|
+
|
17
|
+
Run the fitnio_export command:
|
18
|
+
|
19
|
+
fitnio_export
|
20
|
+
|
21
|
+
The script will ask you for your email and password, and then will try to download your dashboard page with a list of activities. If it works, it will download your activities one by one and will save the converted data as files named e.g. `fitnio-2012-05-03-1730.gpx` in the current directory.
|
22
|
+
|
23
|
+
## Importing into RunKeeper
|
24
|
+
|
25
|
+
I'm not aware of any mass import feature in RunKeeper, so you'll have to import the activities manually one by one. Click "Post new activity", choose activity type, then choose "Import Map" and choose the generated GPX file. You should see the imported map now - if it looks ok, press "Next" and save the map.
|
26
|
+
|
27
|
+
## Credits
|
28
|
+
|
29
|
+
* Fitnio.com is © Fitnio LLC
|
30
|
+
* RunKeeper is © FitnessKeeper Inc.
|
31
|
+
* fitnio_export is © Jakub Suder and licensed under MIT license
|
data/bin/fitnio_export
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib_dir = File.expand_path(File.join(__FILE__, '..', '..', 'lib'))
|
4
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'fitnio_export'
|
8
|
+
require 'highline'
|
9
|
+
|
10
|
+
console = HighLine.new
|
11
|
+
|
12
|
+
puts "Log in to Fitnio:"
|
13
|
+
puts "================="
|
14
|
+
puts
|
15
|
+
|
16
|
+
email = console.ask("Email:")
|
17
|
+
puts
|
18
|
+
|
19
|
+
password = console.ask("Password:") { |q| q.echo = "*" }
|
20
|
+
puts
|
21
|
+
|
22
|
+
begin
|
23
|
+
exporter = FitnioExport.new(email, password)
|
24
|
+
exporter.start
|
25
|
+
rescue FitnioExport::AuthenticationError => e
|
26
|
+
puts "Error: #{e}"
|
27
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
class FitnioExport
|
7
|
+
class AuthenticationError < StandardError; end
|
8
|
+
|
9
|
+
MILE_TO_KM = 1.609344
|
10
|
+
|
11
|
+
SIGNIN_URL = "http://fitnio.com/signIn.htm"
|
12
|
+
DATA_URL = "http://fitnio.com/mapData.htm"
|
13
|
+
|
14
|
+
SPORT_TYPES = {
|
15
|
+
'W' => 'Walking',
|
16
|
+
'R' => 'Running',
|
17
|
+
'B' => 'Biking'
|
18
|
+
}
|
19
|
+
|
20
|
+
GPX_HEADER = <<-HEADER
|
21
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
22
|
+
<gpx
|
23
|
+
version="1.1"
|
24
|
+
creator="fitnio_export (http://github.com/psionides/fitnio_export)"
|
25
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
26
|
+
xmlns="http://www.topografix.com/GPX/1/1"
|
27
|
+
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
|
28
|
+
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1">
|
29
|
+
<trk>
|
30
|
+
HEADER
|
31
|
+
|
32
|
+
GPX_FOOTER = <<-FOOTER
|
33
|
+
</trkseg>
|
34
|
+
</trk>
|
35
|
+
</gpx>
|
36
|
+
FOOTER
|
37
|
+
|
38
|
+
def initialize(email, password)
|
39
|
+
@email = email
|
40
|
+
@password = password
|
41
|
+
@logger = Logger.new(STDOUT)
|
42
|
+
@logger.formatter = lambda { |type, time, program, text| "#{time}: #{text}\n" }
|
43
|
+
@browser = Mechanize.new
|
44
|
+
end
|
45
|
+
|
46
|
+
def start
|
47
|
+
rows = get_activity_rows
|
48
|
+
|
49
|
+
rows.each do |row|
|
50
|
+
id = row['id']
|
51
|
+
json = get_activity_json(id)
|
52
|
+
|
53
|
+
date_row = row.search('td')[1]
|
54
|
+
date_string = date_row.to_s.gsub(/<.*?>/, ' ').strip
|
55
|
+
|
56
|
+
sprite = row.search('.gs-sprite')[0]
|
57
|
+
type = sprite['class'][/me-(\w)/].split('-').last
|
58
|
+
|
59
|
+
save_data_file(json, date_string, type)
|
60
|
+
end
|
61
|
+
|
62
|
+
log "Done."
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def log(text)
|
69
|
+
@logger.info(text)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_activity_rows
|
73
|
+
log "Downloading dashboard page..."
|
74
|
+
|
75
|
+
page = @browser.post(SIGNIN_URL, :email => @email, :password => @password, :createAccount => false)
|
76
|
+
|
77
|
+
if page.search('#me-data').length == 0
|
78
|
+
raise AuthenticationError, "Incorrect email or password"
|
79
|
+
end
|
80
|
+
|
81
|
+
page.search('.session-row')
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_activity_json(id)
|
85
|
+
log "Downloading activity #{id}..."
|
86
|
+
|
87
|
+
json_page = @browser.get(DATA_URL, :key => id)
|
88
|
+
json = json_page.body.gsub(%r(^//), '')
|
89
|
+
|
90
|
+
JSON.parse(json)
|
91
|
+
end
|
92
|
+
|
93
|
+
def save_data_file(json, date_string, type)
|
94
|
+
start_date = Time.parse(date_string)
|
95
|
+
filename = "fitnio-#{start_date.strftime('%Y-%m-%d-%H%M')}.gpx"
|
96
|
+
log "Saving #{filename}..."
|
97
|
+
|
98
|
+
File.open(filename, "w") do |file|
|
99
|
+
file.write GPX_HEADER
|
100
|
+
file.puts "<name>#{SPORT_TYPES[type]} #{date_string}</name>"
|
101
|
+
file.puts "<time>#{start_date.utc.xmlschema}</time>"
|
102
|
+
file.puts "<trkseg>"
|
103
|
+
|
104
|
+
json['points'].each do |point|
|
105
|
+
lat = sprintf("%.9f", point['latitude'])
|
106
|
+
long = sprintf("%.9f", point['longitude'])
|
107
|
+
|
108
|
+
# fitnio seems to return incorrect altitude (it shows ~77 m where Runkeeper shows ~230m),
|
109
|
+
# but it doesn't matter since Runkeeper finds the correct values by itself
|
110
|
+
alt = sprintf("%.2f", point['altitude'] * MILE_TO_KM * 1000)
|
111
|
+
|
112
|
+
time = (start_date + point['timeOffset'] / 1000.0).utc.xmlschema(3)
|
113
|
+
|
114
|
+
file.puts %(<trkpt lat="#{lat}" lon="#{long}"><ele>#{alt}</ele><time>#{time}</time></trkpt>)
|
115
|
+
end
|
116
|
+
|
117
|
+
file.write GPX_FOOTER
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fitnio_export
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jakub Suder
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-03 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mechanize
|
16
|
+
requirement: &70172804489240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.4'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70172804489240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: highline
|
27
|
+
requirement: &70172804488540 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.6.11
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70172804488540
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: json
|
38
|
+
requirement: &70172804486160 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.7'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70172804486160
|
47
|
+
description:
|
48
|
+
email: jakub.suder@gmail.com
|
49
|
+
executables:
|
50
|
+
- fitnio_export
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- MIT-LICENSE
|
55
|
+
- README.markdown
|
56
|
+
- lib/fitnio_export.rb
|
57
|
+
- bin/fitnio_export
|
58
|
+
homepage: http://github.com/psionides/fitnio_export
|
59
|
+
licenses: []
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 1.8.10
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: A tool for exporting activity data from Fitnio in GPX format (for importing
|
82
|
+
into Runkeeper)
|
83
|
+
test_files: []
|