fitbyte 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4fc521fa00248d4a2349cbf48840ca97bc567e5d
4
- data.tar.gz: e7d534a59e218901e7c81b36e4ad8cf4a2a7712c
3
+ metadata.gz: 224202239ccc8345b4cced0077f4f6deb3aac0e6
4
+ data.tar.gz: 172d0d9768c89d91514612791138db1a16471ef6
5
5
  SHA512:
6
- metadata.gz: 3af70dae21133cf999be7567e23859fa5d16edf7179f7cb86c55a3be0287737edb3ee1789261df5d6c472a57731d5ad10a08c9bdef46272e2eabfd3bdbdb89a9
7
- data.tar.gz: 172a7eff592f180bcf973d949d67aa934b026df2ab300adfbf4b855f00fc9afe4c617f61cd37f583cd43918eb096666bd97315a059d358f86d5612fcd1e4c169
6
+ metadata.gz: 1a31ebbfaec0c459045ab8c7d7a358ec8e2abc52e980f9f3d31162ff7177ac044aef48d2cc99efe816e52b70265490a1a617f2e537d6865c03e045d6c3b2cd72
7
+ data.tar.gz: 3d301be5aa02e6800c2715212187654e208aa5e8f4644f88e3d784f7a497108a75a49be57d0675876a4a1915288801403d803d3f38f0255c7e3b2a3dbab63236
@@ -1,3 +1,8 @@
1
+ 0.5.0
2
+ -----
3
+ - Add Heart Rate endpoint support. Add support for Time Series endpoints.
4
+ - Minor improvements to some helper functions
5
+
1
6
  0.4.1
2
7
  -----
3
8
  - Users can now provide either snake_cased or camelCased param attribute keys when POSTing data to Fitbit. Keys are automatically converted to camelCase before a request is sent to Fitbit's API.
data/README.md CHANGED
@@ -51,9 +51,10 @@ client.food_logs Date.today
51
51
  # => { "foods" => [{ "isFavorite" => true, "logDate" => "2015-06-26", "logId" => 1820, "loggedFood" => { "accessLevel" => "PUBLIC", "amount" => 132.57, "brand" => "", "calories" => 752, ...}] }
52
52
  ```
53
53
 
54
- To make the response more easily suited for attribute-assignment, it can be parsed to return a hash whose keys are in snake_case format. This can be done by setting the `snake_case` option to `true`, like so:
54
+ To make the response more easily suited for attribute-assignment, it can be parsed to return a hash whose keys are in snake_case format. This can be done by setting the client's `snake_case` option to `true`, like so:
55
55
 
56
56
  ```ruby
57
+ client.snake_case = true
57
58
  client.food_logs Date.today, snake_case: true
58
59
  # => { "foods" => [{ "is_favorite" => true, "log_date" => "2015-06-26", "log_id" => 1820, "logged_food" => { "access_level" => "PUBLIC", "amount" => 132.57, "brand" => "", "calories" => 752, ...}] }
