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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3848d46ccf722b908e7b42acc1afebccc24fbf1362c36bd0b0a867cd8bdd5b85
4
- data.tar.gz: 3cfbf110c26177478a4ffad5373aeffcb73411b85f014c7af98293ea42739601
3
+ metadata.gz: 3f96ead76c474cc7bd2f579c79ae5457437b7826ea5738fc939e78e7fd15ad9a
4
+ data.tar.gz: 4ca101d8945328f524a4c4fe525eef8c0fa9ed5828a6d7fc1e7d96bccc299015
5
5
  SHA512:
6
- metadata.gz: f46fc77b3eafb462cfbd210d7509293368d9d2306ce8d16dbfbd4aad7a76339e53b689f06c2e50b3cc6eb56be5a390c805f8ae88384f6cfcdfa7e1ce27b34e91
7
- data.tar.gz: ee615279dc5c61e75ba1afd3ffa640b2df9ffafd4ea459cf22558d145e434b117814bd4279fcfd418643146eec4386911735f8f1066babd3ce494df44d15cfba
6
+ metadata.gz: c944b360628c97f3e78e6d1f7287e91c136a33cd8c696c0e8246c18839f97d790aea5457dc402ace57eda565f4937dbc72a51e5c66e70b12d24a1850674f6bcf
7
+ data.tar.gz: 73646b1545692c60714bd7581abef94f6271907587dc1ed2564dbae30adafb63b3c3d546b46f2188933fd2f4035a1eb8922fa4ef0c7e09a4fbd48a5d69c1cb11
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /.vscode/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/.rubocop.yml CHANGED
@@ -7,6 +7,10 @@ AllCops:
7
7
  Metrics/AbcSize:
8
8
  Enabled: false
9
9
 
10
+ # Disabling this becuase we are using `set` and `get` prefixed methods to keep some commonality across SDKs
11
+ Naming/AccessorMethodName:
12
+ Enabled: false
13
+
10
14
  Metrics/BlockLength:
11
15
  Exclude:
12
16
  - '**/*.gemspec'
data/.travis.yml CHANGED
@@ -6,7 +6,6 @@ services:
6
6
  addons:
7
7
  firefox: latest
8
8
  rvm:
9
- - 2.5
10
9
  - 2.6
11
10
  - 2.7
12
11
  before_install:
@@ -25,5 +24,5 @@ deploy:
25
24
  on:
26
25
  tags: true
27
26
  branch: master
28
- rvm: 2.5
27
+ rvm: 2.6
29
28
  skip_cleanup: 'true'
data/Gemfile.lock CHANGED
@@ -1,22 +1,39 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smartcar (2.5.0)
4
+ smartcar (3.0.0)
5
5
  oauth2 (~> 1.4)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
+ addressable (2.7.0)
11
+ public_suffix (>= 2.0.2, < 5.0)
10
12
  ast (2.4.2)
13
+ backport (1.1.2)
11
14
  byebug (11.1.3)
12
15
  childprocess (3.0.0)
13
- diff-lcs (1.3)
14
- faraday (1.3.0)
16
+ codecov (0.5.2)
17
+ simplecov (>= 0.15, < 0.22)
18
+ crack (0.4.5)
19
+ rexml
20
+ diff-lcs (1.4.4)
21
+ docile (1.4.0)
22
+ faraday (1.4.2)
23
+ faraday-em_http (~> 1.0)
24
+ faraday-em_synchrony (~> 1.0)
25
+ faraday-excon (~> 1.1)
15
26
  faraday-net_http (~> 1.0)
27
+ faraday-net_http_persistent (~> 1.1)
16
28
  multipart-post (>= 1.2, < 3)
17
- ruby2_keywords
29
+ ruby2_keywords (>= 0.0.4)
30
+ faraday-em_http (1.0.0)
31
+ faraday-em_synchrony (1.0.0)
32
+ faraday-excon (1.1.0)
18
33
  faraday-net_http (1.0.1)
19
- jwt (2.2.2)
34
+ faraday-net_http_persistent (1.1.0)
35
+ hashdiff (1.0.1)
36
+ jwt (2.2.3)
20
37
  multi_json (1.15.0)
