class FitbitAPI::Client

Constants

ACTIVITY_INTRADAY_RESOURCES
ACTIVITY_RESOURCES
BODY_RESOURCES
FOOD_RESOURCES
PERIODS
SLEEP_RESOURCES

Attributes

api_version[RW]
locale[RW]
scope[RW]
snake_case_keys[RW]
symbolize_keys[RW]
unit_system[RW]
user_id[R]

Public Class Methods

new(opts={}) click to toggle source
# File lib/fitbit_api/client.rb, line 20
def initialize(opts={})
  validate_args(opts)
  assign_attrs(opts)
  set_client
  establish_token(opts)
end

Public Instance Methods

activity(activity_id) click to toggle source

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

If activity has levels, also returns a list of activity level details.
# File lib/fitbit_api/activities.rb, line 73
def activity(activity_id)
  get("activities/#{activity_id}.json")
end
activity_intraday_time_series(resource, opts={}) click to toggle source
# File lib/fitbit_api/activities.rb, line 112
def activity_intraday_time_series(resource, opts={})
  date         = opts[:date] || Date.today
  detail_level = opts[:detail_level]
  start_time   = opts[:start_time]
  end_time     = opts[:end_time]

  unless ACTIVITY_INTRADAY_RESOURCES.include?(resource)
    raise FitbitAPI::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{ACTIVITY_RESOURCES}."
  end

  if [date, detail_level].any?(&:nil?)
    raise FitbitAPI::InvalidArgumentError, 'A date and detail_level are required.'
  end

  unless %(1min 15min).include? detail_level
    raise FitbitAPI::InvalidArgumentError, "Invalid detail_level: \"#{detail_level}\". Please provide one of the following: \"1min\" or \"15min\"."
  end

  if (start_time || end_time) && !(start_time && end_time)
    raise FitbitAPI::InvalidArgumentError, 'Both start_time and end_time are required if time is being specified.'
  end

  if (start_time && end_time)
    get("user/-/activities/#{resource}/date/#{format_date(date)}/1d/#{detail_level}/time/#{format_time(start_time)}/#{format_time(end_time)}.json")
  else
    get("user/-/activities/#{resource}/date/#{format_date(date)}/1d/#{detail_level}.json")
  end
end
activity_logs_list(opts={}) click to toggle source

URL Parameters

  • :beforeDate - the date; formatted in yyyy-MM-ddTHH:mm:ss

  • :afterDate - the date; formatted in yyyy-MM-ddTHH:mm:ss

  • :sort - the sort order of entries by date (asc or desc)

  • :offset - the offset number of entries. Must always be 0

  • :limit - the max of the number of entries returned (max: 20)

# File lib/fitbit_api/activities.rb, line 58
def activity_logs_list(opts={})
  opts[:params] = {}
  param_defaults = { before_date: Date.today, after_date: nil, sort: 'desc', limit: 20, offset: 0 }

  # move param values from top-level opts into :params sub-hash
  param_defaults.each do |key, default_val|
    opts[:params][key] = opts.delete(key) || default_val
  end

  get("user/#{user_id}/activities/list.json", opts)
