cs 0.1.1beta → 0.1.3

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.
@@ -7,10 +7,11 @@ module CS
7
7
  include HTTParty
8
8
 
9
9
  attr_accessor :response_body, :response_code, :response_headers, :errors
10
- attr_reader :session_id
10
+ attr_reader :session_id, :api_key
11
11
 
12
- def initialize(base_uri = nil)
12
+ def initialize(base_uri = nil, api_key = nil)
13
13
  self.base_uri = base_uri
14
+ @api_key = api_key
14
15
  @session_id = nil
15
16
  reset
16
17
  end
@@ -22,10 +23,23 @@ module CS
22
23
  @response_body
23
24
  end
24
25
 
26
+ def process_api_key(path)
27
+ return path if @api_key.nil?
28
+
29
+ if URI(path).query.nil?
30
+ path += "?API_KEY=#{@api_key}"
31
+ else
32
+ path += "&API_KEY=#{@api_key}"
33
+ end
34
+
35
+ path
36
+ end
37
+
25
38
  def get(path, query={}, headers = {})
26
39
  execute do
27
40
  headers = default_headers.merge(headers)
28
41
  options = {query: query, headers: headers}
42
+ path = process_api_key(path)
29
43
  self.class.get(path, options)
30
44
  end
31
45
  end
@@ -66,7 +80,7 @@ module CS
66
80
  header = self.class.default_options[:headers] || {}
67
81
  header.merge!({"Content-Type" => "application/json"})
68
82
  if @session_id
69
- header.merge!('X-SESSION_ID' => self.session_id)
83
+ header = header.merge('X-SESSION_ID' => self.session_id)
70
84
  end
71
85
  header
72
86
  end
@@ -79,18 +93,19 @@ module CS
79
93
  @session_id = session_id
80
94
  end
81
95
 
82
-
83
96
  # login to commonsense
84
97
  # @return [String] session_id
85
- def login(username, password)
86
- password = Digest::MD5.hexdigest password
98
+ def login(username, password, digest=true)
99
+ if digest
100
+ password = Digest::MD5.hexdigest password
101
+ end
87
102
  post('/login.json', {:username => username, :password => password})
88
103
 
89
104
  if @response_code == 200
90
105
  self.session_id = response_body['session_id']
91
106
  else
92
107
  self.session_id = false
93
- errors = [response_body['error']]
108
+ @errors = [response_body['error']]
94
109
  end
95
110
 
96
111
  session_id
@@ -104,6 +119,7 @@ module CS
104
119
  end
105
120
 
106
121
  def parse_response
122
+ return unless @response_body
107
123
  @response_code = @response_body.response.code.to_i
108
124
  @response_headers = @response_body.headers
109
125
  if @response_code >= 400
@@ -0,0 +1,29 @@
1
+ require 'yaml'
2
+
3
+ module CS
4
+ module CLI
5
+ class Config
6
+ @@config = {}
7
+ @@loaded = false
8
+ @@file = ""
9
+
10
+ def self.load_config(file="#{ENV['HOME']}/.cs.yml")
11
+ @@file = file
12
+ @@config = YAML.load_file(file)
13
+ @@loaded = true
14
+ end
15
+
16
+ def self.get(key=nil)
17
+ if !@@loaded
18
+ STDERR.puts("WARNING could not load '#{@@file}'. Is it exists ?")
19
+ end
20
+
21
+ if key.nil?
22
+ return @@config
23
+ else
24
+ return @@config[key.to_s]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ module CS
2
+ ##
3
+ # Module to handle Collection
4
+ module Collection
5
+
6
+ end
7
+ end
@@ -0,0 +1,62 @@
1
+ require 'delegate'
2
+
3
+ module CS
4
+ module Collection
5
+ class SensorDataCollection < SimpleDelegator
6
+ attr_accessor :session
7
+ attr_accessor :batch_size
8
+
9
+ def initialize(session=nil)
10
+ self.session = session
11
+ @batch_size = 1000
12
+ super([])
13
+ end
14
+
15
+ def save!
16
+ check_session!
17
+
18
+ # group batch
19
+ self.each_slice(@batch_size) do |batch|
20
+ body = process_batch(batch)
21
+ @session.post(get_url, body)
22
+ end
23
+ end
24
+
25
+ ##
26
+ # Given array of sensor data it will group the data by sensor_id
27
+ # and construct payload for multiple sensor upload
28
+ def process_batch(batch)
29
+ sensors = {}
30
+ batch.each do |point|
31
+ next if point.nil? || point.sensor_id.nil?
32
+ sensor_id = point.sensor_id
33
+
34
+ if !sensors[sensor_id]
35
+ sensors[sensor_id] = {
36
+ sensor_id: sensor_id,
37
+ data: []
38
+ }
39
+ end
40
+
41
+ sensors[sensor_id][:data].push(point.to_cs_value)
42
+ end
43
+
44
+ retval = []
45
+ sensors.each do |k, v|
46
+ retval.push(v)
47
+ end
48
+
49
+ {sensors: retval}
50
+ end
51
+
52
+ def get_url
53
+ "/sensors/data.json"
54
+ end
55
+
56
+ private
57
+ def check_session!
58
+ raise Error::SessionEmptyError unless @session
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,4 +1,6 @@
1
1
  require 'cs/serializer'
