Class: Fitgem::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/fitgem/foods.rb,
lib/fitgem/sleep.rb,
lib/fitgem/users.rb,
lib/fitgem/water.rb,
lib/fitgem/alarms.rb,
lib/fitgem/badges.rb,
lib/fitgem/client.rb,
lib/fitgem/devices.rb,
lib/fitgem/friends.rb,
lib/fitgem/glucose.rb,
lib/fitgem/helpers.rb,
lib/fitgem/activities.rb,
lib/fitgem/heart_rate.rb,
lib/fitgem/time_range.rb,
lib/fitgem/notifications.rb,
lib/fitgem/blood_pressure.rb,
lib/fitgem/body_measurements.rb

Constant Summary collapse

API_VERSION =
'1'
EMPTY_BODY =
''
SUBSCRIBABLE_TYPES =
[:sleep, :body, :activities, :foods, :all]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Client

Creates a client object to communicate with the fitbit API

There are two primary ways to create a client: one if the current fitbit user has not authenticated through fitbit.com, and another if they have already authenticated and you have a stored token/secret returned by fitbit after the user authenticated and authorized your application.

Examples:

User has not yet authorized with fitbit

client = Fitgem::Client.new { :consumer_key => my_key, :consumer_secret => my_secret }

User has already authorized with fitbit, and we have a stored token/secret

client = Fitgem::Client.new {
  :consumer_key => my_key,
  :consumer_secret => my_secret,
  :token => fitbit_oauth_token,
  :secret => fitbit_oauth_secret
}

Parameters:

  • opts (Hash)

    The constructor options

Options Hash (opts):

  • :consumer_key (String)

    The consumer key (required for OAuth)

  • :consumer_secret (String)

    The consumer secret (required for OAuth)

  • :token (String)

    The token generated by fitbit during the OAuth handshake; stored and re-passed to the constructor to create a ‘logged-in’ client

  • :secret (String)

    The secret generated by fitbit during the OAuth handshake; stored and re-passed to the constructor to create a ‘logged-in’ client

  • :proxy (String)

    A proxy URL to use for API calls

  • :user_id (String)

    The Fitbit user id of the logged-in user

  • :unit_system (Symbol)

    The unit system to use for API calls; use ApiUnitSystem to set during initialization. DEFAULT: ApiUnitSystem.US



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/fitgem/client.rb', line 93

def initialize(opts)
  missing = [:consumer_key, :consumer_secret] - opts.keys
  if missing.size > 0
    raise Fitgem::InvalidArgumentError, "Missing required options: #{missing.join(',')}"
  end
  @consumer_key = opts[:consumer_key]
  @consumer_secret = opts[:consumer_secret]

  @token = opts[:token]
  @secret = opts[:secret]

  @proxy = opts[:proxy] if opts[:proxy]
  @user_id = opts[:user_id] || '-'

  @api_unit_system = opts[:unit_system] || Fitgem::ApiUnitSystem.US
  @api_version = API_VERSION
end

Instance Attribute Details

#api_unit_systemString

Sets or gets the api unit system to be used in API calls

Examples:

Set this using the ApiUnitSystem

client.api_unit_system = Fitgem::ApiUnitSystem.UK

May also be set in the constructor call

client = Fitgem::Client {
  :consumer_key => my_key,
  :consumer_secret => my_secret,
  :token => fitbit_oauth_token,
  :secret => fitbit_oauth_secret,
  :unit_system => Fitgem::ApiUnitSystem.METRIC
}

Returns:

  • (String)


47
48
49
# File 'lib/fitgem/client.rb', line 47

def api_unit_system
  @api_unit_system
end

#api_versionString

Sets or gets the api_version to be used in API calls “

Returns:

  • (String)


31
32
33
# File 'lib/fitgem/client.rb', line 31

def api_version
  @api_version
end

#user_idString

Sets or gets the user id to be used in API calls

Returns:

  • (String)


52
53
54
# File 'lib/fitgem/client.rb', line 52

def user_id
  @user_id
end

Class Method Details

.symbolize_keys(obj) ⇒ Object

Recursively turns arrays and hashes into symbol-key based structures.

Parameters:

  • The (Array, Hash)

    structure to symbolize keys for

Returns:

  • A new structure with the keys symbolized



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/fitgem/helpers.rb', line 142

def self.symbolize_keys(obj)
  case obj
  when Array
    obj.inject([]){|res, val|
      res << case val
      when Hash, Array
        symbolize_keys(val)
      else
        val
      end
      res
    }
  when Hash
    obj.inject({}){|res, (key, val)|
      nkey = case key
      when String
        key.to_sym
      else
        key
      end
      nval = case val
      when Hash, Array
        symbolize_keys(val)
      else
        val
      end
      res[nkey] = nval
      res
    }
  else
    obj
  end
end

Instance Method Details

#accept_invite(requestor_id) ⇒ Hash

Accept a friend invite

Parameters:

  • requestor_id (String)

    The ID of the requestor that sent the friend request

Returns:

  • (Hash)


69
70
71
# File 'lib/fitgem/friends.rb', line 69

def accept_invite(requestor_id)
  respond_to_invite(requestor_id, true)
end

#activitiesHash

Get a list of all activities

The returned list includes all public activities plus any activities that the current user created and logged

Returns:

  • (Hash)

    Hash tree of all activities



13
14
15
# File 'lib/fitgem/activities.rb', line 13

def activities
  get("/activities.json")
end

#activities_on_date(date) ⇒ Hash

Get all of the logged activities on the supplied date

Parameters:

  • date (Datetime)

    the date to retrieve logged activities for

Returns:

  • (Hash)

    the activities logged on the supplied date



21
22
23
# File 'lib/fitgem/activities.rb', line 21

def activities_on_date(date)
  get("/user/#{@user_id}/activities/date/#{format_date(date)}.json")
end

#activity(id) ⇒ Hash

Get the detailed information for a single activity

Parameters:

  • id (Integer, String)

    The ID of the activity. This ID is typcially retrieved by browsing or searching the list of all available activities. Must be a numerical ID in either Integer or String format.

Returns:

  • (Hash)

    a hash structure containing detailed information about the activity



64
65
66
# File 'lib/fitgem/activities.rb', line 64

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

#activity_on_date_range(activity, start, finish) ⇒ Hash

Get activity information for a date range

Parameters:

  • activity (String)

    to retrieve information for

  • start (Datetime)

    of date range

  • end (Datetime)

    of date range

Returns:

  • (Hash)

    activity information for the given date range



31
32
33
# File 'lib/fitgem/activities.rb', line 31

def activity_on_date_range(activity, start, finish)
  get("/user/#{@user_id}/activities/#{activity}/date/#{format_date(start)}/#{format_date(finish)}.json")
end

#activity_statisticsHash

Get the activity statistics for the current user

Returns:

  • (Hash)

    Hash containing statistics for the activities that the user has logged



72
73
74
# File 'lib/fitgem/activities.rb', line 72

def activity_statistics
  get("/user/#{@user_id}/activities.json")
end

#add_alarm(opts) ⇒ Hash

Add a silent alarm to your profile

Parameters:

  • opts (Hash)

    Alarm options

Options Hash (opts):

  • device_id (Integer, String)

    The id of the device you would like to manage the alarm on

  • :time (String)

    Time of the alarm in the format XX:XX+XX:XX, time with timezone

  • :enabled (TrueClass, FalseClass)
  • :recurring (TrueClass, FalseClass)

    One time or recurring alarm

  • :weekDays (String)

    The days the alarm is active on as a list of comma separated values: MONDAY, WEDNESDAY, SATURDAY. For recurring only

  • :snoozeLength (Integer)

    Minutes between the alarms

  • :snoozeCount (Integer)

    Maximum snooze count

  • :label (String)

    Label for the alarm

Returns:

  • (Hash)

    Hash containing the alarm settings



19
20
21
22
# File 'lib/fitgem/alarms.rb', line 19

def add_alarm(opts)
  device_id = opts[:device_id]
  post("/user/#{@user_id}/devices/tracker/#{device_id}/alarms.json", opts)
end

