cs 0.1.0beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +10 -0
  3. data/LICENSE +22 -0
  4. data/README.md +132 -0
  5. data/Rakefile +7 -0
  6. data/cs.gemspec +22 -0
  7. data/lib/commonsense-ruby-lib.rb +127 -0
  8. data/lib/commonsense-ruby-lib/auth/http.rb +117 -0
  9. data/lib/commonsense-ruby-lib/auth/oauth.rb +101 -0
  10. data/lib/commonsense-ruby-lib/end_point.rb +276 -0
  11. data/lib/commonsense-ruby-lib/end_point/group.rb +28 -0
  12. data/lib/commonsense-ruby-lib/end_point/sensor.rb +36 -0
  13. data/lib/commonsense-ruby-lib/end_point/sensor_data.rb +70 -0
  14. data/lib/commonsense-ruby-lib/end_point/user.rb +50 -0
  15. data/lib/commonsense-ruby-lib/error.rb +51 -0
  16. data/lib/commonsense-ruby-lib/relation.rb +233 -0
  17. data/lib/commonsense-ruby-lib/relation/sensor_data_relation.rb +116 -0
  18. data/lib/commonsense-ruby-lib/relation/sensor_relation.rb +162 -0
  19. data/lib/commonsense-ruby-lib/serializer.rb +20 -0
  20. data/lib/commonsense-ruby-lib/session.rb +105 -0
  21. data/lib/commonsense-ruby-lib/version.rb +3 -0
  22. data/spec/features/sensor_data_management_spec.rb +4 -0
  23. data/spec/features/sensor_management_spec.rb +105 -0
  24. data/spec/features/user_management_spec.rb +70 -0
  25. data/spec/lib/commonsense-ruby-lib/end_point/sensor_data_spec.rb +68 -0
  26. data/spec/lib/commonsense-ruby-lib/end_point/sensor_spec.rb +98 -0
  27. data/spec/lib/commonsense-ruby-lib/end_point/user_spec.rb +36 -0
  28. data/spec/lib/commonsense-ruby-lib/end_point_spec.rb +190 -0
  29. data/spec/lib/commonsense-ruby-lib/relation/sensor_data_relation_spec.rb +444 -0
  30. data/spec/lib/commonsense-ruby-lib/relation/sensor_relation_spec.rb +165 -0
  31. data/spec/lib/commonsense-ruby-lib/session_spec.rb +43 -0
  32. data/spec/lib/commonsense-ruby-lib_spec.rb +51 -0
  33. data/spec/spec_helper.rb +40 -0
  34. data/spec/support/spec_config.yml.sample +6 -0
  35. data/spec/support/vcr.rb +5 -0
  36. metadata +175 -0
@@ -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
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in commonsense-ruby-lib.gemspec
4
+ gemspec
5
+ gem "pry"
6
+ gem "pry-nav"
7
+ gem "pry-doc"
8
+ gem "redcarpet"
9
+ gem "time-lord"
10
+ #gem "pry-stack_explorer"
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.
@@ -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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require 'rubygems'
3
+ require "bundler/gem_tasks"
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new('spec')
7
+
@@ -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