fitgem 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Provides access to fitbit.com data through their OAuth/REST API. Fitgem can pull data with or without user authentication. Without user authentication, any data that the a fitbit.com user has denoted as 'public' can be gathered. If a user logs in via OAuth then all exposed data can be gathered.
4
4
 
5
- The fitbit.com API is currently (Late 2011) in BETA and is under development to extend its reach. Since it is early in the lifecycle of the API I expect this gem to go through a number of revisions as we attempt to match the functionality of their platform.
5
+ The fitbit.com API is currently (Early 2012) in BETA and is under development to extend its reach. Since it is early in the lifecycle of the API I expect this gem to go through a number of revisions as we attempt to match the functionality of their platform.
6
6
 
7
7
  # Usage #
8
8
 
@@ -15,7 +15,7 @@ $ gem install fitgem
15
15
 
16
16
  ## Usage in a Rails Application ##
17
17
 
18
- We've started to develop an example app using the fitgem client. See [https://github.com/whazzmaster/fitgem-client](https://github.com/whazzmaster/fitgem-client) for more information or check out [the hosted version](http://www.fitbit-client.com). The fitgem-client project is evolving more slowly than the library itself, but work continues.
18
+ We've started to develop an example app using the fitgem client. See [https://github.com/whazzmaster/fitgem-client](https://github.com/whazzmaster/fitgem-client) for more information or check out [the hosted version](http://www.fitbitclient.com). The fitgem-client project is evolving more slowly than the library itself, but work continues.
19
19
 
20
20
  # Subscriptions #
21
21
 
data/fitgem.gemspec CHANGED
@@ -55,6 +55,9 @@ Gem::Specification.new do |s|
55
55
  'lib/fitgem/units.rb',
56
56
  'lib/fitgem/users.rb',
57
57
  'lib/fitgem/water.rb',
58
+ 'lib/fitgem/blood_pressure.rb',
59
+ 'lib/fitgem/glucose.rb',
60
+ 'lib/fitgem/heart_rate.rb',
58
61
  'spec/fitgem_spec.rb',
59
62
  'spec/spec_helper.rb',
60
63
  'spec/fitgem_notifications_spec.rb',
@@ -0,0 +1,48 @@
1
+ module Fitgem
2
+ class Client
3
+ # ==========================================
4
+ # Blood Pressure Retrieval Methods
5
+ # ==========================================
6
+
7
+ # Get blood pressure log entries for the supplied date
8
+ #
9
+ # @param [DateTime, Date, String] date
10
+ # @return [Hash] Hash containing an average of the days logs, and a
11
+ # list of all individual entries
12
+ def blood_pressure_on_date(date)
13
+ get("/user/#{@user_id}/bp/date/#{format_date(date)}.json")
14
+ end
15
+
16
+ # ==========================================
17
+ # Blood Pressure Logging Methods
18
+ # ==========================================
19
+
20
+ # Log blood pressure information to fitbit
21
+ #
22
+ # @param [Hash] opts Heart rate data
23
+ # @option opts [Integer, String] :systolic Systolic measurement (REQUIRED)
24
+ # @option opts [Integer, String] :diastolic Diastolic measurement (REQUIRED)
25
+ # @option opts [DateTime, Date, String] :date Log entry date (REQUIRED)
26
+ # @option opts [DateTime, Time, String] :time Time of the measurement; hours and minutes in the format HH:mm
27
+ #
28
+ # @return [Hash] Summary of logged information
29
+ def log_blood_pressure(opts)
30
+ unless opts[:systolic] && opts[:diastolic] && opts[:date]
31
+ raise Fitgem::InvalidArgumentError, "Must include :systolic, :diastolic, and :date in order to log blood pressure data"
32
+ end
33
+
34
+ opts[:date] = format_date(opts[:date])
35
+ opts[:time] = format_time(opts[:time]) if opts[:time]
36
+ post("/user/#{@user_id}/bp.json", opts)
37
+ end
38
+
39
+ # Delete logged blood pressure information
40
+ #
41
+ # @param [Integer, String] blood_pressure_log_id The id of previously logged
42
+ # blood pressure data
43
+ # @return [Hash] Empty hash denotes success
44
+ def delete_blood_pressure_log(blood_pressure_log_id)
45
+ delete("/user/-/bp/#{blood_pressure_log_id}.json")
46
+ end
47
+ end
48
+ end
data/lib/fitgem/client.rb CHANGED
@@ -5,6 +5,9 @@ require 'fitgem/users'
5
5
  require 'fitgem/activities'
