fluent-plugin-everysense 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/fluent-plugin-everysense.gemspec +2 -2
- data/tutorial/ja/json_over_http_api_tutorial.md +89 -22
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eaba80f1227fbc540073342d36982663872274a0
|
4
|
+
data.tar.gz: 986c0cc8303e9fa35bec5ac632f61d594bdb9810
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 778e010bfb2b9bb86988e8bfd53c1f7c888c4284f84e25507735ed4557302e3ea4aa2acc03356b89cc497820e0d204937f979e8e3a036a5570c7f785a50771ff
|
7
|
+
data.tar.gz: dcf47c0851d377bb9fee2e7c200d1f9498676cf3c301a5f2dc0d929ac3b703bbb1251f521f1df2a9beb19b21ca6cddc74bc63dbe19bbc796dc544233c9b97a03
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "fluent-plugin-everysense"
|
7
|
-
spec.version = "0.0.
|
7
|
+
spec.version = "0.0.3"
|
8
8
|
spec.authors = ["Toyokazu Akiyama"]
|
9
9
|
spec.email = ["toyokazu@gmail.com"]
|
10
10
|
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/toyokazu/fluent-plugin-everysense"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.gsub(
|
16
|
+
spec.files = `git ls-files`.gsub(/.+images\/[\w\.-]+\n/, "").split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
@@ -1,16 +1,19 @@
|
|
1
1
|
# Ruby を使って EverySense の API で遊んでみよう!
|
2
2
|
|
3
|
-
Ruby のインタラクティブシェル irb あるいは pry などを利用して EverySense の API で遊んでみましょう。遊ぶ前にまず EverySense
|
3
|
+
Ruby のインタラクティブシェル irb あるいは pry などを利用して EverySense の API で遊んでみましょう。遊ぶ前にまず EverySense 基礎用語をおさえておきましょう。
|
4
4
|
|
5
5
|
## EverySense 基礎用語
|
6
6
|
|
7
7
|
https://service.every-sense.com で遊ぶためには最低限以下の用語を抑えておく必要があります。
|
8
8
|
|
9
|
-
- **ファームオーナー**: EverySense
|
9
|
+
- **ファームオーナー**: EverySenseにアップロードするデータを持っている人。デバイスのクラスを使って自分のデバイスを **ファーム** に登録できます。デバイスを登録すると **デバイスのUUID** を取得できます。
|
10
10
|
- **レストランオーナー**: EverySenseからデータをダウンロードして活用する人。自分が欲しいデータの条件を **レシピ** として登録し、**レシピのUUID** を取得します。**レシピ** は検索条件で指定した **ファームオーナー** に送ることができます。検索条件はファームオーナーのキーワードから指定できます。
|
11
11
|
- **デバイスベンダー**: デバイスの開発元やデバイスにとっても詳しいデバイス所有者。デバイスのクラスを定義する権限をもちます。
|
12
12
|
- **レシピ**: **レストランオーナー** から **ファームオーナー** に送られる欲しいデータの条件。**レストランオーナー** は送られてきたレシピに対してデータを送信しても良いかどうか承認処理を行います。承認されたレシピでは承認した **ファームオーナー** のデバイス or ファーム (?)に送られたデータを取得することができます。
|
13
13
|
- **デバイスのクラス**: スマートフォンのようにデバイスには複数のセンサが搭載されていると想定されています。デバイスにどのような精度のセンサが搭載されているのか、例えば製品ごとに事前にクラスとして登録しておくことができます。**ファームオーナー** は保持しているデバイスに対応するクラスを選択して、EverySenseに登録することになります。
|
14
|
+
- **デバイスとセンサ**: **デバイスのクラス** を定義する際には、デバイスに接続された **センサ** を登録する必要があります。1つのデバイスに対して複数の **センサ** が取り付けられることが想定されています。**センサ** は無線接続されたものも含むため、センサごとに設置箇所を登録できます。登録時に指定した **センサ** の名称はデータアップロード時に利用するのでメモしておきましょう。
|
15
|
+
|
16
|
+
![EverySense基礎用語の概説図](https://github.com/toyokazu/fluent-plugin-everysense/tree/master/tutorial/ja/images/every-sense-overview.png "EverySense基礎用語の概説図]")
|
14
17
|
|
15
18
|
## アカウントの登録
|
16
19
|
|
@@ -53,29 +56,44 @@ irb(main):013:0* session_res.code
|
|
53
56
|
irb(main):014:0> session_res.message
|
54
57
|
=> "OK"
|
55
58
|
irb(main):015:0> session_res.body
|
56
|
-
=> "{\"code\":0,\"session_key\":\"
|
59
|
+
=> "{\"code\":0,\"session_key\":\"SSSSSSSS-SSSS-SSSS-SSSS-SSSSSSSSSSSS\"}"
|
57
60
|
```
|
58
61
|
|
59
|
-
ここで取得したsession_keyは、デバイスのAPI(/device_data)およびレシピのAPI(/recipe_data)を読み出す際に必要となります。デバイスのAPI (/device_data)は自分自身が登録したデバイスの情報を EverySense のプラットフォームを経由して取得したい場合に利用します。一方、レシピのAPI (/recipe_data)
|
62
|
+
ここで取得したsession_keyは、デバイスのAPI(/device_data)およびレシピのAPI(/recipe_data)を読み出す際に必要となります。デバイスのAPI (/device_data)は自分自身が登録したデバイスの情報を EverySense のプラットフォームを経由して取得したい場合に利用します。一方、レシピのAPI (/recipe_data) は、ファームオーナーに送ったレシピのうち、承認されたレシピからデータを取得したい場合に利用します。`@session_key`に格納しておきましょう。
|
60
63
|
|
61
64
|
```ruby
|
62
65
|
@session_key = JSON.parse(session_res.body)["session_key"]
|
63
66
|
```
|
64
67
|
|
65
|
-
このあと、ここで作成した
|
68
|
+
このあと、ここで作成した `@uri`, `@https`, `@session_key` を使ってデバイスやレシピにアクセスしていきます。
|
69
|
+
|
70
|
+
もし、上記の`@https`で接続がうまくいかなかった場合は、本番環境では使えませんが、以下の`@http`で試してみてください。変更点は、`use_ssl`を`true`にしていないこと、APIのURIが7001番ポートになっていることです。こちらを使う場合は、以降のコードで`@https`を`@http`に置き換えてください。
|
66
71
|
|
72
|
+
```ruby
|
73
|
+
require 'uri'
|
74
|
+
require 'net/http'
|
75
|
+
require 'json'
|
76
|
+
require 'time'
|
77
|
+
|
78
|
+
@uri = URI.parse('http://api.every-sense.com:7001/')
|
79
|
+
@http = Net::HTTP.new(@uri.host, @uri.port)
|
80
|
+
session_req = Net::HTTP::Post.new(@uri + '/session')
|
81
|
+
session_req.body = {login_name: 'your_name', password: 'your_password'}.to_json
|
82
|
+
session_req.content_type = 'application/json'
|
83
|
+
session_res = @http.request(session_req)
|
84
|
+
```
|
67
85
|
|
68
86
|
### デバイスのデータのアップロードとダウンロード
|
69
87
|
|
70
|
-
|
88
|
+
次にデバイスのデータのアップロード、ダウンロードについて試してみるため、テスト用のデバイスを登録してください。以下では仮に TestDevice という名称でデバイスを登録するものとして記述します。なお、デバイスの登録は以下から行えます。
|
71
89
|
|
72
90
|
https://service.every-sense.com/ja/devices
|
73
91
|
|
74
|
-
|
75
|
-
登録できると、UUIDが表示されます。下記の "
|
92
|
+
デバイス登録時には、登録されているデバイスのクラスから登録するデバイスの種類を選択します。としてTestDeviceを選択し、「追加」します。
|
93
|
+
登録できると、UUIDが表示されます。下記の `"DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD"` の部分を表示されたUUIDに置き換えて `@device_id` に保存し、以降続けていきましょう。
|
76
94
|
|
77
95
|
```ruby
|
78
|
-
@device_id = "
|
96
|
+
@device_id = "DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD"
|
79
97
|
```
|
80
98
|
|
81
99
|
デバイスのデータのアップロード、ダウンロードをする際にUUIDが必要になります。
|
@@ -84,23 +102,72 @@ https://service.every-sense.com/ja/devices
|
|
84
102
|
|
85
103
|
まずはアップロードから試してみましょう。なんと、アップロードには認証は不要です。ということは、デバイスのUUIDを知っている人は誰でもアップロードできてしまうということですね。皆さんUUIDの取り扱いには注意しましょう。
|
86
104
|
|
87
|
-
以下のようにURIにデバイスのUUIDを指定して、アップロードしたいデータをPOSTします。ここでは content_type に 'application/json' を指定して、JSON形式のデータをアップロードしてみます。
|
105
|
+
以下のようにURIにデバイスのUUIDを指定して、アップロードしたいデータをPOSTします。ここでは `content_type` に `'application/json'` を指定して、JSON形式のデータをアップロードしてみます。
|
106
|
+
|
107
|
+
ここでデバイスには複数のセンサが接続できるので、デバイス登録時に指定したデバイスクラスに指定されたセンサの数だけデータをアップロードできます。ただし、指定されたセンサ数よりも少ない数のデータだけアップロードすることもできます。
|
108
|
+
|
109
|
+
アップロードするデータの形式はJSON形式です。センサが1つの場合のサンプル(気温センサの例)を以下に示します。
|
110
|
+
|
111
|
+
```
|
112
|
+
{
|
113
|
+
"data": {
|
114
|
+
"at":"2016-04-14 17:15:00 +0900",
|
115
|
+
"unit":"degree Celsius",
|
116
|
+
"value":23
|
117
|
+
},
|
118
|
+
"sensor_name":"FESTIVAL_Test1_Sensor"
|
119
|
+
}
|
120
|
+
```
|
121
|
+
|
122
|
+
`"unit"`はデフォルト値が設定されているため、省略できます。また、`"sensor_name"`はデバイスクラスで定義したセンサの名称です。
|
123
|
+
|
124
|
+
センサが複数の場合は、Arrayで複数のデータを並べる形になります。センサが2つの場合のサンプル(気温センサ、湿度センサの例、データ部分のみ)を示します。
|
125
|
+
|
126
|
+
```
|
127
|
+
[
|
128
|
+
{
|
129
|
+
"data": {
|
130
|
+
"at": "2016-04-14 17:21:31 +0900",
|
131
|
+
"unit": "degree Celsius",
|
132
|
+
"value": 23
|
133
|
+
},
|
134
|
+
"sensor_name":"FESTIVAL_Test1_Sensor"
|
135
|
+
},
|
136
|
+
{
|
137
|
+
"data": {
|
138
|
+
"at": "2016-04-14 17:21:31 +0900",
|
139
|
+
"unit": "%RH",
|
140
|
+
"value": 30
|
141
|
+
},
|
142
|
+
"sensor_name": "FESTIVAL_Test1_Sensor2"
|
143
|
+
}
|
144
|
+
]
|
145
|
+
```
|
146
|
+
|
147
|
+
以下単一センサの場合のアップロードの例を示します。
|
88
148
|
|
89
149
|
```ruby
|
90
150
|
upload_req = Net::HTTP::Post.new(@uri + "/device_data/#{@device_id}")
|
91
|
-
upload_req.body = {
|
151
|
+
upload_req.body = {"data" => {"at" => Time.now.to_s, "unit" => "degree Celsius", "value" => 23}, "sensor_name" => "FESTIVAL_Test1_Sensor"}.to_json
|
92
152
|
upload_req.content_type = 'application/json'
|
93
153
|
upload_res = @https.request(upload_req)
|
94
154
|
upload_res.body
|
95
155
|
```
|
96
156
|
|
97
|
-
最後の応答に以下のように 'code: 0' が返されていればアップロード成功です。
|
157
|
+
最後の応答に以下のように `'code: 0'` が返されていればアップロード成功です。
|
98
158
|
|
99
159
|
```
|
100
160
|
irb(main):023:0> upload_res.body
|
101
161
|
=> "{\"code\":0}"
|
102
162
|
```
|
103
163
|
|
164
|
+
以下に複数センサの場合の例(HTTPリクエストbody部分のみ)を示します。
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
upload_req.body = [{"data" => {"at" => Time.now.to_s, "unit" => "degree Celsius", "value" => 23}, "sensor_name" => "FESTIVAL_Test1_Sensor"}, {"data" => {"at" => Time.now.to_s, "unit" => "%RH", "value" => 30}, "sensor_name" => "FESTIVAL_Test1_Sensor2"}].to_json
|
168
|
+
```
|
169
|
+
|
170
|
+
|
104
171
|
#### デバイスのデータのダウンロード
|
105
172
|
|
106
173
|
データの取得にはログインID (UUID) + パスワードあるいは、session_keyが要求されます。以下では session_key を利用しています。
|
@@ -111,7 +178,7 @@ device_data_res.body
|
|
111
178
|
```
|
112
179
|
|
113
180
|
しばらくはキャッシュされているので、getすると同じデータがダウンロードされます。そのため、
|
114
|
-
実際には from
|
181
|
+
実際には `from`, `to` でデータが登録された期間を指定して必要なデータをすることになります。
|
115
182
|
|
116
183
|
```ruby
|
117
184
|
@from = (Time.now.utc - 86400).iso8601 # 1日前から 例) "2016-03-11T03:57:23Z"
|
@@ -124,16 +191,12 @@ device_data_res.body
|
|
124
191
|
|
125
192
|
```
|
126
193
|
[50] pry(main)> device_data_res.body
|
127
|
-
=>
|
194
|
+
=> "[{\"test_data\":{\"data1\":\"hoge\",\"data2\":123}},{\"data\":{\"at\":\"2016-04-14 17:33:59 +0900\",\"unit\":\"degree Celsius\",\"value\":23},\"sensor_name\":\"FESTIVAL_Test1_Sensor\"},{\"data\":{\"at\":\"2016-04-14 17:34:05 +0900\",\"unit\":\"degree Celsius\",\"value\":23},\"sensor_name\":\"FESTIVAL_Test1_Sensor\"},{\"data\":{\"at\":\"2016-04-14 17:34:32 +0900\",\"unit\":\"degree Celsius\",\"value\":23},\"sensor_name\":\"FESTIVAL_Test1_Sensor\"},{\"data\":{\"at\":\"2016-04-14 17:34:35 +0900\",\"unit\":\"degree Celsius\",\"value\":23},\"sensor_name\":\"FESTIVAL_Test1_Sensor\"}]"
|
128
195
|
[51] pry(main)> JSON.parse(device_data_res.body)
|
129
|
-
=> [{"test_data"
|
130
|
-
{"test_data"=>{"data1"=>"hoge", "data2"=>123}},
|
131
|
-
{"test_data"=>{"data1"=>"hoge", "data2"=>123}},
|
132
|
-
{"test_data"=>{"data1"=>"hoge", "data2"=>123}},
|
133
|
-
{"test_data"=>{"data1"=>"hoge", "data2"=>123}}]
|
196
|
+
=> [{"test_data":{"data1":"hoge","data2":123}},{"data":{"at":"2016-04-14 17:33:59 +0900","unit":"degree Celsius","value":23},"sensor_name":"FESTIVAL_Test1_Sensor"},{"data":{"at":"2016-04-14 17:34:05 +0900","unit":"degree Celsius","value":23},"sensor_name":"FESTIVAL_Test1_Sensor"},{"data":{"at":"2016-04-14 17:34:32 +0900","unit":"degree Celsius","value":23},"sensor_name":"FESTIVAL_Test1_Sensor"},{"data":{"at":"2016-04-14 17:34:35 +0900","unit":"degree Celsius","value":23},"sensor_name":"FESTIVAL_Test1_Sensor"}]
|
134
197
|
```
|
135
198
|
|
136
|
-
|
199
|
+
データが含まれない場合は空の配列が返されます。`from`, `to` の時刻はUTCで指定してください。 `@from` を適当に変えて、先ほどアップロードしたデータが表示される場合と表示されない場合をそれぞれ確認してみてください。
|
137
200
|
|
138
201
|
|
139
202
|
### レシピからのデータのダウンロード
|
@@ -144,7 +207,7 @@ https://service.every-sense.com/
|
|
144
207
|
|
145
208
|
レストランオーナーに切り替えると、トップ画面に「レシピを作成」というメニューが表示されます。このメニューからレシピを作成してください。
|
146
209
|
|
147
|
-
レシピの作成が完了するとレシピのUUIDが表示されます。以降ではこのUUIDを
|
210
|
+
レシピの作成が完了するとレシピのUUIDが表示されます。以降ではこのUUIDを `@recipe_id` に保存して利用します。また、ダウンロードする際のデータ形式として `@format` に `'json'` を指定しておきましょう。
|
148
211
|
|
149
212
|
```ruby
|
150
213
|
@recipe_id = "ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ"
|
@@ -158,8 +221,12 @@ https://service.every-sense.com/
|
|
158
221
|
```ruby
|
159
222
|
recipe_data_res = @https.get(@uri + "/recipe_data/#{@recipe_id}.#{@format}?session_key=#{@session_key}&from=#{@from}&to=#{@to}")
|
160
223
|
recipe_data_res.body
|
224
|
+
=> "[[{\"farm_uuid\":\"FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF\",\"sensor_name\":\"collection_data_1\",\"data_class_name\":\"AirTemperature\",\"data\":{\"at\":\"2016-04-13 07:26:12 UTC\",\"memo\":null,\"value\":23.0,\"unit\":\"degree Celsius\"}}],[{\"farm_uuid\":\"FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF\",\"sensor_name\":\"collection_data_1\",\"data_class_name\":\"AirTemperature\",\"data\":{\"at\":\"2016-04-13 07:27:48 UTC\",\"memo\":null,\"value\":23.0,\"unit\":\"degree Celsius\"}}],[{\"farm_uuid\":\"FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF\",\"sensor_name\":\"collection_data_1\",\"data_class_name\":\"AirTemperature\",\"data\":{\"at\":\"2016-04-13 07:30:06 UTC\",\"memo\":null,\"value\":23.0,\"unit\":\"degree Celsius\"}}],[{\"farm_uuid\":\"FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF\",\"sensor_name\":\"collection_data_1\",\"data_class_name\":\"AirTemperature\",\"data\":{\"at\":\"2016-04-14 08:33:59 UTC\",\"memo\":null,\"value\":23.0,\"unit\":\"degree Celsius\"}}]]"
|
161
225
|
```
|
162
226
|
|
227
|
+
取得したデータ中の `"FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"` はファームのUUIDを示しています。
|
228
|
+
|
229
|
+
|
163
230
|
### session_keyの無効化について
|
164
231
|
|
165
232
|
device_dataにはlogin_name、passwordでもアクセスできますが、毎回提示すると login_name、passwordが奪われる可能性が高くなるため、今回代わりにsession_keyを用いてアクセスしました。ただし、session_keyが他人に奪われるとsession_keyが有効な期間不正にアクセスされる可能性があるため、利用が終わったらsession_keyを無効化するようにしましょう。以下の手順でsession_keyを無効化できます。
|
@@ -170,7 +237,7 @@ del_session_res = @https.request(del_session_req)
|
|
170
237
|
del_session_res.body
|
171
238
|
```
|
172
239
|
|
173
|
-
以下のように 'code: 0' が返されていれば削除成功です。
|
240
|
+
以下のように `'code: 0'` が返されていれば削除成功です。
|
174
241
|
|
175
242
|
```
|
176
243
|
irb(main):037:0> del_session_res.body
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-everysense
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toyokazu Akiyama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|