embulk-input-healthplanet 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a6559e9ab461422fdb84aae86853330560023ae9
4
+ data.tar.gz: b67eb584c925f946fa95a2e038a2cf82dc389062
5
+ SHA512:
6
+ metadata.gz: f3f1233856605a544b0e10f74d26510c1f6b038f868fe0ca621a2716a41ffbaa6aeabb726fb54387e5f47c1e47007ad421361f81a559ac9e06a62bd0d59bdb3f
7
+ data.tar.gz: c1c046e24a1f549b2d7185bf999814b97924946f6110640e91db0e31369389ec5547ac27091f578270ccd400588fdc82750ece5a2930072b7bed24ae5c31ca5f
@@ -0,0 +1,5 @@
1
+ *~
2
+ /pkg/
3
+ /tmp/
4
+ /.bundle/
5
+ /Gemfile.lock
@@ -0,0 +1 @@
1
+ jruby-9.0.0.0
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org/'
2
+ gemspec
@@ -0,0 +1,21 @@
1
+
2
+ MIT License
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ # Healthplanet input plugin for Embulk
2
+
3
+ Retrieve your innerscan data through Health Planet API v1.
4
+
5
+ This plugin only supports 'innerscan' scope. Other scopes such as 'sphygmomanometer', 'pedometer' and 'smug' are not supported.
6
+
7
+ ## Overview
8
+
9
+ * **Plugin type**: input
10
+ * **Resume supported**: no
11
+ * **Cleanup supported**: no
12
+ * **Guess supported**: no
13
+
14
+ ## Install
15
+
16
+ ```
17
+ $ embulk gem install embulk-input-healthplanet
18
+ ```
19
+
20
+ ## Configuration
21
+
22
+ - **login_id**: Login ID for Health Planet website (string, required)
23
+ - **password**: Password for Health Planet website (string, required)
24
+ - **client_id**: Client ID for your client application using this plugin (string, required)
25
+ - **client_secret**: Client Secret for your client application using this plugin (string, required)
26
+ - **next_from**: Retrieve data from the time '%Y-%m-%d %H:%M:%S' (string, default: 1 year ago)
27
+
28
+ ## Example
29
+
30
+ ```yaml
31
+ in:
32
+ type: healthplanet
33
+ login_id: example_login_id
34
+ password: example_password
35
+ client_id: example.apps.healthplanet.jp
36
+ client_secret: 12345678901123-ExampleClientSecret
37
+ next_from: '2015-01-01 00:00:00'
38
+ exec: {}
39
+ out:
40
+ type: file
41
+ path_prefix: ./healthplanet/
42
+ file_ext: csv
43
+ formatter:
44
+ type: csv
45
+ default_timezone: 'Asia/Tokyo'
46
+ ```
47
+
48
+ If only new records are required, please use -o option as follows:
49
+
50
+ ```
51
+ $ embulk run config.yml -o config.yml
52
+ ```
53
+
54
+ ## References
55
+
56
+ * [Health Planet API Specification Ver. 1.0 (Japanese)](http://www.healthplanet.jp/apis/api.html)
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task default: :build
@@ -0,0 +1,24 @@
1
+
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "embulk-input-healthplanet"
4
+ spec.version = "1.0.0"
5
+ spec.authors = ["Masahiro Yoshizawa"]
6
+ spec.summary = "Healthplanet input plugin for Embulk"
7
+ spec.description = "Retrieve your innerscan data through Health Planet API v1."
8
+ spec.email = ["muziyoshiz@gmail.com"]
9
+ spec.licenses = ["MIT"]
10
+ spec.homepage = "https://github.com/muziyoshiz/embulk-input-healthplanet"
11
+
12
+ spec.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
13
+ spec.test_files = spec.files.grep(%r{^(test|spec)/})
14
+ spec.require_paths = ["lib"]
15
+
16
+ #spec.add_dependency 'YOUR_GEM_DEPENDENCY', ['~> YOUR_GEM_DEPENDENCY_VERSION']
17
+ spec.add_development_dependency 'embulk', ['~> 0.7.10']
18
+ spec.add_development_dependency 'bundler', ['~> 1.0']
19
+ spec.add_development_dependency 'rake', ['>= 10.0']
20
+
21
+ spec.add_dependency 'faraday', ['~> 0.8.11']
22
+ spec.add_dependency 'faraday-cookie_jar', ['~> 0.0.6']
23
+ spec.add_dependency 'oga', ['~> 2.0.0']
24
+ end
@@ -0,0 +1,245 @@
1
+ require 'faraday'
2
+ require 'faraday-cookie_jar'
3
+ require 'oga'
4
+ require 'nkf'
5
+ require 'json'
6
+ require 'time'
7
+
8
+ module Embulk
9
+ module Input
10
+
11
+ class Healthplanet < InputPlugin
12
+ Plugin.register_input("healthplanet", self)
13
+
14
+ # Default redirect URI for Client Application
15
+ REDIRECT_URI = 'https://www.healthplanet.jp/success.html'
16
+
17
+ # Default scope
18
+ DEFAULT_SCOPE = 'innerscan'
19
+
20
+ # Default response type
21
+ DEFAULT_RESPONSE_TYPE = 'code'
22
+
23
+ # Default grant type
24
+ DEFAULT_GRANT_TYPE = 'authorization_code'
25
+
26
+ # All tags for innerscan
27
+ ALL_TAGS = '6021,6022,6023,6024,6025,6026,6027,6028,6029'
28
+
29
+ # Health Planet API can response only in 3 months
30
+ RESPONSE_INTERVAL = 60*60*24*30*3
31
+
32
+ # embulk-input-healthplanet retrieves data from one year ago by default
33
+ # If you need data more than one year ago, please set 'next_from' parameter
34
+ DEFAULT_FROM_TIME = 60*60*24*365
35
+
36
+ def self.transaction(config, &control)
37
+ # configuration code:
38
+ task = {
39
+ # Account for Health Planet
40
+ 'login_id' => config.param('login_id', :string),
41
+ 'password' => config.param('password', :string),
42
+ # Credential for embulk-input-healthplanet, application type "Client Application"
43
+ 'client_id' => config.param('client_id', :string),
44
+ 'client_secret' => config.param('client_secret', :string),
45
+ # This plugin retrieves new data after this time
46
+ 'next_from' => config.param('next_from', :string, :default => nil)
47
+ }
48
+
49
+ columns = [
50
+ Column.new(0, 'time', :timestamp),
51
+ Column.new(1, 'model', :string),
52
+ Column.new(2, 'weight', :double),
53
+ Column.new(3, 'body fat %', :double),
54
+ Column.new(4, 'muscle mass', :double),
55
+ Column.new(5, 'muscle score', :long),
56
+ Column.new(6, 'visceral fat level 2', :double),
57
+ Column.new(7, 'visceral fat level 1', :long),
58
+ Column.new(8, 'basal metabolic rate', :long),
59
+ Column.new(9, 'metabolic age', :long),
60
+ Column.new(10, 'estimated bone mass', :double),
61
+ # Not supported by Health Planet API Ver. 1.0
62
+ # Column.new(11, 'body water mass', :string),
63
+ ]
64
+
65
+ resume(task, columns, 1, &control)
66
+ end
67
+
68
+ def self.resume(task, columns, count, &control)
69
+ task_reports = yield(task, columns, count)
70
+
71
+ next_config_diff = task_reports.first
72
+ return next_config_diff
73
+ end
74
+
75
+ def init
76
+ login_id = task['login_id']
77
+ password = task['password']
78
+ client_id = task['client_id']
79
+ client_secret = task['client_secret']
80
+ if task['next_from']
81
+ @next_from = Time.strptime(task['next_from'], '%Y-%m-%d %H:%M:%S')
82
+ end
83
+
84
+ # Setup connection
85
+ @conn = Faraday.new(:url => 'https://www.healthplanet.jp') do |faraday|
86
+ faraday.request :url_encoded
87
+ faraday.response :logger
88
+ faraday.use :cookie_jar
89
+ faraday.adapter Faraday.default_adapter
90
+ end
91
+
92
+ # Request Authentication page: /oauth/auth
93
+ response = @conn.get do |req|
94
+ req.url '/oauth/auth'
95
+ req.params[:client_id] = client_id
96
+ req.params[:redirect_uri] = REDIRECT_URI
97
+ req.params[:scope] = DEFAULT_SCOPE
98
+ req.params[:response_type] = DEFAULT_RESPONSE_TYPE
99
+ end
100
+
101
+ # Login and set session information
102
+ response = @conn.post 'login_oauth.do', { :loginId => login_id, :passwd => password, :send => '1', :url => "https://www.healthplanet.jp/oauth/auth?client_id=#{client_id}&redirect_uri=#{REDIRECT_URI}&scope=#{DEFAULT_SCOPE}&response_type=#{DEFAULT_RESPONSE_TYPE}" }
103
+
104
+ unless response.status == 302
105
+ # TODO return error in Embulk manner
106
+ print "Login failure\n"
107
+ end
108
+
109
+ # Get auth page again with JSESSIONID
110
+ response = @conn.get do |req|
111
+ req.url '/oauth/auth'
112
+ req.params[:client_id] = client_id
113
+ req.params[:redirect_uri] = REDIRECT_URI
114
+ req.params[:scope] = DEFAULT_SCOPE
115
+ req.params[:response_type] = DEFAULT_RESPONSE_TYPE
116
+ end
117
+
118
+ # Read oauth_token
119
+ document = Oga.parse_html(NKF.nkf('-Sw', response.body))
120
+ oauth_token = document.at_xpath('//input[@name="oauth_token"]').get('value')
121
+
122
+ # Post /oauth/approval.do
123
+ response = @conn.post '/oauth/approval.do', { :approval => 'true', :oauth_token => oauth_token }
124
+
125
+ # Read code
126
+ document = Oga.parse_html(NKF.nkf('-Sw', response.body))
127
+ code = document.at_xpath('//textarea[@id="code"]').text
128
+
129
+ # Get request token
130
+ response = @conn.post do |req|
131
+ req.url '/oauth/token'
132
+ req.params[:client_id] = client_id
133
+ req.params[:client_secret] = client_secret
134
+ req.params[:redirect_uri] = REDIRECT_URI
135
+ req.params[:code] = code
136
+ req.params[:grant_type] = DEFAULT_GRANT_TYPE
137
+ end
138
+
139
+ tokens = JSON.parse(response.body)
140
+ @access_token = tokens['access_token']
141
+ end
142
+
143
+ def run
144
+ from = @next_from.nil? ? (Time.now - DEFAULT_FROM_TIME) : @next_from
145
+ last_date = nil
146
+
147
+ while from < Time.now
148
+ to = from + RESPONSE_INTERVAL
149
+ date = innerscan(from, to)
150
+ # Update last_date if any data exists
151
+ last_date = date if date
152
+
153
+ # Next request must start from 1 minute later to avoid redundant data
154
+ from = to + 60
155
+ end
156
+
157
+ page_builder.finish
158
+
159
+ task_report = {}
160
+ unless preview? or last_date.nil?
161
+ # Next request must start from 1 minute later to avoid redundant data
162
+ task_report = { :next_from => (last_date + 60).strftime('%Y-%m-%d %H:%M:%S') }
163
+ end
164
+ return task_report
165
+ end
166
+
167
+ def innerscan(from = nil, to = nil)
168
+ response = @conn.get do |req|
169
+ req.url 'status/innerscan.json'
170
+ req.params[:access_token] = @access_token
171
+ # 0: registered time, 1: measured time
172
+ req.params[:date] = 1
173
+ req.params[:from] = from.strftime('%Y%m%d%H%M%S') unless from.nil?
174
+ req.params[:to] = to.strftime('%Y%m%d%H%M%S') unless to.nil?
175
+ req.params[:tag] = ALL_TAGS
176
+ end
177
+
178
+ data = JSON.parse(response.body)
179
+
180
+ result = {}
181
+
182
+ data['data'].each do |record|
183
+ date = Time.strptime(record['date'], '%Y%m%d%H%M')
184
+
185
+ result[date] ||= {}
186
+ result[date]['model'] ||= record['model']
187
+ result[date][record['tag']] = record['keydata']
188
+ end
189
+
190
+ dates = result.keys.sort
191
+ last_date = dates.last
192
+
193
+ dates.each do |date|
194
+ page = Array.new(11)
195
+ page[0] = date
196
+ result[date].each do |key, value|
197
+ case key
198
+ when 'model'
199
+ page[1] = value
200
+ when '6021'
201
+ # weight
202
+ page[2] = value.to_f
203
+ when '6022'
204
+ # body fat %
205
+ page[3] = value.to_f
206
+ when '6023'
207
+ # muscle mass
208
+ page[4] = value.to_f
209
+ when '6024'
210
+ # muscle score
211
+ page[5] = value.to_i
212
+ when '6025'
213
+ # visceral fat level 2
214
+ page[6] = value.to_f
215
+ when '6026'
216
+ # visceral fat level 1
217
+ page[7] = value.to_i
218
+ when '6027'
219
+ # basal metabolic rate
220
+ page[8] = value.to_i
221
+ when '6028'
222
+ # metabolic age
223
+ page[9] = value.to_i
224
+ when '6029'
225
+ # estimated bone mass
226
+ page[10] = value.to_f
227
+ end
228
+ end
229
+
230
+ page_builder.add(page)
231
+ end
232
+
233
+ last_date
234
+ end
235
+
236
+ def preview?
237
+ begin
238
+ org.embulk.spi.Exec.isPreview()
239
+ rescue java.lang.NullPointerException => e
240
+ false
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: embulk-input-healthplanet
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Masahiro Yoshizawa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: embulk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.10
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.10
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faraday
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.11
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.11
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday-cookie_jar
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.0.6
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.6
83
+ - !ruby/object:Gem::Dependency
84
+ name: oga
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0
97
+ description: Retrieve your innerscan data through Health Planet API v1.
98
+ email:
99
+ - muziyoshiz@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .ruby-version
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - embulk-input-healthplanet.gemspec
111
+ - lib/embulk/input/healthplanet.rb
112
+ homepage: https://github.com/muziyoshiz/embulk-input-healthplanet
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.0.14
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Healthplanet input plugin for Embulk
136
+ test_files: []