6
6
  require 'fitgem/sleep'
7
7
  require 'fitgem/water'
8
+ require 'fitgem/blood_pressure'
9
+ require 'fitgem/glucose'
10
+ require 'fitgem/heart_rate'
8
11
  require 'fitgem/units'
9
12
  require 'fitgem/foods'
10
13
  require 'fitgem/friends'
@@ -32,7 +35,7 @@ module Fitgem
32
35
  # @example Set this using the {Fitgem::ApiUnitSystem}
33
36
  # client.api_unit_system = Fitgem::ApiUnitSystem.UK
34
37
  # @example May also be set in the constructor call
35
- # client = Fitgem::Client {
38
+ # client = Fitgem::Client {
36
39
  # :consumer_key => my_key,
37
40
  # :consumer_secret => my_secret,
38
41
  # :token => fitbit_oauth_token,
@@ -76,11 +79,11 @@ module Fitgem
76
79
  # client = Fitgem::Client.new { :consumer_key => my_key, :consumer_secret => my_secret }
77
80
  #
78
81
  # @example User has already authorized with fitbit, and we have a stored token/secret
79
- # client = Fitgem::Client.new {
80
- # :consumer_key => my_key,
81
- # :consumer_secret => my_secret,
82
- # :token => fitbit_oauth_token,
83
- # :secret => fitbit_oauth_secret
82
+ # client = Fitgem::Client.new {
83
+ # :consumer_key => my_key,
84
+ # :consumer_secret => my_secret,
85
+ # :token => fitbit_oauth_token,
86
+ # :secret => fitbit_oauth_secret
84
87
  # }
85
88
  #
86
89
  # @return [Client] A Fitgem::Client; may be in a logged-in state or
@@ -168,8 +171,8 @@ module Fitgem
168
171
  private
169
172
 
170
173
  def consumer