#add_favorite_activity(activity_id) ⇒ Hash

Mark an activity as a favorite

Parameters:

  • :activity_id (String, Integer)

    The ID of the activity. This ID is typcially retrieved by browsing or searching the list of all available activities. Must be a numerical ID in either Integer or String format.

Returns:

  • (Hash)

    Empty hash if successfully marked as a favorite



152
153
154
# File 'lib/fitgem/activities.rb', line 152

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

#add_favorite_food(food_id) ⇒ Hash

Mark a food as a favorite

Parameters:

  • food_id (Integer, String)

    Food id

Returns:

  • (Hash)

    Empty denotes success



113
114
115
# File 'lib/fitgem/foods.rb', line 113

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

#authentication_request_token(opts = {}) ⇒ OAuth::RequestToken

Get an authentication request token

Parameters:

  • opts (Hash) (defaults to: {})

    Additional request token request data

Returns:

  • (OAuth::RequestToken)


174
175
176
177
# File 'lib/fitgem/client.rb', line 174

def authentication_request_token(opts={})
  consumer.options[:authorize_path] = '/oauth/authenticate'
  request_token(opts)
end

#authorize(token, secret, opts = {}) ⇒ OAuth::AccessToken

Finalize authentication and retrieve an oauth access token

Parameters:

  • token (String)

    The OAuth token

  • secret (String)

    The OAuth secret

  • opts (Hash) (defaults to: {})

    Additional data

Options Hash (opts):

  • :oauth_verifier (String)

    The verifier token sent by fitbit after user has logged in and authorized the application. Is included in the body of the callback request, if there was one. Otherwise is shown onscreen for the user to copy/paste back into your application. See https://wiki.fitbit.com/display/API/OAuth-Authentication-API for more information.

Returns:

  • (OAuth::AccessToken)

    An oauth access token; this is not needed to make API calls, since it is stored internally. It is returned so that you may make general OAuth calls if need be.



125
126
127
128
129
130
131
# File 'lib/fitgem/client.rb', line 125

def authorize(token, secret, opts={})
  request_token = OAuth::RequestToken.new(consumer, token, secret)
  @access_token = request_token.get_access_token(opts)
  @token = @access_token.token
  @secret = @access_token.secret
  @access_token
end

#badgesHash

Get a list of all badges earned

Returns:

  • (Hash)

    Hash containing an array of badges



7
8
9
# File 'lib/fitgem/badges.rb', line 7

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

#blood_pressure_on_date(date) ⇒ Hash

Get blood pressure log entries for the supplied date

Parameters:

  • date (DateTime, Date, String)

Returns:

  • (Hash)

    Hash containing an average of the days logs, and a list of all individual entries



12
13
14
# File 'lib/fitgem/blood_pressure.rb', line 12

def blood_pressure_on_date(date)
  get("/user/#{@user_id}/bp/date/#{format_date(date)}.json")
end

#body_fat(opts = {}) ⇒ Hash

Get a list of logged body fat entries for the specified period

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • date (Date)

    The date in the format YYYY-mm-dd.

  • base_date (Date)

    The end date when period is provided, in the format yyyy-MM-dd or today; range start date when a date range is provided.

  • period (String)

    The date range period. One of 1d, 7d, 30d, 1w, 1m

  • end_date (Date)

    Range end date when date range is provided. Note that period should not be longer than 31 day

Returns:

  • (Hash)

    A hash containing body fat log entries

Since:

  • v0.9.0



58
59
60
# File 'lib/fitgem/body_measurements.rb', line 58

def body_fat(opts = {})
  get determine_body_uri("/user/#{@user_id}/body/log/fat", opts)
end

#body_fat_goalHash

Retrieve the body fat goal of the current user

Returns:

  • (Hash)

    A hash containing the body fat goal

Since:

  • v0.9.0



67
68
69
# File 'lib/fitgem/body_measurements.rb', line 67

def body_fat_goal
  get("/user/#{@user_id}/body/log/fat/goal.json")
end

#body_measurements_on_date(date) ⇒ Hash

Get the body measurements logged on a specified date

Parameters:

  • date (DateTime, String)

    The date to retrieve body measurements for. May be a DateTime object or a String in ‘yyyy-MM-dd’ format.

Returns:

  • (Hash)

    A hash containing the logged body measurements along with any goals set for the current user.



14
15
16
# File 'lib/fitgem/body_measurements.rb', line 14

def body_measurements_on_date(date)
  get("/user/#{@user_id}/body/date/#{format_date(date)}.json")
end

#body_weight(opts = {}) ⇒ Hash

Get a list of logged body weight entries for the specified period

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • date (Date)

    The date in the format YYYY-mm-dd.

  • base_date (Date)

    The end date when period is provided, in the format yyyy-MM-dd or today; range start date when a date range is provided.

  • period (String)

    The date range period. One of 1d, 7d, 30d, 1w, 1m

  • end_date (Date)

    Range end date when date range is provided. Note that period should not be longer than 31 day

Returns:

  • (Hash)

    A hash containing body weight log entries

Since:

  • v0.9.0



31
32
33
# File 'lib/fitgem/body_measurements.rb', line 31

def body_weight(opts = {})
  get determine_body_uri("/user/#{@user_id}/body/log/weight", opts)
end

#body_weight_goalHash

Retrieve the body weight goal of the current user

Returns:

  • (Hash)

    A hash containing the start date, start weight and current weight.

Since:

  • v0.9.0



41
42
43
# File 'lib/fitgem/body_measurements.rb', line 41

def body_weight_goal
  get("/user/#{@user_id}/body/log/weight/goal.json")
end

#connected?Boolean

Get the current state of the client

Returns:

  • (Boolean)

    True if api calls may be made, false if not



157
158
159
# File 'lib/fitgem/client.rb', line 157

def connected?
  !@access_token.nil?
end

#construct_date_range_fragment(options) ⇒ Object

protected



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/fitgem/time_range.rb', line 73

def construct_date_range_fragment(options)
  range_str = "date/"
  if options[:base_date] && options[:period]
    range_str += "#{format_date(options[:base_date])}/#{options[:period]}"
  elsif options[:base_date] && options[:end_date]
    range_str += "#{format_date(options[:base_date])}/#{format_date(options[:end_date])}"
  else
    raise Fitgem::InvalidTimeRange, "Must supply either base_date and period OR base_date and end_date"
  end
  range_str
end

#create_food(opts) ⇒ Hash

Create a new food and add it to fitbit

Parameters:

  • opts (Hash)

    The data used to create the food

Options Hash (opts):

  • :name (String)

    Food name

  • :defaultFoodMeasurementUnitId (Integer, String)

    Unit id; typically retrieved via previous calls to #foods_on_date, #recent_foods, #favorite_foods, #frequent_foods, #find_food, or #foods_units

  • :defaultServingSize (Integer, String)

    The default serving size of the food

  • :calories (Integer, String)

    The number of calories in the default serving size

  • :formType (String)

    Form type; LIQUID or DRY - use FoodFormType#LIQUID or FoodFormType#DRY

  • :description (String)

    Food description

Returns:

  • (Hash)

    If successful, returns a hash containing confirmation of the food that was added



160
161
162
# File 'lib/fitgem/foods.rb', line 160

def create_food(opts)
  post("/foods.json", opts)
end

#create_or_update_body_fat_goal(fatPercentageGoal) ⇒ Object

Create or update a user’s body fat percentage goal

Parameters:

  • fatPercentageGoal (Decimal, Integer, String)

    Target body fat in %; in the format “X.XX” if a string

Since:

  • v0.9.0



165
166
167
168
# File 'lib/fitgem/body_measurements.rb', line 165

def create_or_update_body_fat_goal(fatPercentageGoal)
  opts = {fat: fatPercentageGoal}
  post("/user/#{@user_id}/body/log/fat/goal.json", opts)
end

#create_or_update_body_weight_goal(startDate, startWeight, goalWeight) ⇒ Object

Create or update a user’s weight goal