21
38
  multi_xml (0.6.0)
22
39
  multipart-post (2.1.1)
@@ -27,45 +44,60 @@ GEM
27
44
  multi_xml (~> 0.5)
28
45
  rack (>= 1.2, < 3)
29
46
  parallel (1.20.1)
30
- parser (3.0.0.0)
47
+ parser (3.0.1.1)
31
48
  ast (~> 2.4.1)
49
+ public_suffix (4.0.6)
32
50
  rack (2.2.3)
33
51
  rainbow (3.0.0)
34
52
  rake (12.3.3)
53
+ readapt (1.3.0)
54
+ backport (~> 1.1)
55
+ thor (~> 1.0)
35
56
  redcarpet (3.5.1)
36
57
  regexp_parser (2.1.1)
37
58
  rexml (3.2.5)
38
- rspec (3.9.0)
39
- rspec-core (~> 3.9.0)
40
- rspec-expectations (~> 3.9.0)
41
- rspec-mocks (~> 3.9.0)
42
- rspec-core (3.9.2)
43
- rspec-support (~> 3.9.3)
44
- rspec-expectations (3.9.2)
59
+ rspec (3.10.0)
60
+ rspec-core (~> 3.10.0)
61
+ rspec-expectations (~> 3.10.0)
62
+ rspec-mocks (~> 3.10.0)
63
+ rspec-core (3.10.1)
64
+ rspec-support (~> 3.10.0)
65
+ rspec-expectations (3.10.1)
45
66
  diff-lcs (>= 1.2.0, < 2.0)
46
- rspec-support (~> 3.9.0)
47
- rspec-mocks (3.9.1)
67
+ rspec-support (~> 3.10.0)
68
+ rspec-mocks (3.10.2)
48
69
  diff-lcs (>= 1.2.0, < 2.0)
49
- rspec-support (~> 3.9.0)
50
- rspec-support (3.9.3)
51
- rubocop (1.12.0)
70
+ rspec-support (~> 3.10.0)
71
+ rspec-support (3.10.2)
72
+ rubocop (1.16.1)
52
73
  parallel (~> 1.10)
53
74
  parser (>= 3.0.0.0)
54
75
  rainbow (>= 2.2.2, < 4.0)
55
76
  regexp_parser (>= 1.8, < 3.0)
56
77
  rexml
57
- rubocop-ast (>= 1.2.0, < 2.0)
78
+ rubocop-ast (>= 1.7.0, < 2.0)
58
79
  ruby-progressbar (~> 1.7)
59
80
  unicode-display_width (>= 1.4.0, < 3.0)
60
- rubocop-ast (1.4.1)
61
- parser (>= 2.7.1.5)
81
+ rubocop-ast (1.7.0)
82
+ parser (>= 3.0.1.1)
62
83
  ruby-progressbar (1.11.0)
63
84
  ruby2_keywords (0.0.4)
64
85
  rubyzip (2.3.0)
65
86
  selenium-webdriver (3.142.7)
66
87
  childprocess (>= 0.5, < 4.0)
67
88
  rubyzip (>= 1.2.2)
89
+ simplecov (0.21.2)
90
+ docile (~> 1.1)
91
+ simplecov-html (~> 0.11)
92
+ simplecov_json_formatter (~> 0.1)
93
+ simplecov-html (0.12.3)
94
+ simplecov_json_formatter (0.1.3)
95
+ thor (1.1.0)
68
96
  unicode-display_width (2.0.0)
97
+ webmock (3.13.0)
98
+ addressable (>= 2.3.6)
99
+ crack (>= 0.3.2)
100
+ hashdiff (>= 0.4.0, < 2.0.0)
69
101
 
70
102
  PLATFORMS
71
103
  ruby
@@ -73,12 +105,15 @@ PLATFORMS
73
105
  DEPENDENCIES
74
106
  bundler (~> 2.0)
75
107
  byebug (~> 11.0)
108
+ codecov (~> 0.5.2)
76
109
  rake (~> 12.3, >= 12.3.3)
110
+ readapt (~> 1.3)
77
111
  redcarpet (~> 3.5.0)
