tesla-api 0.0.1

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.
@@ -0,0 +1,4 @@
1
+ # Defines a set of objects with Vehcile as the root accessor to
2
+ # both read telemetry and control the state.
3
+ module TeslaAPI
4
+ end
@@ -0,0 +1,257 @@
1
+ module TeslaAPI
2
+ # Defines a Model S vehicle returned from the API
3
+ class Vehicle < Data
4
+ # An array of Tesla defined option codes
5
+ attr_reader :option_codes
6
+
7
+ ##
8
+ # :method: color
9
+ # Should be car color but is always nil
10
+
11
+ ##
12
+ # :method: display_name
13
+ # Only observed as nil
14
+
15
+ ##
16
+ # :method: id
17
+ # Vehicle ID used in other API calls
18
+
19
+ ##
20
+ # :method: user_id
21
+ # Logged in user ID
22
+
23
+ ##
24
+ # :method: vehicle_id
25
+ # Vehicle ID used in streaming API
26
+
27
+ ##
28
+ # :method: vin
29
+ # Vehicle Identification Number
30
+
31
+ ##
32
+ # :method: tokens
33
+ # API tokens (first is used for streaming API)
34
+
35
+ ##
36
+ # :method: online_state
37
+ # "online" if currently online with API (streaming?)
38
+
39
+ ##
40
+ # :method: option_codes
41
+ # Array of option codes defining how the vehicle is configured
42
+
43
+ def initialize(tesla, data) # :nodoc:
44
+ @tesla = tesla
45
+
46
+ ivar_from_data("color", "color", data)
47
+ ivar_from_data("display_name", "display_name", data)
48
+ ivar_from_data("id", "id", data)
49
+ ivar_from_data("user_id", "user_id", data)
50
+ ivar_from_data("vehicle_id", "vehicle_id", data)
51
+ ivar_from_data("vin", "vin", data)
52
+ ivar_from_data("tokens", "tokens", data)
53
+ ivar_from_data("online_state", "state", data)
54
+
55
+ @option_codes = data["option_codes"].split(",")
56
+ end
57
+
58
+ # true if the vehicle allows mobile access
59
+ def mobile_access?
60
+ tesla.api_mobile_access?(self)
61
+ end
62
+
63
+ # Returns the option codes as human readable string
64
+ def option_code_descriptions
65
+ option_codes.map { |code| codes_to_description.fetch(code, code) }.join(", ")
66
+ end
67
+
68
+ # Returns the streaming data interface
69
+ def stream
70
+ tesla.stream(self)
71
+ end
72
+
73
+ #################################
74
+ #
75
+ # Commands
76
+ #
77
+ #################################
78
+
79
+ # Wakes up the streaming API
80
+ def wake_up!
81
+ tesla.wake_up!(self)
82
+ end
83
+
84
+ # Opens the charging port
85
+ def open_charge_port!
86
+ tesla.open_charge_port!(self)
87
+ end
88
+
89
+ # Turns on the temperature conditioning
90
+ def auto_conditioning_start!
91
+ tesla.auto_conditioning_start!(self)
92
+ end
93
+
94
+ # Turns off the temperature conditioning
95
+ def auto_conditioning_stop!
96
+ tesla.auto_conditioning_stop!(self)
97
+ end
98
+
99
+ # Sets the temperature for both the driver and passenger
100
+ def set_temperature!(driver_degrees_celcius, passenger_degrees_celcius)
101
+ tesla.set_temperature!(self, driver_degrees_celcius, passenger_degrees_celcius)
102
+ end
103
+
104
+ # Opens the panoramic roof
105
+ #
106
+ # state may be "open", "close", "comfort", or "vent"
107
+ def open_roof!(state)
108
+ tesla.open_roof!(self, state)
109
+ end
110
+
111
+ # Locks the vehicle doors
112
+ def lock_door!
113
+ tesla.lock_door!(self)
114
+ end
115
+
116
+ # Unlocks the vehicle doors
117
+ def unlock_door!
118
+ tesla.unlock_door!(self)
119
+ end
120
+
121
+ # Honks the vehicles horn
122
+ def honk_horn!
123
+ tesla.honk_horn!(self)
124
+ end
125
+
126
+ # Flashes the vehicle lights
127
+ def flash_lights!
128
+ tesla.flash_lights!(self)
129
+ end
130
+
131
+ # Stops the vehicle charging
132
+ def charge_stop!
133
+ tesla.charge_stop!(self)
134
+ end
135
+
136
+ # Starts the vehicle charging
137
+ def charge_start!
138
+ tesla.charge_start!(self)
139
+ end
140
+
141
+ # Charge the vehicle for maximum range
142
+ def charge_max_range!
143
+ tesla.charge_max_range!(self)
144
+ end
145
+
146
+ # Charge the vehicle to standard range
147
+ def charge_standard!
148
+ tesla.charge_standard!(self)
149
+ end
150
+
151
+ #################################
152
+ #
153
+ # Queries
154
+ #
155
+ #################################
156
+
157
+ # Returns the vehicles charge state
158
+ def charge_state
159
+ @charge_state ||= tesla.api_charge_state_for_vehicle(self)
160
+ end
161
+
162
+ # Returns the vehicle climate state
163
+ def climate_state
164
+ @climate_state || tesla.api_climate_state_for_vehicle(self)
165
+ end
166
+
167
+ # Returns the vehicle drive state
168
+ def drive_state
169
+ @drive_state ||= tesla.api_drive_state_for_vehicle(self)
170
+ end
171
+
172
+ # Returns the vehicle gui settings
173
+ def gui_settings
174
+ @gui_settings ||= tesla.api_gui_settings_for_vehicle(self)
175
+ end
176
+
177
+ # Returns the vehicle state
178
+ def state
179
+ @state ||= tesla.api_get_vehicle_state_for_vehicle(self)
180
+ end
181
+
182
+ private
183
+
184
+ def tesla #:nodoc:
185
+ @tesla
186
+ end
187
+
188
+ def codes_to_description #:nodoc:
189
+ {
190
+ "MS01" => "base",
191
+ "RENA" => "region_us",
192
+ "RECA" => "region_canada",
193
+ "TM00" => "standard_trim",
194
+ "TM02" => "signature_trim",
195
+ "DRLH" => "left_hand_drive",
196
+ "DRRH" => "right_hand_drive",
197
+ "PF00" => "no_performance_model",
198
+ "PF01" => "performance_model",
199
+ "BT85" => "battery_85",
200
+ "BT60" => "battery_60",
201
+ "BT40" => "battery_40",
202
+ "PBSB" => "paint_black",
203
+ "PBSW" => "paint_solid_white",
204
+ "PMSS" => "paint_silver",
205
+ "PMTG" => "paint_dolphin_gray_metalic",
206
+ "PMAB" => "paint_metalic_brown",
207
+ "PMMB" => "paint_metalic_blue",
208
+ "PSW" => "paint_pearl_white",
209
+ "PSR" => "paint_signature_red",
210
+ "RFBC" => "roof_body_color",
211
+ "RFPO" => "roof_panorama",
212
+ "WT19" => "wheel_silver_19",
213
+ "WT21" => "wheel_silver_21",
214
+ "WTSP" => "wheel_gray_21",
215
+ "IBSB" => "seats_base_textile",
216
+ "IZMB" => "seats_black_leather",
217
+ "IZMG" => "seats_gray_leather",
218
+ "IPMB" => "seats_performance_black_leather",
219
+ "IDPB" => "interior_piano_black",
220
+ "IDLW" => "interior_lacewood",
221
+ "IDOM" => "interior_obeche_wood_matte",
222
+ "IDCF" => "interior_carbon_fiber",
223
+ "IPMG" => "interior_performance_leather",
224
+ "TR00" => "no_third_row_seating",
225
+ "TR01" => "third_row_seating",
226
+ "SU00" => "no_air_suspension",
227
+ "SU01" => "air_suspension",
228
+ "SC00" => "no_supercharger",
229
+ "SC01" => "supercharger",
230
+ "AU00" => "no_audio_upgrade",
231
+ "AU01" => "audio_upgrade",
232
+ "CH00" => "no_second_charger",
233
+ "CH01" => "second_charger",
234
+ "HP00" => "no_hpwc_ordered",
235
+ "HP01" => "hpwc_ordered",
236
+ "PA00" => "no_paint_armor",
237
+ "PA01" => "pait_armor",
238
+ "PS00" => "no_parcel_shelf",
239
+ "PS01" => "parcel_shelf",
240
+ "TP00" => "no_tech_package",
241
+ "TP01" => "tech_package",
242
+ "AD02" => "power_adapter_nema_14-50",
243
+ "X001" => "power_lift_gate",
244
+ "X003" => "navigation",
245
+ "X007" => "premium_exterior_lighting",
246
+ "X011" => "homelink",
247
+ "X013" => "satellite_radio",
248
+ "X014" => "standard_radio",
249
+ "X019" => "performance_exterior",
250
+ "X020" => "no_performance_exterior",
251
+ "X024" => "performance_powertrain",
252
+ "X025" => "no_performance_powertrain",
253
+ }
254
+ end
255
+ end
256
+ end
257
+
@@ -0,0 +1,92 @@
1
+ module TeslaAPI
2
+ # Defines the current vehicle state
3
+ class VehicleState < Data
4
+ ##
5
+ # :method: firmware_version
6
+ # Current firmware version
7
+
8
+ ##
9
+ # :method: sun_roof_installed?
10
+ # true if the vehicle is configured with the panoramic sun roof
11
+
12
+ ##
13
+ # :method: sun_roof_state
14
+ # Current state of the sun roof
15
+ # Potential values:
16
+ # unknown
17
+ # moving
18
+
19
+ ##
20
+ # :method: sun_roof_percent_open
21
+ # Percentage the sun roof is open
22
+
23
+ ##
24
+ # :method: driver_front_door_open?
25
+ # true if the driver's side front door is open
26
+
27
+ ##
28
+ # :method: driver_rear_door_open?
29
+ # true if the driver's side rear door is open
30
+
31
+ ##
32
+ # :method: passenger_front_door_open?
33
+ # true if the passenger's side front door is open
34
+
35
+ ##
36
+ # :method: passenger_rear_door_open
37
+ # true if the passenger's side rear door is open
38
+
39
+ ##
40
+ # :method: front_trunk_open?
41
+ # true if the front trunk (frunk) is open
42
+
43
+ ##
44
+ # :method: rear_trunk_open?
45
+ # true if the rear trunk is open
46
+
47
+ ##
48
+ # :method: locked?
49
+ # true if the doors are locked
50
+
51
+ ##
52
+ # :method: dark_rims?
53
+ # true if configured with dark colored rims
54
+
55
+ ##
56
+ # :method: spoiler?
57
+ # true if configured with a spoiler
58
+
59
+ ##
60
+ # :method: nineteen_inch_wheels?
61
+ # true if configured with nineteen inch wheels
62
+
63
+ ##
64
+ # :method: panoramic?
65
+ # true if configured with a panoramic roof
66
+
67
+ ##
68
+ # :method: perf?
69
+ # true if a performance configured vehicle
70
+
71
+ def initialize(data) # :nodoc:
72
+ ivar_from_data("firmware_version", "car_version", data)
73
+ ivar_from_data("sun_roof_installed", "sun_roof_installed", data)
74
+ ivar_from_data("sun_roof_state", "sun_roof_state", data)
75
+ ivar_from_data("sun_roof_percent_open", "sun_roof_percent_open", data)
76
+ ivar_from_data("driver_front_door_open", "df", data)
77
+ ivar_from_data("driver_rear_door_open", "dr", data)
78
+ ivar_from_data("passenger_front_door_open", "pf", data)
79
+ ivar_from_data("passenger_rear_door_open", "pr", data)
80
+ ivar_from_data("front_trunk_open", "ft", data)
81
+ ivar_from_data("rear_trunk_open", "rt", data)
82
+ ivar_from_data("locked", "locked", data)
83
+ ivar_from_data("dark_rims", "dark_rims", data)
84
+ ivar_from_data("spoiler", "has_spoiler", data)
85
+
86
+ @nineteen_inch_wheels = data["wheel_type"] == "Base19"
87
+ @panoramic = data["roof_color"] == "None"
88
+ @perf = data["perf_config"] != "Base"
89
+ end
90
+ end
91
+ end
92
+
@@ -0,0 +1,4 @@
1
+ module TeslaAPI # :nodoc:
2
+ # Version Number
3
+ VERSION = "0.0.1"
4
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tesla-api/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "tesla-api"
8
+ gem.version = TeslaAPI::VERSION
9
+ gem.authors = ["Gavin Stark"]
10
+ gem.email = ["gavin@gstark.com"]
11
+ gem.description = %q{Implements the Tesla Model S HTTP API}
12
+ gem.summary = %q{Implements the Tesla Model S HTTP API}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_dependency 'httpclient', "~> 2.3.2"
20
+ gem.add_development_dependency 'vcr', "~> 2.4.0"
21
+ gem.add_development_dependency 'webmock', "~> 1.9.1"
22
+ end
23
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'vcr'
4
+ require 'tesla-api'
5
+
6
+ VCR.configure do |c|
7
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
8
+ c.hook_into :webmock
9
+ end
10
+
@@ -0,0 +1,72 @@
1
+ require 'helper'
2
+
3
+ class ChargeStateTest < Test::Unit::TestCase
4
+ USER = "user@example.com"
5
+ PASSWORD = "password"
6
+ RECORD_MODE = :new_episodes
7
+
8
+ def charge_state
9
+ @charge_state ||= begin
10
+ VCR.use_cassette('charge_state', :record => RECORD_MODE) do
11
+ TeslaAPI::Connection.new(USER, PASSWORD).vehicle.charge_state
12
+ end
13
+ end
14
+ end
15
+
16
+ def test_charge_state
17
+ assert_equal "Disconnected", charge_state.charging_state
18
+ end
19
+
20
+ def test_supercharging
21
+ assert !charge_state.supercharging?
22
+ end
23
+
24
+ def test_charge_port_open
25
+ assert !charge_state.charge_port_open
26
+ end
27
+
28
+ def test_charge_rate_miles_per_hour
29
+ assert_equal -1.0, charge_state.charge_rate_miles_per_hour
30
+ end
31
+
32
+ def test_hours_to_full_charge
33
+ assert_equal nil, charge_state.hours_to_full_charge
34
+ end
35
+
36
+ def test_charge_power
37
+ assert_equal 0, charge_state.charger_power
38
+ end
39
+
40
+ def test_charger_actual_amperage
41
+ assert_equal 0, charge_state.charger_actual_amperage
42
+ end
43
+
44
+ def test_charger_pilot_amperage
45
+ assert_equal 0, charge_state.charger_pilot_amperage
46
+ end
47
+
48
+ def test_charger_voltage
49
+ assert_equal 0, charge_state.charger_voltage
50
+ end
51
+
52
+ def test_battery_current_flow
53
+ assert_equal -0.2, charge_state.battery_current_flow
54
+ end
55
+
56
+ def test_battery_percentage
57
+ assert_equal 70, charge_state.battery_percentage
58
+ end
59
+
60
+ def test_estimated_battery_range_miles
61
+ assert_equal 143.96, charge_state.estimated_battry_range_miles
62
+ end
63
+
64
+ def test_battery_range_miles
65
+ assert_equal 177.38, charge_state.battery_range_miles
66
+ end
67
+
68
+ def test_charging_to_max
69
+ assert !charge_state.charging_to_max?
70
+ end
71
+ end
72
+