Parameters:

  • startDate (DateTime, Date, String)

    Weight goal start date; in the format “yyyy-MM-dd” if a string

  • startWeight (Decimal, Integer, String)

    Weight goal start weight; in the format “X.XX” if a string

  • goalWeight (Decimal, Integer, String)

    Weight goal target weight; in the format “X.XX” if a string

Since:

  • v0.9.0



154
155
156
157
# File 'lib/fitgem/body_measurements.rb', line 154

def create_or_update_body_weight_goal(startDate, startWeight, goalWeight)
  opts = {startDate: format_date(startDate), startWeight: startWeight, weight: goalWeight}
  post("/user/#{@user_id}/body/log/weight/goal.json", opts)
end

#create_or_update_daily_goal(opts) ⇒ Object

Create or update a user’s daily goal

Parameters:

  • :opts (Hash)
  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :type (Symbol)

    The type of goal to create or update; must be one of :steps, :distance, :floors, or :caloriesOut. REQUIRED

  • :value (Decimal, Integer, String)

    The goal value; in the format ‘X.XX’ if a string. REQUIRED

Since:

  • v0.9.0



170
171
172
173
174
175
176
177
178
179
180
# File 'lib/fitgem/activities.rb', line 170

def create_or_update_daily_goal(opts)
  unless opts[:type] && [:steps, :distance, :floors, :caloriesOut].include?(opts[:type])
    raise InvalidArgumentError, 'Must specify type in order to create or update a daily goal. One of (:steps, :distance, :floors, or :caloriesOut) is required.'
  end

  unless opts[:value]
    raise InvalidArgumentError, 'Must specify value of the daily goal to be created or updated.'
  end

  post("/user/#{@user_id}/activities/goals/daily.json", opts)
end

#create_or_update_weekly_goal(opts) ⇒ Object

Create or update a user’s weekly goal

Parameters:

  • :opts (Hash)
  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :type (Symbol)

    The type of goal to create or update; must be one of :steps, :distance, or :floors. REQUIRED

  • :value (Decimal, Integer, String)

    The goal value; in the format ‘X.XX’ if a string. REQUIRED

Since:

  • v0.9.0



192
193
194
195
196
197
198
199
200
201
202
# File 'lib/fitgem/activities.rb', line 192

def create_or_update_weekly_goal(opts)
  unless opts[:type] && [:steps, :distance, :floors].include?(opts[:type])
    raise InvalidArgumentError, 'Must specify type in order to create or update a weekly goal. One of (:steps, :distance, or :floors) is required.'
  end

  unless opts[:value]
    raise InvalidArgumentError, 'Must specify value of the weekly goal to be created or updated.'
  end

  post("/user/#{@user_id}/activities/goals/weekly.json", opts)
end

#create_subscription(opts) ⇒ Integer, Hash

Note:

You must check the HTTP response code to check the status of the request to add a subscription. See https://wiki.fitbit.com/display/API/Fitbit+Subscriptions+API for information about what the codes mean.

Creates a notification subscription

Parameters:

  • opts (Hash)

    The notification subscription data

Options Hash (opts):

  • :type (Symbol)

    The type of subscription (valid values are :activities, :foods, :sleep, :body, and :all). REQUIRED

  • :subscriptionId (Integer, String)

    The subscription id

Returns:

  • (Integer, Hash)

    An array containing the HTTP response code and a hash containing confirmation information for the subscription.

Since:

  • v0.4.0



29
30
31
32
# File 'lib/fitgem/notifications.rb', line 29

def create_subscription(opts)
  resp = raw_post make_subscription_url(opts.merge({:use_subscription_id => true})), EMPTY_BODY, make_headers(opts)
  [resp.code, extract_response_body(resp)]
end

#daily_goalsHash

Get the daily activity goals for the current user

Returns:

  • (Hash)

    Hash containing the calorie, distance, floors, and step goals for the current user

Since:

  • v0.9.0



97
98
99
# File 'lib/fitgem/activities.rb', line 97

def daily_goals
  goals
end

#data_by_time_range(resource_path, opts) ⇒ Hash

Gets historical resource data in the time range specified by options hash param. The time range can either be specified by :base_date and :end_date OR by using :base_date and a :period (supported periods are 1d, 7d, 30d, 1w, 1m, 3m, 6m, 1y, max)

Supported values for resource_path are:

Food:

/foods/log/caloriesIn
/foods/log/water

Activity:

/activities/log/calories
/activities/log/steps
/activities/log/distance
/activities/log/floors
/activities/log/elevation
/activities/log/minutesSedentary
/activities/log/minutesLightlyActive
/activities/log/minutesFairlyActive
/activities/log/minutesVeryActive
/activities/log/activeScore
/activities/log/activityCalories

Raw Tracker Activity:

/activities/tracker/calories
/activities/tracker/steps
/activities/tracker/distance
/activities/tracker/floors
/activities/tracker/elevation
/activities/tracker/activeScore

Sleep:

/sleep/startTime
/sleep/timeInBed
/sleep/minutesAsleep
/sleep/awakeningsCount
/sleep/minutesAwake
/sleep/minutesToFallAsleep
/sleep/minutesAfterWakeup
/sleep/efficiency

Body:

/body/weight
/body/bmi
/body/fat

Examples:

To get the floors traveled for the week of October 24th

data_by_time_range("/activities/log/floors", {:base_date => "2011-10-24", :period => "7d"})

To get all of the body weight logs from April 3rd until July 27th

data_by_time_range("/body/weight", {:base_date => "2011-03-03", :end_date => "2011-07-27"})

Parameters:

  • resource_path (String)

    The resource path to get data for (see note above)

  • opts (Hash)

    The options to specify date ranges, etc.

Options Hash (opts):

  • :base_date (DateTime, Date, String)

    The start date of the period

  • :end_date (DateTime, Date, String)

    The end date of the period

  • :period (String)

    The period (valid values: 1d, 7d, 30d, 1w, 1m, 3m, 6m, 1y, max)

Returns:

  • (Hash)

    Hash containing an array of objects that match your request



66
67
68
69
# File 'lib/fitgem/time_range.rb', line 66

def data_by_time_range(resource_path, opts)
  range = construct_date_range_fragment(opts)
  get("/user/#{@user_id}#{resource_path}/#{range}.json")
end

#decline_invite(requestor_id) ⇒ Hash

Decline a friend invite

Parameters:

  • requestor_id (String)

    The ID of the requestor that sent the friend request

Returns:

  • (Hash)


78
79
80
# File 'lib/fitgem/friends.rb', line 78

def decline_invite(requestor_id)
  respond_to_invite(requestor_id, false)
end

#delete_alarm(alarm_id, device_id) ⇒ Hash

Remove a silent alarm from your profile

Parameters:

  • alarm_id (Integer, String)

    The id of the alarm

  • device_id (Integer, String)

    The id of the device you would like to manage the alarm on

Returns:

  • (Hash)

    Empty hash denotes success



41
42
43
# File 'lib/fitgem/alarms.rb', line 41

def delete_alarm(alarm_id, device_id)
  delete("/user/#{@user_id}/devices/tracker/#{device_id}/alarms/#{alarm_id}.json")
end

#delete_blood_pressure_log(blood_pressure_log_id) ⇒ Hash

Delete logged blood pressure information

Parameters:

  • blood_pressure_log_id (Integer, String)

    The id of previously logged blood pressure data

Returns:

  • (Hash)

    Empty hash denotes success



44
45
46
# File 'lib/fitgem/blood_pressure.rb', line 44

def delete_blood_pressure_log(blood_pressure_log_id)
  delete("/user/-/bp/#{blood_pressure_log_id}.json")
end

#delete_body_fat_log(logId) ⇒ Object

Delete user’s body fat log entry with the given id

Parameters:

  • logId (Integer)

    The id of the body fat entry

Since:

  • v0.9.0



188
189
190
# File 'lib/fitgem/body_measurements.rb', line 188

def delete_body_fat_log(logId)
  delete("/user/#{@user_id}/body/log/fat/#{logId}.json")
end

#delete_body_weight_log(logId) ⇒ Object

Delete user’s body weight log entry with the given id

Parameters:

  • logId (Integer)

    The id of the body weight entry