78
112
  rspec (~> 3.0)
79
113
  rubocop (~> 1.12)
80
114
  selenium-webdriver (~> 3.142)
81
115
  smartcar!
116
+ webmock (~> 3.13)
82
117
 
83
118
  BUNDLED WITH
84
119
  2.1.4
data/README.md CHANGED
@@ -29,28 +29,28 @@ not have access to the dashboard, please
29
29
 
30
30
  ### Flow
31
31
 
32
- - Create a new `AuthClient` object with your `clientId`, `clientSecret`,
33
- `redirectUri`, and required `scope`.
34
- - Redirect the user to Smartcar Connect using `getAuthUrl` or one
32
+ - Create a new `AuthClient` object with your `client_id`, `client_secret`,
33
+ `redirect_uri`.
34
+ - Redirect the user to Smartcar Connect using `get_auth_url` with required `scope` or with one
35
35
  of our frontend SDKs.
36
36
  - The user will login, and then accept or deny your `scope`'s permissions.
37
- - Handle the get request to `redirectUri`.
37
+ - Handle the get request to `redirect_uri`.
38
38
  - If the user accepted your permissions, `req.query.code` will contain an
39
39
  authorization code.
40
- - Use `exchangeCode` with this code to obtain an access object
40
+ - Use `exchange_code` with this code to obtain an access object
41
41
  containing an access token (lasting 2 hours) and a refresh token
42
42
  (lasting 60 days).
43
43
  - Save this access object.
44
44
  - If the user denied your permissions, `req.query.error` will be set
45
45
  to `"access_denied"`.
46
- - If you passed a state parameter to `getAuthUrl`, `req.query.state` will
46
+ - If you passed a state parameter to `get_auth_url`, `req.query.state` will
47
47
  contain the state value.
48
- - Get the user's vehicles with `getVehicleIds`.
49
- - Create a new `Vehicle` object using a `vehicleId` from the previous response,
48
+ - Get the user's vehicles with `getVehicles`.
49
+ - Create a new `Vehicle` object using a `vehicle_id` from the previous response,
50
50
  and the `access_token`.
51
51
  - Make requests to the Smartcar API.
52
- - Use `exchangeRefreshToken` on your saved `refreshToken` to retrieve a new token
53
- when your `accessToken` expires.
52
+ - Use `exchange_refresh_token` on your saved `refresh_token` to retrieve a new token
53
+ when your `access_token` expires.
54
54
 
55
55
  ## Installation
56
56
 
@@ -70,53 +70,47 @@ Or install it yourself as:
70
70
 
71
71
  ## Usage
72
72
 
73
- Setup the environment variables for CLIENT_ID and CLIENT_SECRET.
73
+ Setup the environment variables for SMARTCAR_CLIENT_ID, SMARTCAR_CLIENT_SECRET and SMARTCAR_REDIRECT_URI.
74
74
  ```bash
75
75
  # Get your API keys from https://dashboard.smartcar.com/signup
76
- export CLIENT_ID=<client id>
77
- export CLIENT_SECRET=<client secret>
76
+ export SMARTCAR_CLIENT_ID=<client id>
77
+ export SMARTCAR_CLIENT_SECRET=<client secret>
78
+ export SMARTCAR_REDIRECT_URI=<redirect URI>
78
79
  ```
79
80
 
80
81
  Example Usage for calling the reports API with oAuth token