59
60
  ```
@@ -78,7 +79,7 @@ When initializing a `Fitbyte::Client` instance, you're given access to a handful
78
79
 
79
80
  - `:locale` - The locale to use for response values (default: "en_US" | available: "en_US", "fr_FR", "de_DE", "es_ES", "en_GB", "en_AU", "en_NZ" and "ja_JP")
80
81
 
81
- - `:scope` - A space-delimited list of the permissions you are requesting (default: "activity nutrition profile settings sleep social weight" | available: "activity", "heartrate", "location", "nutrition", "profile", "settings" "sleep", "social" and "weight")
82
+ - `:scope` - A space-delimited list of the permissions you are requesting (default: "activity nutrition profile settings sleep social weight heartrate" | available: "activity", "heartrate", "location", "nutrition", "profile", "settings" "sleep", "social" and "weight")
82
83
 
83
84
  - `:snake_case` - Transform returned object's keys to snake case format (default: false)
84
85
 
@@ -1,5 +1,14 @@
1
1
  module Fitbyte
2
2
  class Client
3
+
4
+ ACTIVITY_RESOURCES = %w(calories caloriesBMR steps distance floors elevation
5
+ minutesSedentary minutesLightlyActive minutesFairlyActive
6
+ minutesVeryActive activityCalories tracker/calories
7
+ tracker/steps tracker/distance tracker/floors
8
+ tracker/elevation tracker/minutesSedentary
9
+ tracker/minutesLightlyActive tracker/minutesFairlyActive
10
+ tracker/minutesVeryActive tracker/activityCalories)
11
+
3
12
  # GET Activities
4
13
  # ==============
5
14
 
@@ -64,6 +73,38 @@ module Fitbyte
64
73
  get("user/#{@user_id}/activities.json", opts)
65
74
  end
66
75
 
76
+ def activity_time_series(resource, opts={})
77
+ start_date = opts[:start_date]
78
+ end_date = opts[:end_date] || Date.today
79
+ period = opts[:period]
80
+
81
+ unless ACTIVITY_RESOURCES.include?(resource)
82
+ raise Fitbyte::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{ACTIVITY_RESOURCES}."
83
+ end
84
+
85
+ if [period, start_date].none?
86
+ raise Fitbyte::InvalidArgumentError, "A start_date or period is required."
87
+ end
88
+
89
+ if period && !PERIODS.include?(period)
90
+ raise Fitbyte::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
91
+ end
92
+
93
+ if period
94
+ result = get("user/#{@user_id}/activities/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
95
+ else
96
+ result = get("user/#{@user_id}/activities/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
97
+ end
98
+ # remove root key from response
99
+ result.values[0]
100
+ end
101
+
102
+ # ACTIVITY_RESOURCES.each do |resource_path|
103
+ # define_method("activity_#{to_snake_case(resource_path).gsub('/', '_')}_series") do |opts={}|
104
+ # activity_time_series(resource_path, opts={})
105
+ # end
106
+ # end
107
+
67
108
  # POST Activities
68
109
  # ===============
69
110
 
@@ -1,5 +1,7 @@
1
1
  module Fitbyte
2
2
  class Client
3
+ BODY_RESOURCES = %w(bmi fat weight)
4
+
3
5
  def weight_logs(date=Date.today, opts={})
4
6
  get("user/-/body/log/weight/date/#{format_date(date)}.json", opts)
5
7
  end
@@ -15,5 +17,31 @@ module Fitbyte
15
17
  def body_fat_goals(opts={})
16
18
  get("user/-/body/log/fat/goal.json", opts)
17
19
  end
20
+
21
+ def body_time_series(resource, opts={})
22
+ start_date = opts[:start_date]
23
+ end_date = opts[:end_date] || Date.today
24
+ period = opts[:period]
25
+
26
+ unless BODY_RESOURCES.include?(resource)
27
+ raise Fitbyte::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{BODY_RESOURCES}."
28
+ end
29
+
30
+ if [period, start_date].none?
31
+ raise Fitbyte::InvalidArgumentError, "A start_date or period is required."
32
+ end
33
+
34
+ if period && !PERIODS.include?(period)
35
+ raise Fitbyte::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
36
+ end
37
+
38
+ if period
39
+ result = get("user/#{@user_id}/body/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
40
+ else
41
+ result = get("user/#{@user_id}/body/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
42
+ end
43
+ # remove root key from response
44
+ result.values[0]
45
+ end
18
46
  end
19
47
  end
@@ -1,5 +1,7 @@
1
1
  require "fitbyte/helpers"
2
+ require "fitbyte/exceptions"
2
3
  require "fitbyte/activities"
4
+ require "fitbyte/heart_rate"
3
5
  require "fitbyte/goals"
4
6
  require "fitbyte/alarms"
5
7
  require "fitbyte/body"
@@ -16,7 +18,7 @@ module Fitbyte
16
18
 
17
19
  def initialize(opts)
18
20
  missing_args = [:client_id, :client_secret, :redirect_uri] - opts.keys
19
- raise ArgumentError, "Required arguments: #{missing_args.join(', ')}" if missing_args.size > 0
21
+ raise Fitbyte::InvalidArgumentError, "Required arguments: #{missing_args.join(', ')}" if missing_args.size > 0
20
22
 
21
23
  opts = defaults.merge(opts)
22
24
 
@@ -99,7 +101,7 @@ module Fitbyte
99
101
  site_url: "https://api.fitbit.com",
100
102
  authorize_url: "https://www.fitbit.com/oauth2/authorize",
101
103
  token_url: "https://api.fitbit.com/oauth2/token",
102
- scope: "activity nutrition profile settings sleep social weight",
104
+ scope: "activity nutrition profile settings sleep social weight heartrate",
103
105
  unit_system: "en_US",
104
106
  locale: "en_US",
105
107
  api_version: "1",
@@ -0,0 +1,4 @@
1
+ module Fitbyte
2
+ class InvalidArgumentError < ArgumentError
3
+ end
4
+ end
@@ -1,5 +1,7 @@
1
1
  module Fitbyte
2
2
  class Client
3
+ FOOD_RESOURCES = %w(caloriesIn water)
4
+
3
5
  def food_logs(date=Date.today, opts={})
4
6
  get("user/#{@user_id}/foods/log/date/#{format_date(date)}.json", opts)
5
7
  end
@@ -19,5 +21,31 @@ module Fitbyte
19
21
  def food_goals(opts={})
20
22
  get("user/#{@user_id}/foods/log/goal.json", opts)
21
23
  end
24
+
25
+ def food_time_series(resource, opts={})
26
+ start_date = opts[:start_date]
27
+ end_date = opts[:end_date] || Date.today
28
+ period = opts[:period]
29
+
30
+ unless FOOD_RESOURCES.include?(resource)
31
+ raise Fitbyte::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{FOOD_RESOURCES}."
32
+ end
33
+
34
+ if [period, start_date].none?
35
+ raise Fitbyte::InvalidArgumentError, "A start_date or period is required."
36
+ end
37
+
38
+ if period && !PERIODS.include?(period)
39
+ raise Fitbyte::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
40
+ end
41
+
42
+ if period
43
+ result = get("user/#{@user_id}/foods/log/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
44
+ else
45
+ result = get("user/#{@user_id}/foods/log/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
46
+ end
47
+ # remove root key from response
48
+ result.values[0]
49
+ end
22
50
  end
23
51
  end
@@ -0,0 +1,25 @@
1
+ module Fitbyte
2
+ class Client
3
+ def heart_rate_time_series(opts={})
4
+ start_date = opts[:start_date]
5
+ end_date = opts[:end_date] || Date.today
6
+ period = opts[:period]
7
+
8
+ if [period, start_date].none?
9
+ raise Fitbyte::InvalidArgumentError, "A start_date or period is required."
10
+ end
11
+
12
+ if period && !PERIODS.include?(period)
13
+ raise Fitbyte::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
14
+ end
15
+
16
+ if period
17
+ result = get("user/#{@user_id}/activities/heart/date/#{format_date(end_date)}/#{period}.json", opts)
18
+ else
19
+ result = get("user/#{@user_id}/activities/heart/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
20
+ end
21
+ # remove root key from response
22
+ result.values[0]
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,8 @@
1
1
  module Fitbyte
2
2
  class Client
3
3
 
4
+ PERIODS = %w(1d 7d 30d 1w 1m 3m 6m 1y max)
5
+
4
6
  def format_date(date)
5
7
  if [Date, Time, DateTime].include?(date.class)
6
8
  date.strftime("%Y-%m-%d")
@@ -8,10 +10,10 @@ module Fitbyte
8
10
  if date =~ /\d{4}\-\d{2}\-\d{2}/
9
11
  date
10
12
  else
11
- raise ArgumentError, "Invalid argument [\"#{date}\"] - string must follow yyyy-MM-dd format."
13
+ raise Fitbyte::InvalidArgumentError, "Invalid argument [\"#{date}\"] - string must follow yyyy-MM-dd format."
12
14
  end
13
15
  else
14
- raise ArgumentError, "Invalid type [#{date.class}] - provide a Date/Time/DateTime or a String(yyyy-MM-dd format)."
16
+ raise Fitbyte::InvalidArgumentError, "Invalid type [#{date.class}] - provide a Date/Time/DateTime or a String(yyyy-MM-dd format)."
15
17
  end
16
18
  end
17
19
 
@@ -20,7 +22,7 @@ module Fitbyte
20
22
  end
21
23
 
22
24
  def deep_keys_to_snake_case!(object)
23
- deep_transform_keys!(object) { |key| to_snake_case(key) }
25
+ deep_transform_keys!(object) { |key| to_snake_case(key, replace_dashes: true) }
24
26
  end
25
27
 
26
28
  def deep_keys_to_camel_case!(object)
@@ -47,11 +49,12 @@ module Fitbyte
47
49
  end
48
50
  end
49
51
 
50
- def to_snake_case(word)
52
+ def to_snake_case(word, opts={})
51
53
  string = word.to_s.dup
52
54
  return string.downcase if string.match(/\A[A-Z]+\z/)
53
55
  string.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
54
56
  string.gsub!(/([a-z])([A-Z])/, '\1_\2')
57
+ string.gsub!("-", "_") if opts[:replace_dashes]
55
58
  string.downcase
56
59
  end
57
60
 
@@ -1,7 +1,36 @@
1
1
  module Fitbyte
2
2
  class Client
3
+ SLEEP_RESOURCES = %w(startTime timeInBed minutesAsleep awakeningsCount
4
+ minutesAwake minutesToFallAsleep minutesAfterWakeup efficiency)
5
+
3
6
  def sleep_logs(date=Date.today, opts={})
4
7
  get("user/#{@user_id}/sleep/date/#{format_date(date)}.json", opts)
5
8
  end
9
+
10
+ def sleep_time_series(resource, opts={})
11
+ start_date = opts[:start_date]
12
+ end_date = opts[:end_date] || Date.today
13
+ period = opts[:period]
14
+
15
+ unless SLEEP_RESOURCES.include?(resource)
16
+ raise Fitbyte::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{SLEEP_RESOURCES}."
17
+ end
18
+
19
+ if [period, start_date].none?
20
+ raise Fitbyte::InvalidArgumentError, "A start_date or period is required."
21
+ end
22
+
23
+ if period && !PERIODS.include?(period)
24
+ raise Fitbyte::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
25
+ end
26
+
27
+ if period
28
+ result = get("user/#{@user_id}/activities/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
29
+ else
30
+ result = get("user/#{@user_id}/activities/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
31
+ end
32
+ # remove root key from response
33
+ result.values[0]
34
+ end
6
35
  end
7
36
  end
@@ -1,4 +1,4 @@
1
1
  module Fitbyte
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  REPO_URL = "https://github.com/zokioki/fitbyte"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fitbyte
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zoran Pesic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-05 00:00:00.000000000 Z
11
+ date: 2016-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -90,9 +90,11 @@ files:
90
90
  - lib/fitbyte/body.rb
91
91
  - lib/fitbyte/client.rb
92
92
  - lib/fitbyte/devices.rb
93
+ - lib/fitbyte/exceptions.rb
93
94
  - lib/fitbyte/food.rb
94
95
  - lib/fitbyte/friends.rb
95
96
  - lib/fitbyte/goals.rb
97
+ - lib/fitbyte/heart_rate.rb
96
98
  - lib/fitbyte/helpers.rb
97
99
  - lib/fitbyte/sleep.rb
98
100
  - lib/fitbyte/user.rb