Skip to content

Instantly share code, notes, and snippets.

@kenkeiter
Created August 20, 2014 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenkeiter/1827a1da743494be29b4 to your computer and use it in GitHub Desktop.
Save kenkeiter/1827a1da743494be29b4 to your computer and use it in GitHub Desktop.
Display RescueTime productivity on the Quirky Nimbus
require 'rest_client'
require 'json'
require 'pp'
class RescueTimeProfile
API_BASE_URL = 'https://www.rescuetime.com/anapi'
TIME_SCORE_SCALE = {
2 => 1,
1 => 0.75,
0 => 0.50,
-1 => 0,
-2 => 0
}
def initialize(api_key)
@api_key = api_key
end
def productivity
query_params = {
key: @api_key,
format: 'json',
op: 'select',
vn: 0,
pv: 'interval',
rs: 'day',
rb: Time.now.strftime('%Y-%m-%d'),
re: (Time.now + (60 * 60 * 24)).strftime('%Y-%m-%d'),
rk: 'productivity'
}
resp = RestClient.get(API_BASE_URL + "/data", params: query_params)
data = JSON.parse(resp)
# go through and parse the data
total_seconds = 0
productive_seconds = 0
data['rows'].each do |row|
seconds = row[1].to_i
score = row[3].to_i
total_seconds += seconds
productive_seconds += seconds * TIME_SCORE_SCALE.fetch(score)
end
return (100 * productive_seconds / total_seconds).round
end
end
class NimbusDial
def initialize(nimbus, state = {})
@nimbus = nimbus
@dial_id = state['dial_id']
@state = {
'name' => state['name'],
'value' => state['value'],
'position' => state['position'].to_f,
'label' => state['label'],
'labels' => state['labels'],
'brightness' => state['brightness'].to_i,
'channel_configuration' => {'channel_id' => 10},
'dial_index' => state['dial_index'].to_i
}
end
def update(opts = {})
@state.merge!(opts.inject({}){ |memo,(k,v)| memo[k.to_s] = v; memo })
@nimbus.request(:put, "/dials/#{@dial_id}", @state)
end
end
class Nimbus
attr_reader :dials
API_BASE_URL = "https://winkapi.quirky.com"
def initialize(opts)
@opts = opts
@dials = []
self.initialize_dials
end
def reauthorize!
creds = {
'client_id' => @opts.fetch(:client_id),
'client_secret' => @opts.fetch(:client_secret),
'username' => @opts.fetch(:username),
'password' => @opts.fetch(:password),
'grant_type' => 'password'
}
headers = {:content_type => 'application/json'}
response = RestClient.post(
Nimbus::API_BASE_URL + '/oauth2/token',
creds.to_json,
headers)
response_data = JSON.parse(response)
@access_token = response_data['access_token']
@refresh_token = response_data['refresh_token']
end
def request(_type, endpoint, data = nil, _headers = {}, &block)
attempts = 0
type = _type.downcase.to_sym
begin
headers = {
authorization: "Bearer #{@access_token}",
content_type: 'application/json'
}.merge!(_headers)
case type
when :get
resp = RestClient.get(API_BASE_URL + endpoint, {params: data}.merge!(headers))
return JSON.parse(resp)
when :post
resp = RestClient.post(API_BASE_URL + endpoint, data.to_json, headers)
return JSON.parse(resp)
when :put
resp = RestClient.put(API_BASE_URL + endpoint, data.to_json, headers)
return JSON.parse(resp)
when :delete
resp = RestClient.delete(API_BASE_URL + endpoint, headers)
return JSON.parse(resp)
end
attempts += 1
rescue RestClient::Exception => e
if e.http_code == 401
self.reauthorize!
retry if attempts < 2
else
raise e
end
end
end
def initialize_dials
# fetch all Wink devices
devices = self.request(:get, '/users/me/wink_devices')
clock = devices["data"].select{|d| d['name'] == "Nimbus" }.first
# get the first clock, and add each of its dials
@dials = []
clock['dials'].each do |dial|
@dials[dial['dial_index'].to_i] = NimbusDial.new(self, dial)
end
return @dials
end
end
#####
# APP
#####
rescue_time = RescueTimeProfile.new('your_api_key')
clock = Nimbus.new(
client_id: 'your_client_id',
client_secret: 'your_client_secret',
username: 'you@example.com',
password: 'your_password'
)
loop do
current_productivity = rescue_time.productivity
clock.dials[1].update(
value: current_productivity,
position: 360 * (current_productivity * 0.01),
label: "PROD. SCORE",
labels: ["#{current_productivity}%", "PRODUCTIVE"]
)
puts "#{Time.now} - Updated productivity: #{current_productivity}%"
sleep(60 * 15) # sleep 15 minutes, and refresh
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment