basis-band 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +40 -10
- data/bin/basis-band +29 -3
- data/lib/basis-band.rb +55 -1
- data/lib/basis-band/api-auth.rb +1 -1
- data/lib/basis-band/api-fetch.rb +19 -0
- data/lib/basis-band/api-response-model.rb +12 -0
- data/lib/basis-band/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
# Basis API Access Gem
|
|
2
2
|
|
|
3
|
+
[](http://badge.fury.io/rb/basis-band)
|
|
4
|
+
|
|
3
5
|
Includes a command line tool that can be used to either capture the raw JSON
|
|
4
6
|
responses from app.mybasis.com, or to convert the metrics from the API
|
|
5
7
|
responses into CSV.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
There are two different versions of the API available at app.mybasis.com. The
|
|
12
|
+
V1 API (which holds most of the detailed data about heartrate and steps) uses a
|
|
13
|
+
user id, while the V2 API (which holds information about activities like
|
|
14
|
+
walking, running or biking state) uses an access token. You can use the -l
|
|
15
|
+
option to the command line tool to dump out both values.
|
|
16
|
+
Just pass the username and password joined with a colon (:).
|
|
17
|
+
Assuming your username is
|
|
11
18
|
'mikerowehl@gmail.com' and your password is 'pppppp' the command would look
|
|
12
19
|
like this:
|
|
13
20
|
|
|
14
21
|
```
|
|
15
22
|
> miker $ basis-band -l mikerowehl@gmail.com:pppppp
|
|
16
|
-
1234567890abcdef12345678
|
|
23
|
+
ID for V1 api: 1234567890abcdef12345678
|
|
24
|
+
token for V2 api: abcdef1234567890abcdef1234567890
|
|
17
25
|
```
|
|
18
26
|
|
|
19
|
-
In this example the userid returned is '1234567890abcdef12345678'
|
|
20
|
-
|
|
27
|
+
In this example the userid returned is '1234567890abcdef12345678' and the
|
|
28
|
+
token is 'abcdef1234567890abcdef1234567890'.
|
|
21
29
|
|
|
22
30
|
If you pass -u and -d options the raw text will be fetched from the API and
|
|
23
31
|
output on standard output:
|
|
@@ -50,7 +58,29 @@ t,state,skin_temp,heartrate,air_temp,calories,gsr,steps
|
|
|
50
58
|
...
|
|
51
59
|
```
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
That example includes instructions for finding your userid.
|
|
61
|
+
If you want the activity info for a given day pass in the access token using
|
|
62
|
+
-t and the date you want with -d:
|
|
56
63
|
|
|
64
|
+
```
|
|
65
|
+
> miker $ basis-band -t abcdef1234567890abcdef1234567890 -d 2013-11-05 | python -mjson.tool
|
|
66
|
+
{
|
|
67
|
+
"content": {
|
|
68
|
+
"activities": [
|
|
69
|
+
{
|
|
70
|
+
"actual_seconds": 1323,
|
|
71
|
+
"calories": 118.8,
|
|
72
|
+
"end_time": {
|
|
73
|
+
"iso": "2013-11-05T22:38:25Z",
|
|
74
|
+
"time_zone": {
|
|
75
|
+
"name": "America/Los_Angeles",
|
|
76
|
+
"offset": -480
|
|
77
|
+
},
|
|
78
|
+
"timestamp": 1383691105
|
|
79
|
+
},
|
|
80
|
+
"heart_rate": {
|
|
81
|
+
"avg": null,
|
|
82
|
+
"max": null,
|
|
83
|
+
"min": null
|
|
84
|
+
},
|
|
85
|
+
...
|
|
86
|
+
```
|
data/bin/basis-band
CHANGED
|
@@ -26,21 +26,47 @@ OptionParser.new do |opts|
|
|
|
26
26
|
opts.on("-c", "--[no-]csv", "Output CSV format") do |c|
|
|
27
27
|
options[:csv] = c
|
|
28
28
|
end
|
|
29
|
+
opts.on("-C", "--cachedir DIR", "Directory to use to cache results") do |c|
|
|
30
|
+
options[:cachedir] = c
|
|
31
|
+
end
|
|
29
32
|
opts.on("-l", "--login username:password", "Login and print user id") do |l|
|
|
30
33
|
options[:login] = l
|
|
31
34
|
end
|
|
35
|
+
opts.on("-s", "--summary", "Summarize all the data from the cache") do |s|
|
|
36
|
+
options[:summary] = s
|
|
37
|
+
end
|
|
38
|
+
opts.on("-t", "--token TOKEN", "Token for v2 API access") do |t|
|
|
39
|
+
options[:token] = t
|
|
40
|
+
end
|
|
32
41
|
end.parse!
|
|
33
42
|
|
|
34
43
|
if options[:login]
|
|
35
44
|
(u,p) = options[:login].split(":", 2)
|
|
36
|
-
|
|
37
|
-
puts
|
|
45
|
+
token, id = ApiAuth.new.login(u, p)
|
|
46
|
+
puts "ID for V1 api: #{id}"
|
|
47
|
+
puts "token for V2 api: #{token}"
|
|
48
|
+
exit
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
b = BasisBand.new(options[:userid])
|
|
52
|
+
if options[:cachedir]
|
|
53
|
+
b.set_cache_dir(options[:cachedir])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if options[:summary]
|
|
57
|
+
all = b.data_for_all
|
|
58
|
+
all.each do |k,v|
|
|
59
|
+
puts "Data for day #{k}"
|
|
60
|
+
t = ApiResponseModel.new(v).summary
|
|
61
|
+
puts " average air_temp = #{t["air_temp"]["avg"]}"
|
|
62
|
+
end
|
|
38
63
|
exit
|
|
39
64
|
end
|
|
40
65
|
|
|
41
66
|
if options[:userid] and options[:date]
|
|
42
|
-
b = BasisBand.new(options[:userid])
|
|
43
67
|
raw = b.data_for_day(options[:date])
|
|
68
|
+
elsif options[:token] and options[:date]
|
|
69
|
+
raw = b.fetch_activities_for_day(options[:date], options[:token])
|
|
44
70
|
else
|
|
45
71
|
raw = $stdin.read
|
|
46
72
|
end
|
data/lib/basis-band.rb
CHANGED
|
@@ -4,12 +4,66 @@ require 'basis-band/api-auth'
|
|
|
4
4
|
require 'basis-band/api-response-model'
|
|
5
5
|
|
|
6
6
|
class BasisBand
|
|
7
|
+
@cache_dir = nil
|
|
8
|
+
|
|
7
9
|
def initialize(userid)
|
|
8
10
|
@userid = userid
|
|
9
11
|
end
|
|
10
12
|
|
|
13
|
+
def set_cache_dir(dir)
|
|
14
|
+
@cache_dir = dir
|
|
15
|
+
end
|
|
16
|
+
|
|
11
17
|
def data_for_day(date)
|
|
18
|
+
r = cached_value_for_day(date)
|
|
19
|
+
if !r
|
|
20
|
+
r = fetch_value_for_day(date)
|
|
21
|
+
end
|
|
22
|
+
r
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def data_for_all
|
|
26
|
+
all = all_cache_files.collect do |f|
|
|
27
|
+
d = File.basename(f, ".json")
|
|
28
|
+
[d, cached_value_for_day(d)]
|
|
29
|
+
end
|
|
30
|
+
Hash[all]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def cache_filename(date)
|
|
34
|
+
File.join(@cache_dir, date + ".json")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def all_cache_files()
|
|
38
|
+
Dir[File.join(@cache_dir, "*.json")]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def cached_value_for_day(date)
|
|
42
|
+
raw = nil
|
|
43
|
+
begin
|
|
44
|
+
File.open(cache_filename(date), "r") { |f|
|
|
45
|
+
raw = f.read
|
|
46
|
+
}
|
|
47
|
+
rescue
|
|
48
|
+
# ignore exception
|
|
49
|
+
end
|
|
50
|
+
raw
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def fetch_value_for_day(date)
|
|
54
|
+
f = ApiFetch.new()
|
|
55
|
+
raw = f.get_day(@userid, date)
|
|
56
|
+
if raw && @cache_dir
|
|
57
|
+
File.open(cache_filename(date), "w") { |f|
|
|
58
|
+
f.write(raw)
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
raw
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def fetch_activities_for_day(date, token)
|
|
12
65
|
f = ApiFetch.new()
|
|
13
|
-
f.
|
|
66
|
+
raw = f.get_activities(token, date)
|
|
67
|
+
raw
|
|
14
68
|
end
|
|
15
69
|
end
|
data/lib/basis-band/api-auth.rb
CHANGED
data/lib/basis-band/api-fetch.rb
CHANGED
|
@@ -31,6 +31,10 @@ class ApiFetch
|
|
|
31
31
|
"https://app.mybasis.com/api/v1/chart/#{userid}.json?#{f}&#{m}"
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def activities_url(date)
|
|
35
|
+
"https://app.mybasis.com/api/v2/users/me/days/#{date}/activities?expand=activities&type=run,walk,bike"
|
|
36
|
+
end
|
|
37
|
+
|
|
34
38
|
def https_fetch(url)
|
|
35
39
|
u = URI.parse(url)
|
|
36
40
|
http = Net::HTTP.new(u.host, u.port)
|
|
@@ -40,8 +44,23 @@ class ApiFetch
|
|
|
40
44
|
http.request(request).body
|
|
41
45
|
end
|
|
42
46
|
|
|
47
|
+
def https_fetch_v2(url, token)
|
|
48
|
+
u = URI.parse(url)
|
|
49
|
+
http = Net::HTTP.new(u.host, u.port)
|
|
50
|
+
http.use_ssl = true
|
|
51
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
52
|
+
request = Net::HTTP::Get.new(u.request_uri)
|
|
53
|
+
request.add_field('Cookie', "access_token=#{token}; scope=login")
|
|
54
|
+
http.request(request).body
|
|
55
|
+
end
|
|
56
|
+
|
|
43
57
|
def get_day(userid, date, summary = true, body_states = true, skip_metrics = [])
|
|
44
58
|
res = https_fetch(url(userid, date, summary, body_states, skip_metrics))
|
|
45
59
|
res
|
|
46
60
|
end
|
|
61
|
+
|
|
62
|
+
def get_activities(token, date)
|
|
63
|
+
res = https_fetch_v2(activities_url(date), token)
|
|
64
|
+
res
|
|
65
|
+
end
|
|
47
66
|
end
|
|
@@ -38,4 +38,16 @@ class ApiResponseModel
|
|
|
38
38
|
hash_for_minute(x)
|
|
39
39
|
}
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
def metric_summary(metric)
|
|
43
|
+
{"avg" => @json["metrics"][metric]["avg"]}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def summary
|
|
47
|
+
res = {}
|
|
48
|
+
for m in @json["metrics"].keys
|
|
49
|
+
res[m] = metric_summary(m)
|
|
50
|
+
end
|
|
51
|
+
res
|
|
52
|
+
end
|
|
41
53
|
end
|
data/lib/basis-band/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: basis-band
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-
|
|
12
|
+
date: 2013-11-06 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: json
|