171
- @consumer ||= OAuth::Consumer.new(@consumer_key, @consumer_secret, {
172
- :site => 'http://api.fitbit.com',
174
+ @consumer ||= OAuth::Consumer.new(@consumer_key, @consumer_secret, {
175
+ :site => 'http://api.fitbit.com',
173
176
  :proxy => @proxy
174
177
  })
175
178
  end
data/lib/fitgem/errors.rb CHANGED
@@ -8,6 +8,9 @@ module Fitgem
8
8
  class InvalidDateArgument < InvalidArgumentError
9
9
  end
10
10
 
11
+ class InvalidTimeArgument < InvalidArgumentError
12
+ end
13
+
11
14
  class InvalidTimeRange < InvalidArgumentError
12
15
  end
13
16
  end
@@ -0,0 +1,45 @@
1
+ module Fitgem
2
+ class Client
3
+ # ==========================================
4
+ # Glucose Retrieval Methods
5
+ # ==========================================
6
+
7
+ # Get glucose log entries for the supplied date
8
+ #
9
+ # @param [DateTime, Date, String] date
10
+ # @return [Hash] Hash containing an average of the days logs, and a
11
+ # list of all individual entries
12
+ def glucose_on_date(date)
13
+ get("/user/#{@user_id}/glucose/date/#{format_date(date)}.json")
14
+ end
15
+
16
+ # ==========================================
17
+ # Glucose Logging Methods
18
+ # ==========================================
19
+
20
+ # Log glucose information to fitbit
21
+ #
22
+ # @param [Hash] opts Glucose data
23
+ # @option opts [String] :tracker Glucose tracker name;
24
+ # predefined or custom tracker name (matches tracker name on the website) (this or :hba1c is REQUIRED)
25
+ # @option opts [String] :hba1c HbA1c measurement; in the format "X.X" (this or :tracker is REQUIRED)
26
+ # @option opts [String] :glucose Glucose measurement; in the format "X.X" (REQUIRED with :tracker, OPTIONAL otherwise)
27
+ # @option opts [DateTime, Date, String] :date Log entry date (REQUIRED)
28
+ # @option opts [DateTime, String] :time Time of the measurement; hours and minutes in the format HH:mm
29
+ #
30
+ # @return [Hash] Summary of logged information
31
+ def log_glucose(opts)
32
+ unless opts[:tracker] || opts[:hba1c]
33
+ raise Fitgem::InvalidArgumentError, "Must include :tracker or :hba1c in order to log glucose data"
34
+ end
35
+
36
+ if opts[:tracker] && opts[:hba1c].nil? && opts[:glucose].nil?
37
+ raise Fitgem::InvalidArgumentError, "Must include :glucose if using :tracker with no :hba1c value in order to log glucose data"
38
+ end
39
+
40
+ opts[:date] = format_date(opts[:date])
41
+ opts[:time] = format_time(opts[:time]) if opts[:time]
42
+ post("/user/#{@user_id}/glucose.json", opts)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
1
+ module Fitgem
2
+ class Client
3
+ # ==========================================
4
+ # Heart Rate Retrieval Methods
5
+ # ==========================================
6
+
7
+ # Get heart rate log entries for the supplied date
8
+ #
9
+ # @param [DateTime, Date, String] date
10
+ # @return [Hash] Hash containing an average of the days logs, and a
11
+ # list of all individual entries
12
+ def heart_rate_on_date(date)
13
+ get("/user/#{@user_id}/heart/date/#{format_date(date)}.json")
14
+ end
15
+
16
+ # ==========================================
17
+ # Heart Rate Logging Methods
18
+ # ==========================================
19
+
20
+ # Log heart rate information to fitbit
21
+ #
22
+ # @param [Hash] opts Heart rate data
23
+ # @option opts [String] :tracker Heart rate tracker name;
24
+ # predefined or custom tracker name (matches tracker name on the website) (REQUIRED)
25
+ # @option opts [Integer, String] :heart_rate Heart rate measurement (REQUIRED)
26
+ # @option opts [DateTime, Date, String] :date Log entry date (REQUIRED)
27
+ # @option opts [DateTime, String] :time Time of the measurement; hours and minutes in the format HH:mm
28
+ #
29
+ # @return [Hash] Summary of logged information
30
+ def log_heart_rate(opts)
31
+ unless opts[:tracker] && opts[:heart_rate] && opts[:date]
32
+ raise Fitgem::InvalidArgumentError, "Must include :tracker, :heart_rate, and :date in order to lof heart rate data"
33
+ end
34
+
35
+ opts[:heartRate] = opts.delete :heart_rate
36
+ opts[:date] = format_date(opts[:date])
37
+ opts[:time] = format_time(opts[:time]) if opts[:time]
38
+ post("/user/#{@user_id}/heart.json", opts)
39
+ end
40
+
41
+ # Delete logged heart rate information
42
+ #
43
+ # @param [Integer, String] heart_rate_log_id The id of previously logged
44
+ # heart rate data
45
+ # @return [Hash] Empty hash denotes success
46
+ def delete_heart_rate_log(heart_rate_log_id)
47
+ delete("/user/-/heart/#{heart_rate_log_id}.json")
48
+ end
49
+ end
50
+ end
@@ -33,5 +33,35 @@ module Fitgem
33
33
  raise Fitgem::InvalidDateArgument, "Date used must be a date/time object or a string in the format YYYY-MM-DD; supplied argument is a #{date.class}"
34
34
  end
35
35
  end
36
+
37
+ # Format any of a variety of time-related types into the formatted string
38
+ # required when using the fitbit API.
39
+ #
40
+ # The time parameter can take several different kind of objects: a DateTime object,
41
+ # a Time object, or a String Object. Furthermore, the string object may be either
42
+ # the date in a preformatted string ("HH:mm"), or it may be the string value "now" to
43
+ # indicate that the time value used is the current localtime.
44
+ #
45
+ # @param [DateTime, Time, String] time The object to format into a time string
46
+ # @raise [Fitgem::InvalidTimeArgument] Raised when the parameter object is not a
47
+ # DateTime, Time, or a valid ("HH:mm" or "now") string object
48
+ # @return [String] Date in "HH:mm" string format
49
+ def format_time(time)
50
+ if time.is_a? String
51
+ case time
52
+ when 'now'
53
+ return DateTime.now.strftime("%H:%M")
54
+ else
55
+ unless time =~ /\d{2}\:\d{2}/
56
+ raise Fitgem::InvalidTimeArgument, "Invalid time (#{time}), must be in HH:mm format"
57
+ end
58
+ return time
59
+ end
60
+ elsif DateTime === time || Time === time
61
+ return time.strftime("%H:%M")
62
+ else
63
+ raise Fitgem::InvalidTimeArgument, "Date used must be a valid time object or a string in the format HH:mm; supplied argument is a #{time.class}"
64
+ end
65
+ end
36
66
  end
37
67
  end
@@ -23,7 +23,15 @@ module Fitgem
23
23
  # /activities/log/minutesVeryActive
24
24
  # /activities/log/activeScore
25
25
  # /activities/log/activityCalories
26
- #
26
+ #
27
+ # Raw Tracker Activity:
28
+ # /activities/tracker/calories
29
+ # /activities/tracker/steps
30
+ # /activities/tracker/distance
31
+ # /activities/tracker/floors
32
+ # /activities/tracker/elevation
33
+ # /activities/tracker/activeScore
34
+ #
27
35
  # Sleep:
28
36
  # /sleep/startTime
29
37
  # /sleep/timeInBed
@@ -1,3 +1,3 @@
1
1
  module Fitgem
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -58,7 +58,7 @@ describe Fitgem::Client do
58
58
  date = "2011-3-2"
59
59
  expect {
60
60
  @client.format_date(date)
61
- }.to raise_error Fitgem::InvalidDateArgument, "Invalid date (2011-3-2), must be in yyyy-MM-dd format"
61
+ }.to raise_error Fitgem::InvalidDateArgument, "Invalid date (2011-3-2), must be in yyyy-MM-dd format"
62
62
  end
63
63
 
64
64
  it "rejects strings are formatted correctly but include non-numeric elements" do
@@ -74,5 +74,54 @@ describe Fitgem::Client do
74
74
  @client.format_date(date)
75
75
  }.to raise_error Fitgem::InvalidDateArgument, "Date used must be a date/time object or a string in the format YYYY-MM-DD; supplied argument is a Fixnum"
