fluent-plugin-everysense 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/fluent-plugin-everysense.gemspec +1 -1
- data/lib/fluent/plugin/everysense_proxy.rb +41 -37
- data/lib/fluent/plugin/in_everysense.rb +45 -10
- data/lib/fluent/plugin/out_everysense.rb +11 -8
- data/tutorial/ja/json_over_http_api_tutorial.md +91 -30
- 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: 662ac79c0cd9386365f14c66e536661f1b373ffc
|
4
|
+
data.tar.gz: 1a7d012016819e509d6a4a90fc303be3ec85e3d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfbf5110f932e922e9b51220f121091bf3794801122d445260840687f4769570987f560789fc3aed2dcf09f9c17ab3ab4f2389d3898763115435f1ae6d9f04e9
|
7
|
+
data.tar.gz: cb02c84c32f87d5f3d06bdf6102017b9753a15bc06274bfe7fcb0d22cdaac4114623d56621431b147b0c7ef7102ba5497fd6f7010b34faeeb28ec581089bf9f1
|
data/README.md
CHANGED
@@ -36,11 +36,12 @@ Input Plugin can be used via source directive in the configuration.
|
|
36
36
|
</source>
|
37
37
|
```
|
38
38
|
|
39
|
-
- **format** (required): type of parser can be specified to parse input data
|
39
|
+
- **format** (required): type of parser can be specified to parse input data. currently only json format is supported. parser plugin options can also be specified.
|
40
40
|
- **tag** (required): tag name appended to the input data inside fluentd network
|
41
41
|
- **login_name** (required): login_name to login https://service.every-sense.com/
|
42
42
|
- **password** (required): password for the login_name
|
43
|
-
- **device_id** (required): the target device id to obtain input data
|
43
|
+
- **device_id** (device_id or recipe_id is required): the target device id to obtain input data
|
44
|
+
- **recipe_id** (device_id or recipe_id is required): the target recipe id to obtain input data
|
44
45
|
- **polling_interval**: interval to poll EverySense JSON over HTTP API
|
45
46
|
|
46
47
|
|
@@ -81,4 +82,3 @@ Recipe related function is not implemented yet.
|
|
81
82
|
## License
|
82
83
|
|
83
84
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
84
|
-
|
@@ -5,6 +5,9 @@ module Fluent
|
|
5
5
|
require 'json'
|
6
6
|
require 'time'
|
7
7
|
|
8
|
+
class EverySenseProxyError
|
9
|
+
end
|
10
|
+
|
8
11
|
def self.included(base)
|
9
12
|
base.desc 'EverySense API URI'
|
10
13
|
base.config_param :url, :string, :default => 'https://api.every-sense.com:8001/'
|
@@ -12,11 +15,14 @@ module Fluent
|
|
12
15
|
base.config_param :login_name, :string, :default => nil # TODO: mandatory option
|
13
16
|
base.desc 'password for EverySense API'
|
14
17
|
base.config_param :password, :string, :default => nil # TODO: mandatory option
|
15
|
-
base.config_param :device_id, :string, :default => nil
|
18
|
+
base.config_param :device_id, :string, :default => nil
|
16
19
|
base.config_param :recipe_id, :string, :default => nil
|
17
20
|
base.config_param :format, :string, :default => 'json'
|
21
|
+
base.config_param :limit, :integer, :default => 1000
|
18
22
|
#base.config_param :keep_alive, :integer, :default => 2
|
19
23
|
base.config_param :from, :string, :default => Time.now.iso8601
|
24
|
+
base.config_param :keep, :bool, :default => false
|
25
|
+
base.config_param :inline, :bool, :default => false
|
20
26
|
end
|
21
27
|
|
22
28
|
def start_proxy
|
@@ -29,7 +35,9 @@ module Fluent
|
|
29
35
|
end
|
30
36
|
|
31
37
|
def shutdown_proxy
|
38
|
+
$log.debug "shutdown_proxy #{@session_key}"
|
32
39
|
delete_session
|
40
|
+
@https.finish() if @https.active?
|
33
41
|
end
|
34
42
|
|
35
43
|
def error_handler(response, message)
|
@@ -47,22 +55,6 @@ module Fluent
|
|
47
55
|
!@session_key.nil? # TODO validate @session_key using EverySense API
|
48
56
|
end
|
49
57
|
|
50
|
-
def validate_device
|
51
|
-
if @device_id.nil?
|
52
|
-
$log.error :error => 'Invalid device id.'
|
53
|
-
return false
|
54
|
-
end
|
55
|
-
return true
|
56
|
-
end
|
57
|
-
|
58
|
-
def validate_recipe
|
59
|
-
if @recipe_id.nil?
|
60
|
-
$log.error :error => 'Invalid recipe id.'
|
61
|
-
return false
|
62
|
-
end
|
63
|
-
return true
|
64
|
-
end
|
65
|
-
|
66
58
|
def create_session_request
|
67
59
|
session_req = Net::HTTP::Post.new(@uri + '/session')
|
68
60
|
session_req.body = {login_name: @login_name, password: @password}.to_json
|
@@ -96,41 +88,53 @@ module Fluent
|
|
96
88
|
end
|
97
89
|
|
98
90
|
def put_message(message)
|
99
|
-
return if !validate_device
|
100
91
|
put_message_res = @https.request(put_message_request(message))
|
101
92
|
error_handler(put_message_res, "put_message: '#{message}' failed.")
|
102
93
|
end
|
103
94
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
95
|
+
def target_path
|
96
|
+
if !@device_id.nil?
|
97
|
+
return "/device_data/#{@device_id}"
|
98
|
+
elsif !@recipe_id.nil?
|
99
|
+
return "/recipe_data/#{@recipe_id}.#{@format}"
|
100
|
+
else
|
101
|
+
raise ConfigError, "device_id or recipe_id must be specified."
|
102
|
+
end
|
108
103
|
end
|
109
104
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
105
|
+
def get_messages_params
|
106
|
+
params = {
|
107
|
+
session_key: @session_key,
|
108
|
+
from: @from,
|
109
|
+
to: Time.now.iso8601,
|
110
|
+
limit: @limit
|
111
|
+
}
|
112
|
+
if !@device_id.nil?
|
113
|
+
return params
|
114
|
+
elsif !@recipe_id.nil?
|
115
|
+
return params.merge({keep: @keep, inline: @inline, format: @format})
|
116
|
+
else
|
117
|
+
raise ConfigError, "device_id or recipe_id must be specified."
|
114
118
|
end
|
115
|
-
return nil if !validate_device
|
116
|
-
get_message_res = @https.get(get_message_request)
|
117
|
-
return nil if !error_handler(get_message_res,"get_message failed.")
|
118
|
-
get_message_res.body
|
119
119
|
end
|
120
120
|
|
121
|
-
def
|
122
|
-
@uri +
|
121
|
+
def get_messages_request
|
122
|
+
get_messages_req = @uri + target_path
|
123
|
+
get_messages_req.query = URI.encode_www_form(get_messages_params)
|
124
|
+
$log.debug "#{@uri + target_path}?#{URI.encode_www_form(get_messages_params)}"
|
125
|
+
# currently time window is automatically updated
|
126
|
+
@from = (Time.now + 1).iso8601
|
127
|
+
get_messages_req
|
123
128
|
end
|
124
129
|
|
125
|
-
def
|
130
|
+
def get_messages
|
126
131
|
if !valid_session?
|
127
132
|
return nil if create_session.nil?
|
128
133
|
$log.debug "session #{@session_key} created."
|
129
134
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
get_recipe_res.body
|
135
|
+
get_messages_res = @https.get(get_messages_request)
|
136
|
+
return nil if !error_handler(get_messages_res,"get_messages failed.")
|
137
|
+
get_messages_res.body
|
134
138
|
end
|
135
139
|
end
|
136
140
|
end
|
@@ -5,11 +5,43 @@ module Fluent
|
|
5
5
|
|
6
6
|
Plugin.register_input('everysense', self)
|
7
7
|
|
8
|
+
# currently EverySenseParser is only used by EverySense Plugin
|
9
|
+
# Parser is implemented internally.
|
10
|
+
class EverySenseParser
|
11
|
+
def initialize(format, parser)
|
12
|
+
case format
|
13
|
+
when 'json'
|
14
|
+
@parser = parser
|
15
|
+
return
|
16
|
+
when 'xml'
|
17
|
+
raise NotImplementedError, "XML parser is not implemented yet."
|
18
|
+
else
|
19
|
+
raise NotImplementedError, "XML parser is not implemented yet."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: parser should be impelented prettier way...
|
24
|
+
# currently once parse JSON array is parsed and in map loop
|
25
|
+
# each message is re-formatted to JSON. After that it is re-parsed
|
26
|
+
# by fluent JSON parser which supports time_format etc. options...
|
27
|
+
def parse(messages)
|
28
|
+
$log.debug messages
|
29
|
+
JSON.parse(messages).map do |message|
|
30
|
+
$log.debug message
|
31
|
+
@parser.parse(message.to_json) do |time, record|
|
32
|
+
yield(time, record)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
8
38
|
desc 'Tag name assigned to inputs'
|
9
39
|
config_param :tag, :string, :default => nil # TODO: mandatory option
|
10
40
|
desc 'Polling interval to get message from EverySense API'
|
11
|
-
config_param :polling_interval, :integer, :default =>
|
41
|
+
config_param :polling_interval, :integer, :default => 60
|
42
|
+
desc 'Adding timestamp to the message for monitoring performance'
|
12
43
|
config_param :recv_time, :bool, :default => false
|
44
|
+
desc 'Attribute name of the timestamp for receiving time'
|
13
45
|
config_param :recv_time_key, :string, :default => "recv_time"
|
14
46
|
|
15
47
|
# Define `router` method of v0.12 to support v0.10 or earlier
|
@@ -25,6 +57,7 @@ module Fluent
|
|
25
57
|
def configure_parser(conf)
|
26
58
|
@parser = Plugin.new_parser(@format)
|
27
59
|
@parser.configure(conf)
|
60
|
+
@everysense_parser = EverySenseParser.new(@format, @parser)
|
28
61
|
end
|
29
62
|
|
30
63
|
def start
|
@@ -34,9 +67,9 @@ module Fluent
|
|
34
67
|
@proxy_thread = Thread.new do
|
35
68
|
while (true)
|
36
69
|
begin
|
37
|
-
|
38
|
-
$log.debug "
|
39
|
-
emit(
|
70
|
+
messages = get_messages
|
71
|
+
$log.debug "get_messages: #{messages}"
|
72
|
+
emit(messages) if !(messages.nil? || messages.empty?)
|
40
73
|
sleep @polling_interval
|
41
74
|
rescue Exception => e
|
42
75
|
$log.error :error => e.to_s
|
@@ -57,20 +90,22 @@ module Fluent
|
|
57
90
|
end
|
58
91
|
end
|
59
92
|
|
60
|
-
def parse(
|
61
|
-
@
|
93
|
+
def parse(messages)
|
94
|
+
@everysense_parser.parse(messages) do |time, record|
|
62
95
|
if time.nil?
|
63
96
|
$log.debug "Since time_key field is nil, Fluent::Engine.now is used."
|
64
97
|
time = Fluent::Engine.now
|
65
98
|
end
|
66
99
|
$log.debug "#{time}, #{add_recv_time(record)}"
|
67
|
-
|
100
|
+
{time: time, record: add_recv_time(record)}
|
68
101
|
end
|
69
102
|
end
|
70
103
|
|
71
|
-
def emit(
|
104
|
+
def emit(messages)
|
72
105
|
begin
|
73
|
-
|
106
|
+
parse(messages).each do |msg|
|
107
|
+
router.emit(@tag, msg[:time], msg[:record])
|
108
|
+
end
|
74
109
|
rescue Exception => e
|
75
110
|
$log.error :error => e.to_s
|
76
111
|
$log.debug_backtrace(e.backtrace)
|
@@ -78,9 +113,9 @@ module Fluent
|
|
78
113
|
end
|
79
114
|
|
80
115
|
def shutdown
|
81
|
-
super
|
82
116
|
@proxy_thread.kill
|
83
117
|
shutdown_proxy
|
118
|
+
super
|
84
119
|
end
|
85
120
|
end
|
86
121
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Fluent
|
2
|
-
class EverySenseOutput <
|
2
|
+
class EverySenseOutput < BufferedOutput
|
3
3
|
require 'fluent/plugin/everysense_proxy'
|
4
4
|
include EverySenseProxy
|
5
5
|
|
@@ -39,20 +39,23 @@ module Fluent
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
def format(tag, time, record)
|
43
|
+
[tag, time, record].to_msgpack
|
44
|
+
end
|
45
|
+
|
46
|
+
def write(chunk)
|
47
|
+
chunk.msgpack_each do |tag, time, record|
|
48
|
+
$log.debug "#{tag}, #{@formatter.format(tag, time, add_send_time(record)).chomp}\n"
|
49
|
+
put_message(@formatter.format(tag, time, add_send_time(record)))
|
50
|
+
end
|
48
51
|
$log.flush
|
49
52
|
end
|
50
53
|
|
51
54
|
# This method is called when shutting down.
|
52
55
|
# Shutdown the thread and close sockets or files here.
|
53
56
|
def shutdown
|
54
|
-
super
|
55
57
|
shutdown_proxy
|
58
|
+
super
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
@@ -1,23 +1,44 @@
|
|
1
1
|
# Ruby を使って EverySense の API で遊んでみよう!
|
2
2
|
|
3
|
-
Ruby のインタラクティブシェル irb あるいは pry などを利用して EverySense の API
|
3
|
+
Ruby のインタラクティブシェル irb あるいは pry などを利用して EverySense の API で遊んでみましょう。遊ぶ前にまず EverySense 基礎用語を抑えておきましょう。
|
4
4
|
|
5
|
-
|
5
|
+
## EverySense 基礎用語
|
6
|
+
|
7
|
+
https://service.every-sense.com で遊ぶためには最低限以下の用語を抑えておく必要があります。
|
8
|
+
|
9
|
+
- **ファームオーナー**: EverySenseにアップロードするデータを持っている人。デバイスのクラスを使って自分のデバイスを登録できます。デバイスを登録すると **デバイスのUUID** を取得できます。
|
10
|
+
- **レストランオーナー**: EverySenseからデータをダウンロードして活用する人。自分が欲しいデータの条件を **レシピ** として登録し、**レシピのUUID** を取得します。**レシピ** は検索条件で指定した **ファームオーナー** に送ることができます。検索条件はファームオーナーのキーワードから指定できます。
|
11
|
+
- **デバイスベンダー**: デバイスの開発元やデバイスにとっても詳しいデバイス所有者。デバイスのクラスを定義する権限をもちます。
|
12
|
+
- **レシピ**: **レストランオーナー** から **ファームオーナー** に送られる欲しいデータの条件。**レストランオーナー** は送られてきたレシピに対してデータを送信しても良いかどうか承認処理を行います。承認されたレシピでは承認した **ファームオーナー** のデバイス or ファーム (?)に送られたデータを取得することができます。
|
13
|
+
- **デバイスのクラス**: スマートフォンのようにデバイスには複数のセンサが搭載されていると想定されています。デバイスにどのような精度のセンサが搭載されているのか、例えば製品ごとに事前にクラスとして登録しておくことができます。**ファームオーナー** は保持しているデバイスに対応するクラスを選択して、EverySenseに登録することになります。
|
14
|
+
|
15
|
+
## アカウントの登録
|
16
|
+
|
17
|
+
EverySenseで遊ぶためには、https://service.every-sense.com でアカウントの登録が必要です。以降で出てくる login_name および password は service.every-sense.com で登録したものに置き換えて下さい。
|
18
|
+
|
19
|
+
以下ではまずデバイスのデータをアップロード、ダウンロードする方法から触れますので、ファームオーナーならびにレストランオーナーの権限が必要です。まずは、ファームオーナー(「センサー情報を提供される方」)でアカウント登録をして、上記サイトにログイン後、トップページにあるボタンで「レストランオーナー」の権限を申請してください。さらに「デバイスオーナー」の権限も登録しておくと、自分でオリジナルデバイスを登録することもできます。
|
20
|
+
|
21
|
+
## JSON over HTTP ゲートウェイで遊ぶっ!
|
6
22
|
|
7
|
-
|
23
|
+
さて、以下順番に遊んでいきましょう。
|
24
|
+
|
25
|
+
### Net::HTTP を使ってREST APIに接続し、session_key を取得してみよう!
|
26
|
+
|
27
|
+
以下では最も標準的な API である JSON over HTTPゲートウェイについて触れています。irb を起動して以下のコードを貼り付けてみましょう。ただし、your_name, your_password の部分は自分のlogin_name、passwordに置き換えてくださいね。
|
8
28
|
|
9
29
|
```ruby
|
10
30
|
require 'uri'
|
11
31
|
require 'net/http'
|
12
32
|
require 'json'
|
33
|
+
require 'time'
|
13
34
|
|
14
|
-
uri = URI.parse('https://api.every-sense.com:8001/')
|
15
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
16
|
-
https.use_ssl = true
|
17
|
-
session_req = Net::HTTP::Post.new(uri + '/session')
|
35
|
+
@uri = URI.parse('https://api.every-sense.com:8001/')
|
36
|
+
@https = Net::HTTP.new(@uri.host, @uri.port)
|
37
|
+
@https.use_ssl = true
|
38
|
+
session_req = Net::HTTP::Post.new(@uri + '/session')
|
18
39
|
session_req.body = {login_name: 'your_name', password: 'your_password'}.to_json
|
19
40
|
session_req.content_type = 'application/json'
|
20
|
-
session_res = https.request(session_req)
|
41
|
+
session_res = @https.request(session_req)
|
21
42
|
|
22
43
|
session_res.code
|
23
44
|
session_res.message
|
@@ -35,31 +56,41 @@ irb(main):015:0> session_res.body
|
|
35
56
|
=> "{\"code\":0,\"session_key\":\"YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYYY\"}"
|
36
57
|
```
|
37
58
|
|
38
|
-
ここで取得したsession_key
|
59
|
+
ここで取得したsession_keyは、デバイスのAPI(/device_data)およびレシピのAPI(/recipe_data)を読み出す際に必要となります。デバイスのAPI (/device_data)は自分自身が登録したデバイスの情報を EverySense のプラットフォームを経由して取得したい場合に利用します。一方、レシピのAPI (/recipe_data) は、ファームオーナーに送ったレシピのうち、承認されたレシピからデータを取得したい場合に利用します。@session_keyに格納しておきましょう。
|
39
60
|
|
40
61
|
```ruby
|
41
|
-
session_key = JSON.parse(session_res.body)["session_key"]
|
62
|
+
@session_key = JSON.parse(session_res.body)["session_key"]
|
42
63
|
```
|
43
64
|
|
65
|
+
このあと、ここで作成した @uri, @https, @session_key を使ってデバイスやレシピにアクセスしていきます。
|
66
|
+
|
67
|
+
|
68
|
+
### デバイスのデータのアップロードとダウンロード
|
69
|
+
|
44
70
|
次にデバイスのデータのアップロード、ダウンロードについて試してみるため、テスト用のデバイス Test_Device を登録してください。デバイスの登録は以下から行えます。
|
45
71
|
|
46
72
|
https://service.every-sense.com/ja/devices
|
47
73
|
|
48
74
|
デバイスクラスとしてTest_Deviceを選択し、「追加」します。
|
49
|
-
登録できると、UUID
|
50
|
-
|
75
|
+
登録できると、UUIDが表示されます。下記の "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" の部分を表示されたUUIDに置き換えて @device_id に保存し、以降続けていきましょう。
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
@device_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
79
|
+
```
|
51
80
|
|
52
81
|
デバイスのデータのアップロード、ダウンロードをする際にUUIDが必要になります。
|
53
82
|
|
54
|
-
|
83
|
+
#### デバイスのデータのアップロード
|
84
|
+
|
85
|
+
まずはアップロードから試してみましょう。なんと、アップロードには認証は不要です。ということは、デバイスのUUIDを知っている人は誰でもアップロードできてしまうということですね。皆さんUUIDの取り扱いには注意しましょう。
|
55
86
|
|
56
|
-
URIにデバイスのUUIDを指定して、アップロードしたいデータをPOSTします。ここでは content_type に 'application/json' を指定して、JSON形式のデータをアップロードしてみます。
|
87
|
+
以下のようにURIにデバイスのUUIDを指定して、アップロードしたいデータをPOSTします。ここでは content_type に 'application/json' を指定して、JSON形式のデータをアップロードしてみます。
|
57
88
|
|
58
89
|
```ruby
|
59
|
-
upload_req = Net::HTTP::Post.new(uri +
|
90
|
+
upload_req = Net::HTTP::Post.new(@uri + "/device_data/#{@device_id}")
|
60
91
|
upload_req.body = {test_data: {data1: "hoge", data2: 123}}.to_json
|
61
92
|
upload_req.content_type = 'application/json'
|
62
|
-
upload_res = https.request(upload_req)
|
93
|
+
upload_res = @https.request(upload_req)
|
63
94
|
upload_res.body
|
64
95
|
```
|
65
96
|
|
@@ -70,42 +101,72 @@ irb(main):023:0> upload_res.body
|
|
70
101
|
=> "{\"code\":0}"
|
71
102
|
```
|
72
103
|
|
104
|
+
#### デバイスのデータのダウンロード
|
105
|
+
|
73
106
|
データの取得にはログインID (UUID) + パスワードあるいは、session_keyが要求されます。以下では session_key を利用しています。
|
74
107
|
|
75
108
|
```ruby
|
76
|
-
|
77
|
-
|
109
|
+
device_data_res = @https.get(@uri + "/device_data/#{@device_id}?session_key=#{@session_key}")
|
110
|
+
device_data_res.body
|
78
111
|
```
|
79
112
|
|
80
113
|
しばらくはキャッシュされているので、getすると同じデータがダウンロードされます。そのため、
|
81
114
|
実際には from, to でデータが登録された期間を指定して必要なデータをすることになります。
|
82
115
|
|
83
116
|
```ruby
|
84
|
-
|
85
|
-
|
117
|
+
@from = (Time.now.utc - 86400).iso8601 # 1日前から 例) "2016-03-11T03:57:23Z"
|
118
|
+
@to = (Time.now.utc + 86400).iso8601 # 1日後まで 例) "2016-03-13T03:57:23Z"
|
119
|
+
device_data_res = @https.get(@uri + "/device_data/#{@device_id}?session_key=#{@session_key}&from=#{@from}&to=#{@to}")
|
120
|
+
device_data_res.body
|
121
|
+
```
|
122
|
+
|
123
|
+
指定した期間に含まれるデータは以下のように配列形式で返されます。
|
124
|
+
|
125
|
+
```
|
126
|
+
[50] pry(main)> device_data_res.body
|
127
|
+
=> "[{\"test_data\":{\"data1\":\"hoge\",\"data2\":123}},{\"test_data\":{\"data1\":\"hoge\",\"data2\":123}},{\"test_data\":{\"data1\":\"hoge\",\"data2\":123}},{\"test_data\":{\"data1\":\"hoge\",\"data2\":123}},{\"test_data\":{\"data1\":\"hoge\",\"data2\":123}}]"
|
128
|
+
[51] pry(main)> JSON.parse(device_data_res.body)
|
129
|
+
=> [{"test_data"=>{"data1"=>"hoge", "data2"=>123}},
|
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}}]
|
86
134
|
```
|
87
135
|
|
88
|
-
from, to の時刻はUTCで指定してください。
|
136
|
+
データが含まれない場合は空の配列が返されます。from, to の時刻はUTCで指定してください。 @from を適当に変えて、先ほどアップロードしたデータが表示される場合と表示されない場合をそれぞれ確認してみてください。
|
89
137
|
|
90
|
-
|
138
|
+
|
139
|
+
### レシピからのデータのダウンロード
|
140
|
+
|
141
|
+
次に「センサー情報収集」のため、レストランオーナーとしてレシピを登録、確認する方法について見ていきます。レストランオーナーになるためには、service.every-sense.com のログイン後画面から「レストランオーナー」の登録を行った上で、「オーナー切替」で「レストランオーナー」を選択して作業してください。
|
91
142
|
|
92
143
|
https://service.every-sense.com/
|
93
144
|
|
94
|
-
|
145
|
+
レストランオーナーに切り替えると、トップ画面に「レシピを作成」というメニューが表示されます。このメニューからレシピを作成してください。
|
146
|
+
|
147
|
+
レシピの作成が完了するとレシピのUUIDが表示されます。以降ではこのUUIDを @recipe_id に保存して利用します。また、ダウンロードする際のデータ形式として @format に 'json' を指定しておきましょう。
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
@recipe_id = "ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ"
|
151
|
+
@format = 'json'
|
152
|
+
```
|
153
|
+
|
154
|
+
レシピを経由してデータを取得するにはファームーオーナーからレシピの承認を得る必要があります。レシピの宛先として特に条件を指定しなければ、条件に一致する全てのファームまたはファームオーナーにレシピが送信されます。レシピの受信にはしばらく時間がかかりますが、1分ほどまって、右上メニューから「ファームオーナー」にオーナーを切り替えると、「オーダー」に先ほど登録したレシピが表示されているはずです。「却下」になっているスライダーを「承認」に切り替えると、オーダーの状態が「稼働」に変わります。これでレシピからのデータ受信準備は完了です。
|
95
155
|
|
156
|
+
レシピからのデータダウンロード時のURIは以下のとおりです。うまくダウンロードできましたか?
|
96
157
|
|
97
158
|
```ruby
|
98
|
-
|
99
|
-
|
159
|
+
recipe_data_res = @https.get(@uri + "/recipe_data/#{@recipe_id}.#{@format}?session_key=#{@session_key}&from=#{@from}&to=#{@to}")
|
160
|
+
recipe_data_res.body
|
100
161
|
```
|
101
162
|
|
102
|
-
|
163
|
+
### session_keyの無効化について
|
103
164
|
|
104
|
-
device_dataにはlogin_name、passwordでもアクセスできますが、毎回提示すると login_name、password
|
165
|
+
device_dataにはlogin_name、passwordでもアクセスできますが、毎回提示すると login_name、passwordが奪われる可能性が高くなるため、今回代わりにsession_keyを用いてアクセスしました。ただし、session_keyが他人に奪われるとsession_keyが有効な期間不正にアクセスされる可能性があるため、利用が終わったらsession_keyを無効化するようにしましょう。以下の手順でsession_keyを無効化できます。
|
105
166
|
|
106
167
|
```ruby
|
107
|
-
del_session_req = Net::HTTP::Delete.new(uri + "/session/#{session_key}")
|
108
|
-
del_session_res = https.request(del_session_req)
|
168
|
+
del_session_req = Net::HTTP::Delete.new(@uri + "/session/#{@session_key}")
|
169
|
+
del_session_res = @https.request(del_session_req)
|
109
170
|
del_session_res.body
|
110
171
|
```
|
111
172
|
|
@@ -116,4 +177,4 @@ irb(main):037:0> del_session_res.body
|
|
116
177
|
=> "{\"code\":0}"
|
117
178
|
```
|
118
179
|
|
119
|
-
現状はsession_keyにはかなり長い時間の有効期間が与えられているようで、1日たってもアクセスできました (^^;;
|
180
|
+
現状はsession_keyにはかなり長い時間の有効期間が与えられているようで、1日たってもアクセスできました (^^;; 忘れずに無効化しておきましょう。
|
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.2
|
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-03-
|
11
|
+
date: 2016-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|