Since:

  • v0.9.0



179
180
181
# File 'lib/fitgem/body_measurements.rb', line 179

def delete_body_weight_log(logId)
  delete("/user/#{@user_id}/body/log/weight/#{logId}.json")
end

#delete_heart_rate_log(heart_rate_log_id) ⇒ Hash

Delete logged heart rate information

Parameters:

  • heart_rate_log_id (Integer, String)

    The id of previously logged heart rate data

Returns:

  • (Hash)

    Empty hash denotes success



46
47
48
# File 'lib/fitgem/heart_rate.rb', line 46

def delete_heart_rate_log(heart_rate_log_id)
  delete("/user/-/heart/#{heart_rate_log_id}.json")
end

#delete_logged_activity(activity_log_id) ⇒ Hash

Delete a logged activity

Parameters:

  • :activity_log_id (String, Integer)

    The ID of a previously logged activity. Note that this is NOT the activity ID itself, but the ID of the logging of the activity (returned when you call #log_activity).

Returns:

  • (Hash)


215
216
217
# File 'lib/fitgem/activities.rb', line 215

def delete_logged_activity(activity_log_id)
  delete("/user/#{@user_id}/activities/#{activity_log_id}.json")
end

#delete_logged_food(food_log_id) ⇒ Hash

Remove a logged food entry

Parameters:

  • food_log_id (Integer, String)

    The ID of the food log, which is the ID returned in the response when #log_food is called.

Returns:

  • (Hash)

    Empty hash denotes success



126
127
128
# File 'lib/fitgem/foods.rb', line 126

def delete_logged_food(food_log_id)
  delete("/user/#{@user_id}/foods/log/#{food_log_id}.json")
end

#delete_sleep_log(sleep_log_id) ⇒ Hash

Delete logged sleep data

The sleep log id is the one returned when sleep data is recorded via #log_sleep.

Parameters:

  • Sleep (Integer, String)

    log id

Returns:

  • (Hash)

    Empty hash denotes successful deletion

Since:

  • v0.4.0



46
47
48
# File 'lib/fitgem/sleep.rb', line 46

def delete_sleep_log(sleep_log_id)
  delete("/user/#{@user_id}/sleep/#{sleep_log_id}.json")
end

#delete_water_log(water_log_id) ⇒ Hash

Delete logged water consumption

Parameters:

  • water_log_id (Integer, String)

    The id of previously logged water consumption

Returns:

  • (Hash)

    Empty hash denotes success



46
47
48
# File 'lib/fitgem/water.rb', line 46

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

#device_info(device_id) ⇒ Hash

Get the details about a specific device

The ID required for this call could be found by getting the list of devices with a call to #devices.

Parameters:

  • device_id (Integer, String)

    The ID of the device to get details for

Returns:

  • (Hash)

    Hash containing device information



23
24
25
# File 'lib/fitgem/devices.rb', line 23

def device_info(device_id)
  get("/user/#{@user_id}/devices/#{device_id}.json")
end

#devicesArray

Get a list of devices for the current account

Returns:

  • (Array)

    An array of hashes, each of which describes a device attaached to the current account



11
12
13
# File 'lib/fitgem/devices.rb', line 11

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

#favorite_activitiesArray

Get a list of activities marked as favorite by the user

Returns:

  • (Array)

    list of user-defined favorite activities



52
53
54
# File 'lib/fitgem/activities.rb', line 52

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

#favorite_foodsArray

Get a list of the favorite logged foods

Returns:

  • (Array)

    A list of foods, each of which is a Hash containing the food details



36
37
38
# File 'lib/fitgem/foods.rb', line 36

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

#find_food(query) ⇒ Array

Search the foods database

Parameters:

  • query (String)

    The query parameters for the food search

Returns:

  • (Array)

    A list of foods, each of which is a Hash containing detailed food information



65
66
67
# File 'lib/fitgem/foods.rb', line 65

def find_food(query)
  get("/foods/search.json?query=#{URI.escape(query)}")
end

#food_info(food_id) ⇒ Hash

Get detailed information for a food

Parameters:

  • food_id (Integer, String)

Returns:

  • (Hash)

    Hash containing detailed food information



73
74
75
# File 'lib/fitgem/foods.rb', line 73

def food_info(food_id)
  get("/foods/#{food_id}.json")
end

#foods_on_date(date) ⇒ Array

Get all foods logged on the supplied date

Parameters:

  • date (DateTime, Date, String)

Returns:

  • (Array)

    A list of the foods, each of which is a Hash containing the food details



12
13
14
# File 'lib/fitgem/foods.rb', line 12

def foods_on_date(date)
  get("/user/#{@user_id}/foods/log/date/#{format_date(date)}.json")
end

#foods_unitsArray

Get a list of all of the available food units

Returns:

  • (Array)

    List of food units



43
44
45
# File 'lib/fitgem/foods.rb', line 43

def foods_units
  get('/foods/units.json')
end

#format_date(date) ⇒ String

Format any of a variety of date types into the formatted string required when using the fitbit API.

The date parameter can take several different kind of objects: a DateTime object, a Date object, a Time object or a String object. Furthermore, the string object may be either the date in a preformatted string (“yyyy-MM-dd”), or it may be the string values “today” or “tomorrow”.

Parameters:

  • date (DateTime, Date, Time, String)

    The object to format into a date string

Returns:

  • (String)

    Date in “yyyy-MM-dd” string format

Raises:



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/fitgem/helpers.rb', line 17

def format_date(date)
  if date.is_a? String
    case date
      when 'today'
        return Date.today.strftime("%Y-%m-%d")
      when 'yesterday'
        return (Date.today-1).strftime("%Y-%m-%d")
      else
        unless date =~ /\d{4}\-\d{2}\-\d{2}/
          raise Fitgem::InvalidDateArgument, "Invalid date (#{date}), must be in yyyy-MM-dd format"
        end
        return date
    end
  elsif Date === date || Time === date || DateTime === date
    return date.strftime("%Y-%m-%d")
  else
    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}"
  end
end

#format_time(time, opts = {}) ⇒ String

Format any of a variety of time-related types into the formatted string required when using the fitbit API.

The time parameter can take several different kind of objects: a DateTime object, a Time object, or a String Object. Furthermore, the string object may be either the date in a preformatted string (“HH:mm”), or it may be the string value “now” to indicate that the time value used is the current localtime.

Parameters:

  • time (DateTime, Time, String)

    The object to format into a time string

  • opts (Hash) (defaults to: {})

    format time options

Options Hash (opts):

  • :include_timezone (TrueClass, FalseClass)

    Include timezone in the output or not

Returns:

  • (String)

    Date in “HH:mm” string format

Raises:

  • (Fitgem::InvalidTimeArgument)

    Raised when the parameter object is not a DateTime, Time, or a valid (“HH:mm” or “now”) string object



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

def format_time(time, opts = {})
  format = opts[:include_timezone] ? "%H:%M%:z" : "%H:%M"
  if time.is_a? String
    case time
      when 'now'
        return DateTime.now.strftime format
      else
        unless time =~ /^\d{2}\:\d{2}$/
          raise Fitgem::InvalidTimeArgument, "Invalid time (#{time}), must be in HH:mm format"
        end
        timezone = DateTime.now.strftime("%:z")
        return opts[:include_timezone] ? [ time, timezone ].join : time
    end
  elsif DateTime === time || Time === time
    return time.strftime format
  else
    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}"
  end
end

#frequent_activitiesArray

Get a list of the frequently logged activities

Returns:

  • (Array)

    list of frequently logged activities



38
39
40
# File 'lib/fitgem/activities.rb', line 38

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

#frequent_foodsArray

Get a list of the frequently logged foods

Returns:

  • (Array)

    A list of foods, each of which is a Hash containing the food details



28
29
30
# File 'lib/fitgem/foods.rb', line 28

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

#friendsArray

Get a list of the current user’s friends

Returns:

  • (Array)

    List of friends, each of which is a Hash containing friend information



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

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

#get_alarms(device_id) ⇒ Hash

Retrieve the silent alarms of your device

