Class: FitgemOauth2::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/fitgem_oauth2/food.rb,
lib/fitgem_oauth2/sleep.rb,
lib/fitgem_oauth2/users.rb,
lib/fitgem_oauth2/utils.rb,
lib/fitgem_oauth2/client.rb,
lib/fitgem_oauth2/devices.rb,
lib/fitgem_oauth2/friends.rb,
lib/fitgem_oauth2/activity.rb,
lib/fitgem_oauth2/heartrate.rb,
lib/fitgem_oauth2/food/series.rb,
lib/fitgem_oauth2/food/metadata.rb,
lib/fitgem_oauth2/subscriptions.rb,
lib/fitgem_oauth2/food/collection.rb,
lib/fitgem_oauth2/body_measurements.rb

Constant Summary collapse

FOOD_SERIES_RESOURCES =
%w[caloriesIn water].freeze
FOOD_SERIES_PERIODS =
%w[1d 7d 30d 1w 1m 3m 6m 1y max].freeze
SLEEP_RESOURCES =
%w[
  startTime timeInBed minutesAsleep awakeningsCount minutesAwake
  minutesToFallAsleep minutesAfterWakeup efficiency
].freeze
SLEEP_PERIODS =
%w[1d 7d 30d 1w 1m 3m 6m 1y max].freeze
DEFAULT_USER_ID =
'-'
API_VERSION =
'1'
ACTIVITY_RESOURCES =
%w[
  calories caloriesBMR steps distance floors elevation minutesSedentary
  minutesLightlyActive minutesFairlyActive minutesVeryActive
  activityCaloriestracker/calories tracker/steps tracker/distance
  tracker/floors tracker/elevation tracker/minutesSedentary
  tracker/minutesLightlyActive tracker/minutesFairlyActive
  tracker/minutesVeryActive tracker/activityCalories
].freeze
ACTIVITY_PERIODS =
%w[1d 7d 30d 1w 1m 3m 6m 1y max].freeze
HR_PERIODS =
%w[1d 7d 30d 1w 1m].freeze
HR_DETAIL_LEVELS =
%w[1sec 1min].freeze
SUBSCRIBABLE_TYPES =
%i[sleep body activities foods all].freeze
FAT_PERIODS =
%w[1d 7d 1w 1m].freeze
WEIGHT_PERIODS =
%w[1d 7d 30d 1w 1m].freeze
BODY_GOALS =
%w[fat weight].freeze
BODY_TIME_SERIES_PERIODS =
%w[1d 7d 30d 1w 1m 3m 6m 1y max].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Client

Returns a new instance of Client.



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/fitgem_oauth2/client.rb', line 30

def initialize(opts)
  missing = %i[client_id client_secret token] - opts.keys
  raise FitgemOauth2::InvalidArgumentError, "Missing required options: #{missing.join(',')}" unless missing.empty?

  @client_id = opts[:client_id]
  @client_secret = opts[:client_secret]
  @token = opts[:token]
  @user_id = (opts[:user_id] || DEFAULT_USER_ID)
  @unit_system = opts[:unit_system]
  @connection = Faraday.new('https://api.fitbit.com')
end

Instance Attribute Details

#client_idObject (readonly)

Returns the value of attribute client_id.



24
25
26
# File 'lib/fitgem_oauth2/client.rb', line 24

def client_id
  @client_id
end

#client_secretObject (readonly)

Returns the value of attribute client_secret.



25
26
27
# File 'lib/fitgem_oauth2/client.rb', line 25

def client_secret
  @client_secret
end

#tokenObject (readonly)

Returns the value of attribute token.



26
27
28
# File 'lib/fitgem_oauth2/client.rb', line 26

def token
  @token
end

#unit_systemObject (readonly)

Returns the value of attribute unit_system.



28
29
30
# File 'lib/fitgem_oauth2/client.rb', line 28

def unit_system
  @unit_system
end

#user_idObject (readonly)

Returns the value of attribute user_id.



27
28
29
# File 'lib/fitgem_oauth2/client.rb', line 27

def user_id
  @user_id
end

Instance Method Details

#activitiesObject

Get a tree of all valid Fitbit public activities from the activities catalog as well as private custom activities the user created in the format requested. If the activity has levels, also get a list of activity level details



141
142
143
# File 'lib/fitgem_oauth2/activity.rb', line 141

def activities
  get_call('activities.json')
end

#activity(id) ⇒ Object

Returns the details of a specific activity in the Fitbit activities database in the format requested.

Parameters:

  • id

    id of the activity for which the details need to be retrieved



147
148
149
# File 'lib/fitgem_oauth2/activity.rb', line 147

def activity(id)
  get_call("activities/#{id}.json")
end

#activity_list(date, sort, limit) ⇒ Object

retrieves activity list for the user



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/fitgem_oauth2/activity.rb', line 117