end
activity_time_series(resource, opts={}) click to toggle source
# File lib/fitbit_api/activities.rb, line 86
def activity_time_series(resource, opts={})
  start_date = opts[:start_date]
  end_date   = opts[:end_date] || Date.today
  period     = opts[:period]

  unless ACTIVITY_RESOURCES.include?(resource)
    raise FitbitAPI::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{ACTIVITY_RESOURCES}."
  end

  if [start_date, period].none?
    raise FitbitAPI::InvalidArgumentError, 'A start_date or period is required.'
  end

  if period && !PERIODS.include?(period)
    raise FitbitAPI::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
  end

  if period
    result = get("user/#{user_id}/activities/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
  else
    result = get("user/#{user_id}/activities/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
  end
  # remove root key from response
  result.values[0]
end
add_alarm(tracker_id, opts={}) click to toggle source

POST Parameters

  • :time - time of day that the alarm vibrates with a UTC timezone offset, e.g. 07:15-08:00

  • :enabled - boolean; if false, alarm does not vibrate until enabled is set to true

  • :recurring - boolean; if false, the alarm is a single event

  • :weekDays - comma separated list of days of the week on which the alarm vibrates (MONDAY,TUESDAY)

# File lib/fitbit_api/alarms.rb, line 23
def add_alarm(tracker_id, opts={})
  post("user/#{user_id}/devices/tracker/#{tracker_id}/alarms.json", opts)
end
add_favorite_activity(activity_id) click to toggle source

Adds the activity with the given ID to user's list of favorite activities.

# File lib/fitbit_api/activities.rb, line 163
def add_favorite_activity(activity_id)
  post("user/#{user_id}/activities/favorite/#{activity_id}.json")
end
alarms(tracker_id, opts={}) click to toggle source

Returns a list of the set alarms connected to a user's account.

# File lib/fitbit_api/alarms.rb, line 8
def alarms(tracker_id, opts={})
  get("user/#{user_id}/devices/tracker/#{tracker_id}/alarms.json", opts)
end
all_activities(opts={}) click to toggle source

Gets a tree of all valid Fitbit public activities from

the activities catalog as well as private custom activities the user created.
# File lib/fitbit_api/activities.rb, line 44
def all_activities(opts={})
  get('activities.json', opts)
end
auth_header() click to toggle source
# File lib/fitbit_api/client.rb, line 51
def auth_header
  { 'Authorization' => ('Basic ' + Base64.encode64(@client_id + ':' + @client_secret)) }
end
auth_url() click to toggle source
# File lib/fitbit_api/client.rb, line 27
def auth_url
  @client.auth_code.authorize_url(redirect_uri: @redirect_uri, scope: @scope)
end
badges(opts={}) click to toggle source
# File lib/fitbit_api/user.rb, line 7
def badges(opts={})
  get("user/#{user_id}/badges.json", opts)
end
body_fat_goal(opts={}) click to toggle source

Retrieves a user's current body fat percentage goal.

# File lib/fitbit_api/goals.rb, line 14
def body_fat_goal(opts={})
  get("user/-/body/log/fat/goal.json", opts)
end
body_fat_logs(date=Date.today, opts={}) click to toggle source
# File lib/fitbit_api/body.rb, line 9
def body_fat_logs(date=Date.today, opts={})
  get("user/-/body/log/fat/date/#{format_date(date)}.json", opts)
end
body_time_series(resource, opts={}) click to toggle source
# File lib/fitbit_api/body.rb, line 13
def body_time_series(resource, opts={})
  start_date = opts[:start_date]
  end_date   = opts[:end_date] || Date.today
  period     = opts[:period]

  unless BODY_RESOURCES.include?(resource)
    raise FitbitAPI::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{BODY_RESOURCES}."
  end

  if [period, start_date].none?
    raise FitbitAPI::InvalidArgumentError, 'A start_date or period is required.'
  end

  if period && !PERIODS.include?(period)
    raise FitbitAPI::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
  end

  if period
    result = get("user/#{user_id}/body/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
  else
    result = get("user/#{user_id}/body/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
  end
  # remove root key from response
  result.values[0]
end
create_or_update_daily_goals(opts={}) click to toggle source

POST Parameters

  • :caloriesOut - calories output goal value; integer

  • :activeMinutes - active minutes goal value; integer

  • :floors - floor goal value; integer

  • :distance - distance goal value; X.XX or integer

  • :steps - steps goal value; integer

# File lib/fitbit_api/goals.rb, line 43
def create_or_update_daily_goals(opts={})
  post("user/#{user_id}/activities/goals/daily.json", opts)
end
create_or_update_weekly_goals(opts={}) click to toggle source

POST Parameters

  • :caloriesOut - calories output goal value; integer

  • :activeMinutes - active minutes goal value; integer

  • :floors - floor goal value; integer

  • :distance - distance goal value; X.XX or integer

  • :steps - steps goal value; integer

# File lib/fitbit_api/goals.rb, line 57
def create_or_update_weekly_goals(opts={})
  post("user/#{user_id}/activities/goals/weekly.json", opts)
end
daily_activity_summary(date=Date.today, opts={}) click to toggle source

Retrieves a summary and list of a user's activities and activity log entries for a given day

in the format requested using units in the unit system which corresponds to the Accept-Language header provided.
# File lib/fitbit_api/activities.rb, line 20
def daily_activity_summary(date=Date.today, opts={})
  get("user/#{user_id}/activities/date/#{format_date(date)}.json", opts)
end
daily_goals(opts={}) click to toggle source

Retrieves a user's current daily activity goals.

# File lib/fitbit_api/goals.rb, line 20
def daily_goals(opts={})
  get("user/#{user_id}/activities/goals/daily.json", opts)
end
deep_keys_to_camel_case!(object) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 42
def deep_keys_to_camel_case!(object)
  deep_transform_keys!(object) { |key| to_camel_case(key, lower: true) }
end
deep_keys_to_snake_case!(object) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 38
def deep_keys_to_snake_case!(object)
  deep_transform_keys!(object) { |key| to_snake_case(key, replace_dashes: true) }
end
deep_symbolize_keys!(object) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 46
def deep_symbolize_keys!(object)
  deep_transform_keys!(object) { |key| key.to_sym rescue key }
end
deep_transform_keys!(object) { |key| ... } click to toggle source

Inspired by ActiveSupport's implementation

# File lib/fitbit_api/helpers/utils.rb, line 51
def deep_transform_keys!(object, &block)
  case object
  when Hash
    object.keys.each do |key|
      value = object.delete(key)
      object[yield(key)] = deep_transform_keys!(value) { |key| yield(key) }
    end
    object
  when Array
    object.map! { |e| deep_transform_keys!(e) { |key| yield(key) } }
  else
    object
  end
end
delete(path, opts={}) click to toggle source
# File lib/fitbit_api/client.rb, line 76
def delete(path, opts={})
  response = token.delete(("#{@api_version}/" + path), headers: request_headers).response
  object = MultiJson.load(response.body) unless response.status == 204
  process_keys!(object, opts)
end
delete_activity(activity_log_id) click to toggle source

Deletes a user's activity log entry with the given ID.

# File lib/fitbit_api/activities.rb, line 172
def delete_activity(activity_log_id)
  delete("user/#{user_id}/activities/#{activity_log_id}.json")
end
delete_alarm(tracker_id, alarm_id, opts={}) click to toggle source

Deletes the user's device alarm entry with the given ID for a given device.

# File lib/fitbit_api/alarms.rb, line 48
def delete_alarm(tracker_id, alarm_id, opts={})
  delete("user/#{user_id}/devices/tracker/#{tracker_id}/alarms/#{alarm_id}.json", opts)
end
delete_body_fat_log(body_fat_log_id, opts={}) click to toggle source
# File lib/fitbit_api/body.rb, line 51
def delete_body_fat_log(body_fat_log_id, opts={})
  delete("user/#{user_id}/body/log/fat/#{body_fat_log_id}.json", opts)
end
delete_favorite_activity(activity_id) click to toggle source

Removes the activity with the given ID from a user's list of favorite activities.

# File lib/fitbit_api/activities.rb, line 178
def delete_favorite_activity(activity_id)
  delete("user/#{user_id}/activities/favorite/#{activity_id}.json")
end
delete_weight_log(weight_log_id, opts={}) click to toggle source
# File lib/fitbit_api/body.rb, line 43
def delete_weight_log(weight_log_id, opts={})
  delete("user/#{user_id}/body/log/weight/#{weight_log_id}.json", opts)
end
devices(opts={}) click to toggle source
# File lib/fitbit_api/devices.rb, line 3
def devices(opts={})
  get("user/#{user_id}/devices.json", opts)
end
favorite_activities(opts={}) click to toggle source

Returns a list of a user's favorite activities.

# File lib/fitbit_api/activities.rb, line 37
def favorite_activities(opts={})
  get("user/#{user_id}/activities/favorite.json", opts)
end
favorite_foods(opts={}) click to toggle source
# File lib/fitbit_api/food.rb, line 17
def favorite_foods(opts={})
  get("user/#{user_id}/foods/log/favorite.json", opts)
end
food_goals(opts={}) click to toggle source
# File lib/fitbit_api/food.rb, line 21
def food_goals(opts={})
  get("user/#{user_id}/foods/log/goal.json", opts)
end
food_logs(date=Date.today, opts={}) click to toggle source
# File lib/fitbit_api/food.rb, line 5
def food_logs(date=Date.today, opts={})
  get("user/#{user_id}/foods/log/date/#{format_date(date)}.json", opts)
end
food_time_series(resource, opts={}) click to toggle source
# File lib/fitbit_api/food.rb, line 25
def food_time_series(resource, opts={})
  start_date = opts[:start_date]
  end_date   = opts[:end_date] || Date.today
  period     = opts[:period]

  unless FOOD_RESOURCES.include?(resource)
    raise FitbitAPI::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{FOOD_RESOURCES}."
  end

  if [period, start_date].none?
    raise FitbitAPI::InvalidArgumentError, 'A start_date or period is required.'
  end

  if period && !PERIODS.include?(period)
    raise FitbitAPI::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
  end

  if period
    result = get("user/#{user_id}/foods/log/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
  else
    result = get("user/#{user_id}/foods/log/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
  end
  # remove root key from response
  result.values[0]
end
format_date(date) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 6
def format_date(date)
  if [Date, Time, DateTime].include?(date.class)
    date.strftime('%Y-%m-%d')
  elsif date.is_a? String
    if date =~ /\d{4}\-\d{2}\-\d{2}/
      date
    else
      raise FitbitAPI::InvalidArgumentError, "Invalid argument [\"#{date}\"] - string must follow yyyy-MM-dd format."
    end
  else
    raise FitbitAPI::InvalidArgumentError, "Invalid type [#{date.class}] - provide a Date/Time/DateTime or a String(yyyy-MM-dd format)."
  end
end
format_scope(scope) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 34
def format_scope(scope)
  scope.is_a?(Array) ? scope.join(' ') : scope
end
format_time(time) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 20
def format_time(time)
  if [Time, DateTime].include?(time.class)
    time.strftime('%H:%M')
  elsif time.is_a? String
    if time =~ /\d{2}\:\d{2}/
      time
    else
      raise FitbitAPI::InvalidArgumentError, "Invalid argument [\"#{time}\"] - string must follow HH:mm format."
    end
  else
    raise FitbitAPI::InvalidArgumentError, "Invalid type [#{time.class}] - provide a Time/DateTime or a String(HH:mm format)."
  end
end
frequent_activities(opts={}) click to toggle source

Retrieves a list of a user's frequent activities in the format requested using units

in the unit system which corresponds to the Accept-Language header provided.
# File lib/fitbit_api/activities.rb, line 27
def frequent_activities(opts={})
  get("user/#{user_id}/activities/frequent.json", opts)
end
frequent_foods(opts={}) click to toggle source
# File lib/fitbit_api/food.rb, line 13
def frequent_foods(opts={})
  get("user/#{user_id}/foods/log/frequent.json", opts)
end
friends(opts={}) click to toggle source
# File lib/fitbit_api/friends.rb, line 3
def friends(opts={})
  get("user/#{user_id}/friends.json", opts)
end
friends_leaderboard(opts={}) click to toggle source
# File lib/fitbit_api/friends.rb, line 7
def friends_leaderboard(opts={})
  get("user/#{user_id}/friends/leaderboard.json", opts)
end
get(path, opts={}) click to toggle source
# File lib/fitbit_api/client.rb, line 63
def get(path, opts={})
  params = opts.delete(:params) || {}
  response = token.get(("#{@api_version}/" + path), params: deep_keys_to_camel_case!(params), headers: request_headers).response
  object = MultiJson.load(response.body) unless response.status == 204
  process_keys!(object, opts)
end
get_token(auth_code) click to toggle source
# File lib/fitbit_api/client.rb, line 31
def get_token(auth_code)
  @token = @client.auth_code.get_token(
    auth_code,
    redirect_uri: @redirect_uri,
    headers: auth_header
  )
  @user_id = @token.params['user_id']
  @token
end
heart_rate_intraday_time_series(opts={}) click to toggle source
# File lib/fitbit_api/heart_rate.rb, line 25
def heart_rate_intraday_time_series(opts={})
  date         = opts[:date] || Date.today
  detail_level = opts[:detail_level]
  start_time   = opts[:start_time]
  end_time     = opts[:end_time]

  if [date, detail_level].any?(&:nil?)
    raise FitbitAPI::InvalidArgumentError, 'A date and detail_level are required.'
  end

  unless %(1sec 1min).include? detail_level
    raise FitbitAPI::InvalidArgumentError, "Invalid detail_level: \"#{detail_level}\". Please provide one of the following: \"1sec\" or \"1min\"."
  end

  if (start_time || end_time) && !(start_time && end_time)
    raise FitbitAPI::InvalidArgumentError, 'Both start_time and end_time are required if time is being specified.'
  end

  if (start_time && end_time)
    get("user/-/activities/heart/date/#{format_date(date)}/1d/#{detail_level}/time/#{format_time(start_time)}/#{format_time(end_time)}.json")
  else
    get("user/-/activities/heart/date/#{format_date(date)}/1d/#{detail_level}.json")
  end
end
heart_rate_time_series(opts={}) click to toggle source
# File lib/fitbit_api/heart_rate.rb, line 3
def heart_rate_time_series(opts={})
  start_date = opts[:start_date]
  end_date   = opts[:end_date] || Date.today
  period     = opts[:period]

  if [period, start_date].none?
    raise FitbitAPI::InvalidArgumentError, 'A start_date or period is required.'
  end

  if period && !PERIODS.include?(period)
    raise FitbitAPI::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
  end

  if period
    result = get("user/#{user_id}/activities/heart/date/#{format_date(end_date)}/#{period}.json", opts)
  else
    result = get("user/#{user_id}/activities/heart/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
  end
  # remove root key from response
  result.values[0]
end
lifetime_stats(opts={}) click to toggle source

Retrieves the user's activity statistics in the format requested using units

in the unit system which corresponds to the Accept-Language header provided.
Activity statistics includes Lifetime and Best achievement values from the
My Achievements tile on the website dashboard.
# File lib/fitbit_api/activities.rb, line 82
def lifetime_stats(opts={})
  get("user/#{user_id}/activities.json", opts)
end
log_activity(opts) click to toggle source

POST Parameters

  • :activityId - activity id

  • :activityName - custom activity name. Either activity ID or activityName must be provided

  • :manualCalories - calories burned, specified manually. Required with activityName, otherwise optional

  • :startTime - activity start time; formatted in HH:mm:ss

  • :durationMillis - duration in milliseconds

  • :date - log entry date; formatted in yyyy-MM-dd

  • :distance - distance; required for logging directory activity; formatted in X.XX

  • :distanceUnit - distance measurement unit

# File lib/fitbit_api/activities.rb, line 157
def log_activity(opts)
  post("user/#{user_id}/activities.json", opts)
end
log_body_fat(opts) click to toggle source
# File lib/fitbit_api/body.rb, line 47
def log_body_fat(opts)
  post("user/#{user_id}/body/log/fat.json", opts)
end
log_weight(opts) click to toggle source
# File lib/fitbit_api/body.rb, line 39
def log_weight(opts)
  post("user/#{user_id}/body/log/weight.json", opts)
end
post(path, opts={}) click to toggle source
# File lib/fitbit_api/client.rb, line 70
def post(path, opts={})
  response = token.post(("#{@api_version}/" + path), body: deep_keys_to_camel_case!(opts), headers: request_headers).response
  object = MultiJson.load(response.body) unless response.status == 204
  process_keys!(object, opts)
end
process_keys!(object, opts={}) click to toggle source
# File lib/fitbit_api/client.rb, line 82
def process_keys!(object, opts={})
  deep_keys_to_snake_case!(object) if (opts[:snake_case_keys] || snake_case_keys)
  deep_symbolize_keys!(object) if (opts[:symbolize_keys] || symbolize_keys)
  return object
end
profile(opts={}) click to toggle source
# File lib/fitbit_api/user.rb, line 3
def profile(opts={})
  get("user/#{user_id}/profile.json", opts)
end
recent_activities(opts={}) click to toggle source
# File lib/fitbit_api/activities.rb, line 31
def recent_activities(opts={})
  get("user/#{user_id}/activities/recent.json", opts)
end
recent_foods(opts={}) click to toggle source
# File lib/fitbit_api/food.rb, line 9
def recent_foods(opts={})
  get("user/#{user_id}/foods/log/recent.json", opts)
end
refresh_token!() click to toggle source
# File lib/fitbit_api/client.rb, line 45
def refresh_token!
  @token = @token.refresh!(headers: auth_header)
  @user_id ||= @token.params['user_id']
  @token
end
request_headers() click to toggle source
# File lib/fitbit_api/client.rb, line 55
def request_headers
  {
    'User-Agent' => "fitbit_api gem (v#{FitbitAPI::VERSION})",
    'Accept-Language' => @unit_system,
    'Accept-Locale' => @locale
  }
end
sleep_logs(date=Date.today, opts={}) click to toggle source
# File lib/fitbit_api/sleep.rb, line 6
def sleep_logs(date=Date.today, opts={})
  get("user/#{user_id}/sleep/date/#{format_date(date)}.json", opts)
end
sleep_time_series(resource, opts={}) click to toggle source
# File lib/fitbit_api/sleep.rb, line 10
def sleep_time_series(resource, opts={})
  start_date = opts[:start_date]
  end_date   = opts[:end_date] || Date.today
  period     = opts[:period]

  unless SLEEP_RESOURCES.include?(resource)
    raise FitbitAPI::InvalidArgumentError, "Invalid resource: \"#{resource}\". Please provide one of the following: #{SLEEP_RESOURCES}."
  end

  if [period, start_date].none?
    raise FitbitAPI::InvalidArgumentError, 'A start_date or period is required.'
  end

  if period && !PERIODS.include?(period)
    raise FitbitAPI::InvalidArgumentError, "Invalid period: \"#{period}\". Please provide one of the following: #{PERIODS}."
  end

  if period
    result = get("user/#{user_id}/sleep/#{resource}/date/#{format_date(end_date)}/#{period}.json", opts)
  else
    result = get("user/#{user_id}/sleep/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json", opts)
  end
  # remove root key from response
  result.values[0]
end
to_camel_case(word, opts={}) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 75
def to_camel_case(word, opts={})
  string = word.to_s
  return string if string.match(/[A-Z]|[a-z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*/)
  string = word.to_s.split('_').collect(&:capitalize).join
  string.gsub!(/^\w{1}/) { |word| word.downcase } if opts[:lower]
  return string
end
to_snake_case(word, opts={}) click to toggle source
# File lib/fitbit_api/helpers/utils.rb, line 66
def to_snake_case(word, opts={})
  string = word.to_s.dup
  return string.downcase if string.match(/\A[A-Z]+\z/)
  string.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
  string.gsub!(/([a-z])([A-Z])/, '\1_\2')
  string.gsub!('-', '_') if opts[:replace_dashes]
  string.downcase
end
token() click to toggle source
# File lib/fitbit_api/client.rb, line 41
def token
  @token.expired? ? refresh_token! : @token
end
update_alarm(tracker_id, alarm_id, opts={}) click to toggle source

POST Parameters

  • :time - time of day that the alarm vibrates with a UTC timezone offset, e.g. 07:15-08:00

  • :enabled - boolean; if false, alarm does not vibrate until enabled is set to true

  • :recurring - boolean; if false, the alarm is a single event

  • :weekDays - comma separated list of days of the week on which the alarm vibrates (MONDAY,TUESDAY)

  • :snoozeLength - integer; minutes between alarms

  • :snoozeCount - integer; maximum snooze count

  • :label - string; label for alarm

  • :vibe - vibe pattern; only one value for now (DEFAULT)

# File lib/fitbit_api/alarms.rb, line 39
def update_alarm(tracker_id, alarm_id, opts={})
  post("user/#{user_id}/devices/tracker/#{tracker_id}/alarms/#{alarm_id}.json", opts)
end
update_profile(opts) click to toggle source
# File lib/fitbit_api/user.rb, line 11
def update_profile(opts)
  post("user/#{user_id}/profile.json", opts)
end
water_logs(date=Date.today, opts={}) click to toggle source
# File lib/fitbit_api/water.rb, line 3
def water_logs(date=Date.today, opts={})
  get("user/#{user_id}/foods/log/water/date/#{format_date(date)}.json", opts)
end
weekly_goals(opts={}) click to toggle source

Retrieves a user's current weekly activity goals.

# File lib/fitbit_api/goals.rb, line 26
def weekly_goals(opts={})
  get("user/#{user_id}/activities/goals/weekly.json", opts)
end
weight_goal(opts={}) click to toggle source

Retrieves a user's current weight goal.

# File lib/fitbit_api/goals.rb, line 8
def weight_goal(opts={})
  get("user/-/body/log/weight/goal.json", opts)
end
weight_logs(date=Date.today, opts={}) click to toggle source
# File lib/fitbit_api/body.rb, line 5
def weight_logs(date=Date.today, opts={})
  get("user/-/body/log/weight/date/#{format_date(date)}.json", opts)
end

Private Instance Methods

assign_attrs(opts) click to toggle source
# File lib/fitbit_api/client.rb, line 103
def assign_attrs(opts)
  attrs = %i[client_id client_secret redirect_uri site_url
             authorize_url token_url unit_system locale scope
             api_version snake_case_keys symbolize_keys].freeze

  attrs.each do |attr|
    instance_variable_set("@#{attr}", (opts[attr] || FitbitAPI.send(attr)))
  end

  @user_id = opts[:user_id]
end
establish_token(opts) click to toggle source
# File lib/fitbit_api/client.rb, line 125
def establish_token(opts)
  return unless opts[:access_token] || opts[:refresh_token]

  if opts[:access_token] && !opts[:user_id]
    raise FitbitAPI::InvalidArgumentError,
          'user_id is required if using existing access token'
  end

  @token = OAuth2::AccessToken.new(
    @client,
    opts[:access_token],
    refresh_token: opts[:refresh_token],
    expires_at: opts[:expires_at]
  )

  refresh_token! if @token.token.empty?
end
set_client() click to toggle source
# File lib/fitbit_api/client.rb, line 115
def set_client
  @client = OAuth2::Client.new(
    @client_id,
    @client_secret,
    site: @site_url,
    authorize_url: @authorize_url,
    token_url: @token_url
  )
end
validate_args(opts) click to toggle source
# File lib/fitbit_api/client.rb, line 90
def validate_args(opts)
  required_args = %i[client_id client_secret].freeze
  missing_args = []

  required_args.each do |arg|
    missing_args << arg if (opts[arg] || FitbitAPI.send(arg)).nil?
  end

  return if missing_args.empty?
  raise FitbitAPI::InvalidArgumentError,
        "Required arguments: #{missing_args.join(', ')}"
end