tesla 0.0.1 → 0.1.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 +7 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +31 -0
- data/CONTRIBUTING.md +45 -0
- data/{LICENSE.txt → LICENSE.md} +1 -1
- data/README.md +366 -0
- data/SECURITY.md +38 -0
- data/lib/tesla/api/alert_endpoints.rb +35 -0
- data/lib/tesla/api/charging_endpoints.rb +115 -0
- data/lib/tesla/api/climate_endpoints.rb +180 -0
- data/lib/tesla/api/closure_endpoints.rb +142 -0
- data/lib/tesla/api/command_endpoints.rb +63 -0
- data/lib/tesla/api/media_endpoints.rb +114 -0
- data/lib/tesla/api/navigation_endpoints.rb +51 -0
- data/lib/tesla/api/oauth_endpoints.rb +118 -0
- data/lib/tesla/api/partner_endpoints.rb +62 -0
- data/lib/tesla/api/security_endpoints.rb +123 -0
- data/lib/tesla/api/software_endpoints.rb +38 -0
- data/lib/tesla/api/user_endpoints.rb +40 -0
- data/lib/tesla/api/vehicle_endpoints.rb +174 -0
- data/lib/tesla/api.rb +39 -0
- data/lib/tesla/authenticator.rb +33 -0
- data/lib/tesla/bearer_token_authenticator.rb +38 -0
- data/lib/tesla/certificate_options.rb +51 -0
- data/lib/tesla/charge_state.rb +111 -0
- data/lib/tesla/charging_site.rb +67 -0
- data/lib/tesla/client.rb +336 -0
- data/lib/tesla/client_credentials.rb +230 -0
- data/lib/tesla/climate_state.rb +116 -0
- data/lib/tesla/configuration.rb +483 -0
- data/lib/tesla/connection.rb +361 -0
- data/lib/tesla/connection_pool.rb +186 -0
- data/lib/tesla/deep_copy.rb +41 -0
- data/lib/tesla/drive_state.rb +80 -0
- data/lib/tesla/errors/bad_gateway.rb +9 -0
- data/lib/tesla/errors/bad_request.rb +9 -0
- data/lib/tesla/errors/client_error.rb +9 -0
- data/lib/tesla/errors/command_failed.rb +42 -0
- data/lib/tesla/errors/device_unexpected_response.rb +12 -0
- data/lib/tesla/errors/error.rb +7 -0
- data/lib/tesla/errors/forbidden.rb +14 -0
- data/lib/tesla/errors/gateway_timeout.rb +9 -0
- data/lib/tesla/errors/http_error.rb +89 -0
- data/lib/tesla/errors/internal_server_error.rb +9 -0
- data/lib/tesla/errors/invalid_response.rb +33 -0
- data/lib/tesla/errors/locked.rb +12 -0
- data/lib/tesla/errors/method_not_allowed.rb +9 -0
- data/lib/tesla/errors/misdirected_request.rb +13 -0
- data/lib/tesla/errors/network_error.rb +30 -0
- data/lib/tesla/errors/not_acceptable.rb +9 -0
- data/lib/tesla/errors/not_found.rb +9 -0
- data/lib/tesla/errors/oauth_error.rb +53 -0
- data/lib/tesla/errors/payment_required.rb +12 -0
- data/lib/tesla/errors/precondition_failed.rb +13 -0
- data/lib/tesla/errors/request_timeout.rb +13 -0
- data/lib/tesla/errors/server_error.rb +9 -0
- data/lib/tesla/errors/service_unavailable.rb +9 -0
- data/lib/tesla/errors/too_many_redirects.rb +9 -0
- data/lib/tesla/errors/too_many_requests.rb +9 -0
- data/lib/tesla/errors/unauthorized.rb +9 -0
- data/lib/tesla/errors/unavailable_for_legal_reasons.rb +12 -0
- data/lib/tesla/errors/unprocessable_content.rb +12 -0
- data/lib/tesla/errors/vehicle_asleep.rb +32 -0
- data/lib/tesla/gui_settings.rb +60 -0
- data/lib/tesla/idempotence.rb +30 -0
- data/lib/tesla/identifiers.rb +27 -0
- data/lib/tesla/json_parsing.rb +38 -0
- data/lib/tesla/nearby_charging_sites.rb +35 -0
- data/lib/tesla/path_escaping.rb +30 -0
- data/lib/tesla/redacted_output.rb +161 -0
- data/lib/tesla/redirect_handler.rb +196 -0
- data/lib/tesla/region.rb +27 -0
- data/lib/tesla/request_builder.rb +138 -0
- data/lib/tesla/resource.rb +403 -0
- data/lib/tesla/response_parser.rb +92 -0
- data/lib/tesla/retry_after.rb +34 -0
- data/lib/tesla/retry_handler.rb +252 -0
- data/lib/tesla/settings.rb +115 -0
- data/lib/tesla/url_validation.rb +131 -0
- data/lib/tesla/user.rb +36 -0
- data/lib/tesla/vehicle.rb +90 -0
- data/lib/tesla/vehicle_config.rb +95 -0
- data/lib/tesla/vehicle_data.rb +67 -0
- data/lib/tesla/vehicle_state.rb +125 -0
- data/lib/tesla/version.rb +6 -0
- data/lib/tesla.rb +139 -0
- data/sig/manifest.yaml +10 -0
- data/sig/tesla.rbs +989 -0
- metadata +134 -118
- data/.document +0 -5
- data/.rvmrc +0 -1
- data/Gemfile +0 -13
- data/Gemfile.lock +0 -20
- data/README.rdoc +0 -19
- data/Rakefile +0 -47
- data/test/helper.rb +0 -19
- data/test/test_tesla.rb +0 -7
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised when a vehicle answers a command by saying it did not carry it out
|
|
7
|
+
#
|
|
8
|
+
# A command the Fleet API could not deliver, such as one sent to a vehicle that is asleep, is answered with an
|
|
9
|
+
# HTTP status and raises the {HTTPError} of that status. This is the error of a command that was delivered: the
|
|
10
|
+
# vehicle read it and refused, such as a charge that cannot be started because no cable is connected.
|
|
11
|
+
#
|
|
12
|
+
# @api public
|
|
13
|
+
class CommandFailed < Error
|
|
14
|
+
# The command the vehicle did not carry out
|
|
15
|
+
# @api public
|
|
16
|
+
# @return [String] the name of the command, as the Fleet API names it
|
|
17
|
+
# @example Get the command
|
|
18
|
+
# error.command # => "charge_start"
|
|
19
|
+
attr_reader :command
|
|
20
|
+
|
|
21
|
+
# The reason the vehicle gave
|
|
22
|
+
# @api public
|
|
23
|
+
# @return [String] the reason, which is empty when the vehicle gave none
|
|
24
|
+
# @example Get the reason
|
|
25
|
+
# error.reason # => "disconnected"
|
|
26
|
+
attr_reader :reason
|
|
27
|
+
|
|
28
|
+
# Initialize a new CommandFailed
|
|
29
|
+
#
|
|
30
|
+
# @api public
|
|
31
|
+
# @param command [String] the name of the command, as the Fleet API names it
|
|
32
|
+
# @param reason [String, nil] the reason the vehicle gave
|
|
33
|
+
# @return [CommandFailed] a new instance
|
|
34
|
+
# @example Create a command failed error
|
|
35
|
+
# Tesla::CommandFailed.new(command: "charge_start", reason: "disconnected")
|
|
36
|
+
def initialize(command:, reason:)
|
|
37
|
+
@command = command
|
|
38
|
+
@reason = reason.to_s
|
|
39
|
+
super(["The vehicle did not carry out #{command}", @reason].reject(&:empty?).join(": "))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "server_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 540 responses, which the Fleet API answers with when the vehicle answered with an error
|
|
7
|
+
#
|
|
8
|
+
# The vehicle may need to be restarted, updated, or serviced.
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
class DeviceUnexpectedResponse < ServerError; end
|
|
12
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 403 Forbidden responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when the access token lacks the scope an endpoint requires, and when a command is
|
|
9
|
+
# sent to a vehicle that takes commands only over the Tesla Vehicle Command Protocol, which signs them: such a
|
|
10
|
+
# vehicle is commanded through the vehicle command proxy, which the client is pointed at with `host`.
|
|
11
|
+
#
|
|
12
|
+
# @api public
|
|
13
|
+
class Forbidden < ClientError; end
|
|
14
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require_relative "../retry_after"
|
|
6
|
+
require_relative "error"
|
|
7
|
+
|
|
8
|
+
module Tesla
|
|
9
|
+
# Base class for HTTP errors from the Tesla Fleet API
|
|
10
|
+
# @api public
|
|
11
|
+
class HTTPError < Error
|
|
12
|
+
include RetryAfter
|
|
13
|
+
|
|
14
|
+
# The HTTP response
|
|
15
|
+
# @api public
|
|
16
|
+
# @return [Net::HTTPResponse] the HTTP response
|
|
17
|
+
# @example Get the response
|
|
18
|
+
# error.response
|
|
19
|
+
attr_reader :response
|
|
20
|
+
|
|
21
|
+
# The HTTP status code
|
|
22
|
+
# @api public
|
|
23
|
+
# @return [Integer] the HTTP status code
|
|
24
|
+
# @example Get the status code
|
|
25
|
+
# error.code
|
|
26
|
+
attr_reader :code
|
|
27
|
+
|
|
28
|
+
# Initialize a new HTTPError
|
|
29
|
+
#
|
|
30
|
+
# The message is the error the Fleet API describes in the JSON of the response body, which is its `error` and
|
|
31
|
+
# its `error_description`. A body that describes no error is the message as it is, and the status message
|
|
32
|
+
# stands in for a body that is empty or an HTML page, such as the error page of a CDN.
|
|
33
|
+
#
|
|
34
|
+
# @api public
|
|
35
|
+
# @param response [Net::HTTPResponse] the HTTP response
|
|
36
|
+
# @return [HTTPError] a new instance
|
|
37
|
+
# @example Create an HTTP error
|
|
38
|
+
# error = Tesla::HTTPError.new(response: response)
|
|
39
|
+
def initialize(response:)
|
|
40
|
+
super(error_message(response))
|
|
41
|
+
@response = response
|
|
42
|
+
@code = Integer(response.code)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# The seconds to wait before retrying the request
|
|
46
|
+
#
|
|
47
|
+
# The Fleet API sends a Retry-After header with a 429 Too Many Requests response, as a number of seconds or an
|
|
48
|
+
# HTTP date.
|
|
49
|
+
#
|
|
50
|
+
# @api public
|
|
51
|
+
# @return [Integer, nil] the seconds to wait, rounded up and never negative, or nil when the response has no
|
|
52
|
+
# Retry-After header or one that is neither a number of seconds nor an HTTP date
|
|
53
|
+
# @example Wait before retrying
|
|
54
|
+
# sleep(error.retry_after || 1)
|
|
55
|
+
def retry_after
|
|
56
|
+
retry_after_of(response)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Get the error message from the response
|
|
62
|
+
# @api private
|
|
63
|
+
# @param response [Net::HTTPResponse] the HTTP response
|
|
64
|
+
# @return [String] the error the body describes, else the body, else the status message if the body is empty or
|
|
65
|
+
# an HTML page
|
|
66
|
+
def error_message(response)
|
|
67
|
+
body = response.body.to_s
|
|
68
|
+
return response.message if body.empty? || response.content_type&.casecmp?("text/html")
|
|
69
|
+
|
|
70
|
+
described_error(body) || body
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# The error a JSON response body describes
|
|
74
|
+
#
|
|
75
|
+
# The Fleet API answers an error with a short identifier as the `error` of a JSON object, and sometimes more
|
|
76
|
+
# about it as the `error_description`.
|
|
77
|
+
#
|
|
78
|
+
# @api private
|
|
79
|
+
# @param body [String] the response body
|
|
80
|
+
# @return [String, nil] the error and its description, or nil when the body is not JSON or describes no error
|
|
81
|
+
def described_error(body)
|
|
82
|
+
error = Hash.try_convert(JSON.parse(body)) || {}
|
|
83
|
+
details = error.values_at("error", "error_description").map(&:to_s).reject(&:empty?)
|
|
84
|
+
details.join(": ") unless details.empty?
|
|
85
|
+
rescue JSON::ParserError
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised when a successful response cannot be read: its body is not JSON, such as the page of a proxy or
|
|
7
|
+
# captive portal, its JSON lacks a field the library reads or has one of another type, or a timestamp in it cannot
|
|
8
|
+
# be parsed
|
|
9
|
+
# @api public
|
|
10
|
+
class InvalidResponse < Error
|
|
11
|
+
# The text that could not be read
|
|
12
|
+
# @api public
|
|
13
|
+
# @return [String] the response body, or the value of the attribute, that could not be read
|
|
14
|
+
# @example Get the body
|
|
15
|
+
# error.body
|
|
16
|
+
attr_reader :body
|
|
17
|
+
|
|
18
|
+
# Initialize a new InvalidResponse
|
|
19
|
+
#
|
|
20
|
+
# @api public
|
|
21
|
+
# @param body [String] the response body, or the value of the attribute, that could not be read
|
|
22
|
+
# @param message [String] the error message
|
|
23
|
+
# @return [InvalidResponse] a new instance
|
|
24
|
+
# @example Create an invalid response error
|
|
25
|
+
# Tesla::InvalidResponse.new(body: "<html>")
|
|
26
|
+
# @example Create an invalid response error for a missing field
|
|
27
|
+
# Tesla::InvalidResponse.new(body: "{}", message: "The response body has no version")
|
|
28
|
+
def initialize(body:, message: "The response body is not JSON")
|
|
29
|
+
super(message)
|
|
30
|
+
@body = body
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 423 Locked responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when Tesla has locked the account.
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
class Locked < ClientError; end
|
|
12
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 421 Misdirected Request responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when the account belongs to another region than the host of the request serves
|
|
9
|
+
# (see {API::UserEndpoints#region}).
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
class MisdirectedRequest < ClientError; end
|
|
13
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "openssl"
|
|
5
|
+
require "timeout"
|
|
6
|
+
require "zlib"
|
|
7
|
+
require_relative "error"
|
|
8
|
+
|
|
9
|
+
module Tesla
|
|
10
|
+
# Error raised when a network error occurs
|
|
11
|
+
# @api public
|
|
12
|
+
class NetworkError < Error
|
|
13
|
+
# The errors of Net::HTTP, and of the socket and TLS layers under it, that are raised as a NetworkError
|
|
14
|
+
#
|
|
15
|
+
# One of these is the `cause` of every NetworkError, so a timeout worth trying again can be told from a
|
|
16
|
+
# connection that was refused.
|
|
17
|
+
#
|
|
18
|
+
# @api public
|
|
19
|
+
WRAPPED = [
|
|
20
|
+
IOError,
|
|
21
|
+
Net::HTTPBadResponse,
|
|
22
|
+
Net::ProtocolError,
|
|
23
|
+
OpenSSL::SSL::SSLError,
|
|
24
|
+
SocketError,
|
|
25
|
+
SystemCallError,
|
|
26
|
+
Timeout::Error,
|
|
27
|
+
Zlib::Error
|
|
28
|
+
].freeze
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised when the token endpoint of Tesla's authorization server turns a request away, or answers with a
|
|
7
|
+
# response no token can be read from
|
|
8
|
+
#
|
|
9
|
+
# The error of the simple_oauth gem, which reads the response, is its `cause`.
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
class OAuthError < Error
|
|
13
|
+
# The error code the token endpoint answered with
|
|
14
|
+
# @api public
|
|
15
|
+
# @return [String, nil] the error code, such as "invalid_grant", or nil when the response carried none
|
|
16
|
+
# @example Get the error code
|
|
17
|
+
# error.code # => "invalid_grant"
|
|
18
|
+
attr_reader :code
|
|
19
|
+
|
|
20
|
+
# The description the token endpoint answered with
|
|
21
|
+
# @api public
|
|
22
|
+
# @return [String, nil] the description, or nil when the response carried none
|
|
23
|
+
# @example Get the description
|
|
24
|
+
# error.description # => "The refresh token is expired."
|
|
25
|
+
attr_reader :description
|
|
26
|
+
|
|
27
|
+
# The HTTP status the token endpoint answered with
|
|
28
|
+
# @api public
|
|
29
|
+
# @return [Integer, nil] the HTTP status
|
|
30
|
+
# @example Get the status
|
|
31
|
+
# error.status # => 401
|
|
32
|
+
attr_reader :status
|
|
33
|
+
|
|
34
|
+
# Initialize a new OAuthError
|
|
35
|
+
#
|
|
36
|
+
# The message is the error code and the description, or names the status when the response carried neither.
|
|
37
|
+
#
|
|
38
|
+
# @api public
|
|
39
|
+
# @param code [String, nil] the error code the token endpoint answered with
|
|
40
|
+
# @param description [String, nil] the description the token endpoint answered with
|
|
41
|
+
# @param status [Integer, nil] the HTTP status the token endpoint answered with
|
|
42
|
+
# @return [OAuthError] a new instance
|
|
43
|
+
# @example Create an OAuth error
|
|
44
|
+
# Tesla::OAuthError.new(code: "invalid_grant", description: "The refresh token is expired.", status: 401)
|
|
45
|
+
def initialize(code: nil, description: nil, status: nil)
|
|
46
|
+
@code = code
|
|
47
|
+
@description = description
|
|
48
|
+
@status = status
|
|
49
|
+
details = [code, description].compact
|
|
50
|
+
super(details.empty? ? "The token endpoint answered with status #{status}" : details.join(": "))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 402 Payment Required responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when the account of the application has a bill to pay before it is served again.
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
class PaymentRequired < ClientError; end
|
|
12
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 412 Precondition Failed responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when the application has not been registered in the region of the request (see
|
|
9
|
+
# {API::PartnerEndpoints#register_partner}).
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
class PreconditionFailed < ClientError; end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 408 Request Timeout responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when the vehicle is asleep or offline, so it is the error of a command or a data
|
|
9
|
+
# request sent to a vehicle that has not been woken (see {API::VehicleEndpoints#wake_up}).
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
class RequestTimeout < ClientError; end
|
|
13
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 451 Unavailable For Legal Reasons responses
|
|
7
|
+
#
|
|
8
|
+
# The Fleet API answers with it when a privacy setting of the vehicle or the account withholds what was asked for.
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
class UnavailableForLegalReasons < ClientError; end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "client_error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised for HTTP 422 Unprocessable Content responses
|
|
7
|
+
#
|
|
8
|
+
# RFC 9110 names the status Unprocessable Content, where the RFCs before it named it Unprocessable Entity.
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
class UnprocessableContent < ClientError; end
|
|
12
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "error"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Error raised when a vehicle that was woken is still not online once the wait for it is over
|
|
7
|
+
#
|
|
8
|
+
# A vehicle can take a minute to wake, and one without a connection, such as one parked underground, does not
|
|
9
|
+
# wake at all.
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
class VehicleAsleep < Error
|
|
13
|
+
# The vehicle as the Fleet API last answered with it
|
|
14
|
+
# @api public
|
|
15
|
+
# @return [Vehicle] the vehicle, whose state says why it is not online
|
|
16
|
+
# @example Get the state the vehicle was last in
|
|
17
|
+
# error.vehicle.state # => "asleep"
|
|
18
|
+
attr_reader :vehicle
|
|
19
|
+
|
|
20
|
+
# Initialize a new VehicleAsleep
|
|
21
|
+
#
|
|
22
|
+
# @api public
|
|
23
|
+
# @param vehicle [Vehicle] the vehicle as the Fleet API last answered with it
|
|
24
|
+
# @return [VehicleAsleep] a new instance
|
|
25
|
+
# @example Create a vehicle asleep error
|
|
26
|
+
# Tesla::VehicleAsleep.new(vehicle: vehicle)
|
|
27
|
+
def initialize(vehicle:)
|
|
28
|
+
@vehicle = vehicle
|
|
29
|
+
super("The vehicle is still #{vehicle.state.inspect} rather than online")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "resource"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# The units and formats a vehicle displays
|
|
7
|
+
# @api public
|
|
8
|
+
class GUISettings < Resource
|
|
9
|
+
inspect_with :distance_units, :temperature_units
|
|
10
|
+
|
|
11
|
+
# @!method distance_units
|
|
12
|
+
# The unit of distance the vehicle displays, "mi/hr" or "km/hr"
|
|
13
|
+
# @api public
|
|
14
|
+
# @return [String, nil] the unit of distance the vehicle displays
|
|
15
|
+
# @example
|
|
16
|
+
# gui_settings.distance_units
|
|
17
|
+
attribute :distance_units, :gui_distance_units
|
|
18
|
+
|
|
19
|
+
# @!method temperature_units
|
|
20
|
+
# The unit of temperature the vehicle displays, "F" or "C"
|
|
21
|
+
# @api public
|
|
22
|
+
# @return [String, nil] the unit of temperature the vehicle displays
|
|
23
|
+
# @example
|
|
24
|
+
# gui_settings.temperature_units
|
|
25
|
+
attribute :temperature_units, :gui_temperature_units
|
|
26
|
+
|
|
27
|
+
# @!method charge_rate_units
|
|
28
|
+
# The unit of charge rate the vehicle displays, such as "mi/hr" or "kW"
|
|
29
|
+
# @api public
|
|
30
|
+
# @return [String, nil] the unit of charge rate the vehicle displays
|
|
31
|
+
# @example
|
|
32
|
+
# gui_settings.charge_rate_units
|
|
33
|
+
attribute :charge_rate_units, :gui_charge_rate_units
|
|
34
|
+
|
|
35
|
+
# @!method range_display
|
|
36
|
+
# The range the vehicle displays, "Rated" or "Ideal"
|
|
37
|
+
# @api public
|
|
38
|
+
# @return [String, nil] the range the vehicle displays
|
|
39
|
+
# @example
|
|
40
|
+
# gui_settings.range_display
|
|
41
|
+
attribute :range_display, :gui_range_display
|
|
42
|
+
|
|
43
|
+
# @!method twenty_four_hour_time?
|
|
44
|
+
# Whether the vehicle displays the time on a 24-hour clock
|
|
45
|
+
# @api public
|
|
46
|
+
# @return [Boolean] whether the vehicle displays the time on a 24-hour clock
|
|
47
|
+
# @example
|
|
48
|
+
# gui_settings.twenty_four_hour_time?
|
|
49
|
+
predicate :twenty_four_hour_time, :gui_24_hour_time
|
|
50
|
+
|
|
51
|
+
# @!method timestamp
|
|
52
|
+
# The time the vehicle reported the state
|
|
53
|
+
# @api public
|
|
54
|
+
# @return [Time, nil] the time the vehicle reported the state
|
|
55
|
+
# @raise [InvalidResponse] if the timestamp is not a number of milliseconds
|
|
56
|
+
# @example
|
|
57
|
+
# gui_settings.timestamp
|
|
58
|
+
time_attribute :timestamp
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tesla
|
|
4
|
+
# Tells whether a request can be sent again, mixed into the client and the connection pool
|
|
5
|
+
#
|
|
6
|
+
# A safe request only asks the server for something, so sending it again leaves the vehicle as it was and is
|
|
7
|
+
# answered as the first one would have been. A request that asks a vehicle to do something, such as honking the
|
|
8
|
+
# horn or opening the trunk, is not safe: it cannot be sent a second time to find out whether the vehicle acted on
|
|
9
|
+
# the first one, so it is not sent again once it may have arrived (see {RetryHandler}).
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
module Idempotence
|
|
13
|
+
# The HTTP methods that ask the server for something rather than asking it to do something
|
|
14
|
+
SAFE_METHODS = %w[GET HEAD OPTIONS TRACE].freeze
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
# Whether a request made with an HTTP method only asks the server for something
|
|
19
|
+
#
|
|
20
|
+
# The method is named rather than the request, so that a caller deciding whether to send a request again does
|
|
21
|
+
# not have to have built one (see {Client#execute_request}).
|
|
22
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
# @param http_method [String, Symbol] the HTTP method, in either case
|
|
25
|
+
# @return [Boolean] whether a request made with the method is safe
|
|
26
|
+
def safe?(http_method)
|
|
27
|
+
SAFE_METHODS.include?(http_method.to_s.upcase)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "vehicle"
|
|
4
|
+
|
|
5
|
+
module Tesla
|
|
6
|
+
# Resolves identifiers from resource objects, so API methods accept either
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
module Identifiers
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
# Resolve the tag the Fleet API knows a vehicle by from a tag or a vehicle
|
|
13
|
+
#
|
|
14
|
+
# A vehicle is known by its VIN or by its ID. The VIN is preferred for a vehicle that carries both, since the
|
|
15
|
+
# vehicle command proxy knows a vehicle only by its VIN.
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
# @param vehicle [String, Integer, Vehicle] a VIN, the ID of a vehicle, or a vehicle
|
|
19
|
+
# @return [String, Integer, nil] the VIN or the ID
|
|
20
|
+
def tag_of(vehicle)
|
|
21
|
+
case vehicle
|
|
22
|
+
when Vehicle then vehicle.vin || vehicle.id
|
|
23
|
+
else vehicle
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|