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.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +5 -0
  3. data/CHANGELOG.md +31 -0
  4. data/CONTRIBUTING.md +45 -0
  5. data/{LICENSE.txt → LICENSE.md} +1 -1
  6. data/README.md +366 -0
  7. data/SECURITY.md +38 -0
  8. data/lib/tesla/api/alert_endpoints.rb +35 -0
  9. data/lib/tesla/api/charging_endpoints.rb +115 -0
  10. data/lib/tesla/api/climate_endpoints.rb +180 -0
  11. data/lib/tesla/api/closure_endpoints.rb +142 -0
  12. data/lib/tesla/api/command_endpoints.rb +63 -0
  13. data/lib/tesla/api/media_endpoints.rb +114 -0
  14. data/lib/tesla/api/navigation_endpoints.rb +51 -0
  15. data/lib/tesla/api/oauth_endpoints.rb +118 -0
  16. data/lib/tesla/api/partner_endpoints.rb +62 -0
  17. data/lib/tesla/api/security_endpoints.rb +123 -0
  18. data/lib/tesla/api/software_endpoints.rb +38 -0
  19. data/lib/tesla/api/user_endpoints.rb +40 -0
  20. data/lib/tesla/api/vehicle_endpoints.rb +174 -0
  21. data/lib/tesla/api.rb +39 -0
  22. data/lib/tesla/authenticator.rb +33 -0
  23. data/lib/tesla/bearer_token_authenticator.rb +38 -0
  24. data/lib/tesla/certificate_options.rb +51 -0
  25. data/lib/tesla/charge_state.rb +111 -0
  26. data/lib/tesla/charging_site.rb +67 -0
  27. data/lib/tesla/client.rb +336 -0
  28. data/lib/tesla/client_credentials.rb +230 -0
  29. data/lib/tesla/climate_state.rb +116 -0
  30. data/lib/tesla/configuration.rb +483 -0
  31. data/lib/tesla/connection.rb +361 -0
  32. data/lib/tesla/connection_pool.rb +186 -0
  33. data/lib/tesla/deep_copy.rb +41 -0
  34. data/lib/tesla/drive_state.rb +80 -0
  35. data/lib/tesla/errors/bad_gateway.rb +9 -0
  36. data/lib/tesla/errors/bad_request.rb +9 -0
  37. data/lib/tesla/errors/client_error.rb +9 -0
  38. data/lib/tesla/errors/command_failed.rb +42 -0
  39. data/lib/tesla/errors/device_unexpected_response.rb +12 -0
  40. data/lib/tesla/errors/error.rb +7 -0
  41. data/lib/tesla/errors/forbidden.rb +14 -0
  42. data/lib/tesla/errors/gateway_timeout.rb +9 -0
  43. data/lib/tesla/errors/http_error.rb +89 -0
  44. data/lib/tesla/errors/internal_server_error.rb +9 -0
  45. data/lib/tesla/errors/invalid_response.rb +33 -0
  46. data/lib/tesla/errors/locked.rb +12 -0
  47. data/lib/tesla/errors/method_not_allowed.rb +9 -0
  48. data/lib/tesla/errors/misdirected_request.rb +13 -0
  49. data/lib/tesla/errors/network_error.rb +30 -0
  50. data/lib/tesla/errors/not_acceptable.rb +9 -0
  51. data/lib/tesla/errors/not_found.rb +9 -0
  52. data/lib/tesla/errors/oauth_error.rb +53 -0
  53. data/lib/tesla/errors/payment_required.rb +12 -0
  54. data/lib/tesla/errors/precondition_failed.rb +13 -0
  55. data/lib/tesla/errors/request_timeout.rb +13 -0
  56. data/lib/tesla/errors/server_error.rb +9 -0
  57. data/lib/tesla/errors/service_unavailable.rb +9 -0
  58. data/lib/tesla/errors/too_many_redirects.rb +9 -0
  59. data/lib/tesla/errors/too_many_requests.rb +9 -0
  60. data/lib/tesla/errors/unauthorized.rb +9 -0
  61. data/lib/tesla/errors/unavailable_for_legal_reasons.rb +12 -0
  62. data/lib/tesla/errors/unprocessable_content.rb +12 -0
  63. data/lib/tesla/errors/vehicle_asleep.rb +32 -0
  64. data/lib/tesla/gui_settings.rb +60 -0
  65. data/lib/tesla/idempotence.rb +30 -0
  66. data/lib/tesla/identifiers.rb +27 -0
  67. data/lib/tesla/json_parsing.rb +38 -0
  68. data/lib/tesla/nearby_charging_sites.rb +35 -0
  69. data/lib/tesla/path_escaping.rb +30 -0
  70. data/lib/tesla/redacted_output.rb +161 -0
  71. data/lib/tesla/redirect_handler.rb +196 -0
  72. data/lib/tesla/region.rb +27 -0
  73. data/lib/tesla/request_builder.rb +138 -0
  74. data/lib/tesla/resource.rb +403 -0
  75. data/lib/tesla/response_parser.rb +92 -0
  76. data/lib/tesla/retry_after.rb +34 -0
  77. data/lib/tesla/retry_handler.rb +252 -0
  78. data/lib/tesla/settings.rb +115 -0
  79. data/lib/tesla/url_validation.rb +131 -0
  80. data/lib/tesla/user.rb +36 -0
  81. data/lib/tesla/vehicle.rb +90 -0
  82. data/lib/tesla/vehicle_config.rb +95 -0
  83. data/lib/tesla/vehicle_data.rb +67 -0
  84. data/lib/tesla/vehicle_state.rb +125 -0
  85. data/lib/tesla/version.rb +6 -0
  86. data/lib/tesla.rb +139 -0
  87. data/sig/manifest.yaml +10 -0
  88. data/sig/tesla.rbs +989 -0
  89. metadata +134 -118
  90. data/.document +0 -5
  91. data/.rvmrc +0 -1
  92. data/Gemfile +0 -13
  93. data/Gemfile.lock +0 -20
  94. data/README.rdoc +0 -19
  95. data/Rakefile +0 -47
  96. data/test/helper.rb +0 -19
  97. data/test/test_tesla.rb +0 -7
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "http_error"
4
+
5
+ module Tesla
6
+ # Base class for client errors (4xx HTTP status codes)
7
+ # @api public
8
+ class ClientError < HTTPError; end
9
+ end
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tesla
4
+ # Base error class for all Tesla errors
5
+ # @api public
6
+ class Error < StandardError; end
7
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "server_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 504 Gateway Timeout responses
7
+ # @api public
8
+ class GatewayTimeout < ServerError; end
9
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "server_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 500 Internal Server Error responses
7
+ # @api public
8
+ class InternalServerError < ServerError; end
9
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 405 Method Not Allowed responses
7
+ # @api public
8
+ class MethodNotAllowed < ClientError; end
9
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 406 Not Acceptable responses
7
+ # @api public
8
+ class NotAcceptable < ClientError; end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 404 Not Found responses
7
+ # @api public
8
+ class NotFound < ClientError; end
9
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "http_error"
4
+
5
+ module Tesla
6
+ # Base class for server errors (5xx HTTP status codes)
7
+ # @api public
8
+ class ServerError < HTTPError; end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "server_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 503 Service Unavailable responses
7
+ # @api public
8
+ class ServiceUnavailable < ServerError; end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "error"
4
+
5
+ module Tesla
6
+ # Error raised when too many redirects are encountered
7
+ # @api public
8
+ class TooManyRedirects < Error; end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 429 Too Many Requests responses
7
+ # @api public
8
+ class TooManyRequests < ClientError; end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client_error"
4
+
5
+ module Tesla
6
+ # Error raised for HTTP 401 Unauthorized responses
7
+ # @api public
8
+ class Unauthorized < ClientError; end
9
+ 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