def activity_list(date, sort, limit)
  date_param = format_date(date)
  if sort == 'asc'
    date_param = "afterDate=#{date_param}"
  elsif sort == 'desc'
    date_param = "beforeDate=#{date_param}"
  else
    raise FitgemOauth2::InvalidArgumentError, 'sort can either be asc or desc'
  end
  get_call("user/#{user_id}/activities/list.json?offset=0&limit=#{limit}&sort=#{sort}&#{date_param}")
end

#activity_tcx(id) ⇒ Object

retrieves activity list in the tcx format



130
131
132
# File 'lib/fitgem_oauth2/activity.rb', line 130

def activity_tcx(id)
  get_call("user/#{user_id}/activities/#{id}.tcx")
end

#activity_time_series(resource: nil, start_date: nil, end_date: nil, period: nil) ⇒ Object

retrieves activity time series, based on the arguments provided

Parameters:

  • resource (defaults to: nil)

    the resource for which the series needs to be retrieved. one of ALLOWED_RESOURCES

  • start_date (defaults to: nil)

    the start date for the series

  • end_date (defaults to: nil)

    the end date for the series. If specifying end_date, do not specify period

  • period (defaults to: nil)

    the period starting from start_date for which the series needs to be retrieved. If specifying period, do not use end_date

Raises:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fitgem_oauth2/activity.rb', line 32

def activity_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
  unless resource && ACTIVITY_RESOURCES.include?(resource)
    raise FitgemOauth2::InvalidArgumentError, "Invalid resource: #{resource}. Valid resources are #{ACTIVITY_RESOURCES}."
  end

  raise FitgemOauth2::InvalidArgumentError, 'Start date must be specified.' unless start_date

  if period && end_date
    raise FitgemOauth2::InvalidArgumentError, 'Both period and end_date are specified. Please specify only one.'
  end

  if period && !ACTIVITY_PERIODS.include?(period)
    raise FitgemOauth2::InvalidArgumentError, "Invalid period: #{period}. Valid periods are #{ACTIVITY_PERIODS}."
  end

  first = format_date(start_date)
  second = period || format_date(end_date)
  url = ['user', user_id, 'activities', resource, 'date', first, second].join('/')
  get_call(url + '.json')
end

#add_alarm(tracker_id, params) ⇒ Object

adds an alaram

Parameters:

  • tracker_id

    ID of the tracker to which the alaram needs to be added

  • params

    POST parameters for adding the alarm



27
28
29
# File 'lib/fitgem_oauth2/devices.rb', line 27

def add_alarm(tracker_id, params)
  post_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms.json", params)
end

#add_favorite_activity(activity_id) ⇒ Object

adds the activity with the given ID to user’s list of favorite activities.

Parameters:

  • activity_id

    ID of the activity to be added to the list of favorite activities



168
169
170
# File 'lib/fitgem_oauth2/activity.rb', line 168

def add_favorite_activity(activity_id)
  post_call("user/#{user_id}/activities/log/favorite/#{activity_id}.json")
end

#add_favorite_food(food_id) ⇒ Object



5
6
7
# File 'lib/fitgem_oauth2/food/metadata.rb', line 5

def add_favorite_food(food_id)
  post_call("user/#{user_id}/foods/log/favorite/#{food_id}.json")
end

#alarms(tracker_id) ⇒ Object

returns list of alarams for the tracker ID

Parameters:

  • tracker_id

    ID for the tracker for which alarams need to be retrieved



20
21
22
# File 'lib/fitgem_oauth2/devices.rb', line 20

def alarms(tracker_id)
  get_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms.json")
end

#badgesObject

retrieve badges for the user



42
43
44
# File 'lib/fitgem_oauth2/friends.rb', line 42

def badges
  get_call("user/#{user_id}/badges.json")
end

#body_fat_logs(start_date: nil, end_date: nil, period: nil) ⇒ Object

retrieves a list of all user’s body fat log entries note: provide either end_date or period

Parameters:

  • start_date (defaults to: nil)

    start date for the logs

  • end_date (optional) (defaults to: nil)

    end date for the logs

  • period (optional) (defaults to: nil)

    period for the logs

Raises:



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/fitgem_oauth2/body_measurements.rb', line 19

def body_fat_logs(start_date: nil, end_date: nil, period: nil)
  raise FitgemOauth2::InvalidArgumentError, 'must specify start_date' unless start_date

  url = ['user', user_id, 'body/log/fat/date', format_date(start_date)].join('/')
  url = [url, format_date(end_date)].join('/') if end_date

  if period
    if FAT_PERIODS.include?(period)
      url = [url, period].join('/')
    else
      raise FitgemOauth2::InvalidArgumentError, "period must be one in #{FAT_PERIODS}"
    end
  end

  url += '.json'

  get_call(url)
end

#body_goals(type) ⇒ Object

retrieves body goals based on the type specified

Parameters:

  • typeor ('fat''weight')

    ype ‘fat’ or ‘weight’



92
93
94
95
96
97
98
# File 'lib/fitgem_oauth2/body_measurements.rb', line 92