76
76
  end
77
- end
77
+ end
78
+
79
+ describe "#format_time" do
80
+ it "accepts DateTime objects" do
81
+ time = DateTime.parse("3rd Feb 2001 04:05:06 PM")
82
+ @client.format_time(time).should == "16:05"
83
+ end
84
+
85
+ it "accepts Time objects" do
86
+ time = Time.mktime 2012, 1, 20, 13, 33, 30
87
+ @client.format_time(time).should == "13:33"
88
+ end
89
+
90
+ it "accepts the string 'now' to denote the current localtime" do
91
+ now = DateTime.now
92
+ @client.format_time('now').should == now.strftime("%H:%M")
93
+ end
94
+
95
+ it "accepts strings in HH:mm format" do
96
+ time = "04:20"
97
+ @client.format_time(time).should == "04:20"
98
+ end
99
+
100
+ it "rejects Date objects" do
101
+ date = Date.today
102
+ expect {
103
+ @client.format_time(date)
104
+ }.to raise_error Fitgem::InvalidTimeArgument
105
+ end
106
+
107
+ it "rejects strings that are not in HH:mm format" do
108
+ time = "4:20pm"
109
+ expect {
110
+ @client.format_time(time)
111
+ }.to raise_error Fitgem::InvalidTimeArgument
112
+ end
113
+
114
+ it "rejects strings that are formatted correctly but include non-numeric elements" do
115
+ time = "4a:33"
116
+ expect {
117
+ @client.format_time(time)
118
+ }.to raise_error Fitgem::InvalidTimeArgument
119
+ end
120
+
121
+ it "rejects arguments that do not conform to accepted types" do
122
+ expect {
123
+ @client.format_time(200)
124
+ }.to raise_error Fitgem::InvalidTimeArgument
125
+ end
126
+ end
78
127
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fitgem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-30 00:00:00.000000000 Z
12
+ date: 2012-01-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: oauth
16
- requirement: &70286226199200 !ruby/object:Gem::Requirement
16
+ requirement: &70184430460560 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70286226199200
24
+ version_requirements: *70184430460560
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70286226198400 !ruby/object:Gem::Requirement
27
+ requirement: &70184430460140 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70286226198400
35
+ version_requirements: *70184430460140
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70286226197760 !ruby/object:Gem::Requirement
38
+ requirement: &70184430495900 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70286226197760
46
+ version_requirements: *70184430495900
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard
49
- requirement: &70286226197240 !ruby/object:Gem::Requirement
49
+ requirement: &70184430494680 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70286226197240
57
+ version_requirements: *70184430494680
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: guard-rspec
60
- requirement: &70286226185880 !ruby/object:Gem::Requirement
60
+ requirement: &70184430493220 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70286226185880
68
+ version_requirements: *70184430493220
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rb-fsevent
71
- requirement: &70286226184860 !ruby/object:Gem::Requirement
71
+ requirement: &70184430492320 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70286226184860
79
+ version_requirements: *70184430492320
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: growl
82
- requirement: &70286226184280 !ruby/object:Gem::Requirement
82
+ requirement: &70184430491460 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70286226184280
90
+ version_requirements: *70184430491460
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: yard
93
- requirement: &70286226183800 !ruby/object:Gem::Requirement
93
+ requirement: &70184430490160 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70286226183800
101
+ version_requirements: *70184430490160
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rdiscount
104
- requirement: &70286226183360 !ruby/object:Gem::Requirement
104
+ requirement: &70184430488900 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70286226183360
112
+ version_requirements: *70184430488900
113
113
  description: A client library to send and retrieve workout, weight, and diet data
114
114
  from fitbit.com
115
115
  email:
@@ -146,6 +146,9 @@ files:
146
146
  - lib/fitgem/units.rb
147
147
  - lib/fitgem/users.rb
148
148
  - lib/fitgem/water.rb
149
+ - lib/fitgem/blood_pressure.rb
150
+ - lib/fitgem/glucose.rb
151
+ - lib/fitgem/heart_rate.rb
149
152
  - spec/fitgem_spec.rb
150
153
  - spec/spec_helper.rb
151
154
  - spec/fitgem_notifications_spec.rb
@@ -163,12 +166,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
166
  - - ! '>='
164
167
  - !ruby/object:Gem::Version
165
168
  version: '0'
169
+ segments:
170
+ - 0
171
+ hash: 2581731821553703730
166
172
  required_rubygems_version: !ruby/object:Gem::Requirement
167
173
  none: false
168
174
  requirements:
169
175
  - - ! '>='
170
176
  - !ruby/object:Gem::Version
171
177
  version: '0'
178
+ segments:
179
+ - 0
180
+ hash: 2581731821553703730
172
181
  requirements: []
173
182
  rubyforge_project: fitgem
174
183
  rubygems_version: 1.8.10