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.
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