def body_goals(type)
  if type && BODY_GOALS.include?(type)
    get_call("user/#{user_id}/body/log/#{type}/goal.json")
  else
    raise FitgemOauth2::InvalidArgumentError, "invalid goal type : #{type}. must be one of #{BODY_GOALS}"
  end
end

#body_time_series(resource: nil, start_date: nil, end_date: nil, period: nil) ⇒ Object

retrieve body time series for the user; provide at least one of end_date and period

Parameters:

  • resource (required) (defaults to: nil)

    the resource requested [‘bmi’, ‘fat’, or ‘weight’]

  • start_date (required) (defaults to: nil)

    the start date for the series

  • end_date (optional) (defaults to: nil)

    the end date for the series

  • period (optional) (defaults to: nil)

    period for the time series. valid periods are BODY_TIME_SERIES_PERIODS



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fitgem_oauth2/body_measurements.rb', line 59

def body_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
  unless resource && start_date
    raise FitgemOauth2::InvalidArgumentError, 'resource and start_date are required parameters. Please specify both.'
  end

  url = ['user', user_id, 'body', resource, 'date', format_date(start_date)].join('/')

  second = ''
  if end_date && period
    raise FitgemOauth2::InvalidArgumentError, 'Please specify either period or end date, not both.'
  end

  if period
    if BODY_TIME_SERIES_PERIODS.include?(period)
      second = period
    else
      raise FitgemOauth2::InvalidArgumentError, "Invalid Period. Body time series period must be in #{BODY_TIME_SERIES_PERIODS}"
    end
  end

  second = format_date(end_date) if end_date

  url = [url, second].join('/')

  get_call(url + '.json')
end

#create_food(params) ⇒ Object



45
46
47
# File 'lib/fitgem_oauth2/food/metadata.rb', line 45

def create_food(params)
  post_call("user/#{user_id}/foods.json", params)
end

#create_meal(params) ⇒ Object



29
30
31
# File 'lib/fitgem_oauth2/food/metadata.rb', line 29

def create_meal(params)
  post_call("user/#{user_id}/meals.json", params)
end

#create_subscription(opts) ⇒ Object



11
12
13
# File 'lib/fitgem_oauth2/subscriptions.rb', line 11

def create_subscription(opts)
  post_call(subscription_url(opts))
end

#daily_activity_summary(date) ⇒ Object

retrieves daily activity summary for a date

Parameters:

  • date

    the date for which the summary is retrieved



18
19
20
# File 'lib/fitgem_oauth2/activity.rb', line 18

def daily_activity_summary(date)
  get_call("user/#{user_id}/activities/date/#{format_date(date)}.json")
end

#delete_call(url) ⇒ Object



80
81
82
83
84
# File 'lib/fitgem_oauth2/client.rb', line 80

def delete_call(url)
  url = "#{API_VERSION}/#{url}"
  response = connection.delete(url) {|request| set_headers(request) }
  parse_response(response)
end

#delete_favorite_food(food_id) ⇒ Object



9
10
11
# File 'lib/fitgem_oauth2/food/metadata.rb', line 9

def delete_favorite_food(food_id)
  delete_call("user/#{user_id}/foods/log/favorite/#{food_id}.json")
end

#delete_food(food_id) ⇒ Object



49
50
51
# File 'lib/fitgem_oauth2/food/metadata.rb', line 49

def delete_food(food_id)
  delete_call("user/#{user_id}/foods/#{food_id}.json")
end

#delete_food_log(food_log_id) ⇒ Object



41
42
43
# File 'lib/fitgem_oauth2/food/collection.rb', line 41

def delete_food_log(food_log_id)
  delete_call("user/#{user_id}/foods/log/#{food_log_id}.json")
end

#delete_logged_activity(id) ⇒ Object

deletes a logged activity

Parameters:

  • id

    id of the activity log to be deleted



112
113
114
# File 'lib/fitgem_oauth2/activity.rb', line 112

def delete_logged_activity(id)
  delete_call("user/#{user_id}/activities/#{id}.json")
end

#delete_logged_body_fat(id) ⇒ Object

delete logged body fat

Parameters:

  • id

    ID of the log to be deleted.



46
47
48
# File 'lib/fitgem_oauth2/body_measurements.rb', line 46

def delete_logged_body_fat(id)
  delete_call("user/#{user_id}/body/log/fat/#{id}.json")
end

#delete_logged_sleep(log_id) ⇒ Object

deleted sleep log

Parameters:

  • log_id

    ID of the sleep log that needs to be removed.



80
81
82
# File 'lib/fitgem_oauth2/sleep.rb', line 80

def delete_logged_sleep(log_id)
  delete_call("user/#{user_id}/sleep/#{log_id}.json")
end

#delete_logged_weight(id) ⇒ Object

delete logged weight

Parameters:

  • id

    ID of the weight log to be deleted



151
152
153
# File 'lib/fitgem_oauth2/body_measurements.rb', line 151