2
+ require 'set'
3
+
2
4
  module CS
3
5
  module EndPoint
4
6
  include CS::Serializer
@@ -0,0 +1,16 @@
1
+ module CS
2
+ module EndPoint
3
+ class Notification
4
+ include EndPoint
5
+
6
+ attribute :type, :text, :destination
7
+
8
+ resources "notifications"
9
+ resource "notification"
10
+
11
+ def initialize(hash={})
12
+ from_hash(hash)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -26,8 +26,8 @@ module CS
26
26
  end
27
27
  end
28
28
 
29
- # overide Endpoint#to_parameters
30
- def to_parameters
29
+
30
+ def to_cs_value
31
31
  param = self.to_h(false)
32
32
  if param[:data_type] == "json"
33
33
  if param[:data_structure] && !param[:data_structure].kind_of?(String)
@@ -35,12 +35,40 @@ module CS
35
35
  end
36
36
  end
37
37
 
38
- {sensor: param}
38
+ param
39
+ end
40
+
41
+ # overide Endpoint#to_parameters
42
+ def to_parameters
43
+ {sensor: to_cs_value}
39
44
  end
40
45
 
41
46
  def data
42
47
  Relation::SensorDataRelation.new(self.id, self.session)
43
48
  end
49
+
50
+ # Copy data from other sensor
51
+ #
52
+ # example :
53
+ #
54
+ # source = client.sensors.find(1234)
55
+ # destination = clint.sensors.find(2345)
56
+ #
57
+ # destination.copy_data(source, start_date: 12345, end_date: 12350)
58
+ #
59
+ def copy_data(sensor, parameters={})
60
+ source = sensor.data
61
+ parameters.each do |k,v|
62
+ source.send(k.to_sym, v)
63
+ end
64
+
65
+ collection = self.data.collection
66
+ source.each do |point|
67
+ collection.push self.data.build(date: point.date, value: point.value)
68
+ end
69
+
70
+ collection.save!
71
+ end
44
72
  end
45
73
  end
46
74
  end
@@ -26,7 +26,7 @@ module CS
26
26
  resources "data"
27
27
  resource "data"
28
28
 
29
- def to_parameters
29
+ def to_cs_value
30
30
  param = self.to_h(false)
31
31
  param.delete(:sensor_id)
32
32
  value = param[:value]
@@ -35,7 +35,12 @@ module CS
35
35
  end
36
36
 
37
37
  param[:date] = CS::Time.new(date).to_f if param[:date]
38
- {data: [param]}
38
+
39
+ param
40
+ end
41
+
42
+ def to_parameters
43
+ {data: [to_cs_value]}
39
44
  end
40
45
 
41
46
  def date_human
@@ -0,0 +1,16 @@
1
+ module CS
2
+ module EndPoint
3
+ class Trigger
4
+ include EndPoint
5
+
6
+ attribute :name, :expression, :inactivity, :creation_date
7
+
8
+ resources "triggers"
9
+ resource "trigger"
10
+
11
+ def initialize(hash={})
12
+ from_hash(hash)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -45,7 +45,7 @@ module CS
45
45
  end
46
46
 
47
47
  def get_data(params={})
48
- get_data!(params) rescue nil
48
+ get_data!(params)
49
49
  end
50
50
 
51
51
  def all
@@ -94,7 +94,6 @@ module CS
94
94
  end
95
95
 
96
96
  def last
97
- total = count
98
97
  resource = get_single_resource(page: count - 1)
99
98
  parse_single_resource(resource)
100
99
  end
@@ -146,7 +145,7 @@ module CS
146
145
  options[:page] = self.page
147
146
  data = get_data(options)
148
147
 
149
- data = data[resource_class.resources_name]
148
+ data = data[resource_class.resources_name] unless data.nil?
150
149
  if !data.nil? && !data.empty?
151
150
  yield data
152
151
  self.page += 1
@@ -0,0 +1,20 @@
1
+ module CS
2
+ module Relation
3
+ class NotificationRelation
4
+ include Relation
5
+
6
+ parameter :page, Integer, default: 0, required: true
7
+ parameter :per_page, Integer, default: 1000, required: true, maximum: 1000
8
+ parameter :total, Boolean
9
+
10
+ private
11
+ def resource_class
12
+ EndPoint::Notification
13
+ end
14
+
15
+ def get_url
16
+ "/notifications.json"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -50,6 +50,14 @@ module CS
50
50
  parse_single_resource(data)
51
51
  end
52
52
 
53
+ def start_date(date)
54
+ from(date)
55
+ end
56
+
57
+ def end_date(date)
58
+ to(date)
59
+ end
60
+
53
61
  def from(start_date)