81
82
  ```ruby
82
83
  2.5.7 :001 > require 'smartcar'
83
84
  => true
84
- 2.5.7 :003 > ids = Smartcar::Vehicle.all_vehicle_ids(token: token)
85
+ 2.5.7 :003 > ids = Smartcar::Vehicle.get_vehicles(token: token).vehicles
85
86
  => ["4bb777b2-bde7-4305-8952-25956f8c0868"]
86
87
  2.5.7 :004 > vehicle = Smartcar::Vehicle.new(token: token, id: ids.first)
87
- => #<Smartcar::Vehicle:0x00005564211a7c48 @token="5ae77cb0-7c1a-486a-ac20-00c76d2fd1aa", @id="4bb777b2-bde7-4305-8952-25956f8c0868", @unit_system="imperial">
88
+ => #<Smartcar::Vehicle:0x0000558dcd7ee608 @token="c900e00e-ee8e-403d-a7bf-f992bc0ad302", @id="e31c9de6-1332-472b-b648-5d74b05b7fda", @options={:unit_system=>"metric", :version=>"2.0"}, @unit_system="metric", @version="2.0", @service=#<Faraday::Connection:0x0000558dcd7d63f0 @parallel_manager=nil, @headers={"User-Agent"=>"Faraday v1.4.2"}, @params={}, @options=#<Faraday::RequestOptions timeout=310>, @ssl=#<Faraday::SSLOptions verify=true>, @default_parallel_manager=nil, @builder=#<Faraday::RackBuilder:0x0000558dcd7c1bf8 @adapter=Faraday::Adapter::NetHttp, @handlers=[Faraday::Request::UrlEncoded], @app=#<Faraday::Request::UrlEncoded:0x0000558dcd7af048 @app=#<Faraday::Adapter::NetHttp:0x0000558dcd7af390 @ssl_cert_store=#<OpenSSL::X509::Store:0x0000558dcd7a36a8 @verify_callback=nil, @error=nil, @error_string=nil, @chain=nil, @time=nil>, @app=#<Proc:0x0000558dcd7af278 /home/ashwinsubramanian/.rvm/gems/ruby-2.7.2/gems/faraday-1.4.2/lib/faraday/adapter.rb:37 (lambda)>, @connection_options={}, @config_block=nil>, @options={}>>, @url_prefix=#<URI::HTTPS https://api.smartcar.com/>, @proxy=nil, @manual_proxy=false>>
88
89
  2.5.7 :006 > vehicle.odometer
89
- => #<Smartcar::Odometer:0x00005564211330f0 @distance=17966.94802354251, @meta={"date"=>"Fri, 12 Jun 2020 06:04:32 GMT", "content-type"=>"application/json; charset=utf-8", "content-length"=>"30", "connection"=>"keep-alive", "access-control-allow-origin"=>"*", "sc-data-age"=>"2020-06-12T06:04:28.843Z", "sc-unit-system"=>"imperial", "sc-request-id"=>"3c447e9e-4cf7-43cb-b688-fba8db3d3582"}>
90
+ => #<OpenStruct distance=39685.33984375, meta=#<OpenStruct data_age=#<DateTime: 2021-06-24T22:28:39+00:00 ((2459390j,80919s,95000000n),+0s,2299161j)>, unit_system="metric", request_id="4962ba7f-5c94-48ab-9955-4e2b101c7b8a">>
90
91
  2.5.7 :007 > vehicle.battery
91
- => #<Smartcar::Battery:0x00005564210fcb18 @range=105.63, @percentRemaining=0.98, @meta={"date"=>"Fri, 12 Jun 2020 06:04:44 GMT", "content-type"=>"application/json; charset=utf-8", "content-length"=>"40", "connection"=>"keep-alive", "access-control-allow-origin"=>"*", "sc-data-age"=>"2020-06-12T06:04:28.843Z", "sc-unit-system"=>"imperial", "sc-request-id"=>"455ed4b0-b768-4961-86d7-436ad71cf0fa"}>
92
+ => #<OpenStruct range=208.82, percentRemaining=0.31, meta=#<OpenStruct data_age=#<DateTime: 2021-06-24T22:28:54+00:00 ((2459390j,80934s,855000000n),+0s,2299161j)>, unit_system="metric", request_id="a88b95ec-b10f-4fc8-979b-5d95fe40d925">, percentage_remaining=0.31>
92
93
  2.5.7 :009 > vehicle.lock!
93
- => true
94
- 2.5.7 :010 > vehicle.batch(["charge","battery"])
95
- => {:charge=>#<Smartcar::Charge:0x000055853d1fd7c8 @state="NOT_CHARGING", @isPluggedIn=false, @meta={"sc-data-age"=>"2020-06-12T06:18:50.581Z"}>, :battery=>#<Smartcar::Battery:0x000055853d1fd638 @range=105.63, @percentRemaining=0.98, @meta={"sc-data-age"=>"2020-06-12T06:18:50.581Z", "sc-unit-system"=>"imperial"}>}
96
- 2.5.7 :011 > vehicle.start_charge!
97
- Traceback (most recent call last):
98
- 5: from /usr/share/rvm/rubies/ruby-2.5.7/bin/irb:11:in `<main>'
99
- 4: from (irb):5
100
- 3: from /home/st-2vgpnn2/.rvm/gems/ruby-2.5.7/gems/smartcar-1.0.0/lib/smartcar/vehicle.rb:118:in `start_charge!'
101
- 2: from /home/st-2vgpnn2/.rvm/gems/ruby-2.5.7/gems/smartcar-1.0.0/lib/smartcar/vehicle.rb:290:in `start_or_stop_charge!'
102
- 1: from /home/st-2vgpnn2/.rvm/gems/ruby-2.5.7/gems/smartcar-1.0.0/lib/smartcar/base.rb:39:in `block (2 levels) in <class:Base>'
103
- Smartcar::ExternalServiceError (API error - {"error":"vehicle_state_error","message":"Charging plug is not connected to the vehicle.","code":"VS_004"})
104
-
94
+ => #<OpenStruct status="success", message="Successfully sent request to vehicle", meta=#<OpenStruct request_id="0c90918f-a9cc-405c-839f-7d9b70e249c4">>
95
+ 2.5.7 :010 > batch_response = vehicle.batch(["/charge","/battery"])
96
+ => #<OpenStruct>
97
+ 2.5.7 :011 > batch_response.charge()
98
+ => #<OpenStruct state="NOT_CHARGING", isPluggedIn=false, meta=#<OpenStruct data_age=#<DateTime: 2021-06-24T22:30:20+00:00 ((2459390j,81020s,892000000n),+0s,2299161j)>, request_id="29a66280-8685-4a57-9733-daa3dfb9970f">, is_plugged_in?=false>
105
99
  ```