def delete_logged_weight(id)
  delete_call("user/#{user_id}/body/log/weight/#{id}.json")
end

#delete_meal(meal_id) ⇒ Object



41
42
43
# File 'lib/fitgem_oauth2/food/metadata.rb', line 41

def delete_meal(meal_id)
  delete_call("user/#{user_id}/meals/#{meal_id}.json")
end

#delete_water_log(water_log_id) ⇒ Object



49
50
51
# File 'lib/fitgem_oauth2/food/collection.rb', line 49

def delete_water_log(water_log_id)
  delete_call("user/#{user_id}/foods/log/water/#{water_log_id}.json")
end

#devicesObject

return list of Fitbit devices linked to the account



10
11
12
# File 'lib/fitgem_oauth2/devices.rb', line 10

def devices
  get_call("user/#{user_id}/devices.json")
end

#favorite_activitiesObject

gets favorite activities



162
163
164
# File 'lib/fitgem_oauth2/activity.rb', line 162

def favorite_activities
  get_call("user/#{user_id}/activities/favorite.json")
end

#favorite_foodsObject



17
18
19
# File 'lib/fitgem_oauth2/food/metadata.rb', line 17

def favorite_foods
  get_call("user/#{user_id}/foods/log/favorite.json")
end

#food(id) ⇒ Object



53
54
55
# File 'lib/fitgem_oauth2/food/metadata.rb', line 53

def food(id)
  get_call("foods/#{id}.json")
end

#food_goalsObject



5
6
7
# File 'lib/fitgem_oauth2/food/collection.rb', line 5

def food_goals
  get_call("user/#{user_id}/foods/log/goal.json")
end

#food_logs(date) ⇒ Object



9
10
11
# File 'lib/fitgem_oauth2/food/collection.rb', line 9

def food_logs(date)
  get_call("user/#{user_id}/foods/log/date/#{format_date(date)}.json")
end

#food_series_for_date_range(start_date, end_date) ⇒ Object



5
6
7
8
9
# File 'lib/fitgem_oauth2/food/series.rb', line 5

def food_series_for_date_range(start_date, end_date)
  validate_start_date(start_date)
  validate_end_date(end_date)
  get_call(food_series_url(user_id, format_date(start_date), format_date(end_date)))
end

#food_series_for_period(start_date, period) ⇒ Object



11
12
13
14
15
# File 'lib/fitgem_oauth2/food/series.rb', line 11

def food_series_for_period(start_date, period)
  validate_start_date(start_date)
  validate_food_series_period(period)
  get_call(food_series_url(user_id, format_date(start_date), period))
end

#food_unitsObject



57
58
59
# File 'lib/fitgem_oauth2/food/metadata.rb', line 57

def food_units
  get_call('foods/units.json')
end

#format_date(date) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/fitgem_oauth2/utils.rb', line 5

def format_date(date)
  return nil if date.nil?

  valid_semantic_date = %w[today yesterday].include? date
  valid_date_string = (date =~ /\d{4}\-\d{2}\-\d{2}/) == 0
  if valid_date_string
    date
  elsif valid_semantic_date
    date_from_semantic(date)
  elsif date.is_a?(Date) || date.is_a?(Time) || date.is_a?(DateTime)
    date.strftime('%Y-%m-%d')
  else
    raise FitgemOauth2::InvalidDateArgument, "Date used must be a date/time object or a string in the format YYYY-MM-DD; supplied argument is a #{date.class}"
  end
end

#format_time(time) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'lib/fitgem_oauth2/utils.rb', line 21

def format_time(time)
  if (time =~ /\d{2}:\d{2}/) == 0
    time
  elsif time.is_a?(DateTime) || time.is_a?(Time)
    time.strftime('%H:%M')
  else
    raise FitgemOauth2::InvalidTimeArgument, "Time used must be a DateTime/Time object or a string in the format hh:mm; supplied argument is a #{time.class}"
  end
end

#frequent_activitiesObject

gets frequent activities



152
153
154
# File 'lib/fitgem_oauth2/activity.rb', line 152

def frequent_activities
  get_call("user/#{user_id}/activities/frequent.json")
end

#frequent_foodsObject



21
22
23
# File 'lib/fitgem_oauth2/food/metadata.rb', line 21

def frequent_foods
  get_call("user/#{user_id}/foods/log/frequent.json")
end

#friend_invitationsObject

retrieve list of friend invitations



26
27
28
# File 'lib/fitgem_oauth2/friends.rb', line 26

def friend_invitations
  get_call("user/#{user_id}/friends/invitations.json")
end

#friendsObject

retrieves list of friends for the current user



6
7
8
# File 'lib/fitgem_oauth2/friends.rb', line 6

def friends
  get_call("user/#{user_id}/friends.json")
end

#friends_leaderboardObject

retrieves leaderboard for the user



11
12
13
# File 'lib/fitgem_oauth2/friends.rb', line 11

def friends_leaderboard
  get_call("user/#{user_id}/friends/leaderboard.json")
