cs 0.1.0beta3
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/.gitignore +21 -0
- data/Gemfile +10 -0
- data/LICENSE +22 -0
- data/README.md +132 -0
- data/Rakefile +7 -0
- data/cs.gemspec +22 -0
- data/lib/commonsense-ruby-lib.rb +127 -0
- data/lib/commonsense-ruby-lib/auth/http.rb +117 -0
- data/lib/commonsense-ruby-lib/auth/oauth.rb +101 -0
- data/lib/commonsense-ruby-lib/end_point.rb +276 -0
- data/lib/commonsense-ruby-lib/end_point/group.rb +28 -0
- data/lib/commonsense-ruby-lib/end_point/sensor.rb +36 -0
- data/lib/commonsense-ruby-lib/end_point/sensor_data.rb +70 -0
- data/lib/commonsense-ruby-lib/end_point/user.rb +50 -0
- data/lib/commonsense-ruby-lib/error.rb +51 -0
- data/lib/commonsense-ruby-lib/relation.rb +233 -0
- data/lib/commonsense-ruby-lib/relation/sensor_data_relation.rb +116 -0
- data/lib/commonsense-ruby-lib/relation/sensor_relation.rb +162 -0
- data/lib/commonsense-ruby-lib/serializer.rb +20 -0
- data/lib/commonsense-ruby-lib/session.rb +105 -0
- data/lib/commonsense-ruby-lib/version.rb +3 -0
- data/spec/features/sensor_data_management_spec.rb +4 -0
- data/spec/features/sensor_management_spec.rb +105 -0
- data/spec/features/user_management_spec.rb +70 -0
- data/spec/lib/commonsense-ruby-lib/end_point/sensor_data_spec.rb +68 -0
- data/spec/lib/commonsense-ruby-lib/end_point/sensor_spec.rb +98 -0
- data/spec/lib/commonsense-ruby-lib/end_point/user_spec.rb +36 -0
- data/spec/lib/commonsense-ruby-lib/end_point_spec.rb +190 -0
- data/spec/lib/commonsense-ruby-lib/relation/sensor_data_relation_spec.rb +444 -0
- data/spec/lib/commonsense-ruby-lib/relation/sensor_relation_spec.rb +165 -0
- data/spec/lib/commonsense-ruby-lib/session_spec.rb +43 -0
- data/spec/lib/commonsense-ruby-lib_spec.rb +51 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/support/spec_config.yml.sample +6 -0
- data/spec/support/vcr.rb +5 -0
- metadata +175 -0
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.rspec
|
6
|
+
.autotest
|
7
|
+
.yardoc
|
8
|
+
Gemfile.lock
|
9
|
+
InstalledFiles
|
10
|
+
_yardoc
|
11
|
+
coverage
|
12
|
+
doc/
|
13
|
+
lib/bundler/man
|
14
|
+
pkg
|
15
|
+
rdoc
|
16
|
+
spec/reports
|
17
|
+
test/tmp
|
18
|
+
test/version_tmp
|
19
|
+
tmp
|
20
|
+
spec/vcr
|
21
|
+
spec/support/spec_config.yml
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ahmy Yulrizka
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# Commonsense::Ruby::Lib
|
2
|
+
Client library to communicate with CommonSense written in ruby
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
gem 'commonsense-ruby-lib'
|
9
|
+
|
10
|
+
And then execute:
|
11
|
+
|
12
|
+
$ bundle
|
13
|
+
|
14
|
+
Or install it yourself as:
|
15
|
+
|
16
|
+
$ gem install commonsense-ruby-lib
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
### Authentication
|
21
|
+
```ruby
|
22
|
+
client = CommonSense::Client.new
|
23
|
+
client.login('username','password')
|
24
|
+
|
25
|
+
# get current user
|
26
|
+
current_user = client.current_user
|
27
|
+
```
|
28
|
+
|
29
|
+
### Querying Sensor
|
30
|
+
```ruby
|
31
|
+
# create sensors relation
|
32
|
+
sensors = client.sensors
|
33
|
+
|
34
|
+
# is the same as
|
35
|
+
sensors = CommonSense::Relation::Sensors.new
|
36
|
+
sensors.session = session
|
37
|
+
|
38
|
+
# Get all sensor
|
39
|
+
sensors = client.sensors
|
40
|
+
sensors.to_a
|
41
|
+
|
42
|
+
# Get sensor by specifying parameters
|
43
|
+
client.sensors.where(page: 0, per_page: 1000)
|
44
|
+
client.sensors.where(owned: true)
|
45
|
+
client.sensors.where(physical: true)
|
46
|
+
client.sensors.where(page: 0, per_page: 1000, physical: true, owned: true, details: "full")
|
47
|
+
|
48
|
+
# process each sensor
|
49
|
+
client.sensors.where(owned: true).each {|sensor| puts sensor.name}
|
50
|
+
|
51
|
+
# Chain parameters
|
52
|
+
client.sensors.where(page:0, per_page: 10).where(physical: true)
|
53
|
+
|
54
|
+
# Find sensor by name
|
55
|
+
client.sensors.find_by_name(/position/)
|
56
|
+
client.sensors.find_by_name(/position/, owned: true) # or
|
57
|
+
client.sensors.where(owned: true).find_by_name(/position/)
|
58
|
+
|
59
|
+
# Get first sensor or last sensor
|
60
|
+
sensor = client.sensors.first
|
61
|
+
sensor = client.sensors.last
|
62
|
+
|
63
|
+
# Get number of sensors
|
64
|
+
client.sensors.count
|
65
|
+
client.sensors.where(owned: true).count
|
66
|
+
```
|
67
|
+
|
68
|
+
### Creating Sensor
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
sensor = client.sensor.build
|
72
|
+
sensor.name = "light"
|
73
|
+
sensor.display_name = "Light"
|
74
|
+
sensor.device_type = "Android"
|
75
|
+
sensor.pager_type = ""
|
76
|
+
sensor.data_type = "json"
|
77
|
+
sensor.data_structure = {lux: "integer"}
|
78
|
+
sensor.save!
|
79
|
+
```
|
80
|
+
|
81
|
+
### Uploading data point
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# Find the first position sensor
|
85
|
+
sensor = client.sensors.find_by_name(/position/).first
|
86
|
+
|
87
|
+
# save data point
|
88
|
+
data = sensor.data.build
|
89
|
+
data.date = Time.now
|
90
|
+
data.value = {"lux" => 1}
|
91
|
+
data.save!
|
92
|
+
|
93
|
+
# more compact version
|
94
|
+
sensor.data.build(date: Time.now, value: {"lux" => 1}).save!
|
95
|
+
```
|
96
|
+
|
97
|
+
### Debuging
|
98
|
+
|
99
|
+
To get information about the API response (body, code, headers) inspect the session
|
100
|
+
|
101
|
+
example
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
# do some API call
|
105
|
+
current_user = client.current_user
|
106
|
+
|
107
|
+
# get the session
|
108
|
+
session = client.session
|
109
|
+
|
110
|
+
response_code = session.response_code
|
111
|
+
response_body = session.resopnse_body
|
112
|
+
header = session.response_headers
|
113
|
+
|
114
|
+
# dump the output to text file
|
115
|
+
session.dump_to_text("/tmp/output.txt")
|
116
|
+
|
117
|
+
# open output in browser. Require 'launchy' gem
|
118
|
+
session.open_in_browser
|
119
|
+
```
|
120
|
+
|
121
|
+
## Testing
|
122
|
+
|
123
|
+
$ cp spec/support/spec_config.yml.sample spec/support/spec_config.yml
|
124
|
+
$ rspec
|
125
|
+
|
126
|
+
## Contributing
|
127
|
+
|
128
|
+
1. Fork it
|
129
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
130
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
131
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
132
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/cs.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/commonsense-ruby-lib/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Ahmy Yulrizka"]
|
6
|
+
gem.email = ["ahmy@sense-os.nl"]
|
7
|
+
gem.description = %q{CommonSense API client library}
|
8
|
+
gem.summary = %q{Client library to communicate with CommonSense written in ruby}
|
9
|
+
gem.homepage = "https://github.com/senseobservationsystems/commonsense-ruby-lib"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "cs"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = CommonSense::VERSION
|
17
|
+
gem.add_development_dependency("rspec", "~> 2.13.0")
|
18
|
+
gem.add_development_dependency("launchy", "~> 2.3.0")
|
19
|
+
gem.add_development_dependency("fakeweb", "~> 1.3.0")
|
20
|
+
gem.add_dependency('httparty', '~> 0.11.0')
|
21
|
+
gem.add_dependency('oauth', '~> 0.4.7')
|
22
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require "commonsense-ruby-lib/version"
|
2
|
+
require "commonsense-ruby-lib/error"
|
3
|
+
require "commonsense-ruby-lib/auth/http"
|
4
|
+
require "commonsense-ruby-lib/auth/oauth"
|
5
|
+
require "commonsense-ruby-lib/session"
|
6
|
+
require "commonsense-ruby-lib/end_point"
|
7
|
+
require "commonsense-ruby-lib/end_point/user"
|
8
|
+
require "commonsense-ruby-lib/end_point/group"
|
9
|
+
require "commonsense-ruby-lib/end_point/sensor"
|
10
|
+
require "commonsense-ruby-lib/end_point/sensor_data"
|
11
|
+
require "commonsense-ruby-lib/relation"
|
12
|
+
require "commonsense-ruby-lib/relation/sensor_relation"
|
13
|
+
require "commonsense-ruby-lib/relation/sensor_data_relation"
|
14
|
+
|
15
|
+
module CommonSense
|
16
|
+
|
17
|
+
# Main entry class of the library.
|
18
|
+
#
|
19
|
+
# The login functionality always comes in two pair. The Bang (!) method
|
20
|
+
# will raise an exception when there is an error and the normal (without !)
|
21
|
+
# will return nil when it fails.
|
22
|
+
#
|
23
|
+
# The response can be viewed by looking at the {CommonSense::Session}
|
24
|
+
#
|
25
|
+
# client.session # will return the session object
|
26
|
+
#
|
27
|
+
# == Authentication with User And Password
|
28
|
+
#
|
29
|
+
# client = CommonSense::Client.new
|
30
|
+
# client.login('username', 'password')
|
31
|
+
#
|
32
|
+
# == Authentication using OAuth
|
33
|
+
#
|
34
|
+
# client = CommonSense::Client.new
|
35
|
+
# client.oauth('CONSUMER_KEY', 'CONSUMER_SECRET', 'ACCESS_TOKEN', 'ACCESS_TOKEN_SECRET')
|
36
|
+
#
|
37
|
+
# == Using different API server
|
38
|
+
#
|
39
|
+
# client = CommonSense::Client.new(base_uri: 'https://api.dev.sense-os.nl')
|
40
|
+
# # or
|
41
|
+
# client.base_uri = 'https://api.dev.sense-os.nl'
|
42
|
+
#
|
43
|
+
class Client
|
44
|
+
attr_accessor :session, :base_uri
|
45
|
+
|
46
|
+
def initialize(opts={})
|
47
|
+
options = {
|
48
|
+
base_uri: 'https://api.sense-os.nl',
|
49
|
+
}.merge(opts)
|
50
|
+
@base_uri = options[:base_uri]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create a new session to CommonSense using username and plain text password
|
54
|
+
# with `login!` it will throw exception if there is an error
|
55
|
+
#
|
56
|
+
# client = CommonSense::Client.new
|
57
|
+
# client.login!('username', 'password')
|
58
|
+
def login!(user, password)
|
59
|
+
@session = Session.new(base_uri: @base_uri)
|
60
|
+
@session.login(user, password)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Create a new session to CommonSense using username and plain text password
|
64
|
+
# with `login` it will return nil if it not successful
|
65
|
+
#
|
66
|
+
# client = CommonSense::Client.new
|
67
|
+
# client.login('username', 'password')
|
68
|
+
def login(user, password)
|
69
|
+
login!(user, password) rescue nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# Create a new session to CommonSense using OAuth credentials
|
73
|
+
#
|
74
|
+
# client = CommonSense::Client.new
|
75
|
+
# client.login('username', 'password')
|
76
|
+
def oauth(consumer_key, consumer_secret, access_token, access_token_secret)
|
77
|
+
@session = Session.new(base_uri: @base_uri)
|
78
|
+
@session.oauth(consumer_key, consumer_secret, access_token, access_token_secret)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Create new session by manually specifiying `session_id` parameter
|
82
|
+
#
|
83
|
+
# client = CommonSense::Client.new
|
84
|
+
# client.session_id('12345')
|
85
|
+
def set_session_id(session_id)
|
86
|
+
@session = Session.new(base_uri: @base_uri)
|
87
|
+
@session.session_id = session_id
|
88
|
+
end
|
89
|
+
|
90
|
+
# Retrun logged in user
|
91
|
+
def current_user
|
92
|
+
user = EndPoint::User.new
|
93
|
+
user.session = @session
|
94
|
+
user.current_user
|
95
|
+
end
|
96
|
+
|
97
|
+
# Create a new user
|
98
|
+
#
|
99
|
+
# client = CommonSense::Client.new
|
100
|
+
# client.new_user(username: 'Ahmy')
|
101
|
+
# client.email = 'ahmy@gmail.com'
|
102
|
+
# ...
|
103
|
+
# client.save!
|
104
|
+
def new_user(hash={})
|
105
|
+
user = EndPoint::User.new(hash)
|
106
|
+
user.session = Session.new(base_uri: @base_uri, authentication: false)
|
107
|
+
user
|
108
|
+
end
|
109
|
+
|
110
|
+
# @see CommonSense::Relation::SensorRelation
|
111
|
+
def sensors
|
112
|
+
Relation::SensorRelation.new(@session)
|
113
|
+
end
|
114
|
+
|
115
|
+
def current_groups
|
116
|
+
group = EndPoint::Group.new
|
117
|
+
group.session = @session
|
118
|
+
group.current_groups
|
119
|
+
end
|
120
|
+
|
121
|
+
# return errors got from session
|
122
|
+
def errors
|
123
|
+
return @session.errors if @session
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module CommonSense
|
5
|
+
module Auth
|
6
|
+
class HTTP
|
7
|
+
include HTTParty
|
8
|
+
|
9
|
+
attr_accessor :response_body, :response_code, :response_headers, :errors
|
10
|
+
attr_reader :session_id
|
11
|
+
|
12
|
+
def initialize(base_uri = nil)
|
13
|
+
self.base_uri = base_uri
|
14
|
+
@session_id = nil
|
15
|
+
reset
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(path, query={}, headers = {})
|
19
|
+
reset
|
20
|
+
headers = default_headers.merge(headers)
|
21
|
+
options = {query: query, headers: headers}
|
22
|
+
@response_body = self.class.get(path, options)
|
23
|
+
parse_response
|
24
|
+
@response_body
|
25
|
+
end
|
26
|
+
|
27
|
+
def post(path, body = '', headers = {})
|
28
|
+
reset
|
29
|
+
headers = default_headers.merge(headers)
|
30
|
+
@response_body = self.class.post(path, prepare(body, headers))
|
31
|
+
parse_response
|
32
|
+
@response_body
|
33
|
+
end
|
34
|
+
|
35
|
+
def put(path, body = '', headers = {})
|
36
|
+
reset
|
37
|
+
headers = default_headers.merge(headers)
|
38
|
+
@response_body = self.class.put(path, prepare(body, headers))
|
39
|
+
parse_response
|
40
|
+
@response_body
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete(path, query={}, headers = {})
|
44
|
+
reset
|
45
|
+
headers = default_headers.merge(headers)
|
46
|
+
options = {query: query, headers: headers}
|
47
|
+
@response_body = self.class.delete(path, options)
|
48
|
+
parse_response
|
49
|
+
@response_body
|
50
|
+
end
|
51
|
+
|
52
|
+
def head(path, headers = {})
|
53
|
+
reset
|
54
|
+
@response_body = self.class.head(path, prepare(nil, headers))
|
55
|
+
parse_response
|
56
|
+
@response_body
|
57
|
+
end
|
58
|
+
|
59
|
+
def base_uri=(uri = nil)
|
60
|
+
self.class.base_uri uri
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_headers
|
64
|
+
header = self.class.default_options[:headers] || {}
|
65
|
+
header.merge({"Content-Type" => "application/json"})
|
66
|
+
if @session_id
|
67
|
+
header.merge!('X-SESSION_ID' => self.session_id)
|
68
|
+
end
|
69
|
+
header
|
70
|
+
end
|
71
|
+
|
72
|
+
def default_headers=(header_hash)
|
73
|
+
self.class.default_options[:headers] = header_hash
|
74
|
+
end
|
75
|
+
|
76
|
+
def session_id=(session_id)
|
77
|
+
@session_id = session_id
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# login to commonsense
|
82
|
+
# @return [String] session_id
|
83
|
+
def login(username, password)
|
84
|
+
password = Digest::MD5.hexdigest password
|
85
|
+
post('/login.json', {:username => username, :password => password})
|
86
|
+
|
87
|
+
if @response_code == 200
|
88
|
+
self.session_id = response_body['session_id']
|
89
|
+
else
|
90
|
+
errors = [response_body['error']]
|
91
|
+
end
|
92
|
+
|
93
|
+
session_id
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def reset
|
98
|
+
@errors = nil
|
99
|
+
@response_code = nil
|
100
|
+
@response_body = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_response
|
104
|
+
@response_code = @response_body.response.code.to_i
|
105
|
+
@response_headers = @response_body.headers
|
106
|
+
if @response_code >= 400
|
107
|
+
@errors = [response_body['error']]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def prepare(body=nil, headers={})
|
112
|
+
headers = default_headers.merge(headers)
|
113
|
+
{:body => body.to_json, :headers => headers}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|