fitgem 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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