106
100
 
107
101
  Example Usage for oAuth -
108
102
  ```ruby
109
103
  # To get the redirect URL :
110
- 2.5.5 :002 > options = {test_mode: true,scope: ["read_battery","read_charge","read_fuel","read_location","control_security","read_odometer","read_tires","read_vin","read_vehicle_info"],flags: ["country:DE"]}
104
+ 2.5.5 :002 > options = {test_mode: true}
111
105
  2.5.5 :003 > require 'smartcar'
112
- 2.5.5 :004 > client = Smartcar::Oauth.new(options)
113
- 2.5.5 :005 > url = client.authorization_url
106
+ 2.5.5 :004 > client = Smartcar::AuthClient.new(options)
107
+ 2.5.5 :005 > url = client.get_auth_url(["read_battery","read_charge","read_fuel","read_location","control_security","read_odometer","read_tires","read_vin","read_vehicle_info"], {flags: ["country:DE"]})
114
108
  => "https://connect.smartcar.com/oauth/authorize?approval_prompt=auto&client_id=<client id>&mode=test&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fcallback&response_type=code&scope=read_battery+read_charge+read_fuel+read_location+control_security+read_odometer+read_tires+read_vin+read_vehicle_info&flags=country%3ADE"
115
109
  # Redirect user to the above URL.
116
110
  # After authentication user control reaches the callback URL with code.
117
111
  # Use the code from the parameters and request a token
118
- 2.5.5 :006 > token_hash = client.get_token(code)
119
- => {"token_type"=>"Bearer", :access_token=>"56801a5e-6a0b-4d05-a43e-52a4d5e6648f", :refresh_token=>"4f46e7e4-28c5-47b3-ba8d-7dcef73d05dd", :expires_at=>1577875279}
112
+ 2.5.5 :006 > token_hash = client.exchange_code(code)
113
+ => #<OpenStruct token_type="Bearer", access_token="20e24b4a-3055-4cc8-9cf3-2b3c5afba3e6", refresh_token="cf89c62e-7b36-4e13-a9df-d9c2a5296280", expires_at=1624581588>
120
114
  # This access_token can be used to call the Smartcar APIs as given above.
121
115
  # Store this hash and if it expired refresh the token OR use the code again to
122
116
  # get a new token or use .
@@ -128,8 +122,10 @@ To install this gem onto your local machine, run `bundle exec rake install`.
128
122
 
129
123
  To run tests, make sure you have the env variables setup for client id and secret.
130
124
  ```shell