Parameters:

  • device_id (Integer, String)

    The id of the device you would like to manage the alarms of

Returns:

  • (Hash)

    Hash containing the alarms and it’s settings



30
31
32
# File 'lib/fitgem/alarms.rb', line 30

def get_alarms(device_id)
  get("/user/#{@user_id}/devices/tracker/#{device_id}/alarms.json")
end

#glucose_on_date(date) ⇒ Hash

Get glucose log entries for the supplied date

Parameters:

  • date (DateTime, Date, String)

Returns:

  • (Hash)

    Hash containing an average of the days logs, and a list of all individual entries



12
13
14
# File 'lib/fitgem/glucose.rb', line 12

def glucose_on_date(date)
  get("/user/#{@user_id}/glucose/date/#{format_date(date)}.json")
end

#goalsHash

Deprecated.

Use the daily_goals method; in v1.0.0 this method will be removed

Get the daily activity goals for the current user

Returns:

  • (Hash)

    Hash containing the calorie, distance, floors, and step goals for the current user



87
88
89
# File 'lib/fitgem/activities.rb', line 87

def goals
  get("/user/#{@user_id}/activities/goals/daily.json")
end

#heart_rate_on_date(date) ⇒ Hash

Get heart rate log entries for the supplied date

Parameters:

  • date (DateTime, Date, String)

Returns:

  • (Hash)

    Hash containing an average of the days logs, and a list of all individual entries



12
13
14
# File 'lib/fitgem/heart_rate.rb', line 12

def heart_rate_on_date(date)
  get("/user/#{@user_id}/heart/date/#{format_date(date)}.json")
end

#intraday_time_series(opts) ⇒ Hash

Get intraday time series data for the specified resource

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :resource (Symbol)

    The sub-resource you want to retrieve time series data for; must be one of :calories, :steps, :floors, or :elevation. This value is REQUIRED for all calls.

  • :date (String, Datetime, Date)

    The date to retrieve a time series on. This value is REQUIRED for all calls.

  • :detailLevel (String)

    The resolution of the time series data; must be one of “1min” or “15min”.

Returns:

  • (Hash)

    A hash containing time series data



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/fitgem/activities.rb', line 245

def intraday_time_series(opts)
  unless opts[:resource] && [:calories, :steps, :distance, :floors, :elevation].include?(opts[:resource])
    raise Fitgem::InvalidArgumentError, 'Must specify resource to fetch intraday time series data for. One of (:calories, :steps, :distance, :floors, or :elevation) is required.'
  end

  unless opts[:date]
    raise Fitgem::InvalidArgumentError, 'Must specify the date to fetch intraday time series data for.'
  end

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

  resource = opts.delete(:resource)
  date = format_date(opts.delete(:date))
  detail_level = opts.delete(:detailLevel)
  time_window_specified = opts[:startTime] || opts[:endTime]
  resource_path = "/user/#{@user_id}/activities/"

  if time_window_specified
    start_time = format_time(opts.delete(:startTime))
    end_time = format_time(opts.delete(:endTime))
    resource_path += "#{resource}/date/#{date}/1d/#{detail_level}/time/#{start_time}/#{end_time}.json"
  else
    resource_path += "#{resource}/date/#{date}/1d/#{detail_level}.json"
  end

  get(resource_path, opts)
end

#invite_friend(opts) ⇒ Hash

Create an invite for a user to connect with the current user as a friend

In order to invite a user, either an :email or a valid :userId must be supplied in the opts param hash.

Parameters:

  • opts (Hash)

    The invite data

Options Hash (opts):

  • :email (String)

    Email address of user to invite

  • :userId (String)

    User ID of the user to invite

Returns:

  • (Hash)


54
55
56
57
58
59
60
61
62
# File 'lib/fitgem/friends.rb', line 54

def invite_friend(opts)
  unless opts[:email] || opts[:user_id]
    raise InvalidArgumentError.new "invite_friend hash argument must include :email or :user_id"
  end
  translated_options = {}
  translated_options[:invitedUserEmail] = opts[:email] if opts[:email]
  translated_options[:invitedUserId] = opts[:user_id] if opts[:user_id]
  post("/user/#{@user_id}/friends/invitations.json", translated_options)
end

#label_for_measurement(measurement_type, respect_user_unit_preferences = true) ⇒ String

Fetch the correct label for the desired measurement unit.

The general use case for this method is that you are using the client for a specific user, and wish to get the correct labels for the unit measurements returned for that user.

A secondary use case is that you wish to get the label for a measurement given a unit system that you supply (by setting the Fitgem::Client.api_unit_system attribute).

In order for this method to get the correct value for the current user’s preferences, the client must have the ability to make API calls. If you respect_user_unit_preferences is passed as ‘true’ (or left as the default value) and the client cannot make API calls then an error will be raised by the method.

Parameters:

  • measurement_type (Symbol)

    The measurement type to fetch the label for

  • respect_user_unit_preferences (Boolean) (defaults to: true)

    Should the method fetch the current user’s specific measurement preferences and use those (true), or use the value set on Fitgem::Client.api_unit_system (false)

Returns:

  • (String)

    The string label corresponding to the measurement type and current api_unit_system.

Raises:

  • (Fitgem::ConnectionRequiredError)

    Raised when respect_user_unit_preferences is true but the client is not capable of making API calls.

  • (Fitgem::InvalidUnitSystem)

    Raised when the current value of Fitgem::Client.api_unit_system is not one of [ApiUnitSystem.US, ApiUnitSystem.UK, ApiUnitSystem.METRIC]

  • (Fitgem::InvalidMeasurementType)

    Raised when the supplied measurement_type is not one of

    :duration, :distance, :elevation, :height, :weight, :measurements, :liquids, :blood_glucose


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/fitgem/helpers.rb', line 96

def label_for_measurement(measurement_type, respect_user_unit_preferences=true)
  unless [:duration, :distance, :elevation, :height, :weight, :measurements, :liquids, :blood_glucose].include?(measurement_type)
    raise InvalidMeasurementType, "Supplied measurement_type parameter must be one of [:duration, :distance, :elevation, :height, :weight, :measurements, :liquids, :blood_glucose], current value is :#{measurement_type}"
  end

  selected_unit_system = api_unit_system

  if respect_user_unit_preferences
    unless connected?
      raise ConnectionRequiredError, "No connection to Fitbit API; one is required when passing respect_user_unit_preferences=true"
    end
    # Cache the unit systems for the current user
    @unit_systems ||= self.['user'].select {|key, value| key =~ /Unit$/ }

    case measurement_type
      when :distance
        selected_unit_system = @unit_systems["distanceUnit"]
      when :height
        selected_unit_system = @unit_systems["heightUnit"]
      when :liquids
        selected_unit_system = @unit_systems["waterUnit"]
      when :weight
        selected_unit_system = @unit_systems["weightUnit"]
      when :blood_glucose
        selected_unit_system = @unit_systems["glucoseUnit"]
      else
        selected_unit_system = api_unit_system
    end
  end

  # Fix the METRIC system difference
  selected_unit_system = Fitgem::ApiUnitSystem.METRIC if selected_unit_system == "METRIC"

  # Ensure the target unit system is one that we know about
  unless [ApiUnitSystem.US, ApiUnitSystem.UK, ApiUnitSystem.METRIC].include?(selected_unit_system)
    raise InvalidUnitSystem, "The select unit system must be one of [ApiUnitSystem.US, ApiUnitSystem.UK, ApiUnitSystem.METRIC], current value is #{selected_unit_system}"
  end

  unit_mappings[selected_unit_system][measurement_type]
end

#leaderboardHash

Get the leaderboard of friends’ weekly activities

Returns:

  • (Hash)

    Friends’ information



18
19
20
# File 'lib/fitgem/friends.rb', line 18

def leaderboard
  get("/user/#{@user_id}/friends/leaderboard.json")
end

#log_activity(opts) ⇒ Hash

Log an activity to fitbit

Parameters:

  • opts (Hash)

    The options used to log the activity for the current user

