evercam 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []