smartcar 0.1.1 → 1.0.5
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.
- checksums.yaml +4 -4
- data/.travis.yml +24 -3
- data/.yardopts +2 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile.lock +28 -20
- data/README.md +88 -16
- data/lib/smartcar.rb +19 -2
- data/lib/smartcar/base.rb +24 -22
- data/lib/smartcar/battery.rb +5 -6
- data/lib/smartcar/charge.rb +4 -5
- data/lib/smartcar/engine_oil.rb +4 -6
- data/lib/smartcar/fuel.rb +5 -5
- data/lib/smartcar/location.rb +4 -5
- data/lib/smartcar/oauth.rb +80 -82
- data/lib/smartcar/odometer.rb +4 -6
- data/lib/smartcar/permissions.rb +5 -7
- data/lib/smartcar/tire_pressure.rb +8 -6
- data/lib/smartcar/user.rb +5 -5
- data/lib/smartcar/utils.rb +34 -10
- data/lib/smartcar/vehicle.rb +202 -94
- data/lib/smartcar/vehicle_attributes.rb +12 -0
- data/lib/smartcar/version.rb +2 -1
- data/lib/smartcar/vin.rb +4 -5
- data/ruby-sdk.gemspec +18 -11
- metadata +37 -5
data/lib/smartcar/fuel.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Smartcar
|
2
2
|
# class to represent Fuel info
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
#@attr [Number] amountRemaining Amount of fuel remaining.
|
4
|
+
#@attr [Number] percentageRemaining Decimal value representing the remaining fuel percent.
|
5
|
+
#@attr [Number] range Remaining range of the vehicle.
|
6
6
|
class Fuel < Base
|
7
|
-
|
7
|
+
# Path Proc for hitting fuel end point
|
8
8
|
PATH = Proc.new{|id| "/vehicles/#{id}/fuel"}
|
9
|
-
|
9
|
+
attr_reader :amountRemaining, :percentRemaining, :range
|
10
10
|
|
11
11
|
# just to have Ruby-esque method names
|
12
12
|
alias_method :amount_remaining, :amountRemaining
|
data/lib/smartcar/location.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
module Smartcar
|
2
2
|
# class to represent Location info
|
3
|
-
|
4
|
-
|
5
|
-
#
|
3
|
+
#@attr [Number] latitude Latitude of last recorded location.
|
4
|
+
#@attr [Number] longitude Longitude of last recorded location.
|
6
5
|
class Location < Base
|
7
|
-
|
6
|
+
# Path Proc for hitting location end point
|
8
7
|
PATH = Proc.new{|id| "/vehicles/#{id}/location"}
|
9
|
-
|
8
|
+
attr_reader :latitude, :longitude
|
10
9
|
end
|
11
10
|
end
|
data/lib/smartcar/oauth.rb
CHANGED
@@ -1,93 +1,91 @@
|
|
1
1
|
module Smartcar
|
2
|
-
# Oauth class to take care of the Oauth 2.0 with
|
3
|
-
#
|
4
|
-
# @author [ashwin]
|
2
|
+
# Oauth class to take care of the Oauth 2.0 with Smartcar APIs
|
5
3
|
#
|
6
4
|
class Oauth < Base
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
response_type: CODE
|
39
|
-
}
|
40
|
-
parameters[:scope] = options[:scope].join(' ') if options[:scope]
|
41
|
-
%I(state make).each do |parameter|
|
42
|
-
parameters[:parameter] = options[:parameter] unless options[:parameter].nil?
|
43
|
-
end
|
44
|
-
|
45
|
-
client.auth_code.authorize_url(parameters)
|
46
|
-
end
|
5
|
+
extend Utils
|
6
|
+
# By default users are not shown the permission dialog if they have already
|
7
|
+
# approved the set of scopes for this application. The application can elect
|
8
|
+
# to always display the permissions dialog to the user by setting
|
9
|
+
# approval_prompt to `force`.
|
10
|
+
#
|
11
|
+
# @param options [Hash]
|
12
|
+
# @option options[:client_id] [String] - Client ID, if not passed fallsback to ENV['CLIENT_ID']
|
13
|
+
# @option options[:client_secret] [String] - Client Secret, if not passed fallsback to ENV['CLIENT_SECRET']
|
14
|
+
# @option options[:redirect_uri] [String] - Redirect URI, if not passed fallsback to ENV['REDIRECT_URI']
|
15
|
+
# @option options[:state] [String] - OAuth state parameter passed to the
|
16
|
+
# redirect uri. This parameter may be used for identifying the user who
|
17
|
+
# initiated the request.
|
18
|
+
# @option options[:test_mode] [Boolean] - Setting this to 'true' runs it in test mode.
|
19
|
+
# @option options[:force_prompt] [Boolean] - Setting `force_prompt` to
|
20
|
+
# `true` will show the permissions approval screen on every authentication
|
21
|
+
# attempt, even if the user has previously consented to the exact scope of
|
22
|
+
# permissions.
|
23
|
+
# @option options[:make] [String] - `make' is an optional parameter that allows
|
24
|
+
# users to bypass the car brand selection screen.
|
25
|
+
# For a complete list of supported makes, please see our
|
26
|
+
# [API Reference](https://smartcar.com/docs/api#authorization) documentation.
|
27
|
+
# @option options[:scope] [Array of Strings] - array of scopes that specify what the user can access
|
28
|
+
# EXAMPLE : ['read_odometer', 'read_vehicle_info', 'required:read_location']
|
29
|
+
# For further details refer to https://smartcar.com/docs/guides/scope/
|
30
|
+
#
|
31
|
+
# @return [Smartcar::Oauth] Returns a Smartcar::Oauth Object that has other methods
|
32
|
+
def initialize(options)
|
33
|
+
@redirect_uri = options[:redirect_uri] || get_config('REDIRECT_URI')
|
34
|
+
@client_id = options[:client_id] || get_config('CLIENT_ID')
|
35
|
+
@client_secret = options[:client_secret] || get_config('CLIENT_SECRET')
|
47
36
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
redirect_uri: get_config('REDIRECT_URI')
|
58
|
-
).to_hash
|
37
|
+
@auth_parameters = {
|
38
|
+
redirect_uri: @redirect_uri,
|
39
|
+
approval_prompt: options[:force_prompt] ? FORCE : AUTO,
|
40
|
+
mode: options[:test_mode] ? TEST : LIVE,
|
41
|
+
response_type: CODE
|
42
|
+
}
|
43
|
+
@auth_parameters[:scope] = options[:scope].join(' ') if options[:scope]
|
44
|
+
%I(state make).each do |parameter|
|
45
|
+
parameters[:parameter] = options[:parameter] unless options[:parameter].nil?
|
59
46
|
end
|
47
|
+
end
|
60
48
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
token_object = OAuth2::AccessToken.from_hash(client, token_hash)
|
68
|
-
token_object = token_object.refresh!
|
69
|
-
token_object.to_hash
|
70
|
-
end
|
49
|
+
# Generate the OAuth authorization URL.
|
50
|
+
#
|
51
|
+
# @return [String] Authorization URL string
|
52
|
+
def authorization_url
|
53
|
+
client.auth_code.authorize_url(@auth_parameters)
|
54
|
+
end
|
71
55
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
56
|
+
# Generates the tokens hash using the code returned in oauth process.
|
57
|
+
# @param auth_code [String] This is the code that is returned after user
|
58
|
+
# visits and authorizes on the authorization URL.
|
59
|
+
#
|
60
|
+
# @return [Hash] Hash of token, refresh token, expiry info and token type
|
61
|
+
def get_token(auth_code)
|
62
|
+
client.auth_code
|
63
|
+
.get_token(
|
64
|
+
auth_code,
|
65
|
+
redirect_uri: @redirect_uri
|
66
|
+
).to_hash
|
67
|
+
end
|
82
68
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
69
|
+
# Refreshing the access token
|
70
|
+
# @param token_hash [Hash] This is the hash that is returned with the
|
71
|
+
# get_token method
|
72
|
+
#
|
73
|
+
# @return [Hash] Hash of token, refresh token, expiry info and token type
|
74
|
+
def refresh_token(token_hash)
|
75
|
+
token_object = OAuth2::AccessToken.from_hash(client, token_hash)
|
76
|
+
token_object = token_object.refresh!
|
77
|
+
token_object.to_hash
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
# gets the Oauth Client object
|
82
|
+
#
|
83
|
+
# @return [OAuth2::Client] A Oauth Client object.
|
84
|
+
def client
|
85
|
+
@client ||= OAuth2::Client.new( @client_id,
|
86
|
+
@client_secret,
|
87
|
+
:site => OAUTH_PATH
|
88
|
+
)
|
91
89
|
end
|
92
90
|
end
|
93
91
|
end
|
data/lib/smartcar/odometer.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
module Smartcar
|
2
|
-
# class to
|
3
|
-
|
4
|
-
# @author [ashwin]
|
5
|
-
#
|
2
|
+
# class to represent Odometer
|
3
|
+
#@attr [Number] distanceLast recorded odometer reading.
|
6
4
|
class Odometer < Base
|
7
|
-
|
5
|
+
# Path Proc for hitting odometer end point
|
8
6
|
PATH = Proc.new{|id| "/vehicles/#{id}/odometer"}
|
9
|
-
|
7
|
+
attr_reader :distance
|
10
8
|
end
|
11
9
|
end
|
data/lib/smartcar/permissions.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
module Smartcar
|
2
|
-
# class to
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class Permissions
|
7
|
-
include Utils
|
2
|
+
# class to represent permissions response
|
3
|
+
#@attr [Array] permissions Array of permissions granted on the vehicle.
|
4
|
+
class Permissions < Base
|
5
|
+
# Path Proc for hitting permissions end point
|
8
6
|
PATH = Proc.new{|id| "/vehicles/#{id}/permissions"}
|
9
|
-
|
7
|
+
attr_reader :permissions
|
10
8
|
end
|
11
9
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module Smartcar
|
2
|
-
# class to represent
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
# class to represent Tire Pressure response
|
3
|
+
#@attr [Number] back_left Last recorded tire pressure of the back left tire.
|
4
|
+
#@attr [Number] back_right Last recorded tire pressure of the back right tire.
|
5
|
+
#@attr [Number] front_left Last recorded tire pressure of the front left tire.
|
6
|
+
#@attr [Number] front_right Last recorded tire pressure of the front right tire.
|
7
|
+
|
6
8
|
class TirePressure < Base
|
7
|
-
|
9
|
+
# Path Proc for hitting tire pressure end point
|
8
10
|
PATH = Proc.new{|id| "/vehicles/#{id}/tires/pressure"}
|
9
|
-
|
11
|
+
attr_reader :backLeft, :backRight, :frontLeft, :frontRight
|
10
12
|
|
11
13
|
# just to have Ruby-esque method names
|
12
14
|
alias_method :back_left, :backLeft
|
data/lib/smartcar/user.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Smartcar
|
2
2
|
# Class to get to user API.
|
3
|
-
|
4
|
-
|
5
|
-
#
|
3
|
+
#@attr [String] id Smartcar user id.
|
4
|
+
#@attr [String] token Access token used to connect to Smartcar API.
|
6
5
|
class User < Base
|
6
|
+
# Path for hitting user end point
|
7
7
|
USER_PATH = '/user'.freeze
|
8
|
-
|
8
|
+
attr_reader :id, :token
|
9
9
|
|
10
10
|
def initialize(token:)
|
11
11
|
raise InvalidParameterValue.new, "Access Token(token) is a required field" if token.nil?
|
@@ -21,6 +21,6 @@ module Smartcar
|
|
21
21
|
def self.user_id(token:)
|
22
22
|
new(token: token).get(USER_PATH)['id']
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
end
|
26
26
|
end
|
data/lib/smartcar/utils.rb
CHANGED
@@ -1,11 +1,35 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
# Utils module , provides utility methods to underlying classes
|
2
|
+
module Utils
|
3
|
+
# A constructor to take a hash and assign it to the instance variables
|
4
|
+
# @param options = {} [Hash] Could by any class's hash, but the first level keys should be defined in the class
|
5
|
+
#
|
6
|
+
# @return [Subclass os Base] Returns object of any subclass like Report
|
7
|
+
def initialize(options = {})
|
8
|
+
options.each do |attribute, value|
|
9
|
+
instance_variable_set("@#{attribute}", value)
|
10
10
|
end
|
11
|
-
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# gets a given env variable, checks for existence and throws exception if not present
|
14
|
+
# @param config_name [String] key of the env variable
|
15
|
+
#
|
16
|
+
# @return [String] value of the env variable
|
17
|
+
def get_config(config_name)
|
18
|
+
config_name = "INTEGRATION_#{config_name}" if ENV['MODE'] == 'test'
|
19
|
+
raise Smartcar::ConfigNotFound, "Environment variable #{config_name} not found !" unless ENV[config_name]
|
20
|
+
ENV[config_name]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Given the response from smartcar API, returns an error object if needed
|
24
|
+
# @param response [Object] response Object with status and body
|
25
|
+
#
|
26
|
+
# @return [Object] nil OR Error object
|
27
|
+
def get_error(response)
|
28
|
+
status = response.status
|
29
|
+
return nil if [200,204].include?(status)
|
30
|
+
return Smartcar::ServiceUnavailableError.new("Service Unavailable - #{response.body}") if status == 404
|
31
|
+
return Smartcar::BadRequestError.new("Bad Request - #{response.body}") if status == 400
|
32
|
+
return Smartcar::AuthenticationError.new("Authentication error") if status == 401
|
33
|
+
return Smartcar::ExternalServiceError.new("API error - #{response.body}")
|
34
|
+
end
|
35
|
+
end
|
data/lib/smartcar/vehicle.rb
CHANGED
@@ -4,14 +4,21 @@ module Smartcar
|
|
4
4
|
# For Ex. Vehicle object will be treate as an entity and doing vehicle_object.
|
5
5
|
# Battery should return Battery object.
|
6
6
|
#
|
7
|
-
|
8
|
-
|
7
|
+
#@attr [String] token Access token used to connect to Smartcar API.
|
8
|
+
#@attr [String] id Smartcar vehicle ID.
|
9
|
+
#@attr [String] unit_system unit system to represent the data in.
|
9
10
|
class Vehicle < Base
|
11
|
+
include Utils
|
12
|
+
|
10
13
|
|
14
|
+
# Path for hitting compatibility end point
|
11
15
|
COMPATIBLITY_PATH = '/compatibility'.freeze
|
16
|
+
|
17
|
+
# Path for hitting vehicle ids end point
|
12
18
|
PATH = Proc.new{|id| "/vehicles/#{id}"}
|
13
|
-
attr_accessor :token, :id, :unit_system
|
14
19
|
|
20
|
+
attr_reader :id
|
21
|
+
attr_accessor :token, :unit_system
|
15
22
|
|
16
23
|
def initialize(token:, id:, unit_system: IMPERIAL)
|
17
24
|
raise InvalidParameterValue.new, "Invalid Units provided : #{unit_system}" unless UNITS.include?(unit_system)
|
@@ -22,13 +29,6 @@ module Smartcar
|
|
22
29
|
@unit_system = unit_system
|
23
30
|
end
|
24
31
|
|
25
|
-
# Accessor method for vehicle attributes.
|
26
|
-
%I(make model year).each do |method_name|
|
27
|
-
define_method method_name do
|
28
|
-
vehicle_attributes.send(method_name)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
32
|
# Class method Used to get all the vehicles in the app. This only returns
|
33
33
|
# API - https://smartcar.com/docs/api#get-all-vehicles
|
34
34
|
# @param token [String] - Access token
|
@@ -36,10 +36,11 @@ module Smartcar
|
|
36
36
|
#
|
37
37
|
# @return [Array] of vehicle IDs(Strings)
|
38
38
|
def self.all_vehicle_ids(token:, options: {})
|
39
|
-
new(token: token, id: 'none').fetch(
|
39
|
+
response, meta = new(token: token, id: 'none').fetch(
|
40
40
|
path: PATH.call(''),
|
41
41
|
options: options
|
42
|
-
)
|
42
|
+
)
|
43
|
+
response['vehicles']
|
43
44
|
end
|
44
45
|
|
45
46
|
# Class method Used to check compatiblity for VIN and scope
|
@@ -52,13 +53,26 @@ module Smartcar
|
|
52
53
|
raise InvalidParameterValue.new, "vin is a required field" if vin.nil?
|
53
54
|
raise InvalidParameterValue.new, "scope is a required field" if scope.nil?
|
54
55
|
|
55
|
-
new(token: 'none', id: 'none').fetch(path: COMPATIBLITY_PATH,
|
56
|
+
response, meta = new(token: 'none', id: 'none').fetch(path: COMPATIBLITY_PATH,
|
56
57
|
options: {
|
57
58
|
vin: vin,
|
58
59
|
scope: scope.join(' ')
|
59
60
|
},
|
60
61
|
auth: BASIC
|
61
|
-
)
|
62
|
+
)
|
63
|
+
response['compatible']
|
64
|
+
end
|
65
|
+
|
66
|
+
# Method to get batch requests
|
67
|
+
# API - https://smartcar.com/docs/api#post-batch-request
|
68
|
+
# @param attributes [Array] Array of strings or symbols of attributes to be fetched together
|
69
|
+
#
|
70
|
+
# @return [Hash] Hash wth key as requested attribute(symbol) and value as Error OR Object of the requested attribute
|
71
|
+
def batch(attributes = [])
|
72
|
+
raise InvalidParameterValue.new, "vin is a required field" if attributes.nil?
|
73
|
+
request_body = get_batch_request_body(attributes)
|
74
|
+
response, _meta = post(PATH.call(id) + "/batch", request_body)
|
75
|
+
process_batch_response(response)
|
62
76
|
end
|
63
77
|
|
64
78
|
# Fetch the list of permissions that this application has been granted for
|
@@ -68,10 +82,7 @@ module Smartcar
|
|
68
82
|
#
|
69
83
|
# @return [Array] of permissions (Strings)
|
70
84
|
def permissions(options: {})
|
71
|
-
Permissions
|
72
|
-
path: Permissions::PATH.call(id),
|
73
|
-
options: options
|
74
|
-
)).permissions
|
85
|
+
get_attribute(Permissions)
|
75
86
|
end
|
76
87
|
|
77
88
|
# Method Used toRevoke access for the current requesting application
|
@@ -83,104 +94,201 @@ module Smartcar
|
|
83
94
|
response['status'] == SUCCESS
|
84
95
|
end
|
85
96
|
|
86
|
-
# Methods Used lock
|
97
|
+
# Methods Used to lock car
|
87
98
|
# API - https://smartcar.com/docs/api#post-security
|
88
99
|
#
|
89
100
|
# @return [Boolean] true if success
|
90
|
-
|
91
|
-
|
92
|
-
lock_or_unlock!(action: Smartcar.const_get(method_name.upcase))
|
93
|
-
end
|
101
|
+
def lock!
|
102
|
+
lock_or_unlock!(action: Smartcar::LOCK)
|
94
103
|
end
|
95
104
|
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
# API - https://smartcar.com/docs/api#get-ev-battery
|
103
|
-
#
|
104
|
-
# @return [Battery] object
|
105
|
-
battery: Battery,
|
106
|
-
# Returns the current charge status of the vehicle.
|
107
|
-
# API - https://smartcar.com/docs/api#get-ev-battery
|
108
|
-
#
|
109
|
-
# @return [Charge] object
|
110
|
-
charge: Charge,
|
111
|
-
# Returns the remaining life span of a vehicle's engine oil
|
112
|
-
# API - https://smartcar.com/docs/api#get-engine-oil-life
|
113
|
-
#
|
114
|
-
# @return [EngineOil] object
|
115
|
-
engine_oil: EngineOil,
|
116
|
-
# Returns the status of the fuel remaining in the vehicle's gas tank.
|
117
|
-
# API - https://smartcar.com/docs/api#get-fuel-tank
|
118
|
-
#
|
119
|
-
# @return [Fuel] object
|
120
|
-
fuel: Fuel,
|
121
|
-
# Returns the last known location of the vehicle in geographic coordinates.
|
122
|
-
# API - https://smartcar.com/docs/api#get-location
|
123
|
-
#
|
124
|
-
# @return [Location] object
|
125
|
-
location: Location,
|
126
|
-
# Returns the vehicle's last known odometer reading.
|
127
|
-
# API - https://smartcar.com/docs/api#get-odometer
|
128
|
-
#
|
129
|
-
# @return [Odometer] object
|
130
|
-
odometer: Odometer,
|
131
|
-
# Returns the air pressure of each of the vehicle's tires.
|
132
|
-
# API - https://smartcar.com/docs/api#get-tire-pressure
|
133
|
-
#
|
134
|
-
# @return [TirePressure] object
|
135
|
-
tire_pressure: TirePressure,
|
136
|
-
}.each do |method_name, klass|
|
137
|
-
define_method method_name do
|
138
|
-
klass.new(
|
139
|
-
fetch(
|
140
|
-
path: klass::PATH.call(id)
|
141
|
-
)
|
142
|
-
)
|
143
|
-
end
|
105
|
+
# Methods Used to unlock car
|
106
|
+
# API - https://smartcar.com/docs/api#post-security
|
107
|
+
#
|
108
|
+
# @return [Boolean] true if success
|
109
|
+
def unlock!
|
110
|
+
lock_or_unlock!(action: Smartcar::UNLOCK)
|
144
111
|
end
|
145
112
|
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
113
|
+
# Method used to start charging a car
|
114
|
+
#
|
115
|
+
#
|
116
|
+
# @return [Boolean] true if success
|
117
|
+
def start_charge!
|
118
|
+
start_or_stop_charge!(action: Smartcar::START_CHARGE)
|
119
|
+
end
|
149
120
|
|
150
|
-
#
|
151
|
-
# API - https://smartcar.com/docs/api#get-vin
|
121
|
+
# Method used to stop charging a car
|
152
122
|
#
|
153
|
-
#
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
path: Vin::PATH.call(id)
|
158
|
-
)
|
159
|
-
).vin
|
123
|
+
#
|
124
|
+
# @return [Boolean] true if success
|
125
|
+
def stop_charge!
|
126
|
+
start_or_stop_charge!(action: Smartcar::STOP_CHARGE)
|
160
127
|
end
|
161
128
|
|
162
|
-
# Returns
|
163
|
-
# API - https://smartcar.com/
|
129
|
+
# Returns make model year and id of the vehicle
|
130
|
+
# API - https://smartcar.com/api#get-vehicle-attributes
|
164
131
|
#
|
165
132
|
# @return [VehicleAttributes] object
|
166
133
|
def vehicle_attributes
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
134
|
+
get_attribute(VehicleAttributes)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns the state of charge (SOC) and remaining range of an electric or
|
138
|
+
# plug-in hybrid vehicle's battery.
|
139
|
+
# API - https://smartcar.com/docs/api#get-ev-battery
|
140
|
+
#
|
141
|
+
# @return [Battery] object
|
142
|
+
def battery
|
143
|
+
get_attribute(Battery)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns the current charge status of the vehicle.
|
147
|
+
# API - https://smartcar.com/docs/api#get-ev-battery
|
148
|
+
#
|
149
|
+
# @return [Charge] object
|
150
|
+
def charge
|
151
|
+
get_attribute(Charge)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns the remaining life span of a vehicle's engine oil
|
155
|
+
# API - https://smartcar.com/docs/api#get-engine-oil-life
|
156
|
+
#
|
157
|
+
# @return [EngineOil] object
|
158
|
+
def engine_oil
|
159
|
+
get_attribute(EngineOil)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns the status of the fuel remaining in the vehicle's gas tank.
|
163
|
+
# API - https://smartcar.com/docs/api#get-fuel-tank
|
164
|
+
#
|
165
|
+
# @return [Fuel] object
|
166
|
+
def fuel
|
167
|
+
get_attribute(Fuel)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the last known location of the vehicle in geographic coordinates.
|
171
|
+
# API - https://smartcar.com/docs/api#get-location
|
172
|
+
#
|
173
|
+
# @return [Location] object
|
174
|
+
def location
|
175
|
+
get_attribute(Location)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns the vehicle's last known odometer reading.
|
179
|
+
# API - https://smartcar.com/docs/api#get-odometer
|
180
|
+
#
|
181
|
+
# @return [Odometer] object
|
182
|
+
def odometer
|
183
|
+
get_attribute(Odometer)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Returns the air pressure of each of the vehicle's tires.
|
187
|
+
# API - https://smartcar.com/docs/api#get-tire-pressure
|
188
|
+
#
|
189
|
+
# @return [TirePressure] object
|
190
|
+
def tire_pressure
|
191
|
+
get_attribute(TirePressure)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns the vehicle's manufacturer identifier (VIN).
|
195
|
+
# API - https://smartcar.com/docs/api#get-vin
|
196
|
+
#
|
197
|
+
# @return [String] Vin of the vehicle.
|
198
|
+
def vin
|
199
|
+
_object = get_attribute(Vin)
|
200
|
+
@vin ||= _object.vin
|
172
201
|
end
|
173
202
|
|
174
203
|
private
|
175
204
|
|
205
|
+
def allowed_attributes
|
206
|
+
@allowed_attributes ||= {
|
207
|
+
battery: get_path(Battery),
|
208
|
+
charge: get_path(Charge),
|
209
|
+
engine_oil: get_path(EngineOil),
|
210
|
+
fuel: get_path(Fuel),
|
211
|
+
location: get_path(Location),
|
212
|
+
odometer: get_path(Odometer),
|
213
|
+
permissions: get_path(Permissions),
|
214
|
+
tire_pressure: get_path(TirePressure),
|
215
|
+
vin: get_path(Vin),
|
216
|
+
}
|
217
|
+
end
|
218
|
+
|
219
|
+
def path_to_class
|
220
|
+
@path_to_class ||= {
|
221
|
+
get_path(Battery) => Battery,
|
222
|
+
get_path(Charge) => Charge,
|
223
|
+
get_path(EngineOil) => EngineOil,
|
224
|
+
get_path(Fuel) => Fuel,
|
225
|
+
get_path(Location) => Location,
|
226
|
+
get_path(Odometer) => Odometer,
|
227
|
+
get_path(Permissions) => Permissions,
|
228
|
+
get_path(TirePressure) => TirePressure,
|
229
|
+
get_path(Vin) => Vin,
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
# @private
|
234
|
+
BatchItemResponse = Struct.new(:body, :status, :headers) do
|
235
|
+
def body_with_meta
|
236
|
+
body.merge(meta: headers)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def get_batch_request_body(attributes)
|
241
|
+
attributes = validated_attributes(attributes)
|
242
|
+
requests = attributes.each_with_object([]) do |item, requests|
|
243
|
+
requests << { path: allowed_attributes[item] }
|
244
|
+
end
|
245
|
+
{ requests: requests }
|
246
|
+
end
|
247
|
+
|
248
|
+
def process_batch_response(responses)
|
249
|
+
inverted_map = allowed_attributes.invert
|
250
|
+
responses["responses"].each_with_object({}) do |response, result|
|
251
|
+
item_response = BatchItemResponse.new(response["body"], response["code"], response["headers"])
|
252
|
+
error = get_error(item_response)
|
253
|
+
path = response["path"]
|
254
|
+
result[inverted_map[path]] = error || get_object(path_to_class[path], item_response.body_with_meta)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def validated_attributes(attributes)
|
259
|
+
attributes.map!(&:to_sym)
|
260
|
+
unsupported_attributes = (attributes - allowed_attributes.keys) || []
|
261
|
+
unless unsupported_attributes.empty?
|
262
|
+
message = "Unsupported attribute(s) requested in batch - #{unsupported_attributes.join(',')}"
|
263
|
+
raise InvalidParameterValue.new, message
|
264
|
+
end
|
265
|
+
attributes
|
266
|
+
end
|
267
|
+
|
268
|
+
def get_attribute(klass)
|
269
|
+
body, meta = fetch(
|
270
|
+
path: klass::PATH.call(id)
|
271
|
+
)
|
272
|
+
get_object(klass, body.merge(meta: meta))
|
273
|
+
end
|
274
|
+
|
275
|
+
def get_object(klass, data)
|
276
|
+
klass.new(data)
|
277
|
+
end
|
278
|
+
|
279
|
+
def get_path(klass)
|
280
|
+
path = klass::PATH.call(id)
|
281
|
+
path.split("/vehicles/#{id}").last
|
282
|
+
end
|
283
|
+
|
176
284
|
def lock_or_unlock!(action:)
|
177
|
-
response = post(PATH.call(id) + "/security", {action: action}
|
285
|
+
response, meta = post(PATH.call(id) + "/security", { action: action })
|
178
286
|
response['status'] == SUCCESS
|
179
287
|
end
|
180
288
|
|
181
|
-
|
182
|
-
|
183
|
-
|
289
|
+
def start_or_stop_charge!(action:)
|
290
|
+
response, meta = post(PATH.call(id) + "/charge", { action: action })
|
291
|
+
response['status'] == SUCCESS
|
184
292
|
end
|
185
293
|
end
|
186
294
|
end
|