smartcar 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +28 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +22 -1
- data/Rakefile +11 -3
- data/bin/console +4 -3
- data/lib/smartcar.rb +36 -26
- data/lib/smartcar/base.rb +14 -12
- data/lib/smartcar/battery.rb +6 -4
- data/lib/smartcar/battery_capacity.rb +4 -2
- data/lib/smartcar/charge.rb +6 -4
- data/lib/smartcar/engine_oil.rb +5 -3
- data/lib/smartcar/fuel.rb +8 -6
- data/lib/smartcar/location.rb +5 -3
- data/lib/smartcar/oauth.rb +45 -37
- data/lib/smartcar/odometer.rb +4 -2
- data/lib/smartcar/permissions.rb +4 -2
- data/lib/smartcar/tire_pressure.rb +11 -10
- data/lib/smartcar/user.rb +7 -4
- data/lib/smartcar/utils.rb +14 -5
- data/lib/smartcar/vehicle.rb +19 -242
- data/lib/smartcar/vehicle_attributes.rb +7 -5
- data/lib/smartcar/vehicle_utils/actions.rb +61 -0
- data/lib/smartcar/vehicle_utils/batch.rb +83 -0
- data/lib/smartcar/vehicle_utils/data.rb +110 -0
- data/lib/smartcar/version.rb +3 -1
- data/lib/smartcar/vin.rb +4 -2
- data/ruby-sdk.gemspec +24 -21
- metadata +29 -11
data/lib/smartcar/odometer.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Smartcar
|
2
4
|
# class to represent Odometer
|
3
|
-
|
5
|
+
# @attr [Number] distanceLast recorded odometer reading.
|
4
6
|
class Odometer < Base
|
5
7
|
# Path Proc for hitting odometer end point
|
6
|
-
PATH =
|
8
|
+
PATH = proc { |id| "/vehicles/#{id}/odometer" }
|
7
9
|
attr_reader :distance
|
8
10
|
end
|
9
11
|
end
|
data/lib/smartcar/permissions.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Smartcar
|
2
4
|
# class to represent permissions response
|
3
|
-
|
5
|
+
# @attr [Array] permissions Array of permissions granted on the vehicle.
|
4
6
|
class Permissions < Base
|
5
7
|
# Path Proc for hitting permissions end point
|
6
|
-
PATH =
|
8
|
+
PATH = proc { |id| "/vehicles/#{id}/permissions" }
|
7
9
|
attr_reader :permissions
|
8
10
|
end
|
9
11
|
end
|
@@ -1,19 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Smartcar
|
2
4
|
# class to represent Tire Pressure response
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# @attr [Number] back_left Last recorded tire pressure of the back left tire.
|
6
|
+
# @attr [Number] back_right Last recorded tire pressure of the back right tire.
|
7
|
+
# @attr [Number] front_left Last recorded tire pressure of the front left tire.
|
8
|
+
# @attr [Number] front_right Last recorded tire pressure of the front right tire.
|
8
9
|
class TirePressure < Base
|
9
10
|
# Path Proc for hitting tire pressure end point
|
10
|
-
PATH =
|
11
|
+
PATH = proc { |id| "/vehicles/#{id}/tires/pressure" }
|
11
12
|
attr_reader :backLeft, :backRight, :frontLeft, :frontRight
|
12
13
|
|
13
14
|
# just to have Ruby-esque method names
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
alias back_left backLeft
|
16
|
+
alias back_right backRight
|
17
|
+
alias front_left frontLeft
|
18
|
+
alias front_right frontRight
|
18
19
|
end
|
19
20
|
end
|
data/lib/smartcar/user.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Smartcar
|
2
4
|
# Class to get to user API.
|
3
|
-
|
4
|
-
|
5
|
+
# @attr [String] id Smartcar user id.
|
6
|
+
# @attr [String] token Access token used to connect to Smartcar API.
|
5
7
|
class User < Base
|
6
8
|
# Path for hitting user end point
|
7
|
-
USER_PATH = '/user'
|
9
|
+
USER_PATH = '/user'
|
8
10
|
attr_reader :id
|
9
11
|
|
10
12
|
# Class method Used to get user id
|
@@ -15,7 +17,8 @@ module Smartcar
|
|
15
17
|
# @return [String] User ID
|
16
18
|
def self.user_id(token:, version: Smartcar.get_api_version)
|
17
19
|
# @deprecated Please use {#get} instead
|
18
|
-
warn
|
20
|
+
warn '[DEPRECATION] `Smartcar::User.user_id` is deprecated and will be removed in next major version update.
|
21
|
+
Please use `Smartcar::User.get` instead.'
|
19
22
|
get(token: token, version: version).id
|
20
23
|
end
|
21
24
|
|
data/lib/smartcar/utils.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Smartcar
|
4
|
+
# Utils module , provides utility methods to underlying classes
|
3
5
|
module Utils
|
4
6
|
# A constructor to take a hash and assign it to the instance variables
|
5
7
|
# @param options = {} [Hash] Could by any class's hash, but the first level keys should be defined in the class
|
@@ -16,7 +18,7 @@ module Smartcar
|
|
16
18
|
# @return [Hash] hash of all instance variables
|
17
19
|
def to_hash
|
18
20
|
instance_variables.each_with_object({}) do |attribute, hash|
|
19
|
-
hash[attribute.to_s.delete(
|
21
|
+
hash[attribute.to_s.delete('@').to_sym] = instance_variable_get(attribute)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -27,6 +29,7 @@ module Smartcar
|
|
27
29
|
def get_config(config_name)
|
28
30
|
config_name = "INTEGRATION_#{config_name}" if ENV['MODE'] == 'test'
|
29
31
|
raise Smartcar::ConfigNotFound, "Environment variable #{config_name} not found !" unless ENV[config_name]
|
32
|
+
|
30
33
|
ENV[config_name]
|
31
34
|
end
|
32
35
|
|
@@ -36,11 +39,17 @@ module Smartcar
|
|
36
39
|
# @return [Object] nil OR Error object
|
37
40
|
def get_error(response)
|
38
41
|
status = response.status
|
39
|
-
return nil if [200,204].include?(status)
|
42
|
+
return nil if [200, 204].include?(status)
|
40
43
|
return Smartcar::ServiceUnavailableError.new("Service Unavailable - #{response.body}") if status == 404
|
41
44
|
return Smartcar::BadRequestError.new("Bad Request - #{response.body}") if status == 400
|
42
|
-
return Smartcar::AuthenticationError.new(
|
43
|
-
|
45
|
+
return Smartcar::AuthenticationError.new('Authentication error') if status == 401
|
46
|
+
|
47
|
+
Smartcar::ExternalServiceError.new("API error - #{response.body}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def handle_errors(response)
|
51
|
+
error = get_error(response)
|
52
|
+
raise error if error
|
44
53
|
end
|
45
54
|
end
|
46
55
|
end
|
data/lib/smartcar/vehicle.rb
CHANGED
@@ -1,25 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Smartcar
|
2
4
|
# Vehicle class to connect to vehicle basic info,disconnect, lock unlock and get all vehicles API
|
3
5
|
# For ease of use, this also has methods define to be able to call other resources on a vehicle object
|
4
6
|
# For Ex. Vehicle object will be treate as an entity and doing vehicle_object.
|
5
7
|
# Battery should return Battery object.
|
6
8
|
#
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
# @attr [String] token Access token used to connect to Smartcar API.
|
10
|
+
# @attr [String] id Smartcar vehicle ID.
|
11
|
+
# @attr [String] unit_system unit system to represent the data in.
|
10
12
|
class Vehicle < Base
|
13
|
+
include VehicleUtils::Data
|
14
|
+
include VehicleUtils::Actions
|
15
|
+
include VehicleUtils::Batch
|
11
16
|
# Path for hitting compatibility end point
|
12
|
-
COMPATIBLITY_PATH = '/compatibility'
|
17
|
+
COMPATIBLITY_PATH = '/compatibility'
|
13
18
|
|
14
19
|
# Path for hitting vehicle ids end point
|
15
|
-
PATH =
|
20
|
+
PATH = proc { |id| "/vehicles/#{id}" }
|
16
21
|
|
17
22
|
attr_reader :id
|
18
23
|
|
19
24
|
def initialize(token:, id:, unit_system: IMPERIAL, version: Smartcar.get_api_version)
|
25
|
+
super
|
20
26
|
raise InvalidParameterValue.new, "Invalid Units provided : #{unit_system}" unless UNITS.include?(unit_system)
|
21
|
-
raise InvalidParameterValue.new,
|
22
|
-
raise InvalidParameterValue.new,
|
27
|
+
raise InvalidParameterValue.new, 'Vehicle ID (id) is a required field' if id.nil?
|
28
|
+
raise InvalidParameterValue.new, 'Access Token(token) is a required field' if token.nil?
|
29
|
+
|
23
30
|
@token = token
|
24
31
|
@id = id
|
25
32
|
@unit_system = unit_system
|
@@ -33,7 +40,7 @@ module Smartcar
|
|
33
40
|
#
|
34
41
|
# @return [Array] of vehicle IDs(Strings)
|
35
42
|
def self.all_vehicle_ids(token:, options: {}, version: Smartcar.get_api_version)
|
36
|
-
response,
|
43
|
+
response, = new(token: token, id: 'none', version: version).fetch(
|
37
44
|
path: PATH.call(''),
|
38
45
|
options: options
|
39
46
|
)
|
@@ -50,10 +57,11 @@ module Smartcar
|
|
50
57
|
#
|
51
58
|
# @return [Boolean] true or false
|
52
59
|
def self.compatible?(vin:, scope:, country: 'US', version: Smartcar.get_api_version)
|
53
|
-
raise InvalidParameterValue.new,
|
54
|
-
raise InvalidParameterValue.new,
|
60
|
+
raise InvalidParameterValue.new, 'vin is a required field' if vin.nil?
|
61
|
+
raise InvalidParameterValue.new, 'scope is a required field' if scope.nil?
|
55
62
|
|
56
|
-
response,
|
63
|
+
response, = new(token: 'none', id: 'none', version: version).fetch(
|
64
|
+
path: COMPATIBLITY_PATH,
|
57
65
|
options: {
|
58
66
|
vin: vin,
|
59
67
|
scope: scope.join(' '),
|
@@ -64,241 +72,10 @@ module Smartcar
|
|
64
72
|
response['compatible']
|
65
73
|
end
|
66
74
|
|
67
|
-
# Method to get batch requests
|
68
|
-
# API - https://smartcar.com/docs/api#post-batch-request
|
69
|
-
# @param attributes [Array] Array of strings or symbols of attributes to be fetched together
|
70
|
-
#
|
71
|
-
# @return [Hash] Hash wth key as requested attribute(symbol) and value as Error OR Object of the requested attribute
|
72
|
-
def batch(attributes = [])
|
73
|
-
raise InvalidParameterValue.new, "vin is a required field" if attributes.nil?
|
74
|
-
request_body = get_batch_request_body(attributes)
|
75
|
-
response, _meta = post(PATH.call(id) + "/batch", request_body)
|
76
|
-
process_batch_response(response)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Fetch the list of permissions that this application has been granted for
|
80
|
-
# this vehicle
|
81
|
-
# EX : Smartcar::Vehicle.new(token: token, id: id).permissions
|
82
|
-
# @param options [Hash] - Optional filter parameters (check documentation)
|
83
|
-
#
|
84
|
-
# @return [Permissions] object
|
85
|
-
def permissions(options: {})
|
86
|
-
get_attribute(Permissions)
|
87
|
-
end
|
88
|
-
|
89
|
-
# Method Used toRevoke access for the current requesting application
|
90
|
-
# API - https://smartcar.com/docs/api#delete-disconnect
|
91
|
-
#
|
92
|
-
# @return [Boolean] true if success
|
93
|
-
def disconnect!
|
94
|
-
response = delete(PATH.call(id) + "/application")
|
95
|
-
response['status'] == SUCCESS
|
96
|
-
end
|
97
|
-
|
98
|
-
# Methods Used to lock car
|
99
|
-
# API - https://smartcar.com/docs/api#post-security
|
100
|
-
#
|
101
|
-
# @return [Boolean] true if success
|
102
|
-
def lock!
|
103
|
-
lock_or_unlock!(action: Smartcar::LOCK)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Methods Used to unlock car
|
107
|
-
# API - https://smartcar.com/docs/api#post-security
|
108
|
-
#
|
109
|
-
# @return [Boolean] true if success
|
110
|
-
def unlock!
|
111
|
-
lock_or_unlock!(action: Smartcar::UNLOCK)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Method used to start charging a car
|
115
|
-
#
|
116
|
-
#
|
117
|
-
# @return [Boolean] true if success
|
118
|
-
def start_charge!
|
119
|
-
start_or_stop_charge!(action: Smartcar::START_CHARGE)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Method used to stop charging a car
|
123
|
-
#
|
124
|
-
#
|
125
|
-
# @return [Boolean] true if success
|
126
|
-
def stop_charge!
|
127
|
-
start_or_stop_charge!(action: Smartcar::STOP_CHARGE)
|
128
|
-
end
|
129
|
-
|
130
|
-
# Returns make model year and id of the vehicle
|
131
|
-
# API - https://smartcar.com/api#get-vehicle-attributes
|
132
|
-
#
|
133
|
-
# @return [VehicleAttributes] object
|
134
|
-
def vehicle_attributes
|
135
|
-
get_attribute(VehicleAttributes)
|
136
|
-
end
|
137
|
-
|
138
|
-
# Returns the state of charge (SOC) and remaining range of an electric or
|
139
|
-
# plug-in hybrid vehicle's battery.
|
140
|
-
# API - https://smartcar.com/docs/api#get-ev-battery
|
141
|
-
#
|
142
|
-
# @return [Battery] object
|
143
|
-
def battery
|
144
|
-
get_attribute(Battery)
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns the capacity of an electric or
|
148
|
-
# plug-in hybrid vehicle's battery.
|
149
|
-
# API - https://smartcar.com/docs/api#get-ev-battery-capacity
|
150
|
-
#
|
151
|
-
# @return [Battery] object
|
152
|
-
def battery_capacity
|
153
|
-
get_attribute(BatteryCapacity)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Returns the current charge status of the vehicle.
|
157
|
-
# API - https://smartcar.com/docs/api#get-ev-battery
|
158
|
-
#
|
159
|
-
# @return [Charge] object
|
160
|
-
def charge
|
161
|
-
get_attribute(Charge)
|
162
|
-
end
|
163
|
-
|
164
|
-
# Returns the remaining life span of a vehicle's engine oil
|
165
|
-
# API - https://smartcar.com/docs/api#get-engine-oil-life
|
166
|
-
#
|
167
|
-
# @return [EngineOil] object
|
168
|
-
def engine_oil
|
169
|
-
get_attribute(EngineOil)
|
170
|
-
end
|
171
|
-
|
172
|
-
# Returns the status of the fuel remaining in the vehicle's gas tank.
|
173
|
-
# API - https://smartcar.com/docs/api#get-fuel-tank
|
174
|
-
#
|
175
|
-
# @return [Fuel] object
|
176
|
-
def fuel
|
177
|
-
get_attribute(Fuel)
|
178
|
-
end
|
179
|
-
|
180
|
-
# Returns the last known location of the vehicle in geographic coordinates.
|
181
|
-
# API - https://smartcar.com/docs/api#get-location
|
182
|
-
#
|
183
|
-
# @return [Location] object
|
184
|
-
def location
|
185
|
-
get_attribute(Location)
|
186
|
-
end
|
187
|
-
|
188
|
-
# Returns the vehicle's last known odometer reading.
|
189
|
-
# API - https://smartcar.com/docs/api#get-odometer
|
190
|
-
#
|
191
|
-
# @return [Odometer] object
|
192
|
-
def odometer
|
193
|
-
get_attribute(Odometer)
|
194
|
-
end
|
195
|
-
|
196
|
-
# Returns the air pressure of each of the vehicle's tires.
|
197
|
-
# API - https://smartcar.com/docs/api#get-tire-pressure
|
198
|
-
#
|
199
|
-
# @return [TirePressure] object
|
200
|
-
def tire_pressure
|
201
|
-
get_attribute(TirePressure)
|
202
|
-
end
|
203
|
-
|
204
|
-
# Returns the vehicle's manufacturer identifier (VIN).
|
205
|
-
# API - https://smartcar.com/docs/api#get-vin
|
206
|
-
#
|
207
|
-
# @return [String] Vin of the vehicle.
|
208
|
-
def vin
|
209
|
-
_object = get_attribute(Vin)
|
210
|
-
@vin ||= _object.vin
|
211
|
-
end
|
212
|
-
|
213
75
|
private
|
214
76
|
|
215
|
-
def allowed_attributes
|
216
|
-
@allowed_attributes ||= {
|
217
|
-
battery: get_path(Battery),
|
218
|
-
charge: get_path(Charge),
|
219
|
-
engine_oil: get_path(EngineOil),
|
220
|
-
fuel: get_path(Fuel),
|
221
|
-
location: get_path(Location),
|
222
|
-
odometer: get_path(Odometer),
|
223
|
-
permissions: get_path(Permissions),
|
224
|
-
tire_pressure: get_path(TirePressure),
|
225
|
-
vin: get_path(Vin),
|
226
|
-
}
|
227
|
-
end
|
228
|
-
|
229
|
-
def path_to_class
|
230
|
-
@path_to_class ||= {
|
231
|
-
get_path(Battery) => Battery,
|
232
|
-
get_path(Charge) => Charge,
|
233
|
-
get_path(EngineOil) => EngineOil,
|
234
|
-
get_path(Fuel) => Fuel,
|
235
|
-
get_path(Location) => Location,
|
236
|
-
get_path(Odometer) => Odometer,
|
237
|
-
get_path(Permissions) => Permissions,
|
238
|
-
get_path(TirePressure) => TirePressure,
|
239
|
-
get_path(Vin) => Vin,
|
240
|
-
}
|
241
|
-
end
|
242
|
-
|
243
|
-
# @private
|
244
|
-
BatchItemResponse = Struct.new(:body, :status, :headers) do
|
245
|
-
def body_with_meta
|
246
|
-
body.merge(meta: headers)
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
def get_batch_request_body(attributes)
|
251
|
-
attributes = validated_attributes(attributes)
|
252
|
-
requests = attributes.each_with_object([]) do |item, requests|
|
253
|
-
requests << { path: allowed_attributes[item] }
|
254
|
-
end
|
255
|
-
{ requests: requests }
|
256
|
-
end
|
257
|
-
|
258
|
-
def process_batch_response(responses)
|
259
|
-
inverted_map = allowed_attributes.invert
|
260
|
-
responses["responses"].each_with_object({}) do |response, result|
|
261
|
-
item_response = BatchItemResponse.new(response["body"], response["code"], response["headers"])
|
262
|
-
error = get_error(item_response)
|
263
|
-
path = response["path"]
|
264
|
-
result[inverted_map[path]] = error || get_object(path_to_class[path], item_response.body_with_meta)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def validated_attributes(attributes)
|
269
|
-
attributes.map!(&:to_sym)
|
270
|
-
unsupported_attributes = (attributes - allowed_attributes.keys) || []
|
271
|
-
unless unsupported_attributes.empty?
|
272
|
-
message = "Unsupported attribute(s) requested in batch - #{unsupported_attributes.join(',')}"
|
273
|
-
raise InvalidParameterValue.new, message
|
274
|
-
end
|
275
|
-
attributes
|
276
|
-
end
|
277
|
-
|
278
|
-
def get_attribute(klass)
|
279
|
-
body, meta = fetch(
|
280
|
-
path: klass::PATH.call(id)
|
281
|
-
)
|
282
|
-
get_object(klass, body.merge(meta: meta))
|
283
|
-
end
|
284
|
-
|
285
77
|
def get_object(klass, data)
|
286
78
|
klass.new(data)
|
287
79
|
end
|
288
|
-
|
289
|
-
def get_path(klass)
|
290
|
-
path = klass::PATH.call(id)
|
291
|
-
path.split("/vehicles/#{id}").last
|
292
|
-
end
|
293
|
-
|
294
|
-
def lock_or_unlock!(action:)
|
295
|
-
response, meta = post(PATH.call(id) + "/security", { action: action })
|
296
|
-
response['status'] == SUCCESS
|
297
|
-
end
|
298
|
-
|
299
|
-
def start_or_stop_charge!(action:)
|
300
|
-
response, meta = post(PATH.call(id) + "/charge", { action: action })
|
301
|
-
response['status'] == SUCCESS
|
302
|
-
end
|
303
80
|
end
|
304
81
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Smartcar
|
2
4
|
# class to represent Vehicle attributes like make model year
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
# @attr [String] id Smartcar vehicle ID
|
6
|
+
# @attr [String] make Manufacturer of the vehicle.
|
7
|
+
# @attr [String] model Model of the vehicle.
|
8
|
+
# @attr [Number] year Model year of the vehicle.
|
7
9
|
class VehicleAttributes < Base
|
8
10
|
# Path Proc for hitting vehicle attributes end point
|
9
|
-
PATH =
|
11
|
+
PATH = proc { |id| "/vehicles/#{id}" }
|
10
12
|
attr_accessor :id, :make, :model, :year
|
11
13
|
end
|
12
14
|
end
|