evercam 0.1.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c0feb0f02abd86da77568762f1270e426d26eead
4
+ data.tar.gz: 34520893b15f4b1a5e25a7704e54c1b830b06daf
5
+ SHA512:
6
+ metadata.gz: 930158c12281cd62abb347e98e429dcf11832b0daf537129d18cf4bd87603b24eaa36790ca4816f935b891edec21c93295ba9f5182d1bd5970246f72b8d5a738
7
+ data.tar.gz: 192aa69fff15dcdc0d601bbc4ab6244511e7c9db052dc6b7df5baf91a62bec81c601a2cd1b5b42ad68378511599c5bca8c7daa11473a14a07d828f778bc6e01b
@@ -0,0 +1 @@
1
+ # Change Log
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Peter Wood
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,42 @@
1
+ # Evercam
2
+
3
+ This gem provides a wrapper around the Evercam REST API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'evercam'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install evercam
18
+
19
+ ## Usage
20
+
21
+ To use the library in your code the first step is to include the library into
22
+ your sources with the line...
23
+
24
+ require 'evercam'
25
+
26
+ With the library included you next need to create an instance of the API class.
27
+ This requires that you provide your Evercam API id and key and the following
28
+ code...
29
+
30
+ api = Evercam::API.new(api_id: '1234567', api_key: '1a2b3c4d5e6a7b8c9d0e')
31
+
32
+ Once you have an instance of the API class you can make calls to Evercam through
33
+ it such as the following...
34
+
35
+ cameras = api.get_user_cameras('my_user_name')
36
+
37
+ ### Logging
38
+
39
+ To add a logger to the Evercam API object you can do this during the creation
40
+ of the object as follows...
41
+
42
+ api = Evercam::API.new(api_id: '1234567', api_key: '1a2b3c4d5e6a7b8c9d0e', logger: Logger.new(STDOUT))
@@ -0,0 +1,25 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ require "faraday"
4
+ require "faraday_middleware"
5
+ require "json"
6
+ require "logger"
7
+ require "net/https"
8
+ require "stringio"
9
+ require "typhoeus"
10
+ require "typhoeus/adapters/faraday"
11
+ require "evercam/version"
12
+ require "evercam/exceptions"
13
+ require "evercam/null_logger"
14
+ require "evercam/cameras"
15
+ require "evercam/logs"
16
+ require "evercam/models"
17
+ require "evercam/public"
18
+ require "evercam/shares"
19
+ require "evercam/snapshots"
20
+ require "evercam/users"
21
+ require "evercam/vendors"
22
+ require "evercam/api"
23
+
24
+ module Evercam
25
+ end
@@ -0,0 +1,215 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ class API
5
+ # Include the module components.
6
+ include Cameras
7
+ include Logs
8
+ include Models
9
+ include Public
10
+ include Shares
11
+ include Snapshots
12
+ include Users
13
+ include Vendors
14
+
15
+ # Constructor for the API class.
16
+ #
17
+ # ==== Parameters
18
+ # options:: A Hash of additional options to be used by the instance. At
19
+ # a minimum this must include keys for :api_id and :api_key.
20
+ def initialize(options={})
21
+ @api_id = options[:api_id]
22
+ @api_key = options[:api_key]
23
+ @logger = NullLogger.new(STDOUT)
24
+ @host = "api.evercam.io"
25
+ @port = nil
26
+ @scheme = "https"
27
+ @version = "1"
28
+ assign_options(options)
29
+ end
30
+
31
+ # This method will ping Evercam and provide feedback details that include
32
+ # whether the API credentials provided are valid.
33
+ def test
34
+ handle_response(call("/test"))
35
+ end
36
+
37
+ private
38
+
39
+ # This method is used internally by the class to assign recognised options
40
+ # to class settings.
41
+ #
42
+ # ==== Parameters
43
+ # options:: A Hash of the options to be processed.
44
+ def assign_options(options)
45
+ @logger = options[:logger] if options.include?(:logger)
46
+ @host = options[:host] if options.include?(:host)
47
+ @port = options[:port] if options.include?(:port)
48
+ @scheme = options[:scheme] if options.include?(:scheme)
49
+ @version = options[:version] if options.include?(:version)
50
+ end
51
+
52
+ # This method makes the actual call to the API endpoint for a request.
53
+ #
54
+ # ==== Parameters
55
+ # path:: The path to the API endpoint to be called.
56
+ # verb:: The HTTP verb to be used when making the request. Defaults
57
+ # to :get.
58
+ # parameters:: A Hash of the parameters to be sent with the request.
59
+ # Defaults to an empty Hash and need not include the
60
+ # requesters API credentials as these are added to the
61
+ # request automatically.
62
+ def call(path, verb=:get, parameters={})
63
+ connection = Faraday.new(url: base_url) do |faraday|
64
+ faraday.request :url_encoded
65
+ faraday.use FaradayMiddleware::FollowRedirects
66
+ faraday.adapter :typhoeus
67
+ end
68
+
69
+ values = {}.merge(parameters)
70
+ if @api_id && @api_key
71
+ values = values.merge(api_id: @api_id, api_key: @api_key)
72
+ end
73
+
74
+ started = Time.now
75
+ response = nil
76
+ case verb
77
+ when :get
78
+ @logger.info "GET #{endpoint_url(path)}"
79
+ @logger.info "Parameters: #{values}"
80
+ response = connection.get(api_path(path), values)
81
+ when :delete
82
+ @logger.info "DELETE #{endpoint_url(path)}"
83
+ @logger.info "Parameters: #{values}"
84
+ response = connection.delete(api_path(path), values)
85
+ when :patch
86
+ @logger.info "PATCH #{endpoint_url(path)}"
87
+ @logger.info "Parameters: #{values}"
88
+ response = connection.patch(api_path(path), values)
89
+ when :post
90
+ @logger.info "POST #{endpoint_url(path)}"
91
+ @logger.info "Parameters: #{values}"
92
+ response = connection.post(api_path(path), values)
93
+ when :put
94
+ @logger.info "PUT #{endpoint_url(path)}"
95
+ @logger.info "Parameters: #{values}"
96
+ response = connection.put(api_path(path), values)
97
+ else
98
+ message = "Unrecognised HTTP method '#{verb}' specified for request."
99
+ @logger.error message
100
+ raise EvercamError.new(message)
101
+ end
102
+ finished = Time.now
103
+ @logger.info "API Call Took: #{finished - started}"
104
+ response
105
+ end
106
+
107
+ # This method provides generic processing of responses from a call to the
108
+ # API. The response status is first checked to see whether a success code
109
+ # was returned from the server. The response will then be checked for
110
+ # contents and an error raised if there are none. The contents will then
111
+ # be checked to see if they contain an error response and an error raised
112
+ # if this is the case. Finally, if all is well the parsed contents are
113
+ # returned.
114
+ def handle_response(response)
115
+ data = nil
116
+ if (200..299).include?(response.status)
117
+ if !response.body.nil? && response.body.strip != ''
118
+ data = parse_response_body(response)
119
+ if data.nil?
120
+ message = "API call failed to return any data or "\
121
+ "contained data that could not be parsed."
122
+ @logger.error message
123
+ raise EvercamError.new(message, "invalid_response", response.status)
124
+ end
125
+ handle_error_response(data, response.status) if data.include?("message")
126
+ end
127
+ else
128
+ @logger.error "API call returned with a status of #{response.status}."
129
+ handle_error_response(parse_response_body(response), response.status)
130
+ end
131
+ data
132
+ end
133
+
134
+ # This method is similar to the handle_response method with the exception
135
+ # that, if the request returns a success status, the method returns the
136
+ # response body as is, without trying to parse it as JSON.
137
+ #
138
+ # ==== Parameters
139
+ # response:: The request response to be handled.
140
+ def handle_raw(response)
141
+ data = nil
142
+ if !(200..299).include?(response.status)
143
+ data = parse_response_body(response)
144
+ message = nil
145
+ if !data.nil? && data.include?("message")
146
+ handle_error_response(data, response.status)
147
+ else
148
+ message = "Evercam API call returned a #{response.status} code. "\
149
+ "Response body was '#{response.body}'."
150
+ @logger.error message
151
+ raise EvercamError.new(message, "invalid_response", response.status)
152
+ end
153
+ else
154
+ data = response.body
155
+ end
156
+ data
157
+ end
158
+
159
+ # This method encapsulates the functionality and error handling for
160
+ # parsing the contents of an API response. The nethod returns nil if it
161
+ # is unable to parse out contents from the response.
162
+ #
163
+ # ==== Parameters
164
+ # response:: The API call response to be parsed.
165
+ def parse_response_body(response)
166
+ contents = nil
167
+ if !response.body.nil? && response.body.strip != ""
168
+ begin
169
+ contents = JSON.parse(response.body)
170
+ rescue => error
171
+ @logger.error "Error interpreting response for API call.\nCause: #{error}"
172
+ end
173
+ end
174
+ contents
175
+ end
176
+
177
+ # This method fetches the base URL component for all API endpoints and
178
+ # constructs it from settings within the class instance.
179
+ def base_url
180
+ url = StringIO.new
181
+ url << @scheme << "://" << @host
182
+ url << ":" << @port if !@port.nil?
183
+ url.string
184
+ end
185
+
186
+ # This method generates a versioned path for an API endpoint.
187
+ #
188
+ # ==== Parameters
189
+ # suffix:: The API call dependent part of the path.
190
+ def api_path(suffix)
191
+ ((/.+\..+$/ =~ suffix) != 0) ? "/v1#{suffix}.json" : "/v1#{suffix}"
192
+ end
193
+
194
+ # This method generates the fully qualified URL for an API endpoint.
195
+ #
196
+ # ==== Parameters
197
+ # suffix:: The API call dependent part of the path.
198
+ def endpoint_url(suffix)
199
+ "#{base_url}#{api_path(suffix)}"
200
+ end
201
+
202
+ # This method processes a standard Evercam API error response to raise
203
+ # an exception from it.
204
+ #
205
+ # ==== Parameters
206
+ # data:: The parsed response data.
207
+ # status:: The HTTP status code associated with the response.
208
+ def handle_error_response(data, status)
209
+ message = (data["message"] || "Evercam API call returned an error.")
210
+ @logger.error "API response contains error details.\nMessage: #{message}\n"\
211
+ "Code: #{data["code"]}\nStatus: #{status}"
212
+ raise EvercamError.new(message, data["code"], status, *data["context"])
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,116 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Cameras
5
+ # Test whether a given set of camera parameters are correct.
6
+ #
7
+ # ==== Parameters
8
+ # external_url:: The external URL of the camera to be tested.
9
+ # jpg_url:: The JPEG URL of the camera to be tested.
10
+ # user_name:: The camera user name to be used in the test.
11
+ # password:: The camera password to be used in the test.
12
+ def test_camera(external_url, jpg_url, user_name, password)
13
+ parameters = {external_url: external_url,
14
+ jpg_url: jpg_url,
15
+ cam_username: user_name,
16
+ cam_password: password}
17
+ handle_response(call("/cameras/test", :get, parameters))
18
+ end
19
+
20
+ # This method attempts to retrieve the details for a specific camera.
21
+ #
22
+ # ==== Parameters
23
+ # camera_id:: The unique identifier for the camera to query.
24
+ def get_camera(camera_id)
25
+ data = handle_response(call("/cameras/#{camera_id}"))
26
+ if !data.include?("cameras") || data["cameras"].size == 0
27
+ message = "Invalid response received from server."
28
+ @logger.error message
29
+ raise EvercamError.new(message)
30
+ end
31
+ data["cameras"][0]
32
+ end
33
+
34
+ # This method attempts to update the details associated with a camera.
35
+ #
36
+ # ==== Parameters
37
+ # camera_id:: The unique identifier of the camera to be updated.
38
+ # values:: A Hash of the values to be set. Keys recognosed in this
39
+ # parameter include :name, :is_public, :external_host,
40
+ # :internal_host, :external_http_port, :internal_http_port,
41
+ # :external_rtsp_port, :internal_rtsp_port, :jpg_url,
42
+ # :cam_username and :cam_password - all other parameters
43
+ # will be ignored.
44
+ def update_camera(camera_id, values={})
45
+ handle_response(call("/cameras/#{camera_id}", :patch, values)) if !values.empty?
46
+ self
47
+ end
48
+
49
+ # Delete a camera from the system.
50
+ #
51
+ # ==== Parameters
52
+ # camera_id:: The unique identifier of the camera to be deleted.
53
+ def delete_camera(camera_id)
54
+ handle_response(call("/cameras/#{camera_id}", :delete))
55
+ self
56
+ end
57
+
58
+ # This method fetches details for a set of cameras based on their unique
59
+ # identifiers.
60
+ #
61
+ # ==== Parameters
62
+ # camera_ids:: A collection of 1 or more camera ids for the cameras to
63
+ # fetch details for.
64
+ def get_cameras(*camera_ids)
65
+ data = handle_response(call("", :get, {ids: camera_ids.join(",")})) if !camera_ids.empty?
66
+ if !data.include?("cameras")
67
+ message = "Invalid response received from server."
68
+ @logger.error message
69
+ raise EvercamError.new(message)
70
+ end
71
+ data["cameras"]
72
+ end
73
+
74
+ # This method creates a new camera in the system.
75
+ #
76
+ # ==== Parameters
77
+ # camera_id:: The unique identifier to be assigned to the new camera.
78
+ # name:: The name for the new camera.
79
+ # is_public:: A boolean to indicate whether the new camera is public.
80
+ # values:: A Hash of additional settings for the camera. The following
81
+ # keys are recognised :external_host, internal_host,
82
+ # :external_http_port, :internal_http_port,
83
+ # :external_rtsp_port, :internal_rtsp_port, :jpg_url,
84
+ # :cam_username and :cam_password.
85
+ def create_camera(camera_id, name, is_public, values={})
86
+ parameters = {id: camera_id,
87
+ name: name,
88
+ is_public: is_public}.merge(values)
89
+ data = handle_response(call("/cameras", :post, parameters))
90
+ if !data.include?("cameras") || data["cameras"].size == 0
91
+ message = "Invalid response received from server."
92
+ @logger.error message
93
+ raise EvercamError.new(message)
94
+ end
95
+ data["cameras"][0]
96
+ end
97
+
98
+ # This method changes the owner of a camera. You must be the owner of the
99
+ # camera to call this method and all artifacts relating to the camera
100
+ # transfer ownership when the camera does.
101
+ #
102
+ # ==== Parameters
103
+ # camera_id:: The unique identifier of the camera to be transferred.
104
+ # user_id: The Evercam user name or email address of the new owner for
105
+ # the camera.
106
+ def change_camera_owner(camera_id, user_id)
107
+ data = handle_response(call("/cameras/#{camera_id}", :put, {user_id: user_id}))
108
+ if !data.include?("cameras") || data["cameras"].empty?
109
+ message = "Invalid response received from server."
110
+ @logger.error message
111
+ raise EvercamError.new(message)
112
+ end
113
+ data["cameras"].first
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ # This is the base error class for exceptions generated within the Evercam
5
+ # library.
6
+ class EvercamError < StandardError
7
+ # Constructor for the EvercamError class.
8
+ #
9
+ # ==== Parameters
10
+ # message:: A String containing the error message for the exception.
11
+ # code:: The error code associated with the exception if one is
12
+ # available. Defaults to nil.
13
+ # status:: The HTTP status code associated with the exception if one
14
+ # is available. Defaults to nil.
15
+ # *context:: A collection of contextual data associated with the
16
+ # exception.
17
+ def initialize(message, code=nil, status=nil, *context)
18
+ super(message)
19
+ @code = code
20
+ @status = status
21
+ @context = context
22
+ end
23
+
24
+ attr_reader :status, :context
25
+
26
+ def code
27
+ (@code || "unknown_error")
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Logs
5
+ # This method fetches activity log details for a specified camera from
6
+ # the system.
7
+ #
8
+ # ==== Parameters
9
+ # camera_id:: The unique identifier of the camera to fetch the logs for.
10
+ # options:: A Hash of additional parameters for the request. Currently
11
+ # recognised keys for this request are :from, :to, :limit,
12
+ # :page, :types and :objects.
13
+ def get_logs(camera_id, options={})
14
+ parameters = {}
15
+ parameters[:from] = options[:from].to_i if options.include?(:from)
16
+ parameters[:to] = options[:to].to_i if options.include?(:to)
17
+ parameters[:limit] = options[:limit] if options.include?(:limit)
18
+ parameters[:page] = options[:page] if options.include?(:page)
19
+ if options.include?(:types)
20
+ values = options[:types]
21
+ if values.kind_of?(Array)
22
+ parameters[:types] = options[:types].join(",")
23
+ else
24
+ parameters[:types] = options[:types]
25
+ end
26
+ end
27
+ parameters[:objects] = (options[:objects] == true) if options.include?(:objects)
28
+ data = handle_response(call("/cameras/#{camera_id}/logs", :get, parameters))
29
+ if !data.include?("logs") || !data.include?("pages")
30
+ message = "Invalid response received from server."
31
+ @logger.error message
32
+ raise EvercamError.new(message)
33
+ end
34
+ {logs: data["logs"], pages: data["pages"]}
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Models
5
+ # This method fetches a list of all models support within Evercam.
6
+ def get_all_models
7
+ data = handle_response(call("/models"))
8
+ if !data.include?("vendors")
9
+ message = "Invalid response received from server."
10
+ @logger.error message
11
+ raise EvercamError.new(message)
12
+ end
13
+ data["vendors"]
14
+ end
15
+
16
+ # This method fetches a list of models for a specified vendor.
17
+ #
18
+ # ==== Parameters
19
+ # vendor:: The unique identifier for the vendor to fetch the list of
20
+ # models for.
21
+ def get_vendor_models(vendor)
22
+ data = handle_response(call("/models/#{vendor}"))
23
+ if !data.include?("vendors") || data["vendors"].empty?
24
+ message = "Invalid response received from server."
25
+ @logger.error message
26
+ raise EvercamError.new(message)
27
+ end
28
+ data["vendors"].first
29
+ end
30
+
31
+ # This method fetches details for a specific model for a given vendor.
32
+ #
33
+ # ==== Parameters
34
+ # vendor:: The unique identifier for the vendor who owns the model.
35
+ # model:: The unique identifier for the model to fetch.
36
+ def get_vendor_model(vendor, model)
37
+ data = handle_response(call("/models/#{vendor}/#{model}"))
38
+ if !data.include?("models") || data["models"].empty?
39
+ message = "Invalid response received from server."
40
+ @logger.error message
41
+ raise EvercamError.new(message)
42
+ end
43
+ data["models"].first
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ class NullLogger < Logger
5
+ def initialize(*args)
6
+ super(*args)
7
+ end
8
+
9
+ def add(*args, &block)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Public
5
+ # This method fetches a list of public and discoverable cameras from
6
+ # with Evercam.
7
+ #
8
+ # ==== Parameters
9
+ # critera:: A Hash of search criteria to use for the list returned
10
+ # by the request. Currently recognised options include
11
+ # :case_sensitive, :id_starts_with, :id_ends_with,
12
+ # :id_contains, :offset and :limit.
13
+ def get_public_cameras(criteria={})
14
+ data = handle_response(call("/public/cameras", :get, criteria))
15
+ if !data.include?("cameras")
16
+ message = "Invalid response received from server."
17
+ @logger.error message
18
+ raise EvercamError.new(message)
19
+ end
20
+ {cameras: data["cameras"], pages: data["pages"]}
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,169 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Shares
5
+ # Fetches details for the camera share for a specific camera and user.
6
+ #
7
+ # ==== Parameters
8
+ # camera_id:: The unique identifier of the camera that was shared.
9
+ # user_id:: Either the user name or email address of the user that the
10
+ # camera was shared with.
11
+ def get_camera_share(camera_id, user_id)
12
+ data = handle_response(call("/shares", :get, camera_id: camera_id, user_id: user_id))
13
+ if !data.include?("shares")
14
+ message = "Invalid response received from server."
15
+ @logger.error message
16
+ raise EvercamError.new(message)
17
+ end
18
+ data["shares"].first
19
+ end
20
+
21
+ # This method fetches a list of shares for a specified camera.
22
+ #
23
+ # ==== Parameters
24
+ # camera_id:: The unique identifier of the camera to produce the list of
25
+ # shares for.
26
+ def get_camera_shares(camera_id)
27
+ data = handle_response(call("/shares/cameras/#{camera_id}"))
28
+ if !data.include?("shares")
29
+ message = "Invalid response received from server."
30
+ @logger.error message
31
+ raise EvercamError.new(message)
32
+ end
33
+ data["shares"]
34
+ end
35
+
36
+ # This method shares an existing camera with an email address. If the
37
+ # email address ties to an Evercam user account then a share is created
38
+ # for the account. If this is not the case then an email is dispatched
39
+ # to invite the user to come join Evercam and make use of the camera
40
+ # shared with them.
41
+ #
42
+ # ==== Parameters
43
+ # camera_id:: The unique identifier for the camera being shared.
44
+ # email:: The email address of the individual to share the camera
45
+ # with.
46
+ # rights:: Either a String indicating the rights to be granted
47
+ # to the user as a comma separated list or an Array of
48
+ # Strings containing the name of the rights to be granted
49
+ # with the share.
50
+ # options:: A Hash of addition parameters to the request. Currently
51
+ # recognised keys within this Hash are :grantor, :message
52
+ # and :notify.
53
+ def share_camera(camera_id, email, rights, options={})
54
+ parameters = {email: email}
55
+ parameters[:rights] = (rights.kind_of?(String) ? rights : rights.join(","))
56
+ parameters[:grantor] = options[:grantor] if options.include?(:grantor)
57
+ parameters[:message] = options[:message] if options.include?(:message)
58
+ parameters[:notify] = (options[:notify] == true) if options.include?(:notify)
59
+ data = handle_response(call("/shares/cameras/#{camera_id}", :post, parameters))
60
+
61
+ output = nil
62
+ if data.include?("shares")
63
+ if !data["shares"].empty?
64
+ output = data["shares"].first
65
+ output["type"] = "share"
66
+ end
67
+ elsif data.include?("share_requests")
68
+ if !data["share_requests"].empty?
69
+ output = data["share_requests"].first
70
+ output["type"] = "share_request"
71
+ end
72
+ end
73
+
74
+ if output.nil?
75
+ message = "Invalid response received from server."
76
+ @logger.error message
77
+ raise EvercamError.new(message)
78
+ end
79
+ output
80
+ end
81
+
82
+ # This method deletes an existing camera share.
83
+ #
84
+ # ==== Parameters
85
+ # camera_id:: The unique identifier for the camera that was shared.
86
+ # share_id:: The unique identifier of the share that is being deleted.
87
+ def delete_camera_share(camera_id, share_id)
88
+ handle_response(call("/shares/cameras/#{camera_id}", :delete, share_id: share_id))
89
+ self
90
+ end
91
+
92
+ # This method updates the settings on a camera share, altering the right
93
+ # available to the user that the camera was shared with.
94
+ #
95
+ # ==== Parameters
96
+ # share_id:: The unique identifier of the camera share to be updated.
97
+ # rights:: Either an array of right name strings or a single string
98
+ # consisting of a comma separated array of right names.
99
+ def update_camera_share(share_id, rights)
100
+ parameters = {rights: (rights.kind_of?(String) ? rights : rights.join(","))}
101
+ handle_response(call("/shares/cameras/#{share_id}", :patch, parameters))
102
+ self
103
+ end
104
+
105
+ # Fetches a list of the camera shares currently available to a specified
106
+ # user.
107
+ #
108
+ # ==== Parameters
109
+ # user_id:: The unique identifier of the user to fetch the list of shares
110
+ # for.
111
+ def get_user_camera_shares(user_id)
112
+ data = handle_response(call("/shares/users/#{user_id}"))
113
+ if !data.include?("shares")
114
+ message = "Invalid response received from server."
115
+ @logger.error message
116
+ raise EvercamError.new(message)
117
+ end
118
+ data["shares"]
119
+ end
120
+
121
+ # This method fetches a list of share requests pending on a specified
122
+ # camera.
123
+ #
124
+ # ==== Parameters
125
+ # camera_id:: The unique identifier for the camera to fetch the list
126
+ # of pending share requests for.
127
+ # status:: The status of the camera share requests to be retrieved.
128
+ # This should be either 'PENDING', 'USED' or 'CANCELLED'.
129
+ # Defaults to nil to indicate no particular status is
130
+ # being requested.
131
+ def get_camera_share_requests(camera_id, status=nil)
132
+ parameters = {}
133
+ parameters[:status] = status if !status.nil?
134
+ data = handle_response(call("/shares/requests/#{camera_id}", :get, parameters))
135
+ if !data.include?("share_requests")
136
+ message = "Invalid response received from server."
137
+ @logger.error message
138
+ raise EvercamError.new(message)
139
+ end
140
+ data["share_requests"]
141
+ end
142
+
143
+ # This method is used to cancel a pending camera share request.
144
+ #
145
+ # ==== Parameters
146
+ # request_id:: The unique identifier of the share request to be
147
+ # cancelled.
148
+ # email:: The email address associated with the share request
149
+ # being cancelled.
150
+ def cancel_camera_share_request(request_id, email)
151
+ handle_response(call("/shares/requests/#{request_id}", :delete, email: email))
152
+ self
153
+ end
154
+
155
+ # This method updates the rights to be granted when a pending camera share
156
+ # request is accepted.
157
+ #
158
+ # ==== Parameters
159
+ # request_id:: The unique identifier of the share request to be
160
+ # updated.
161
+ # rights:: Either an array of right name strings or a string
162
+ # containing a comma separated list of right names.
163
+ def update_camera_share_request(request_id, rights)
164
+ parameters = {rights: (rights.kind_of?(String) ? rights : rights.join(","))}
165
+ handle_response(call("/shares/requests/#{request_id}", :patch, parameters))
166
+ self
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,204 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Snapshots
5
+ # This method fetches a Base64 encoded snapshot from a camera.
6
+ #
7
+ # ==== Parameters
8
+ # camera_id:: The unique identifier for the camera to take the snapshot
9
+ # from.
10
+ def get_live_image(camera_id)
11
+ data = handle_response(call("/cameras/#{camera_id}/live"))
12
+ if !data.include?("data")
13
+ message = "Invalid response received from server."
14
+ @logger.error message
15
+ raise EvercamError.new(message)
16
+ end
17
+ data["data"]
18
+ end
19
+
20
+ # This method returns details for all snapshots stored for a specified
21
+ # camera.
22
+ #
23
+ # ==== Parameters
24
+ # camera_id:: The unique identifier for the camera to list snapshots
25
+ # for.
26
+ def get_snapshots(camera_id)
27
+ data = handle_response(call("/cameras/#{camera_id}/snapshots"))
28
+ if !data.include?("snapshots")
29
+ message = "Invalid response received from server."
30
+ @logger.error message
31
+ raise EvercamError.new(message)
32
+ end
33
+ data["snapshots"].inject([]) do |list, entry|
34
+ entry["created_at"] = Time.at(entry["created_at"])
35
+ list << entry
36
+ end
37
+ end
38
+
39
+ # This method grabs a snapshot from a specified camera and stores it using
40
+ # the current timestamp.
41
+ #
42
+ # ==== Parameters
43
+ # camera_id:: The unique identifier for the camera to grab the snapshot
44
+ # from.
45
+ # comment:: An optional comment to put on the newly created snapshot.
46
+ # Defaults to nil to indicate no comment.
47
+ def store_snapshot(camera_id, comment=nil)
48
+ parameters = {}
49
+ parameters[:notes] = comment.to_s if !comment.nil?
50
+ data = handle_response(call("/cameras/#{camera_id}/snapshots", :post, parameters))
51
+ if !data.include?("snapshots") || data["snapshots"].size == 0
52
+ message = "Invalid response received from server."
53
+ @logger.error message
54
+ raise EvercamError.new(message)
55
+ end
56
+ data["snapshots"].first["created_at"] = Time.at(data["snapshots"].first["created_at"])
57
+ data["snapshots"].first
58
+ end
59
+
60
+ # This method fetches the most up-to-date snapshot for a specified camera
61
+ # stored in the system.
62
+ #
63
+ # ==== Parameters
64
+ # camera_id:: The unique identifier to fetch the snapshot for.
65
+ # complete:: A flag to indicate whether the response should include the
66
+ # image data for the snapshot. Defaults to false.
67
+ def get_latest_snapshot(camera_id, complete=false)
68
+ parameters = {}
69
+ parameters[:with_data] = true if complete == true
70
+ data = handle_response(call("/cameras/#{camera_id}/snapshots/latest", :get, parameters))
71
+ if !data.include?("snapshots")
72
+ message = "Invalid response received from server."
73
+ @logger.error message
74
+ raise EvercamError.new(message)
75
+ end
76
+ snapshot = nil
77
+ if !data["snapshots"].empty?
78
+ snapshot = data["snapshots"].first
79
+ snapshot["created_at"] = Time.at(snapshot["created_at"])
80
+ end
81
+ snapshot
82
+ end
83
+
84
+ # This method fetches a list of snapshot stored in the system for a
85
+ # specified camera between a stated start and end date.
86
+ #
87
+ # ==== Parameters
88
+ # camera_id:: The unique identifier of the camera to fetch snapshots for.
89
+ # from:: The date/time of the start of the range to fetch snapshots
90
+ # for.
91
+ # to:: The date/time of the end of the range to fetch snapshots
92
+ # for.
93
+ # options:: A Hash of the options to be given to the request. Keys
94
+ # recognised in this Hash are :with_data, :limit and
95
+ # :page.
96
+ def get_snapshots_in_date_range(camera_id, from, to, options={})
97
+ parameters = {from: from.to_i, to: to.to_i, with_data: (options[:with_data] == true)}
98
+ if options.include?(:limit)
99
+ parameters[:limit] = options[:limit]
100
+ else
101
+ parameters[:limit] = (options[:with_data] ? 10 : 100)
102
+ end
103
+ parameters[:page] = options[:page] if options.include?(:page)
104
+ data = handle_response(call("/cameras/#{camera_id}/snapshots/range", :get, parameters))
105
+ if !data.include?("snapshots")
106
+ message = "Invalid response received from server."
107
+ @logger.error message
108
+ raise EvercamError.new(message)
109
+ end
110
+ data["snapshots"].inject([]) do |list, entry|
111
+ entry["created_at"] = Time.at(entry["created_at"])
112
+ list << entry
113
+ end
114
+ end
115
+
116
+ # This method returns a list of dates for which stored snapshots are
117
+ # available on a specified camera given a specific month and year.
118
+ #
119
+ # ==== Parameters
120
+ # camera_id:: The unique identifier of the camera to perform the check
121
+ # for.
122
+ # month:: The month of the year, as an integer, to perform the
123
+ # check for. Defaults to nil to indicate the current
124
+ # month.
125
+ # year:: The year to perform the check for. Defaults to nil to
126
+ # indicate the current year.
127
+ def get_snapshot_dates(camera_id, month=nil, year=nil)
128
+ month = (month || Time.now.month)
129
+ year = (year || Time.now.year)
130
+ data = handle_response(call("/cameras/#{camera_id}/snapshots/#{year}/#{month}/days"))
131
+ if !data.include?("days")
132
+ message = "Invalid response received from server."
133
+ @logger.error message
134
+ raise EvercamError.new(message)
135
+ end
136
+ data["days"].inject([]) {|list, entry| list << Time.local(year, month, entry)}
137
+ end
138
+
139
+ # This method retrieves a list of Time objects for a specified camera for
140
+ # which their are snapshots stored in the system. The Time objects
141
+ # returned aren't specific snapshot timestamps but are used to indicate
142
+ # the hours during the day for which snapshots are available.
143
+ #
144
+ # ==== Parameters
145
+ # camera_id:: The unique identifier of the camera to fetch the snapshot
146
+ # details for.
147
+ # date:: The day to perfom this check for. The time part of this
148
+ # value is not taken into consideration. Defaults to the
149
+ # current date.
150
+ def get_snapshots_by_hour(camera_id, date=Time.now)
151
+ data = handle_response(call("/cameras/#{camera_id}/snapshots/#{date.year}/#{date.month}/#{date.day}/hours"))
152
+ if !data.include?("hours")
153
+ message = "Invalid response received from server."
154
+ @logger.error message
155
+ raise EvercamError.new(message)
156
+ end
157
+ data["hours"].inject([]) {|list, entry| list << Time.local(date.year, date.month, date.day, entry)}
158
+ end
159
+
160
+ # This method fetches a snapshot for a given timestamp.
161
+ #
162
+ # ==== Parameters
163
+ # camera_id:: The unique identifier for the camera that generated the
164
+ # snapshot.
165
+ # timestamp:: The timestamp of the snapshot to retrieve.
166
+ # options:: A Hash of optional settings for the request. Keys
167
+ # recognised in this Hash are :with_data and :range.
168
+ def get_snapshot_at(camera_id, timestamp, options={})
169
+ parameters = {with_data: (options[:with_data] == true)}
170
+ parameters[:range] = options[:range] if options.include?(:range)
171
+ data = handle_response(call("/cameras/#{camera_id}/snapshots/#{timestamp.to_i}",
172
+ :get, parameters))
173
+ if !data.include?("snapshots") || data["snapshots"].size == 0
174
+ message = "Invalid response received from server."
175
+ @logger.error message
176
+ raise EvercamError.new(message)
177
+ end
178
+ data["snapshots"].first["created_at"] = Time.at(data["snapshots"].first["created_at"])
179
+ data["snapshots"].first
180
+ end
181
+
182
+ # This method deletes a snapshot from the system.
183
+ #
184
+ # ==== Parameters
185
+ # camera_id:: The unique identifier of the camera that the snapshot
186
+ # is stored under.
187
+ # timestamp:: The timestamp of the snapshot to be deleted.
188
+ def delete_snapshot(camera_id, timestamp)
189
+ data = handle_response(call("/cameras/#{camera_id}/snapshots/#{timestamp.to_i}", :delete))
190
+ self
191
+ end
192
+
193
+ # This method takes a snapshot from a specified camera and returns
194
+ # it's details. Note that the method, when successful, returns a String
195
+ # containing the raw image data.
196
+ #
197
+ # ==== Parameters
198
+ # camera_id:: The unique identifier for the camera to get the snapshot
199
+ # from.
200
+ def get_snapshot(camera_id)
201
+ handle_raw(call("/cameras/#{camera_id}/snapshot.jpg"))
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,87 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Users
5
+ # Fetch details for a specified user.
6
+ #
7
+ # ==== Parameters
8
+ # user:: The Evercam user name or email address of the user to fetch
9
+ # the list of cameras for.
10
+ def get_user(user)
11
+ data = handle_response(call("/users/#{user}"))
12
+ if !data.include?("users") || data["users"].size == 0
13
+ message = "Invalid response received from server."
14
+ @logger.error message
15
+ raise EvercamError.new(message)
16
+ end
17
+ data["users"][0]
18
+ end
19
+
20
+ # Fetches a list of user cameras for a specified user.
21
+ #
22
+ # ==== Parameters
23
+ # user:: The Evercam user name or email address of the user to fetch
24
+ # the list of cameras for.
25
+ # shared:: A boolean to indicate if shared cameras should be included in
26
+ # the fetch. Defaults to false.
27
+ def get_user_cameras(user, shared=false)
28
+ data = handle_response(call("/users/#{user}/cameras", :get, include_shared: shared))
29
+ if !data.include?("cameras")
30
+ message = "Invalid response received from server."
31
+ @logger.error message
32
+ raise EvercamError.new(message)
33
+ end
34
+ data["cameras"]
35
+ end
36
+
37
+ # Updates the details for a user.
38
+ #
39
+ # ==== Parameters
40
+ # user:: The Evercam user name or email address of the user to be
41
+ # updated.
42
+ # values:: A Hash of the values to be updated. Recognized keys in this
43
+ # Hash are :forename, :lastname, :username, :country and :email.
44
+ def update_user(user, values={})
45
+ handle_response(call("/users/#{user}", :patch, values)) if !values.empty?
46
+ self
47
+ end
48
+
49
+ # This method deletes a user account and all details associated with it.
50
+ #
51
+ # ==== Parameters
52
+ # user:: The Evercam user name or email address of the user to be
53
+ # deleted.
54
+ def delete_user(user)
55
+ handle_response(call("/users/#{user}", :delete))
56
+ self
57
+ end
58
+
59
+ # This method creates a new user within the Evercam system.
60
+ #
61
+ # ==== Parameters
62
+ # first_name:: The first name for the new user.
63
+ # last_name:: The last name for the new user.
64
+ # user_name:: The unique system user name for the new user.
65
+ # email:: The email address for the new user.
66
+ # password:: The new users password.
67
+ # country:: The country for the new user.
68
+ # key:: A share request key to be processed during the process
69
+ # of creating the new user account. Defaults to nil.
70
+ def create_user(first_name, last_name, user_name, email, password, country, key=nil)
71
+ parameters = {forename: first_name,
72
+ lastname: last_name,
73
+ username: user_name,
74
+ country: country,
75
+ email: email,
76
+ password: password}
77
+ parameters[:share_request_key] = key if !key.nil?
78
+ data = handle_response(call("/users", :post, parameters))
79
+ if !data.include?('users') || data['users'].empty?
80
+ message = "Invalid response received from server."
81
+ @logger.error message
82
+ raise EvercamError.new(message)
83
+ end
84
+ data['users'].first
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ module Vendors
5
+ # This method returns a list of all vendors in Evercam.
6
+ def get_all_vendors
7
+ data = handle_response(call("/vendors"))
8
+ if !data.include?("vendors")
9
+ message = "Invalid response received from server."
10
+ @logger.error message
11
+ raise EvercamError.new(message)
12
+ end
13
+ data["vendors"]
14
+ end
15
+
16
+ # This method returns a list of vendors that match a specified MAC
17
+ # address prefix.
18
+ #
19
+ # ==== Parameters
20
+ # mac_prefix:: The MAC address prefix to use in the vendor search.
21
+ def get_vendors_by_mac(mac_prefix)
22
+ data = handle_response(call("/vendors/#{mac_prefix}"))
23
+ if !data.include?("vendors")
24
+ message = "Invalid response received from server."
25
+ @logger.error message
26
+ raise EvercamError.new(message)
27
+ end
28
+ data["vendors"]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ # Copyright © 2014, Evercam.
2
+
3
+ module Evercam
4
+ VERSION = "0.1.1"
5
+ end
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evercam
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Evercam
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mocha
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0.beta2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0.beta2
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.8'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.17'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.17'
111
+ - !ruby/object:Gem::Dependency
112
+ name: faraday
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.9'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.9'
125
+ - !ruby/object:Gem::Dependency
126
+ name: faraday_middleware
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.9'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.9'
139
+ - !ruby/object:Gem::Dependency
140
+ name: typhoeus
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.6'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.6'
153
+ description: This library provides a wrapper for using the Evercam API.
154
+ email:
155
+ - howrya@evercam.io
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - CHANGELOG.md
161
+ - LICENSE.txt
162
+ - README.md
163
+ - lib/evercam.rb
164
+ - lib/evercam/api.rb
165
+ - lib/evercam/cameras.rb
166
+ - lib/evercam/exceptions.rb
167
+ - lib/evercam/logs.rb
168
+ - lib/evercam/models.rb
169
+ - lib/evercam/null_logger.rb
170
+ - lib/evercam/public.rb
171
+ - lib/evercam/shares.rb
172
+ - lib/evercam/snapshots.rb
173
+ - lib/evercam/users.rb
174
+ - lib/evercam/vendors.rb
175
+ - lib/evercam/version.rb
176
+ homepage: https://evercam.io
177
+ licenses:
178
+ - Commercial Proprietary
179
+ metadata: {}
180
+ post_install_message:
181
+ rdoc_options: []
182
+ require_paths:
183
+ - lib
184
+ required_ruby_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ required_rubygems_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ requirements: []
195
+ rubyforge_project:
196
+ rubygems_version: 2.2.2
197
+ signing_key:
198
+ specification_version: 4
199
+ summary: A wrapper for the Evercam API.
200
+ test_files: []