smartcar 2.5.0 → 3.0.0
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/.gitignore +1 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +1 -2
- data/Gemfile.lock +56 -21
- data/README.md +38 -36
- data/lib/open_struct_extensions.rb +21 -0
- data/lib/smartcar.rb +158 -57
- data/lib/smartcar/auth_client.rb +154 -0
- data/lib/smartcar/base.rb +12 -22
- data/lib/smartcar/utils.rb +82 -21
- data/lib/smartcar/vehicle.rb +211 -54
- data/lib/smartcar/version.rb +1 -1
- data/lib/smartcar_error.rb +49 -0
- data/ruby-sdk.gemspec +3 -0
- metadata +47 -18
- data/lib/smartcar/battery.rb +0 -15
- data/lib/smartcar/battery_capacity.rb +0 -11
- data/lib/smartcar/charge.rb +0 -15
- data/lib/smartcar/engine_oil.rb +0 -14
- data/lib/smartcar/fuel.rb +0 -17
- data/lib/smartcar/location.rb +0 -12
- data/lib/smartcar/oauth.rb +0 -127
- data/lib/smartcar/odometer.rb +0 -11
- data/lib/smartcar/permissions.rb +0 -11
- data/lib/smartcar/tire_pressure.rb +0 -20
- data/lib/smartcar/user.rb +0 -38
- data/lib/smartcar/vehicle_attributes.rb +0 -14
- data/lib/smartcar/vehicle_utils/actions.rb +0 -61
- data/lib/smartcar/vehicle_utils/batch.rb +0 -83
- data/lib/smartcar/vehicle_utils/data.rb +0 -110
- data/lib/smartcar/vin.rb +0 -12
data/lib/smartcar/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Custom SmartcarError class to represent errors from Smartcar APIs.
|
4
|
+
class SmartcarError < StandardError
|
5
|
+
attr_reader :code, :status_code, :request_id, :type, :description, :doc_url, :resolution, :detail
|
6
|
+
|
7
|
+
def initialize(status, body, headers)
|
8
|
+
@status_code = status
|
9
|
+
if body.is_a?(String)
|
10
|
+
super(body)
|
11
|
+
@request_id = headers['sc-request-id']
|
12
|
+
return
|
13
|
+
end
|
14
|
+
body = coerce_attributes(body)
|
15
|
+
|
16
|
+
super("#{body[:type]}:#{body[:code]} - #{body[:description]}")
|
17
|
+
@request_id = body[:requestId] || headers['sc-request-id']
|
18
|
+
set_attributes(body)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def coerce_attributes(body)
|
24
|
+
body[:type] = body.delete(:error) if body[:error]
|
25
|
+
unless body[:description]
|
26
|
+
body[:description] = if body[:error_description]
|
27
|
+
body.delete(:error_description)
|
28
|
+
elsif body[:message]
|
29
|
+
body.delete(:message)
|
30
|
+
else
|
31
|
+
'Unknown error'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
body
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_attributes(body)
|
39
|
+
body.each do |attribute, value|
|
40
|
+
instance_variable_set("@#{attribute}", value)
|
41
|
+
end
|
42
|
+
@doc_url = body[:docURL]
|
43
|
+
@type = @error if @error
|
44
|
+
|
45
|
+
return unless @resolution
|
46
|
+
|
47
|
+
@resolution = @resolution.is_a?(String) ? OpenStruct.new({ type: @resolution }) : OpenStruct.new(@resolution)
|
48
|
+
end
|
49
|
+
end
|
data/ruby-sdk.gemspec
CHANGED
@@ -27,10 +27,13 @@ Gem::Specification.new do |spec|
|
|
27
27
|
|
28
28
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
29
29
|
spec.add_development_dependency 'byebug', '~> 11.0'
|
30
|
+
spec.add_development_dependency 'codecov', '~> 0.5.2'
|
30
31
|
spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
|
32
|
+
spec.add_development_dependency 'readapt', '~> 1.3'
|
31
33
|
spec.add_development_dependency 'redcarpet', '~> 3.5.0'
|
32
34
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
35
|
spec.add_development_dependency 'rubocop', '~> 1.12'
|
34
36
|
spec.add_development_dependency 'selenium-webdriver', '~> 3.142'
|
37
|
+
spec.add_development_dependency 'webmock', '~> 3.13'
|
35
38
|
spec.add_dependency 'oauth2', '~> 1.4'
|
36
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smartcar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ashwin Subramanian
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '11.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: codecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.5.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.5.2
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,6 +72,20 @@ dependencies:
|
|
58
72
|
- - ">="
|
59
73
|
- !ruby/object:Gem::Version
|
60
74
|
version: 12.3.3
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: readapt
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.3'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.3'
|
61
89
|
- !ruby/object:Gem::Dependency
|
62
90
|
name: redcarpet
|
63
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +142,20 @@ dependencies:
|
|
114
142
|
- - "~>"
|
115
143
|
- !ruby/object:Gem::Version
|
116
144
|
version: '3.142'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: webmock
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '3.13'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '3.13'
|
117
159
|
- !ruby/object:Gem::Dependency
|
118
160
|
name: oauth2
|
119
161
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,27 +191,14 @@ files:
|
|
149
191
|
- Rakefile
|
150
192
|
- bin/console
|
151
193
|
- bin/setup
|
194
|
+
- lib/open_struct_extensions.rb
|
152
195
|
- lib/smartcar.rb
|
196
|
+
- lib/smartcar/auth_client.rb
|
153
197
|
- lib/smartcar/base.rb
|
154
|
-
- lib/smartcar/battery.rb
|
155
|
-
- lib/smartcar/battery_capacity.rb
|
156
|
-
- lib/smartcar/charge.rb
|
157
|
-
- lib/smartcar/engine_oil.rb
|
158
|
-
- lib/smartcar/fuel.rb
|
159
|
-
- lib/smartcar/location.rb
|
160
|
-
- lib/smartcar/oauth.rb
|
161
|
-
- lib/smartcar/odometer.rb
|
162
|
-
- lib/smartcar/permissions.rb
|
163
|
-
- lib/smartcar/tire_pressure.rb
|
164
|
-
- lib/smartcar/user.rb
|
165
198
|
- lib/smartcar/utils.rb
|
166
199
|
- lib/smartcar/vehicle.rb
|
167
|
-
- lib/smartcar/vehicle_attributes.rb
|
168
|
-
- lib/smartcar/vehicle_utils/actions.rb
|
169
|
-
- lib/smartcar/vehicle_utils/batch.rb
|
170
|
-
- lib/smartcar/vehicle_utils/data.rb
|
171
200
|
- lib/smartcar/version.rb
|
172
|
-
- lib/
|
201
|
+
- lib/smartcar_error.rb
|
173
202
|
- ruby-sdk.gemspec
|
174
203
|
homepage: https://rubygems.org/gems/smartcar
|
175
204
|
licenses:
|
data/lib/smartcar/battery.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Battery info
|
5
|
-
# @attr [Number] percentRemaining Decimal value representing the remaining charge percent.
|
6
|
-
# @attr [Number] range Remaining range of the vehicle.
|
7
|
-
class Battery < Base
|
8
|
-
# Path Proc for hitting battery end point
|
9
|
-
PATH = proc { |id| "/vehicles/#{id}/battery" }
|
10
|
-
attr_reader :percentRemaining, :range
|
11
|
-
|
12
|
-
# just to have Ruby-esque method names
|
13
|
-
alias percentage_remaining percentRemaining
|
14
|
-
end
|
15
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Battery Capacity info
|
5
|
-
# @attr [Number] capacity Decimal value representing the battery's total capacity in kWh.
|
6
|
-
class BatteryCapacity < Base
|
7
|
-
# Path Proc for hitting battery capacity end point
|
8
|
-
PATH = proc { |id| "/vehicles/#{id}/battery/capacity" }
|
9
|
-
attr_reader :capacity
|
10
|
-
end
|
11
|
-
end
|
data/lib/smartcar/charge.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Charge info
|
5
|
-
# @attr [Boolean] isPluggedIn Specifies if the vehicle is plugged in.
|
6
|
-
# @attr [String] state Charging state of the vehicle.
|
7
|
-
class Charge < Base
|
8
|
-
# Path Proc for hitting charge end point
|
9
|
-
PATH = proc { |id| "/vehicles/#{id}/charge" }
|
10
|
-
attr_reader :isPluggedIn, :state
|
11
|
-
|
12
|
-
# just to have Ruby-esque method names
|
13
|
-
alias is_plugged_in? isPluggedIn
|
14
|
-
end
|
15
|
-
end
|
data/lib/smartcar/engine_oil.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Engine oil info
|
5
|
-
# @attr [Number] lifeRemaining Remaining life of the engine oil
|
6
|
-
class EngineOil < Base
|
7
|
-
# Path Proc for hitting engine oil end point
|
8
|
-
PATH = proc { |id| "/vehicles/#{id}/engine/oil" }
|
9
|
-
attr_reader :lifeRemaining
|
10
|
-
|
11
|
-
# just to have Ruby-esque method names
|
12
|
-
alias life_remaining lifeRemaining
|
13
|
-
end
|
14
|
-
end
|
data/lib/smartcar/fuel.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Fuel info
|
5
|
-
# @attr [Number] amountRemaining Amount of fuel remaining.
|
6
|
-
# @attr [Number] percentageRemaining Decimal value representing the remaining fuel percent.
|
7
|
-
# @attr [Number] range Remaining range of the vehicle.
|
8
|
-
class Fuel < Base
|
9
|
-
# Path Proc for hitting fuel end point
|
10
|
-
PATH = proc { |id| "/vehicles/#{id}/fuel" }
|
11
|
-
attr_reader :amountRemaining, :percentRemaining, :range
|
12
|
-
|
13
|
-
# just to have Ruby-esque method names
|
14
|
-
alias amount_remaining amountRemaining
|
15
|
-
alias percent_remaining percentRemaining
|
16
|
-
end
|
17
|
-
end
|
data/lib/smartcar/location.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Location info
|
5
|
-
# @attr [Number] latitude Latitude of last recorded location.
|
6
|
-
# @attr [Number] longitude Longitude of last recorded location.
|
7
|
-
class Location < Base
|
8
|
-
# Path Proc for hitting location end point
|
9
|
-
PATH = proc { |id| "/vehicles/#{id}/location" }
|
10
|
-
attr_reader :latitude, :longitude
|
11
|
-
end
|
12
|
-
end
|
data/lib/smartcar/oauth.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# Oauth class to take care of the Oauth 2.0 with Smartcar APIs
|
5
|
-
#
|
6
|
-
class Oauth < Base
|
7
|
-
extend Smartcar::Utils
|
8
|
-
|
9
|
-
attr_reader :redirect_uri, :client_id, :client_secret, :scope, :mode
|
10
|
-
|
11
|
-
# By default users are not shown the permission dialog if they have already
|
12
|
-
# approved the set of scopes for this application. The application can elect
|
13
|
-
# to always display the permissions dialog to the user by setting
|
14
|
-
# approval_prompt to `force`.
|
15
|
-
#
|
16
|
-
# @param options [Hash]
|
17
|
-
# @option options[:client_id] [String] - Client ID, if not passed fallsback to ENV['CLIENT_ID']
|
18
|
-
# @option options[:client_secret] [String] - Client Secret, if not passed fallsback to ENV['CLIENT_SECRET']
|
19
|
-
# @option options[:redirect_uri] [String] - Redirect URI, if not passed fallsback to ENV['REDIRECT_URI']
|
20
|
-
# @option options[:scope] [Array of Strings] - array of scopes that specify what the user can access
|
21
|
-
# EXAMPLE : ['read_odometer', 'read_vehicle_info', 'required:read_location']
|
22
|
-
# For further details refer to https://smartcar.com/docs/guides/scope/
|
23
|
-
# @option options[:test_mode] [Boolean] - Setting this to 'true' runs it in test mode.
|
24
|
-
#
|
25
|
-
# @return [Smartcar::Oauth] Returns a Smartcar::Oauth Object that has other methods
|
26
|
-
def initialize(options)
|
27
|
-
options[:redirect_uri] ||= get_config('REDIRECT_URI')
|
28
|
-
options[:client_id] ||= get_config('CLIENT_ID')
|
29
|
-
options[:client_secret] ||= get_config('CLIENT_SECRET')
|
30
|
-
options[:mode] = options[:test_mode].nil? || !options[:test_mode] ? LIVE : TEST
|
31
|
-
super
|
32
|
-
end
|
33
|
-
|
34
|
-
# Generate the OAuth authorization URL.
|
35
|
-
# @param options [Hash]
|
36
|
-
# @option options[:state] [String] - OAuth state parameter passed to the
|
37
|
-
# redirect uri. This parameter may be used for identifying the user who
|
38
|
-
# initiated the request.
|
39
|
-
# @option options[:force_prompt] [Boolean] - Setting `force_prompt` to
|
40
|
-
# `true` will show the permissions approval screen on every authentication
|
41
|
-
# attempt, even if the user has previously consented to the exact scope of
|
42
|
-
# permissions.
|
43
|
-
# @option options[:make] [String] - `make' is an optional parameter that allows
|
44
|
-
# users to bypass the car brand selection screen.
|
45
|
-
# For a complete list of supported makes, please see our
|
46
|
-
# [API Reference](https://smartcar.com/docs/api#authorization) documentation.
|
47
|
-
# @option options[:single_select] [Boolean, Hash] - An optional value that sets the
|
48
|
-
# behavior of the grant dialog displayed to the user. If set to `true`,
|
49
|
-
# `single_select` limits the user to selecting only one vehicle. If `single_select`
|
50
|
-
# is an hash with the property `vin`, Smartcar will only authorize the vehicle
|
51
|
-
# with the specified VIN. See the
|
52
|
-
# [Single Select guide](https://smartcar.com/docs/guides/single-select/)
|
53
|
-
# for more information.
|
54
|
-
# @option options[:flags] [Array of Strings] - an optional array of early access features to enable.
|
55
|
-
#
|
56
|
-
# @return [String] Authorization URL string
|
57
|
-
def authorization_url(options = {})
|
58
|
-
initialize_auth_parameters(options)
|
59
|
-
add_single_select_options(options[:single_select])
|
60
|
-
client.auth_code.authorize_url(@auth_parameters)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Generates the tokens hash using the code returned in oauth process.
|
64
|
-
# @param auth_code [String] This is the code that is returned after user
|
65
|
-
# visits and authorizes on the authorization URL.
|
66
|
-
#
|
67
|
-
# @return [Hash] Hash of token, refresh token, expiry info and token type
|
68
|
-
def get_token(auth_code)
|
69
|
-
client.auth_code
|
70
|
-
.get_token(
|
71
|
-
auth_code,
|
72
|
-
redirect_uri: redirect_uri
|
73
|
-
).to_hash
|
74
|
-
end
|
75
|
-
|
76
|
-
# Refreshing the access token
|
77
|
-
# @param refresh_token [String] refresh_token received during token exchange
|
78
|
-
#
|
79
|
-
# @return [Hash] Hash of token, refresh token, expiry info and token type
|
80
|
-
def exchange_refresh_token(refresh_token)
|
81
|
-
token_object = OAuth2::AccessToken.from_hash(client, { refresh_token: refresh_token })
|
82
|
-
token_object = token_object.refresh!
|
83
|
-
token_object.to_hash
|
84
|
-
end
|
85
|
-
|
86
|
-
# Checks if token is expired using Oauth2 classes
|
87
|
-
# @param expires_at [Number] expires_at as time since epoch
|
88
|
-
#
|
89
|
-
# @return [Boolean]
|
90
|
-
def expired?(expires_at)
|
91
|
-
OAuth2::AccessToken.from_hash(client, { expires_at: expires_at }).expired?
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def initialize_auth_parameters(options)
|
97
|
-
@auth_parameters = {
|
98
|
-
response_type: CODE,
|
99
|
-
redirect_uri: redirect_uri,
|
100
|
-
mode: mode,
|
101
|
-
state: options[:state],
|
102
|
-
make: options[:make],
|
103
|
-
approval_prompt: options[:force_prompt] ? FORCE : AUTO,
|
104
|
-
flags: options[:flags]&.join(' '),
|
105
|
-
scope: scope&.join(' ')
|
106
|
-
}
|
107
|
-
end
|
108
|
-
|
109
|
-
def add_single_select_options(single_select)
|
110
|
-
if single_select.is_a?(Hash)
|
111
|
-
@auth_parameters[:single_select_vin] = single_select[:vin]
|
112
|
-
@auth_parameters[:single_select] = true
|
113
|
-
else
|
114
|
-
@auth_parameters[:single_select] = !single_select.nil?
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# gets the Oauth Client object
|
119
|
-
#
|
120
|
-
# @return [OAuth2::Client] A Oauth Client object.
|
121
|
-
def client
|
122
|
-
@client ||= OAuth2::Client.new(client_id,
|
123
|
-
client_secret,
|
124
|
-
site: OAUTH_PATH)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
data/lib/smartcar/odometer.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Odometer
|
5
|
-
# @attr [Number] distanceLast recorded odometer reading.
|
6
|
-
class Odometer < Base
|
7
|
-
# Path Proc for hitting odometer end point
|
8
|
-
PATH = proc { |id| "/vehicles/#{id}/odometer" }
|
9
|
-
attr_reader :distance
|
10
|
-
end
|
11
|
-
end
|
data/lib/smartcar/permissions.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent permissions response
|
5
|
-
# @attr [Array] permissions Array of permissions granted on the vehicle.
|
6
|
-
class Permissions < Base
|
7
|
-
# Path Proc for hitting permissions end point
|
8
|
-
PATH = proc { |id| "/vehicles/#{id}/permissions" }
|
9
|
-
attr_reader :permissions
|
10
|
-
end
|
11
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Smartcar
|
4
|
-
# class to represent Tire Pressure response
|
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.
|
9
|
-
class TirePressure < Base
|
10
|
-
# Path Proc for hitting tire pressure end point
|
11
|
-
PATH = proc { |id| "/vehicles/#{id}/tires/pressure" }
|
12
|
-
attr_reader :backLeft, :backRight, :frontLeft, :frontRight
|
13
|
-
|
14
|
-
# just to have Ruby-esque method names
|
15
|
-
alias back_left backLeft
|
16
|
-
alias back_right backRight
|
17
|
-
alias front_left frontLeft
|
18
|
-
alias front_right frontRight
|
19
|
-
end
|
20
|
-
end
|