131
- export INTEGRATION_CLIENT_ID=<client id>
132
- export INTEGRATION_CLIENT_SECRET=<client secret>
125
+ export E2E_SMARTCAR_CLIENT_ID=<client id>
126
+ export E2E_SMARTCAR_CLIENT_SECRET=<client secret>
127
+ export E2E_SMARTCAR_AMT=<amt from dashboard for webhooks>
128
+ export E2E_SMARTCAR_WEBHOOK_ID=<webhook id to use for tests>
133
129
  ```
134
130
 
135
131
  Tests can be run using either default rake command OR specific rspec command.
@@ -164,3 +160,9 @@ To contribute, please:
164
160
 
165
161
  [gem-image]: https://badge.fury.io/rb/smartcar
166
162
  [gem-url]: https://badge.fury.io/rb/smartcar.svg
163
+
164
+ ## Supported Ruby Branches
165
+
166
+ Smartcar aims to support the SDK on all Ruby branches that have a status of "normal maintenance" or "security maintenance" as defined in the [Ruby Branches documentation](https://www.ruby-lang.org/en/downloads/branches/).
167
+
168
+ In accordance with the Semantic Versioning specification, the addition of support for new Ruby branches would result in a MINOR version bump and the removal of support for Ruby branches would result in a MAJOR version bump.
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Extension to OpenStruct to convert a nested OpenStruct object to a hash.
4
+ # Using this method any of the API response can be converted back to hash
5
+ # or JSON (from hash) for convenience.
6
+ # Example Usage :
7
+ # response = {a: { b: {c: "test", d: [{x: 1}, {y: 3}]}}}
8
+ class OpenStruct
9
+ def deep_to_h
10
+ to_h.transform_values do |value|
11
+ case value
12
+ when is_a?(OpenStruct)
13
+ value.deep_to_h
14
+ when is_a?(Array)
15
+ value.map { |item| item.is_a?(OpenStruct) ? item.deep_to_h : item }
16
+ else
17
+ value
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/smartcar.rb CHANGED
@@ -1,83 +1,184 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'smartcar_error'
3
4
  require 'smartcar/utils'
4
5
  require 'smartcar/version'
5
6
  require 'smartcar/base'
6
- require 'smartcar/oauth'
7
- require 'smartcar/permissions'
8
- require 'smartcar/battery'
9
- require 'smartcar/battery_capacity'
10
- require 'smartcar/charge'
11
- require 'smartcar/engine_oil'
12
- require 'smartcar/fuel'
13
- require 'smartcar/location'
14
- require 'smartcar/odometer'
15
- require 'smartcar/tire_pressure'
16
- require 'smartcar/vin'
17
- require 'smartcar/vehicle_attributes'
18
- require 'smartcar/vehicle_utils/batch'
19
- require 'smartcar/vehicle_utils/data'
20
- require 'smartcar/vehicle_utils/actions'
7
+ require 'smartcar/auth_client'
21
8
  require 'smartcar/vehicle'
22
- require 'smartcar/user'
23
9
 
24
10
  # Main Smartcar umbrella module
25
11
  module Smartcar
26
12
  # Error raised when a config is not found
27
13
  class ConfigNotFound < StandardError; end
28
14
 
29
- # Error raised when Smartcar returns non 400, 404, 401, 200 or 204 response
30
- class ExternalServiceError < StandardError; end
31
-
32
- # Error raised when Smartcar returns 404
33
- class ServiceUnavailableError < ExternalServiceError; end
34
-
35
- # Error raised when Smartcar returns Authentication Error with status 401
36
- class AuthenticationError < ExternalServiceError; end
37
-
38
- # Error raised when Smartcar returns 400 response
39
- class BadRequestError < ExternalServiceError; end
40
-
41
15
  # Host to connect to smartcar
42
- SITE = 'https://api.smartcar.com/'
16
+ API_ORIGIN = 'https://api.smartcar.com/'
17
+ PATHS = {
18
+ compatibility: '/compatibility',
19
+ user: '/user',
20
+ vehicles: '/vehicles'
21
+ }.freeze
43
22
 
44
23
  # Path for smartcar oauth
45
- OAUTH_PATH = 'https://connect.smartcar.com/oauth/authorize'
24
+ AUTH_ORIGIN = 'https://connect.smartcar.com'
46
25
  %w[success code test live force auto metric imperial].each do |constant|
47
26
  # Constant to represent the value
48
27
  const_set(constant.upcase, constant.freeze)
49
28
  end
50
29
 
51
- # Lock value sent in request body
52
- LOCK = 'LOCK'
53
- # Unlock value sent in request body
54
- UNLOCK = 'UNLOCK'
55
- # Start charge value sent in request body
56
- START_CHARGE = 'START'
57
- # Stop charge value sent in request body
58
- STOP_CHARGE = 'STOP'
59
30
  # Constant for units
60
31
  UNITS = [IMPERIAL, METRIC].freeze
61
32
 
62
- # Smartcar API version variable - defaulted to 1.0
63
- @api_version = '1.0'
64
-
65
- # rubocop:disable Naming/AccessorMethodName
66
- # Module method Used to set api version to be used.
67
- # This method can be used at the top to set the version and any
68
- # following request will use the version set here unless overridden
69
- # separately.
70
- # @param version [String] version to be set without 'v' prefix.
71
- def self.set_api_version(version)
72
- instance_variable_set('@api_version', version)
73
- end
33
+ # Smartcar API version variable - defaulted to 2.0
34
+ @api_version = '2.0'
35
+
36
+ class << self
37
+ # Module method Used to set api version to be used.
38
+ # This method can be used at the top to set the version and any
39
+ # following request will use the version set here unless overridden
40
+ # separately.
41
+ # @param version [String] version to be set without 'v' prefix.
42
+ def set_api_version(version)
43
+ instance_variable_set('@api_version', version)
44
+ end
45
+
46
+ # Module method Used to get api version to be used.
47
+ # This is the getter for the class instance variable @api_version
48
+ #
49
+ # @return [String] api version number without 'v' prefix
50
+ def get_api_version
51
+ instance_variable_get('@api_version')
52
+ end
53
+
54
+ # Module method Used to check compatiblity for VIN and scope
55
+ #
56
+ # API Documentation - https://smartcar.com/docs/api#connect-compatibility
57
+ # @param vin [String] VIN of the vehicle to be checked
58
+ # @param scope [Array of Strings] - array of scopes
59
+ # @param country [String] An optional country code according to
60
+ # [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).
61
+ # Defaults to US.
62
+ # @param options [Hash] Other optional parameters including overrides
63
+ # @option options [String] :client_id Client ID that overrides ENV
64
+ # @option options [String] :client_secret Client Secret that overrides ENV
65
+ # @option options [String] :version API version to use, defaults to what is globally set
66
+ # @option options [Hash] :flags A hash of flag name string as key and a string or boolean value.
67
+ # @option options [Boolean] :test_mode Wether to use test mode or not.
68
+ # @option options [String] :test_mode_compatibility_level this is required argument while using
69
+ # test mode with a real vin. For more information refer to docs.
70
+ #
71
+ # @return [OpenStruct] And object representing the JSON response mentioned in https://smartcar.com/docs/api#connect-compatibility
72
+ # and a meta attribute with the relevant items from response headers.
73
+ def get_compatibility(vin:, scope:, country: 'US', options: {})
74
+ raise InvalidParameterValue.new, 'vin is a required field' if vin.nil?
75
+ raise InvalidParameterValue.new, 'scope is a required field' if scope.nil?
76
+
77
+ base_object = Base.new(
78
+ {
79
+ version: options[:version] || Smartcar.get_api_version,
80
+ auth_type: Base::BASIC
81
+ }
82
+ )
83
+
84
+ base_object.token = generate_basic_auth(options, base_object)
85
+
86
+ base_object.build_response(*base_object.fetch(
87
+ {
88
+ path: PATHS[:compatibility],
89
+ query_params: build_compatibility_params(vin, scope, country, options)
90
+ }
91
+ ))
92
+ end
93
+
94
+ # Module method Used to get user id
95
+ #
96
+ # API Documentation - https://smartcar.com/docs/api#get-user
97
+ # @param token [String] Access token
98
+ #
99
+ # @return [OpenStruct] And object representing the JSON response mentioned in https://smartcar.com/docs/api#get-user
100
+ # and a meta attribute with the relevant items from response headers.
101
+ def get_user(token:, version: Smartcar.get_api_version)
102
+ base_object = Base.new(
103
+ {
104
+ token: token,
105
+ version: version
106
+ }
107
+ )
108
+ base_object.build_response(*base_object.fetch({ path: PATHS[:user] }))
109
+ end
110
+
111
+ # Module method Returns a paged list of all vehicles connected to the application for the current authorized user.
112
+ #
113
+ # API Documentation - https://smartcar.com/docs/api#get-all-vehicles
114
+ # @param token [String] - Access token
115
+ # @param paging [Hash] - Optional filter parameters (check documentation)
116
+ #
117
+ # @return [OpenStruct] And object representing the JSON response mentioned in https://smartcar.com/docs/api#get-all-vehicles
118
+ # and a meta attribute with the relevant items from response headers.
119
+ def get_vehicles(token:, paging: {}, version: Smartcar.get_api_version)
120
+ base_object = Base.new(
121
+ {
122
+ token: token,
123
+ version: version
124
+ }
125
+ )
126
+ base_object.build_response(*base_object.fetch(
127
+ {
128
+ path: PATHS[:vehicles],
129
+ query_params: paging
130
+ }
131
+ ))
132
+ end
133
+
134
+ # Module method to generate hash challenge for webhooks. It does HMAC_SHA256(amt, challenge)
135
+ #
136
+ # @param amt [String] - Application Management Token
137
+ # @param challenge [String] - Challenge string
138
+ #
139
+ # @return [String] String representing the hex digest
140
+ def hash_challenge(amt, challenge)
141
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), amt, challenge)
142
+ end
143
+
144
+ # Module method used to verify webhook payload with AMT and signature.
145
+ #
146
+ # @param amt [String] - Application Management Token
147
+ # @param signature [String] - sc-signature header value
148
+ # @param body [Object] - webhook response body
149
+ #
150
+ # @return [true, false] - true if signature matches the hex digest of amt and body
151
+ def verify_payload(amt, signature, body)
152
+ hash_challenge(amt, body.to_json) == signature
153
+ end
154
+
155
+ private
156
+
157
+ def build_compatibility_params(vin, scope, country, options)
158
+ query_params = {
159
+ vin: vin,
160
+ scope: scope.join(' '),
161
+ country: country
162
+ }
163
+ query_params[:flags] = options[:flags].map { |key, value| "#{key}:#{value}" }.join(' ') if options[:flags]
164
+ query_params[:mode] = options[:test_mode].is_a?(TrueClass) ? 'test' : 'live' unless options[:test_mode].nil?
165
+
166
+ if options[:test_mode_compatibility_level]
167
+ query_params[:test_mode_compatibility_level] =
168
+ options[:test_mode_compatibility_level]
169
+ query_params[:mode] = 'test'
170
+ end
171
+
172
+ query_params
173
+ end
74
174
 
75
- # Module method Used to get api version to be used.
76
- # This is the getter for the class instance variable @api_version
77
- #
78
- # @return [String] api version number without 'v' prefix
79
- def self.get_api_version
80
- instance_variable_get('@api_version')
175
+ # returns auth token for Basic auth
176
+ #
177
+ # @return [String] Base64 encoding of CLIENT:SECRET
178
+ def generate_basic_auth(options, base_object)
179
+ client_id = options[:client_id] || base_object.get_config('SMARTCAR_CLIENT_ID')
180
+ client_secret = options[:client_secret] || base_object.get_config('SMARTCAR_CLIENT_SECRET')
181
+ Base64.strict_encode64("#{client_id}:#{client_secret}")
182
+ end
81
183
  end
82
- # rubocop:enable Naming/AccessorMethodName
83
184
  end