Options Hash (opts):

  • :activityId (String)

    The id of the activity, directory activity or intensity level activity. See activity types at http://wiki.fitbit.com/display/API/API-Log-Activity for more information. This value OR activityName is REQUIRED for all calls.

  • :activityName (String)

    The name of the activity to log. This value OR activityId is REQUIRED for alls.

  • :durationMillis (String, Integer)

    Activity duration in milliseconds. Must be a numeric value in Integer or String format. This value is REQUIRED for all calls.

  • :startTime (String)

    Activity start time, in the format “HH:mm” using hours and seconds. This value is REQUIRED for all calls.

  • :date (String)

    Activity date, in “yyyy-MM-dd” format. This value is REQUIRED for all calls.

  • :distance (String)

    Distance traveled, a string in the format “X.XX”. This value is REQUIRED when logging a directory activity, OPTIONAL otherwise.

  • :manualCalories (String, Integer)

    The number of calories to log against the activity. This value is REQUIRED if using the activityName, OPTIONAL otherwise.

  • :distanceUnit (String)

    One of ApiDistanceUnit. The “steps” units are available only for “Walking” and “Running” directory activities and their intensity levels

Returns:

  • (Hash)

    A hash with a summary of the logged activity



140
141
142
# File 'lib/fitgem/activities.rb', line 140

def log_activity(opts)
  post("/user/#{@user_id}/activities.json", opts)
end

#log_blood_pressure(opts) ⇒ Hash

Log blood pressure information to fitbit

Parameters:

  • opts (Hash)

    Heart rate data

Options Hash (opts):

  • :systolic (Integer, String)

    Systolic measurement (REQUIRED)

  • :diastolic (Integer, String)

    Diastolic measurement (REQUIRED)

  • :date (DateTime, Date, String)

    Log entry date (REQUIRED)

  • :time (DateTime, Time, String)

    Time of the measurement; hours and minutes in the format HH:mm

Returns:

  • (Hash)

    Summary of logged information



29
30
31
32
33
34
35
36
37
# File 'lib/fitgem/blood_pressure.rb', line 29

def log_blood_pressure(opts)
  unless opts[:systolic] && opts[:diastolic] && opts[:date]
    raise Fitgem::InvalidArgumentError, "Must include :systolic, :diastolic, and :date in order to log blood pressure data"
  end

  opts[:date] = format_date(opts[:date])
  opts[:time] = format_time(opts[:time]) if opts[:time]
  post("/user/#{@user_id}/bp.json", opts)
end

#log_body_fat(fatPercentage, date, opts = {}) ⇒ Object

Log body fat percentage

Parameters:

  • fatPercentage (Decimal, Integer, String)

    Body fat percentage to log, in format “X.XX” if a string

  • date (DateTime, Date, String)

    The date to log body fat percentage on, in format “yyyy-MM-dd” if a string

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :time (DateTime, Time, String)

    The time to log body fat percentage at, in “ HH:mm:ss” format if a String

Since:

  • v0.9.0



137
138
139
140
141
142
# File 'lib/fitgem/body_measurements.rb', line 137

def log_body_fat(fatPercentage, date, opts={})
  opts[:fat] = fatPercentage
  opts[:date] = format_date(date)
  opts[:time] = format_time(opts[:time]) if opts[:time]
  post("/user/#{@user_id}/body/fat.json", opts)
end

#log_body_measurements(opts) ⇒ Hash

Log body measurements to fitbit for the current user

At least ONE measurement item is REQUIRED in the call, as well as the date. All measurement values to be logged for the user must be either an Integer, a Decimal value, or a String in “X.XX” format. The measurement units used for the supplied measurements are based on which ApiUnitSystem is set in #api_unit_system.

Parameters:

  • opts (Hash)

    The options including data to log for the user

Options Hash (opts):

  • :weight (Integer, Decimal, String)

    Weight measurement

  • :waist (Integer, Decimal, String)

    Waist measurement

  • :thigh (Integer, Decimal, String)

    Thigh measurement

  • :neck (Integer, Decimal, String)

    Neck measurement

  • :hips (Integer, Decimal, String)

    Hips measurement

  • :forearm (Integer, Decimal, String)

    Forearm measurement

  • :fat (Integer, Decimal, String)

    Body fat percentage measurement

  • :chest (Integer, Decimal, String)

    Chest measurement

  • :calf (Integer, Decimal, String)

    Calf measurement

  • :bicep (Integer, Decimal, String)

    Bicep measurement

  • :date (DateTime, Date, String)

    Date to log measurements for; provided either as a DateTime, Date, or a String in “yyyy-MM-dd” format

Returns:

  • (Hash)

    Hash containing the key :body with an inner hash of all of the logged measurements

Since:

  • v0.4.0



102
103
104
105
106
# File 'lib/fitgem/body_measurements.rb', line 102

def log_body_measurements(opts)
  # Update the date (if exists)
  opts[:date] = format_date(opts[:date]) if opts[:date]
  post("/user/#{@user_id}/body.json", opts)
end

#log_food(opts) ⇒ Hash

Log food to fitbit for the current user

To log a food, either a foodId or foodName is REQUIRED.

Parameters:

  • opts (Hash)

    Food log options

Options Hash (opts):

  • :foodId (Integer, String)

    Food id

  • :foodName (String)

    Food entry name

  • :brandName (String)

    Brand name, valid only with foodName

  • :calories (Integer, String)

    Calories for this serving size, valid only with foodName

  • :mealTypeId (Integer, String)

    Meal type id; (1 - Breakfast, 2 - Morning Snack, 3 - Lunch, 4 - Afternoon Snack, 5 - Dinner, 7 - Anytime)

  • :unitId (Integer, String)

    Unit id; typically retrieved via previous calls to #foods_on_date, #recent_foods, #favorite_foods, #frequent_foods, #find_food, or #foods_units

  • :amount (Integer, Decimal, String)

    Amount consumed; if a String, must be in the format “X.XX”

  • :date (DateTime, Date, String)

    Log entry date; in the format “yyyy-MM-dd” if a String

  • :favorite (Boolean)

    Add food to favorites after creating the log

Returns:

  • (Hash)

    Hash containing confirmation of the logged food



105
106
107
# File 'lib/fitgem/foods.rb', line 105

def log_food(opts)
  post("/user/#{@user_id}/foods/log.json", opts)
end

#log_glucose(opts) ⇒ Hash

Log glucose information to fitbit

Parameters:

  • opts (Hash)

    Glucose data

Options Hash (opts):

  • :tracker (String)

    Glucose tracker name; predefined or custom tracker name (matches tracker name on the website) (this or :hba1c is REQUIRED)

  • :hba1c (String)

    HbA1c measurement; in the format “X.X” (this or :tracker is REQUIRED)

  • :glucose (String)

    Glucose measurement; in the format “X.X” (REQUIRED with :tracker, OPTIONAL otherwise)

  • :date (DateTime, Date, String)

    Log entry date (REQUIRED)

  • :time (DateTime, String)

    Time of the measurement; hours and minutes in the format HH:mm

Returns:

  • (Hash)

    Summary of logged information



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fitgem/glucose.rb', line 31

def log_glucose(opts)
  unless opts[:tracker] || opts[:hba1c]
    raise Fitgem::InvalidArgumentError, "Must include :tracker or :hba1c in order to log glucose data"
  end

  if opts[:tracker] && opts[:hba1c].nil? && opts[:glucose].nil?
    raise Fitgem::InvalidArgumentError, "Must include :glucose if using :tracker with no :hba1c value in order to log glucose data"
  end

  opts[:date] = format_date(opts[:date])
  opts[:time] = format_time(opts[:time]) if opts[:time]
  post("/user/#{@user_id}/glucose.json", opts)
end

#log_heart_rate(opts) ⇒ Hash

Log heart rate information to fitbit

Parameters:

  • opts (Hash)

    Heart rate data

Options Hash (opts):

  • :tracker (String)

    Heart rate tracker name; predefined or custom tracker name (matches tracker name on the website) (REQUIRED)

  • :heart_rate (Integer, String)

    Heart rate measurement (REQUIRED)

  • :date (DateTime, Date, String)

    Log entry date (REQUIRED)

  • :time (DateTime, String)

    Time of the measurement; hours and minutes in the format HH:mm