54
62
  param_option = self.class.parameters[:start_date]
55
63
  self.start_date = process_param_time(:start_date, start_date, param_option)
@@ -62,6 +70,10 @@ module CS
62
70
  self
63
71
  end
64
72
 
73
+ def collection
74
+ Collection::SensorDataCollection.new(session)
75
+ end
76
+
65
77
  private
66
78
  def resource_class
67
79
  EndPoint::SensorData
@@ -100,6 +100,23 @@ module CS
100
100
  self.select { |sensor| sensor.name =~ regex }
101
101
  end
102
102
 
103
+ def triggers()
104
+ Relation::SensorTriggersRelation.new(@session)
105
+ end
106
+
107
+ # Create new sensor with properties from other sensor
108
+ #
109
+ # example :
110
+ #
111
+ # client.sensors.clone_from(client.sensors.find(123))
112
+ def clone_from(other_sensor)
113
+ sensor = EndPoint::Sensor.new(other_sensor.to_cs_value)
114
+ sensor.id = nil
115
+ sensor.session = self.session
116
+
117
+ sensor
118
+ end
119
+
103
120
  private
104
121
  def resource_class
105
122
  EndPoint::Sensor
@@ -109,5 +126,15 @@ module CS
109
126
  "/sensors.json"
110
127
  end
111
128
  end
129
+
130
+ class SensorTriggersRelation
131
+ include Relation
132
+
133
+ parameter :page, Integer, default: 0, required: true
134
+
135
+ def get_url
136
+ "/sensors/triggers.json"
137
+ end
138
+ end
112
139
  end
113
140
  end
@@ -0,0 +1,21 @@
1
+ module CS
2
+ module Relation
3
+ class TriggerRelation
4
+ include Relation
5
+
6
+ parameter :page, Integer, default: 0, required: true
7
+ parameter :per_page, Integer, default: 1000, required: true, maximum: 1000
8
+ parameter :total, Boolean
9
+
10
+
11
+ private
12
+ def resource_class
13
+ EndPoint::Trigger
14
+ end
15
+
16
+ def get_url
17
+ "/triggers.json"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -13,9 +13,9 @@ module CS
13
13
 
14
14
  # login to commonsense
15
15
  # @return [String] session_id
16
- def login(username, password)
16
+ def login(username, password, digest=true)
17
17
  @auth_proxy = CS::Auth::HTTP.new(@base_uri)
18
- @auth_proxy.login(username, password)
18
+ @auth_proxy.login(username, password, digest)
19
19
  end
20
20
 
21
21
  def oauth(consumer_key, consumer_secret, access_token, access_token_secret)
@@ -28,11 +28,20 @@ module CS
28
28
  auth_proxy.session_id
29
29
  end
30
30
 
31
+ def api_key
32
+ auth_proxy.api_key
33
+ end
34
+
31
35
  def session_id=(session_id)
32
36
  @auth_proxy = CS::Auth::HTTP.new(@base_uri)
33
37
  @auth_proxy.session_id = session_id
34
38
  end
35
39
 
40
+ def api_key=(api_key)
41
+ @api_key = api_key
42
+ @auth_proxy = CS::Auth::HTTP.new(@base_uri, api_key)
43
+ end
44
+
36
45
  def auth_proxy
37
46
  raise 'The session is not logged in' unless @auth_proxy
38
47
  @auth_proxy
@@ -55,18 +64,25 @@ module CS
55
64
  logger.info("")
56
65
  logger.info("#{type} #{path}")
57
66
  logger.debug("headers: #{headers.inspect}")
58
- logger.info("parameters: #{body.inspect}")
67
+ if ["POST", "PUT"].include?(type)
68
+ logger.debug("request: #{body.inspect}")
69
+ else
70
+ logger.info("request: #{body.inspect}")
71
+ end
59
72
  end
60
73
 
61
- def log_response
62
- logger.info("response: #{self.response_code}")
63
- logger.debug("body: #{self.response_body}")
74
+ def log_response(elapsed)
75
+ logger.info("result: #{self.response_code} in #{elapsed}ms")
76
+ logger.debug("response: #{self.response_body}")
64
77
  end
65
78
 
66
79
  def execute(type, path, body, headers, &block)
80
+ start_time = Time.now
67
81
  log_request(type, path, body, headers) if logger
68
82
  response = retry_on_509 { yield }
69
- log_response if logger
83
+
84
+ elapsed = (Time.now - start_time) * 1000.0
85
+ log_response(elapsed) if logger
70
86
 
71
87
  response
72
88
  end
@@ -146,7 +162,12 @@ module CS
146
162
  end
147
163
 
148
164
  def to_s
149
- "\"#{self.session_id}\""
165
+ if session_id
166
+ return "SESSION_ID \"#{session_id}\""
167
+ elsif api_key
168
+ return "API_KEY \"#{api_key}\""
169
+ end
170
+ return ""
150
171
  end
151
172
 
152
173
  def inspect