end

#get_call(url) ⇒ Object



53
54
55
56
57
# File 'lib/fitgem_oauth2/client.rb', line 53

def get_call(url)
  url = "#{API_VERSION}/#{url}"
  response = connection.get(url) {|request| set_headers(request) }
  parse_response(response)
end

#get_call_1_2(url) ⇒ Object

This method is a helper method (like get_call) for 1.2 version of the API_VERSION This method is needed because Fitbit API supports both versions as of current date (Nov 5, 2017)



62
63
64
65
66
# File 'lib/fitgem_oauth2/client.rb', line 62

def get_call_1_2(url)
  url = "1.2/#{url}"
  response = connection.get(url) {|request| set_headers(request) }
  parse_response(response)
end

#goals(period) ⇒ Object

retrieve activity goals for a period



184
185
186
187
188
189
190
# File 'lib/fitgem_oauth2/activity.rb', line 184

def goals(period)
  unless period && %w[daily weekly].include?(period)
    raise FitgemOauth2::InvalidArgumentError, "Goal period should either be 'daily' or 'weekly'"
  end

  get_call("user/#{user_id}/activities/goals/#{period}.json")
end

#hr_series_for_date_range(start_date, end_date) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/fitgem_oauth2/heartrate.rb', line 8

def hr_series_for_date_range(start_date, end_date)
  validate_start_date(start_date)
  validate_end_date(end_date)

  url = ['user', user_id, 'activities/heart/date', format_date(start_date), format_date(end_date)].join('/')
  get_call(url + '.json')
end

#hr_series_for_period(start_date, period) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/fitgem_oauth2/heartrate.rb', line 16

def hr_series_for_period(start_date, period)
  validate_start_date(start_date)
  validate_hr_period(period)

  url = ['user', user_id, 'activities/heart/date', format_date(start_date), period].join('/')
  get_call(url + '.json')
end

#intraday_activity_time_series(resource: nil, start_date: nil, end_date: nil, detail_level: nil, start_time: nil, end_time: nil) ⇒ Object

retrieves intraday activity time series.

Parameters:

  • resource (required) (defaults to: nil)

    for which the intrady series is retrieved. one of ‘calories’, ‘steps’, ‘distance’, ‘floors’, ‘elevation’

  • start_date (required) (defaults to: nil)

    start date for the series

  • end_date (optional) (defaults to: nil)

    end date for the series, if not specified, the series is for 1 day

  • detail_level (required) (defaults to: nil)

    level of detail for the series

  • start_time (optional) (defaults to: nil)

    start time for the series

  • end_time (defaults to: nil)

    the (optional)end time for the series. specify both start_time and end_time, if using either



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/fitgem_oauth2/activity.rb', line 60

def intraday_activity_time_series(resource: nil, start_date: nil, end_date: nil, detail_level: nil,
                                  start_time: nil, end_time: nil)

  # converting to symbol to allow developer to use either 'calories' or :calories
  resource = resource.to_sym

  unless %i[calories steps distance floors elevation].include?(resource)
    raise FitgemOauth2::InvalidArgumentError,
          'Must specify resource to fetch intraday time series data for.'\
          ' One of (:calories, :steps, :distance, :floors, or :elevation) is required.'
  end

  unless start_date
    raise FitgemOauth2::InvalidArgumentError,
          'Must specify the start_date to fetch intraday time series data'
  end

  end_date ||= '1d'

  unless detail_level && %w[1min 15min].include?(detail_level)
    raise FitgemOauth2::InvalidArgumentError,
          'Must specify the data resolution to fetch intraday time series data for.'\
          ' One of (\"1d\" or \"15min\") is required.'
  end

  resource_path = [
    'user', @user_id,
    'activities', resource,
    'date', format_date(start_date),
    end_date, detail_level
  ].join('/')

  if start_time || end_time
    resource_path =
      [resource_path, 'time', format_time(start_time), format_time(end_time)].join('/')
  end
  get_call("#{resource_path}.json")
end

#intraday_heartrate_time_series(start_date: nil, end_date: nil, detail_level: nil, start_time: nil, end_time: nil) ⇒ Object

retrieve intraday series for heartrate



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/fitgem_oauth2/heartrate.rb', line 25

def intraday_heartrate_time_series(start_date: nil, end_date: nil, detail_level: nil, start_time: nil, end_time: nil)
  intraday_series_guard(
    start_date: start_date,
    end_date: end_date,
    detail_level: detail_level,
    start_time: start_time,
    end_time: end_time
  )

  end_date = format_date(end_date) || '1d'

  url = ['user', user_id, 'activities/heart/date', format_date(start_date), end_date, detail_level].join('/')

  url = [url, 'time', format_time(start_time), format_time(end_time)].join('/') if start_time && end_time

  get_call(url + '.json')
end

#invite_friend(params) ⇒ Object

send an invitation to a friend

Parameters:

  • params

    POST parameters for sending friend invite.