Returns:

  • (Hash)

    Summary of logged information



30
31
32
33
34
35
36
37
38
39
# File 'lib/fitgem/heart_rate.rb', line 30

def log_heart_rate(opts)
  unless opts[:tracker] && opts[:heart_rate] && opts[:date]
    raise Fitgem::InvalidArgumentError, "Must include :tracker, :heart_rate, and :date in order to lof heart rate data"
  end

  opts[:heartRate] = opts.delete :heart_rate
  opts[:date] = format_date(opts[:date])
  opts[:time] = format_time(opts[:time]) if opts[:time]
  post("/user/#{@user_id}/heart.json", opts)
end

#log_sleep(opts) ⇒ Hash

Log sleep data to fitbit for current user

All aspects of the options hash are REQUIRED.

Parameters:

  • opts (Hash)

    Sleep data to log

Options Hash (opts):

  • :startTime (String)

    Hours and minutes in the format “HH:mm”

  • :duration (Integer, String)

    Sleep duration, in miliseconds

  • :date (DateTime, Date, String)

    Sleep log entry date; if a string it must be in the yyyy-MM-dd format, or the values ‘today’ or ‘tomorrow’

Returns:

  • (Hash)

    Summary of the logged sleep data

Since:

  • v0.4.0



33
34
35
# File 'lib/fitgem/sleep.rb', line 33

def log_sleep(opts)
  post("/user/#{@user_id}/sleep.json", opts)
end

#log_water(opts) ⇒ Hash

Log water consumption to fitbit

Parameters:

  • opts (Hash)

    Water consumption data

Options Hash (opts):

  • :amount (Integer, Decimal, String)

    Amount of water consumed; if String must be in “X.X” format

  • :unit (String)

    Unit of water consumed; valid values are (“ml”, “fl oz” or “cup”)

  • :date (DateTime, Date, String)

    Date of water consumption

Returns:

  • (Hash)

    Summary of logged information



32
33
34
35
36
37
38
39
# File 'lib/fitgem/water.rb', line 32

def log_water(opts)
  unless opts[:amount] && opts[:date]
    raise Fitgem::InvalidArgumentError, "Must include both an :amount and :date to log water"
  end

  opts[:date] = format_date(opts[:date])
  post("/user/#{@user_id}/foods/log/water.json",opts)
end

#log_weight(weight, date, opts = {}) ⇒ Hash

Log weight to fitbit for the current user

Parameters:

  • weight (Integer, String)

    The weight to log, as either an integer or a string in “X.XX’” format

  • date (DateTime, String)

    The date the weight should be logged, as either a DateTime or a String in ‘yyyy-MM-dd’ format

Returns:

  • (Hash)

Since:

  • v0.9.0



121
122
123
124
# File 'lib/fitgem/body_measurements.rb', line 121

def log_weight(weight, date, opts={})
  opts[:time] = format_time(opts[:time]) if opts[:time]
  post("/user/#{@user_id}/body/log/weight.json", opts.merge(:weight => weight, :date => format_date(date)))
end

#make_headers(opts) ⇒ Hash (protected)

Create the headers hash for subscription management calls

This method both adds approriate headers given what is in the options hash, as well as removes extraneous hash entries that are not needed in the headers of the request sent to the API.

Parameters:

  • opts (Hash)

    The options for header creation

Options Hash (opts):

  • :subscriber_id (String)

    The subscriber id of the client application, created via http://dev.fitbit.com

Returns:

  • (Hash)

    The headers has to pass to the get/post/put/delete methods



83
84
85
86
87
88
89
# File 'lib/fitgem/notifications.rb', line 83

def make_headers(opts)
  headers = {}
  if opts[:subscriber_id]
    headers['X-Fitbit-Subscriber-Id'] = opts[:subscriber_id]
  end
  headers
end

#make_subscription_url(opts) ⇒ String (protected)

Create the subscription management API url

Parameters:

  • opts (Hash)

    The options on how to construct the subscription API url

Options Hash (opts):

  • :type (Symbol)

    The type of subscription; valid values are (:sleep, :body, :activities, :foods, and :all)

  • :use_subscription_id (Symbol)

    If true, then opts will be used in url construction

  • :subscription_id (String)

    The id of the subscription that the URL is for

Returns:

  • (String)

    The url to use for subscription management



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/fitgem/notifications.rb', line 103

def make_subscription_url(opts)
  validate_subscription_type opts[:type]
  path = if opts[:type] == :all
    ""
  else
    "/"+opts[:type].to_s
  end
  url = "/user/#{@user_id}#{path}/apiSubscriptions"
  if opts[:use_subscription_id]
    unless opts[:subscription_id]
      raise Fitgem::InvalidArgumentError, "Must include options[:subscription_id]"
    end
    url += "/#{opts[:subscription_id]}"
  end
  url += ".json"
end

#mealsHash

Get a hash containing the user’s meal informarion

Returns:

  • (Hash)

    Meal information

Since:

  • v0.9.0



52
53
54
# File 'lib/fitgem/foods.rb', line 52

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

#monthly_leaderboardHash

Deprecated.

Monthly leaderboards are no longer available from Fitbit. Please update to use #leaderboard

Get the leaderboard of friends’ weekly activities

Returns:

  • (Hash)

    Friends’ information

Raises:



27
28
29
# File 'lib/fitgem/friends.rb', line 27

def monthly_leaderboard
  raise DeprecatedApiError, 'Fitbit no longer exposes a monthly leaderboard. See https://wiki.fitbit.com/display/API/API-Get-Friends-Leaderboard for more information. Use #leaderboard() instead.'
end

#recent_activitiesArray

Get a list of recently logged activities

Returns:

  • (Array)

    list of of recently-logged activities



45
46
47
# File 'lib/fitgem/activities.rb', line 45

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

#recent_foodsArray

Get a list of the recently logged foods

Returns:

  • (Array)

    A list of foods, each of which is a Hash containing the food details



20
21
22
# File 'lib/fitgem/foods.rb', line 20

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

#reconnect(token, secret) ⇒ OAuth::AccessToken

Reconnect to the fitbit API with a stored oauth token and oauth secret

This method should be used if you have previously directed a user through the OAuth process and received a token and secret that were stored for later use. Using reconnect you can ‘reconstitute’ the access_token required for API calls without needing the user to go through the OAuth process again.

Parameters:

  • token (String)

    The stored OAuth token

  • secret (String)

    The stored OAuth secret

Returns:

  • (OAuth::AccessToken)

    An oauth access token; this is not needed to make API calls, since it is stored internally. It is returned so that you may make general OAuth calls if need be.



148
149
150
151
152
# File 'lib/fitgem/client.rb', line 148

def reconnect(token, secret)
  @token = token
  @secret = secret
  access_token
end

#remove_favorite_activity(activity_id) ⇒ Hash

Unmark an activity as a favorite

Parameters:

  • :activity_id (String, Integer)

    The activity ID of the activity to remove as a favorite.

Returns:

  • (Hash)


224
225
226
# File 'lib/fitgem/activities.rb', line 224

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

#remove_favorite_food(food_id) ⇒ Hash

Unmark a food as a favorite

Parameters:

  • food_id (Integer, String)

    Food id

Returns:

  • (Hash)

    Empty hash denotes success



134
135
136
# File 'lib/fitgem/foods.rb', line 134

def remove_favorite_food(food_id)
  delete("/user/#{@user_id}/foods/favorite/#{food_id}.json")
end

#remove_subscription(opts) ⇒ Integer, Hash

Note:

You must check the HTTP response code to check the status of the request to remove a subscription. See https://wiki.fitbit.com/display/API/Fitbit+Subscriptions+API for information about what the codes mean.

Removes a notification subscription

Parameters:

  • opts (Hash)

    The notification subscription data

Options Hash (opts):

  • :type (Symbol)

    The type of subscription to remove; valid values are :activities, :foods, :sleep, :body, and :all). REQUIRED

  • :subscription_id (Integer, String)

    The id of the subscription to remove.

  • :subscriber_id (Inteter, Stri)g)

    The subscriber id of the client application, created via http://dev.fitbit.com

Returns:

  • (Integer, Hash)

    An array containing the HTTP response code and a hash containing confirmation information for the subscription.

Since:

  • v0.4.0



50
51
52
53
# File 'lib/fitgem/notifications.rb', line 50

def remove_subscription(opts)
  resp = raw_delete make_subscription_url(opts.merge({:use_subscription_id => true})), make_headers(opts)
  [resp.code, extract_response_body(resp)]
end

#request_token(opts = {}) ⇒ OAuth::RequestToken

Get an oauth request token

Parameters:

  • opts (Hash) (defaults to: {})

    Request token request data; can be used to override default endpoint information for the oauth process

Returns:

  • (OAuth::RequestToken)


166
167
168
# File 'lib/fitgem/client.rb', line 166

def request_token(opts={})
  consumer.get_request_token(opts)
end

#sleep_on_date(date) ⇒ Array

Get sleep data for specified date

Parameters:

  • date (DateTime, Date, String)

Returns:

  • (Array)

    List of sleep items for the supplied date



11
12
13
# File 'lib/fitgem/sleep.rb', line 11

def sleep_on_date(date)
  get("/user/#{@user_id}/sleep/date/#{format_date(date)}.json")
end

#subscriptions(opts) ⇒ Hash

Get a list of all subscriptions

Parameters:

  • opts (Hash)

    Subscription query data

Options Hash (opts):

  • :type (Integer, String)

    The type of subscription (valid values are :activities, :foods, :sleep, :body, and :all). REQUIRED

Returns:

  • (Hash)

    Hash contain subscription information

Since:

  • v0.4.0



13
14
15
# File 'lib/fitgem/notifications.rb', line 13

def subscriptions(opts)
  get make_subscription_url(opts), make_headers(opts)
end

#unit_mappingsObject (protected)

Defined mappings for unit measurements to labels



179
180
181
182
183
184
185
# File 'lib/fitgem/helpers.rb', line 179

def unit_mappings
  {
    ApiUnitSystem.US => { :duration => "milliseconds", :distance => "miles", :elevation => "feet", :height => "inches", :weight => "pounds", :measurements => "inches", :liquids => "fl oz", :blood_glucose => "mg/dL" },
    ApiUnitSystem.UK => { :duration => "milliseconds", :distance => "kilometers", :elevation => "meters", :height => "centimeters", :weight => "stone", :measurements => "centimeters", :liquids => "mL", :blood_glucose => "mmol/l" },
    ApiUnitSystem.METRIC => { :duration => "milliseconds", :distance => "kilometers", :elevation => "meters", :height => "centimeters", :weight => "kilograms", :measurements => "centimeters", :liquids => "mL", :blood_glucose => "mmol/l" }
  }
end

#update_alarm(alarm_id, device_id, opts) ⇒ Hash

Update an existing alarm

Parameters:

  • alarm_id (Integer, String)

    The id of the alarm

  • device_id (Integer, String)

    The id of the device you would like to manage the alarm on

  • opts (Hash)

    Alarm settings

Options Hash (opts):

  • :time (DateTime, Time, String)

    Time of the alarm

  • :enabled (TrueClass, FalseClass)
  • :recurring (TrueClass, FalseClass)

    One time or recurring alarm

  • :weekDays (String)

    The days the alarm is active on as a list of comma separated values: MONDAY, WEDNESDAY, SATURDAY. For recurring only

  • :snoozeLength (Integer)

    Minutes between the alarms

  • :snoozeCount (Integer)

    Maximum snooze count

  • :label (String)

    Label for the alarm

Returns:

  • (Hash)

    Hash containing updated alarm settings



61
62
63
64
# File 'lib/fitgem/alarms.rb', line 61

def update_alarm(alarm_id, device_id, opts)
  opts[:time] = format_time opts[:time], include_timezone: true
  post("/user/#{@user_id}/devices/tracker/#{device_id}/alarms/#{alarm_id}.json", opts)
end

#update_user_info(opts) ⇒ Hash

Update profile information for current user

Parameters:

  • opts (Hash)

    User profile information

Options Hash (opts):

  • :gender (String)

    Gender, valid values are MALE, FEMALE, NA

  • :birthday (DateTime, Date, String)

    Birthday, in “yyyy-MM-dd” if a String

  • :height (Decimal, Integer, String)

    Height, in format “X.XX” if a String

  • :nickname (String)

    Nickname

  • :aboutMe (String)

    About Me description

  • :fullName (String)

    Full name

  • :country; (String)

    two-character code

  • :state; (String)

    two-character code

  • :city (String)
  • :strideLengthWalking (Decimal, Integer, String)

    Walking stride length, in format “X.XX” if a String

  • :strideLengthRunning (Decimal, Integer, String)

    Running stride length, in format “X.XX” if a String

  • :weightUnit (String)

    Default water unit on website (doesn’t affect API); one of (en_US, en_GB, “any” for METRIC)

  • :heightUnit (String)

    Default height/distance unit on website (doesn’t affect API); one of (en_US, “any” for METRIC)

  • :waterUnit (String)

    Default water unit on website (doesn’t affect API); one of (en_US, “any” for METRIC)

  • :glucoseUnit (String)

    Default glucose unit on website (doesn’t affect API); one of (en_US, “any” for METRIC)

  • :timezone (String)

    Time zone; in the format “America/Los Angelos”

  • :foodsLocale (String)

    Food Database Locale; in the format “xx_XX”

  • :locale (String)

    Locale of website (country/language); one of the locales, see wiki.fitbit.com/display/API/API-Update-User-Info for the currently supported values.

Returns:

  • (Hash)

    Hash containing updated profile information



46
47
48
49
# File 'lib/fitgem/users.rb', line 46

def (opts)
  opts[:birthday] = format_date(opts[:birthday]) if opts[:birthday]
  post("/user/#{@user_id}/profile.json", opts)
end

#user_info(opts = {}) ⇒ Hash

Get information aobut current user

Parameters:

  • opts (Hash) (defaults to: {})

    User information request data

Returns:

  • (Hash)

    User information



7
8
9
# File 'lib/fitgem/users.rb', line 7

def (opts={})
  get("/user/#{@user_id}/profile.json", opts)
end

#validate_subscription_type(subscription_type) ⇒ Boolean (protected)

Ensures that the type supplied is valid

Parameters:

  • subscription_type (Symbol)

    The type of subscription; valid values are (:sleep, :body, :activities, :foods, and :all)

Returns:

  • (Boolean)

Raises:



65
66
67
68
69
70
# File 'lib/fitgem/notifications.rb', line 65

def validate_subscription_type(subscription_type)
  unless subscription_type && SUBSCRIBABLE_TYPES.include?(subscription_type)
    raise Fitgem::InvalidArgumentError, "Invalid subscription type (valid values are #{SUBSCRIBABLE_TYPES.join(', ')})"
  end
  true
end

#water_on_date(date) ⇒ Hash

Get water log entries for the supplied date

Parameters:

  • date (DateTime, Date, String)

Returns:

  • (Hash)

    Hash containing the summary of the days logs, and a list of all individual entries



12
13
14
# File 'lib/fitgem/water.rb', line 12

def water_on_date(date)
  get("/user/#{@user_id}/foods/log/water/date/#{format_date(date)}.json")
end

#weekly_goalsHash

Get the weekly activity goals for the current user

Returns:

  • (Hash)

    Hash containing the distance, floors and step goals for the current user



105
106
107
# File 'lib/fitgem/activities.rb', line 105

def weekly_goals
  get("/user/#{@user_id}/activities/goals/weekly.json")
end

#weekly_leaderboardHash

Deprecated.

Please update to use #leaderboard

Get the leaderboard of friends’ weekly activities

Returns:

  • (Hash)

    Friends’ information

Raises:



36
37
38
# File 'lib/fitgem/friends.rb', line 36

def weekly_leaderboard
  raise DeprecatedApiError, 'Fitbit now only exposes a weekly leaderboard, Use #leaderboard() instead.'
end