21
22
23
# File 'lib/fitgem_oauth2/friends.rb', line 21

def invite_friend(params)
  post_call("user/#{user_id}/friends/invitations.json", params)
end

#lifetime_statsObject

retrieves lifetime statistics for the user



204
205
206
# File 'lib/fitgem_oauth2/activity.rb', line 204

def lifetime_stats
  get_call("user/#{user_id}/activities.json")
end

#log_activity(params) ⇒ Object

logs activity using the params.

Parameters:



106
107
108
# File 'lib/fitgem_oauth2/activity.rb', line 106

def log_activity(params)
  post_call("user/#{user_id}/activities.json", params)
end

#log_body_fat(params) ⇒ Object

logs body fat

Parameters:

  • params

    POST parameters for logging body fat



40
41
42
# File 'lib/fitgem_oauth2/body_measurements.rb', line 40

def log_body_fat(params)
  post_call("user/#{user_id}/body/log/fat.json", params)
end

#log_food(params) ⇒ Object



21
22
23
# File 'lib/fitgem_oauth2/food/collection.rb', line 21

def log_food(params)
  post_call("user/#{user_id}/foods/log.json", params)
end

#log_sleep(params) ⇒ Object

log sleep

Parameters:

  • params

    POST params for creating sleep log



74
75
76
# File 'lib/fitgem_oauth2/sleep.rb', line 74

def log_sleep(params)
  post_call_1_2("user/#{user_id}/sleep.json", params)
end

#log_water(params) ⇒ Object



29
30
31
# File 'lib/fitgem_oauth2/food/collection.rb', line 29

def log_water(params)
  post_call("user/#{user_id}/foods/log/water.json", params)
end

#log_weight(params) ⇒ Object

logs weight for the user

Parameters:

  • params

    POST message for logging weight



145
146
147
# File 'lib/fitgem_oauth2/body_measurements.rb', line 145

def log_weight(params)
  post_call("user/#{user_id}/body/log/weight.json", params)
end

#meal(meal_id) ⇒ Object



33
34
35
# File 'lib/fitgem_oauth2/food/metadata.rb', line 33

def meal(meal_id)
  get_call("user/#{user_id}/meals/#{meal_id}.json")
end

#mealsObject



25
26
27
# File 'lib/fitgem_oauth2/food/metadata.rb', line 25

def meals
  get_call("user/#{user_id}/meals.json")
end

#post_call(url, params = {}) ⇒ Object



68
69
70
71
72
# File 'lib/fitgem_oauth2/client.rb', line 68

def post_call(url, params={})
  url = "#{API_VERSION}/#{url}"
  response = connection.post(url, params) {|request| set_headers(request) }
  parse_response(response)
end

#post_call_1_2(url, params = {}) ⇒ Object



74
75
76
77
78
# File 'lib/fitgem_oauth2/client.rb', line 74

def post_call_1_2(url, params={})
  url = "1.2/#{url}"
  response = connection.post(url, params) {|request| set_headers(request) }
  parse_response(response)
end

#recent_activitiesObject

gets recent activities



157
158
159
# File 'lib/fitgem_oauth2/activity.rb', line 157

def recent_activities
  get_call("user/#{user_id}/activities/recent.json")
end

#recent_foodsObject



13
14
15
# File 'lib/fitgem_oauth2/food/metadata.rb', line 13

def recent_foods
  get_call("user/#{user_id}/foods/recent.json")
end

#refresh_access_token(refresh_token) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/fitgem_oauth2/client.rb', line 42

def refresh_access_token(refresh_token)
  response = connection.post('/oauth2/token') do |request|
    encoded = Base64.strict_encode64("#{@client_id}:#{@client_secret}")
    request.headers['Authorization'] = "Basic #{encoded}"
    request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
    request.params['grant_type'] = 'refresh_token'
    request.params['refresh_token'] = refresh_token
  end
  JSON.parse(response.body)
end

#remove_alarm(tracker_id, alarm_id) ⇒ Object

removes an existing alaram

Parameters:

  • tracker_id

    ID of the tracker from which alaram needs to be removed



42
43
44
# File 'lib/fitgem_oauth2/devices.rb', line 42

def remove_alarm(tracker_id, alarm_id)
  delete_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms/#{alarm_id}.json")
end

#remove_favorite_activity(activity_id) ⇒ Object

removes the activity with given ID from list of favorite activities.

Parameters:

  • activity_id

    ID of the activity to be removed from favorite activity



174
175
176
# File 'lib/fitgem_oauth2/activity.rb', line 174

def remove_favorite_activity(activity_id)
  delete_call("user/#{user_id}/activities/log/favorite/#{activity_id}.json")
end

#remove_subscription(opts) ⇒ Object



15
16
17
# File 'lib/fitgem_oauth2/subscriptions.rb', line 15

def remove_subscription(opts)
  delete_call(subscription_url(opts))
end

#respond_to_invitation(from_user_id, params) ⇒ Object

respond to a friend invite

Parameters:

  • from_user_id

    the ID of the friend

  • params

    POST parameters for responding to the invite.



33
34
35
# File 'lib/fitgem_oauth2/friends.rb', line 33

def respond_to_invitation(from_user_id, params)
  post_call("user/#{user_id}/friends/invitations/#{from_user_id}.json", params)
end

#search_foods(params) ⇒ Object



61
62
63
# File 'lib/fitgem_oauth2/food/metadata.rb', line 61

def search_foods(params)
  post_call('foods/search.json', params)
end

#sleep_goalObject

retrieve sleep goal for the user



35
36
37
# File 'lib/fitgem_oauth2/sleep.rb', line 35

def sleep_goal
  get_call("user/#{user_id}/sleep/goal.json")
end

#sleep_logs(date) ⇒ Object

retrieve sleep logs for a date

Parameters:

  • date

    date for which sleep logs needs to be accessed



14
15
16
# File 'lib/fitgem_oauth2/sleep.rb', line 14

def sleep_logs(date)
  get_call_1_2("user/#{user_id}/sleep/date/#{format_date(date)}.json")
end

#sleep_logs_by_date_range(start_date, end_date) ⇒ Object



18
19
20
# File 'lib/fitgem_oauth2/sleep.rb', line 18

def sleep_logs_by_date_range(start_date, end_date)
  get_call_1_2("user/#{user_id}/sleep/date/#{format_date(start_date)}/#{format_date(end_date)}.json")
end

#sleep_logs_list(date, sort, limit) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/fitgem_oauth2/sleep.rb', line 22

def sleep_logs_list(date, sort, limit)
  date_param = format_date(date)
  if sort == 'asc'
    date_param = "afterDate=#{date_param}"
  elsif sort == 'desc'
    date_param = "beforeDate=#{date_param}"
  else
    raise FitgemOauth2::InvalidArgumentError, 'sort can either be asc or desc'
  end
  get_call_1_2("user/#{user_id}/sleep/list.json?#{date_param}&offset=0&sort=#{sort}&limit=#{limit}")
end

#sleep_time_series(resource: nil, start_date: nil, end_date: nil, period: nil) ⇒ Object

retrieve time series data for sleep

Parameters:

  • resource (defaults to: nil)

    sleep resource to be requested

  • start_date (defaults to: nil)

    starting date for sleep time series

  • end_date (defaults to: nil)

    ending date for sleep time series

  • period (defaults to: nil)

    period for sleep time series

Raises:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/fitgem_oauth2/sleep.rb', line 50

def sleep_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
  raise FitgemOauth2::InvalidArgumentError, 'Start date not provided.' unless start_date

  unless resource && SLEEP_RESOURCES.include?(resource)
    raise FitgemOauth2::InvalidArgumentError, "Invalid resource: #{resource}. Valid resources are #{SLEEP_RESOURCES}."
  end

  if period && end_date
    raise FitgemOauth2::InvalidArgumentError, 'Both end_date and period specified. Specify only one.'
  end

  if period && !SLEEP_PERIODS.include?(period)
    raise FitgemOauth2::InvalidArgumentError, "Invalid period: #{period}. Valid periods are #{SLEEP_PERIODS}."
  end

  second = period || format_date(end_date)

  url = ['user', user_id, 'sleep', resource, 'date', format_date(start_date), second].join('/')

  get_call(url + '.json')
end

#subscriptions(opts) ⇒ Object



7
8
9
# File 'lib/fitgem_oauth2/subscriptions.rb', line 7

def subscriptions(opts)
  get_call(subscription_url(opts))
end

#update_activity_goals(period, params) ⇒ Object

update activity goals

Parameters:

  • period

    period for the goal (‘weekly’ or ‘daily’)

  • params

    the POST params for the request. Refer to Fitbit documentation for accepted format



195
196
197
198
199
200
201
# File 'lib/fitgem_oauth2/activity.rb', line 195

def update_activity_goals(period, params)
  unless period && %w[daily weekly].include?(period)
    raise FitgemOauth2::InvalidArgumentError, "Goal period should either be 'daily' or 'weekly'"
  end

  post_call("user/#{user_id}/activities/goals/#{period}.json", params)
end

#update_alarm(tracker_id, alarm_id, params) ⇒ Object

update an existing alarm

Parameters:

  • tracker_id

    ID of the tracker to which alaram needs to be added.

  • alarm_id

    ID of the alarm that needs to be updated

  • params

    POST parameters for updating the alarm



35
36
37
# File 'lib/fitgem_oauth2/devices.rb', line 35

def update_alarm(tracker_id, alarm_id, params)
  post_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms/#{alarm_id}.json", params)
end

#update_body_fat_goal(params) ⇒ Object

update body fat goal

Parameters:

  • params

    POST params for updating body fat goal



102
103
104
# File 'lib/fitgem_oauth2/body_measurements.rb', line 102

def update_body_fat_goal(params)
  post_call("user/#{user_id}/body/log/fat/goal.json", params)
end

#update_food_goal(params) ⇒ Object



33
34
35
# File 'lib/fitgem_oauth2/food/collection.rb', line 33

def update_food_goal(params)
  post_call("user/#{user_id}/foods/log/goal.json", params)
end

#update_food_log(food_log_id, params) ⇒ Object



25
26
27
# File 'lib/fitgem_oauth2/food/collection.rb', line 25

def update_food_log(food_log_id, params)
  post_call("user/#{user_id}/foods/log/#{food_log_id}.json", params)
end

#update_meal(meal_id, params) ⇒ Object



37
38
39
# File 'lib/fitgem_oauth2/food/metadata.rb', line 37

def update_meal(meal_id, params)
  post_call("user/#{user_id}/meals/#{meal_id}.json", params)
end

#update_sleep_goal(params) ⇒ Object

update sleep goal

Parameters:

  • params

    POST parameters for updating sleep goal



41
42
43
# File 'lib/fitgem_oauth2/sleep.rb', line 41

def update_sleep_goal(params)
  post_call("user/#{user_id}/sleep/goal.json", params)
end

#update_water_goal(params) ⇒ Object



37
38
39
# File 'lib/fitgem_oauth2/food/collection.rb', line 37

def update_water_goal(params)
  post_call("user/#{user_id}/foods/log/water/goal.json", params)
end

#update_water_log(water_log_id, params) ⇒ Object



45
46
47
# File 'lib/fitgem_oauth2/food/collection.rb', line 45

def update_water_log(water_log_id, params)
  post_call("user/#{user_id}/foods/log/water/#{water_log_id}.json", params)
end

#update_weight_goal(params) ⇒ Object

update weight goal

Parameters:

  • params

    POST params for updating weight goal



108
109
110
# File 'lib/fitgem_oauth2/body_measurements.rb', line 108

def update_weight_goal(params)
  post_call("user/#{user_id}/body/log/weight/goal.json", params)
end

#user_infoObject



5
6
7
# File 'lib/fitgem_oauth2/users.rb', line 5

def 
  get_call("user/#{user_id}/profile.json")
end

#validate_end_date(end_date) ⇒ Object



35
36
37
# File 'lib/fitgem_oauth2/utils.rb', line 35

def validate_end_date(end_date)
  raise FitgemOauth2::InvalidArgumentError, 'Please specify a valid end date.' unless end_date
end

#validate_start_date(start_date) ⇒ Object



31
32
33
# File 'lib/fitgem_oauth2/utils.rb', line 31

def validate_start_date(start_date)
  raise FitgemOauth2::InvalidArgumentError, 'Please specify a valid start date.' unless start_date
end

#water_goalObject



17
18
19
# File 'lib/fitgem_oauth2/food/collection.rb', line 17

def water_goal
  get_call("user/#{user_id}/foods/log/water/goal.json")
end

#water_logs(date) ⇒ Object



13
14
15
# File 'lib/fitgem_oauth2/food/collection.rb', line 13

def water_logs(date)
  get_call("user/#{user_id}/foods/log/water/date/#{format_date(date)}.json")
end

#water_series_for_date_range(start_date, end_date) ⇒ Object



17
18
19
20
21
# File 'lib/fitgem_oauth2/food/series.rb', line 17

def water_series_for_date_range(start_date, end_date)
  validate_start_date(start_date)
  validate_end_date(end_date)
  get_call(water_series_url(user_id, format_date(start_date), format_date(end_date)))
end

#water_series_for_period(start_date, period) ⇒ Object



23
24
25
26
27
# File 'lib/fitgem_oauth2/food/series.rb', line 23

def water_series_for_period(start_date, period)
  validate_start_date(start_date)
  validate_food_series_period(period)
  get_call(water_series_url(user_id, format_date(start_date), period))
end

#weight_logs(start_date: nil, end_date: nil, period: nil) ⇒ Object

retrieve weight logs; specify either the end_date or period

Parameters:

  • start_date (defaults to: nil)

    start date for the logs

  • end_date (optional) (defaults to: nil)

    end_date for the logs

  • period (optional) (defaults to: nil)

    period for the logs

Raises:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/fitgem_oauth2/body_measurements.rb', line 120

def weight_logs(start_date: nil, end_date: nil, period: nil)
  raise FitgemOauth2::InvalidArgumentError, 'start_date not specified.' unless start_date

  if period && end_date
    raise FitgemOauth2::InvalidArgumentError, 'both end_date and period specified. please provide only one.'
  end

  if period
    unless WEIGHT_PERIODS.include?(period)
      raise FitgemOauth2::InvalidArgumentError, "valid period not specified. please choose a period from #{WEIGHT_PERIODS}"
    end
  end

  first = format_date(start_date)
  url = ['user', user_id, 'body/log/weight/date', first].join('/')
  if period || end_date
    second = period || format_date(end_date)
    url = [url, second].join('/')
  end

  get_call(url + '.json')
end