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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 20e84c22651e2f1856d02fc5288277ec8ec512cc
4
+ data.tar.gz: b4a0471a5d0ca51c0974071b0ef526d7603a531c
5
+ SHA512:
6
+ metadata.gz: 6b0fc114f6cd257b6d52dbcc6aa6d3902a4241fd536cc39c75554ba96b5a88d56dc69e6076d15479c30e4133a1ca24573224daa054222dc04c7843a0a2f1ae17
7
+ data.tar.gz: f6f63dc83fd699d418c3f2702cf612f772c16a6a4980765a57d254eded2ded59a6cd065b3ed70762dc589464844720a2859d48b861bfa9b1c6b6ffd1da7e4902
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tesla_api.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Tim Dorr
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Tesla JSON API
2
+
3
+ [View Documentation](http://docs.timdorr.apiary.io/)
4
+
5
+ This is unofficial documentation of the Tesla Model S JSON API used by the iOS and Android apps.
6
+ The API provides functionality to monitor and control the Model S (and future Tesla vehicles) remotely.
7
+ The project provides both a documention of the API and a Ruby library to for accessing it.
8
+
9
+ ## Ruby Library
10
+
11
+ This gem provides a basic wrapper around the API to easily query and command the car remotely.
12
+ It also provides access to the streaming API and a means to process data coming from it.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+ ```ruby
18
+ gem 'tesla_api'
19
+ ```
20
+
21
+ Or install it yourself:
22
+ ```sh
23
+ gem install tesla_api
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ Here's a quick example:
29
+
30
+ ```ruby
31
+ require 'tesla_api'
32
+
33
+ tesla_api = TeslaApi.new(email, password, client_id, client_secret)
34
+ model_s = tesla_api.vehicles.first
35
+
36
+ model_s.wake_up
37
+ model_s.auto_conditioning_start unless model_s.climate_state["is_auto_conditioning_on"]
38
+
39
+ model_s.set_charge_limit(90)
40
+ model_s.charge_start
41
+
42
+ charge_state = model_s.charge_state
43
+ puts "Your Model S is #{charge_state["charging_state"]} " +
44
+ "with a SOC of #{charge_state["battery_level"]}% " +
45
+ "and an estimate range of #{charge_state["est_battery_range"]} miles"
46
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/apiary.apib ADDED
@@ -0,0 +1,433 @@
1
+ FORMAT: 1A
2
+ HOST: https://portal.vn.teslamotors.com
3
+
4
+ # Tesla Model S JSON API
5
+ This is unofficial documentation of the Tesla Model S JSON API used by the iOS and Android apps. It features functionality to monitor and control the Model S remotely.
6
+
7
+ # Group Authentication Flow
8
+ These endpoints handle login and session management
9
+
10
+ ## GET /login
11
+ Returns the login form. Sets a `_s_portal_session` cookie for the session
12
+ + Response 200
13
+
14
+ + Headers
15
+
16
+ Set-Cookie: _s_portal_session={cookie}; path=/; secure; HttpOnly
17
+
18
+ + Body
19
+
20
+ Login Screen HTML
21
+
22
+ ## POST /login
23
+ Performs the login. Takes in an plain text email and password, matching the owner's login from [http://teslamotors.com/mytesla](http://teslamotors.com/mytesla).
24
+
25
+ Sets a `user_credentials` cookie that expires in 3 months, which is passed along with all future requests to authenticate the user.
26
+
27
+ Redirects back to a dummy welcome page. This page is ignored by the smartphone app and can be ignored by your API client.
28
+ + Request (application/x-www-form-urlencoded)
29
+
30
+ + Body
31
+
32
+ user_session%5Bemail%5D=string&user_session%5Bpassword%5D=string
33
+
34
+ + Response 302
35
+
36
+ + Headers
37
+
38
+ Set-Cookie: _s_portal_session={cookie}; path=/; secure; HttpOnly
39
+ Set-Cookie: user_credentials=x; path=/; expires=Fri, 03-May-2013 03:01:54 GMT; secure; HttpOnly
40
+ Location: https://portal.vn.teslamotors.com/
41
+
42
+
43
+ + Body
44
+
45
+ Dummy Welcome Page
46
+
47
+
48
+ # Group Vehicle List
49
+ A logged in user can have multiple vehicles under their account. This resource is primarily responsible for listing the vehicles and the basic details about them.
50
+
51
+ Must have a `_s_portal_session` and `user_credentials` cookie set for all requests.
52
+
53
+ ## GET /vehicles
54
+ Retrieve a list of your owned vehicles (includes vehicles not yet shipped!)
55
+ + Response 200 (application/json)
56
+
57
+ + Body
58
+
59
+ [{
60
+ "color": null,
61
+ "display_name": null,
62
+ "id": 321,
63
+ "option_codes": "MS01,RENA,TM00,DRLH,PF00,BT85,PBCW,RFPO,WT19,IBMB,IDPB,TR00,SU01,SC01,TP01,AU01,CH00,HP00,PA00,PS00,AD02,X020,X025,X001,X003,X007,X011,X013",
64
+ "user_id": 123,
65
+ "vehicle_id": 1234567890,
66
+ "vin": "5YJSA1CN5CFP01657",
67
+ "tokens": ["x", "x"],
68
+ "state": "online"
69
+ }]
70
+
71
+
72
+ # Group Vehicle Status
73
+ These resources are read-only and determine the state of the vehicle's various sub-systems.
74
+
75
+ Must have a `_s_portal_session` and `user_credentials` cookie set for all requests.
76
+
77
+ ## GET /vehicles/{id}/mobile_enabled
78
+ Determines if mobile access to the vehicle is enabled.
79
+ + Parameters
80
+
81
+ + id (number) ... The ID number of the car
82
+
83
+ + Response 200 (application/json)
84
+
85
+ + Body
86
+
87
+ {
88
+ "reason":"",
89
+ "result":true
90
+ }
91
+
92
+ ## GET /vehicles/{id}/command/charge_state
93
+ Returns the state of charge in the battery.
94
+ + Parameters
95
+
96
+ + id (number) ... The ID number of the car
97
+
98
+ + Response 200 (application/json)
99
+
100
+ + Body
101
+
102
+ {
103
+ "charging_state": "Complete", // "Charging", ??
104
+ "charge_to_max_range": false, // current std/max-range setting
105
+ "max_range_charge_counter": 0,
106
+ "fast_charger_present": false, // connected to Supercharger?
107
+ "battery_range": 239.02, // rated miles
108
+ "est_battery_range": 155.79, // range estimated from recent driving
109
+ "ideal_battery_range": 275.09, // ideal miles
110
+ "battery_level": 91, // integer charge percentage
111
+ "battery_current": -0.6, // current flowing into battery
112
+ "charge_starting_range": null,
113
+ "charge_starting_soc": null,
114
+ "charger_voltage": 0, // only has value while charging
115
+ "charger_pilot_current": 40, // max current allowed by charger & adapter
116
+ "charger_actual_current": 0, // current actually being drawn
117
+ "charger_power": 0, // kW (rounded down) of charger
118
+ "time_to_full_charge": null, // valid only while charging
119
+ "charge_rate": -1.0, // float mi/hr charging or -1 if not charging
120
+ "charge_port_door_open": true
121
+ }
122
+
123
+ ## GET /vehicles/{id}/command/climate_state
124
+ Returns the current temperature and climate control state.
125
+ + Parameters
126
+
127
+ + id (number) ... The ID number of the car
128
+
129
+ + Response 200 (application/json)
130
+
131
+ + Body
132
+
133
+ {
134
+ "inside_temp": 17.0, // degC inside car
135
+ "outside_temp": 9.5, // degC outside car or null
136
+ "driver_temp_setting": 22.6, // degC of driver temperature setpoint
137
+ "passenger_temp_setting": 22.6, // degC of passenger temperature setpoint
138
+ "is_auto_conditioning_on": false, // apparently even if on
139
+ "is_front_defroster_on": null, // null or boolean as integer?
140
+ "is_rear_defroster_on": false,
141
+ "fan_status": 0 // fan speed 0-6 or null
142
+ }
143
+
144
+ ## GET /vehicles/{id}/command/drive_state
145
+ Returns the driving and position state of the vehicle.
146
+ + Parameters
147
+
148
+ + id (number) ... The ID number of the car
149
+
150
+ + Response 200 (application/json)
151
+
152
+ + Body
153
+
154
+ {
155
+ "shift_state": null, //
156
+ "speed": null, //
157
+ "latitude": 33.794839, // degrees N of equator
158
+ "longitude": -84.401593, // degrees W of the prime meridian
159
+ "heading": 4, // integer compass heading, 0-359
160
+ "gps_as_of": 1359863204 // Unix timestamp of GPS fix
161
+ }
162
+
163
+ ## GET /vehicles/{id}/command/gui_settings
164
+ Returns various information about the GUI settings of the car, such as unit format and range display.
165
+ + Parameters
166
+
167
+ + id (number) ... The ID number of the car
168
+
169
+ + Response 200 (application/json)
170
+
171
+ + Body
172
+
173
+ {
174
+ "gui_distance_units": "mi/hr",
175
+ "gui_temperature_units": "F",
176
+ "gui_charge_rate_units": "mi/hr",
177
+ "gui_24_hour_time": false,
178
+ "gui_range_display": "Rated"
179
+ }
180
+
181
+ ## GET /vehicles/{id}/command/vehicle_state
182
+ Returns the vehicle's physical state, such as which doors are open.
183
+ + Parameters
184
+
185
+ + id (number) ... The ID number of the car
186
+
187
+ + Response 200 (application/json)
188
+
189
+ + Body
190
+
191
+ {
192
+ "df": false, // driver's side front door open
193
+ "dr": false, // driver's side rear door open
194
+ "pf": false, // passenger's side front door open
195
+ "pr": false, // passenger's side rear door open
196
+ "ft": false, // front trunk is open
197
+ "rt": false, // rear trunk is open
198
+ "car_verson": "1.19.42", // car firmware version
199
+ "locked": true, // car is locked
200
+ "sun_roof_installed": false, // panoramic roof is installed
201
+ "sun_roof_state": "unknown",
202
+ "sun_roof_percent_open": 0, // null if not installed
203
+ "dark_rims": false, // gray rims installed
204
+ "wheel_type": "Base19", // wheel type installed
205
+ "has_spoiler": false, // spoiler is installed
206
+ "roof_color": "Colored", // "None" for panoramic roof
207
+ "perf_config": "Base"
208
+ }
209
+
210
+ # Group Vehicle Commands
211
+ These commands alter the vehicles state, and return result (true/false) to indicate success, and if failure reason contains the cause of failure.
212
+
213
+ Must have a `_s_portal_session` and `user_credentials` cookie set for all requests.
214
+
215
+ ## GET /vehicles/{id}/command/charge_port_door_open
216
+ Open the charge port.
217
+ + Parameters
218
+
219
+ + id (number) ... The ID number of the car
220
+
221
+ + Response 200 (application/json)
222
+
223
+ + Body
224
+
225
+ {
226
+ "result": false,
227
+ "reason": "failure reason"
228
+ }
229
+
230
+ ## GET /vehicles/{id}/command/charge_standard
231
+ Set the charge mode to standard (~90% under the new percentage system introduced in 4.5).
232
+ + Parameters
233
+
234
+ + id (number) ... The ID number of the car
235
+
236
+ + Response 200 (application/json)
237
+
238
+ + Body
239
+
240
+ {
241
+ "result": false,
242
+ "reason": "failure reason"
243
+ }
244
+
245
+ ## GET /vehicles/{id}/command/charge_max_range
246
+ Set the charge mode to max range (100% under the new percentage system introduced in 4.5).
247
+ + Parameters
248
+
249
+ + id (number) ... The ID number of the car
250
+
251
+ + Response 200 (application/json)
252
+
253
+ + Body
254
+
255
+ {
256
+ "result": false,
257
+ "reason": "failure reason"
258
+ }
259
+
260
+ ## GET /vehicles/{id}/command/set_charge_limit?percent={limit_value}
261
+ Set the charge limit to a custom percentage.
262
+ + Parameters
263
+
264
+ + id (number) ... The ID number of the car
265
+ + limit_value (number) ... The percentage value
266
+
267
+ + Response 200 (application/json)
268
+
269
+ + Body
270
+
271
+ {
272
+ "result": false,
273
+ "reason": "failure reason"
274
+ }
275
+
276
+ ## GET /vehicles/{id}/command/charge_start
277
+ Start charging.
278
+ + Parameters
279
+
280
+ + id (number) ... The ID number of the car
281
+
282
+ + Response 200 (application/json)
283
+
284
+ + Body
285
+
286
+ {
287
+ "result": false,
288
+ "reason": "failure reason" // "already started" if a charge is in progress
289
+ }
290
+
291
+ ## GET /vehicles/{id}/command/charge_stop
292
+ Stop charging.
293
+ + Parameters
294
+
295
+ + id (number) ... The ID number of the car
296
+
297
+ + Response 200 (application/json)
298
+
299
+ + Body
300
+
301
+ {
302
+ "result": false,
303
+ "reason": "failure reason" // "not_charging" if a charge was not in progress
304
+ }
305
+
306
+ ## GET /vehicles/{id}/command/flash_lights
307
+ Flash the lights once.
308
+ + Parameters
309
+
310
+ + id (number) ... The ID number of the car
311
+
312
+ + Response 200 (application/json)
313
+
314
+ + Body
315
+
316
+ {
317
+ "result": false,
318
+ "reason": "failure reason"
319
+ }
320
+
321
+ ## GET /vehicles/{id}/command/honk_horn
322
+ Honk the horn once.
323
+ + Parameters
324
+
325
+ + id (number) ... The ID number of the car
326
+
327
+ + Response 200 (application/json)
328
+
329
+ + Body
330
+
331
+ {
332
+ "result": false,
333
+ "reason": "failure reason"
334
+ }
335
+
336
+ ## GET /vehicles/{id}/command/door_unlock
337
+ Unlock the car's doors.
338
+ + Parameters
339
+
340
+ + id (number) ... The ID number of the car
341
+
342
+ + Response 200 (application/json)
343
+
344
+ + Body
345
+
346
+ {
347
+ "result": false,
348
+ "reason": "failure reason"
349
+ }
350
+
351
+ ## GET /vehicles/{id}/command/door_lock
352
+ Lock the car's doors.
353
+ + Parameters
354
+
355
+ + id (number) ... The ID number of the car
356
+
357
+ + Response 200 (application/json)
358
+
359
+ + Body
360
+
361
+ {
362
+ "result": false,
363
+ "reason": "failure reason"
364
+ }
365
+
366
+ ## GET /vehicles/{id}/command/set_temps?driver_temp={driver_degC}&passenger_temp={pass_degC}
367
+ Set the temperature target for the HVAC system.
368
+ + Parameters
369
+
370
+ + id (number) ... The ID number of the car
371
+ + driver_degC (number) ... The desired temperature on the driver's side in celcius.
372
+ + pass_degC (number) ... The desired temperature on the passenger's side in celcius.
373
+
374
+ + Response 200 (application/json)
375
+
376
+ + Body
377
+
378
+ {
379
+ "result": false,
380
+ "reason": "failure reason"
381
+ }
382
+
383
+ ## GET /vehicles/{id}/command/auto_conditioning_start
384
+ Start the HVAC system. Will cool or heat automatically, depending on set temperature.
385
+ + Parameters
386
+
387
+ + id (number) ... The ID number of the car
388
+
389
+ + Response 200 (application/json)
390
+
391
+ + Body
392
+
393
+ {
394
+ "result": false,
395
+ "reason": "failure reason"
396
+ }
397
+
398
+ ## GET /vehicles/{id}/command/auto_conditioning_stop
399
+ Stop the HVAC system.
400
+ + Parameters
401
+
402
+ + id (number) ... The ID number of the car
403
+
404
+ + Response 200 (application/json)
405
+
406
+ + Body
407
+
408
+ {
409
+ "result": false,
410
+ "reason": "failure reason"
411
+ }
412
+
413
+ ## GET /vehicles/{id}/command/sun_roof_control?state={state}
414
+ Controls the car's panoramic roof, if installed.
415
+ + Parameters
416
+
417
+ + id (number) ... The ID number of the car
418
+ + state (string)
419
+ The desired state of the panoramic roof. The approximate percent open values for each state are `open` = 100%, `close` = 0%, `comfort` = 80%, and `vent` = ~15%
420
+ + Values
421
+ + `open`
422
+ + `close`
423
+ + `comfort`
424
+ + `vent`
425
+
426
+ + Response 200 (application/json)
427
+
428
+ + Body
429
+
430
+ {
431
+ "result": false,
432
+ "reason": "failure reason"
433
+ }
data/lib/tesla_api.rb ADDED
@@ -0,0 +1,172 @@
1
+ require "tesla_api/version"
2
+
3
+ class TeslaApi
4
+ include HTTParty
5
+ base_uri "https://owner-api.teslamotors.com/api/1"
6
+ format :json
7
+
8
+ attr_reader :email
9
+
10
+ def initialize(email, password, client_id, client_secret)
11
+ @email = email
12
+ response = self.class.post(
13
+ "https://owner-api.teslamotors.com/oauth/token",
14
+ body: {
15
+ "grant_type" => "password",
16
+ "client_id" => client_id,
17
+ "client_secret" => client_secret,
18
+ "email" => email,
19
+ "password" => password
20
+ }
21
+ )
22
+ self.class.headers "Authorization" => "Bearer #{response["access_token"]}"
23
+ end
24
+
25
+ def vehicles
26
+ self.class.get("/vehicles")["response"].map { |v| Vehicle.new(self.class, email, v["id"], v) }
27
+ end
28
+
29
+ class Vehicle
30
+ attr_reader :api, :email, :id, :vehicle
31
+
32
+ def initialize(api, email, id, vehicle)
33
+ @api = api
34
+ @email = email
35
+ @id = id
36
+ @vehicle = vehicle
37
+ end
38
+
39
+ def [](key)
40
+ vehicle[key]
41
+ end
42
+
43
+ # State
44
+
45
+ def mobile_enabled
46
+ api.get("/vehicles/#{id}/mobile_enabled")["response"]
47
+ end
48
+
49
+ def charge_state
50
+ api.get("/vehicles/#{id}/data_request/charge_state")["response"]
51
+ end
52
+
53
+ def climate_state
54
+ api.get("/vehicles/#{id}/data_request/climate_state")["response"]
55
+ end
56
+
57
+ def drive_state
58
+ api.get("/vehicles/#{id}/data_request/drive_state")["response"]
59
+ end
60
+
61
+ def gui_settings
62
+ api.get("/vehicles/#{id}/data_request/gui_settings")["response"]
63
+ end
64
+
65
+ def vehicle_state
66
+ api.get("/vehicles/#{id}/data_request/vehicle_state")["response"]
67
+ end
68
+
69
+ # Commands
70
+
71
+ def wake_up
72
+ api.post("/vehicles/#{id}/wake_up")
73
+ end
74
+
75
+ def charge_port_door_open
76
+ api.post("/vehicles/#{id}/command/charge_port_door_open")
77
+ end
78
+
79
+ def charge_standard
80
+ api.post("/vehicles/#{id}/command/charge_standard")
81
+ end
82
+
83
+ def charge_max_range
84
+ api.post("/vehicles/#{id}/command/charge_max_range")
85
+ end
86
+
87
+ def set_charge_limit(percent)
88
+ api.post("/vehicles/#{id}/command/set_charge_limit", query: {state: "set", percent: percent})
89
+ end
90
+
91
+ def charge_start
92
+ api.post("/vehicles/#{id}/command/charge_start")
93
+ end
94
+
95
+ def charge_stop
96
+ api.post("/vehicles/#{id}/command/charge_stop")
97
+ end
98
+
99
+ def flash_lights
100
+ api.post("/vehicles/#{id}/command/flash_lights")
101
+ end
102
+
103
+ def honk_horn
104
+ api.post("/vehicles/#{id}/command/honk_horn")
105
+ end
106
+
107
+ def door_unlock
108
+ api.post("/vehicles/#{id}/command/door_unlock")
109
+ end
110
+
111
+ def door_lock
112
+ api.post("/vehicles/#{id}/command/door_lock")
113
+ end
114
+
115
+ def set_temps(driver_temp, passenger_temp)
116
+ api.post("/vehicles/#{id}/command/set_temps", query: {driver_temp: driver_temp, passenger_temp: passenger_temp})
117
+ end
118
+
119
+ def auto_conditioning_start
120
+ api.post("/vehicles/#{id}/command/auto_conditioning_start")
121
+ end
122
+
123
+ def auto_conditioning_stop
124
+ api.post("/vehicles/#{id}/command/auto_conditioning_stop")
125
+ end
126
+
127
+ def sun_roof_control(state)
128
+ api.post("/vehicles/#{id}/command/sun_roof_control", query: {state: state})
129
+ end
130
+
131
+ def sun_roof_move(percent)
132
+ api.post("/vehicles/#{id}/command/sun_roof_control", query: {state: "move", percent: percent})
133
+ end
134
+
135
+ # Streaming
136
+
137
+ def stream(&reciever)
138
+ EventMachine.run do
139
+ request = EventMachine::HttpRequest.new(
140
+ "https://streaming.vn.teslamotors.com/stream/#{self["vehicle_id"]}/" +
141
+ "?values=speed,odometer,soc,elevation,est_heading,est_lat,est_lng,power")
142
+
143
+ http = request.get(
144
+ head: {
145
+ "authorization" => [
146
+ email,
147
+ self["tokens"].first
148
+ ]
149
+ },
150
+ inactivity_timeout: 15)
151
+
152
+ http.stream do |chunk|
153
+ attributes = chunk.split(",")
154
+ reciever.call({
155
+ time: DateTime.strptime((attributes[0].to_i/1000).to_s, "%s"),
156
+ speed: attributes[1].to_f,
157
+ odometer: attributes[2].to_f,
158
+ soc: attributes[3].to_f,
159
+ elevation: attributes[4].to_f,
160
+ est_heading: attributes[5].to_f,
161
+ est_lat: attributes[6].to_f,
162
+ est_lng: attributes[7].to_f,
163
+ power: attributes[8].to_f
164
+ })
165
+ end
166
+
167
+ http.callback { EventMachine.stop }
168
+ http.errback { EventMachine.stop }
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,3 @@
1
+ module TeslaApi
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,44 @@
1
+ GET /login HTTP/1.1
2
+ Host: portal.vn.teslamotors.com
3
+ Connection: Keep-Alive
4
+ Accept-Encoding: gzip deflate
5
+
6
+
7
+ HTTP/1.1 200 OK
8
+ Content-Type: text/html; charset=utf-8
9
+ X-UA-Compatible: IE=Edge,chrome=1
10
+ ETag: "68693d0c80ee503a112cafc18a273525"
11
+ Cache-Control: max-age=0, private, must-revalidate
12
+ Set-Cookie: _s_portal_session=x; path=/; secure; HttpOnly
13
+ X-Request-Id: 80985fcba166592ed09cce956fd395d6
14
+ X-Runtime: 0.006161
15
+ Date: Sun, 03 Feb 2013 03:01:52 GMT
16
+ X-Rack-Cache: miss
17
+ Server: thin 1.4.1 codename Chromeo
18
+ Transfer-Encoding: chunked
19
+
20
+ 205
21
+ <!DOCTYPE html>
22
+ <html>
23
+ <head>
24
+ <title>Portal</title>
25
+ <script src="/assets/application-a5592d882a1bdc39d6b26c108a8ffbe0.js" type="text/javascript"></script>
26
+ <meta content="authenticity_token" name="csrf-param" />
27
+ <meta content="kOHBAsesbSMy0AJKsPC7f9aI/QgE9g4SxbUcfZAhvdg=" name="csrf-token" />
28
+ <meta name="csrf-token" content="kOHBAsesbSMy0AJKsPC7f9aI/QgE9g4SxbUcfZAhvdg=">
29
+
30
+ <link href='/images/favicon.ico' rel='shortcut icon'>
31
+
32
+ </head>
33
+ <body>
34
+ <header>
35
+ <li><a href="/login">Login</a></li>
36
+ </header>
37
+
38
+
39
+ </body>
40
+ </html>
41
+
42
+ 0
43
+
44
+
@@ -0,0 +1,29 @@
1
+ POST /login HTTP/1.1
2
+ Content-Length: 81
3
+ Content-Type: application/x-www-form-urlencoded; charset=UTF-8
4
+ Host: portal.vn.teslamotors.com
5
+ Connection: Keep-Alive
6
+ Cookie: _s_portal_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWI2YzM0ZTJkMzZkMTk4ZWVkYjkzYzBiYWNmMzI3MTZkBjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMWtPSEJBc2VzYlNNeTBBSktzUEM3ZjlhSS9RZ0U5ZzRTeGJVY2ZaQWh2ZGc9BjsARg%3D%3D--da659682afba93065edfe2932903edc6eb16d0ac
7
+ Cookie2: $Version=1
8
+ Accept-Encoding: gzip deflate
9
+
10
+ user_session%5Bpassword%5D=xxx&user_session%5Bemail%5D=xxx%40xxx.com
11
+ HTTP/1.1 302 Found
12
+ Location: https://portal.vn.teslamotors.com/
13
+ Content-Type: text/html; charset=utf-8
14
+ X-UA-Compatible: IE=Edge,chrome=1
15
+ Cache-Control: no-cache
16
+ Set-Cookie: user_credentials=x; path=/; expires=Fri, 03-May-2013 03:01:54 GMT; secure; HttpOnly
17
+ Set-Cookie: _s_portal_session=x; path=/; secure; HttpOnly
18
+ X-Request-Id: a1c6e1dc7d2ba9c1c8cdec6ad536b2e4
19
+ X-Runtime: 1.129245
20
+ Date: Sun, 03 Feb 2013 03:01:54 GMT
21
+ X-Rack-Cache: invalidate, pass
22
+ Server: thin 1.4.1 codename Chromeo
23
+ Transfer-Encoding: chunked
24
+
25
+ 64
26
+ <html><body>You are being <a href="https://portal.vn.teslamotors.com/">redirected</a>.</body></html>
27
+ 0
28
+
29
+
data/logs/root.GET.log ADDED
@@ -0,0 +1,50 @@
1
+ GET / HTTP/1.1
2
+ Host: portal.vn.teslamotors.com
3
+ Connection: Keep-Alive
4
+ Cookie: _s_portal_session=x; user_credentials=x
5
+ Cookie2: $Version=1
6
+ Accept-Encoding: gzip deflate
7
+
8
+
9
+ HTTP/1.1 200 OK
10
+ Content-Type: text/html; charset=utf-8
11
+ X-UA-Compatible: IE=Edge,chrome=1
12
+ ETag: "389b2980d80c9fac569172b31c06dddb"
13
+ Cache-Control: must-revalidate, private, max-age=0
14
+ Set-Cookie: _s_portal_session=x; path=/; secure; HttpOnly
15
+ X-Request-Id: 2c54d0edded8b93de51a3cbf8a5dd3e9
16
+ X-Runtime: 0.007121
17
+ Date: Sun, 03 Feb 2013 03:01:54 GMT
18
+ X-Rack-Cache: miss
19
+ Server: thin 1.4.1 codename Chromeo
20
+ Transfer-Encoding: chunked
21
+
22
+ 249
23
+ <!DOCTYPE html>
24
+ <html>
25
+ <head>
26
+ <title>Portal</title>
27
+ <script src="/assets/application-a5592d882a1bdc39d6b26c108a8ffbe0.js" type="text/javascript"></script>
28
+ <meta content="authenticity_token" name="csrf-param" />
29
+ <meta content="6/1QjgCk7xTyDJGAK8xIpCNAShD8a6NSco4rbEyz6bw=" name="csrf-token" />
30
+ <meta name="csrf-token" content="6/1QjgCk7xTyDJGAK8xIpCNAShD8a6NSco4rbEyz6bw=">
31
+
32
+ <link href='/images/favicon.ico' rel='shortcut icon'>
33
+
34
+ </head>
35
+ <body>
36
+ <header>
37
+
38
+ <li>
39
+ <a href="/logout" data-method="delete" rel="nofollow">Logout</a>
40
+ </li>
41
+ </header>
42
+
43
+ Welcome to the portal app.
44
+
45
+ </body>
46
+ </html>
47
+
48
+ 0
49
+
50
+
data/tesla_api.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'tesla_api/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "tesla_api"
7
+ spec.version = TeslaApi::VERSION
8
+ spec.authors = ["Tim Dorr"]
9
+ spec.email = ["timdorr@timdorr.com"]
10
+ spec.summary = %q{A wrapper for the Tesla API}
11
+ spec.description = %q{Check the state of your Tesla Model S and issue basic commands. Stream data from the car's telematics system.}
12
+ spec.homepage = "https://github.com/timdorr/model-s-api"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tesla_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tim Dorr
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Check the state of your Tesla Model S and issue basic commands. Stream
42
+ data from the car's telematics system.
43
+ email:
44
+ - timdorr@timdorr.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - apiary.apib
55
+ - lib/tesla_api.rb
56
+ - lib/tesla_api/version.rb
57
+ - logs/login.GET.log
58
+ - logs/login.POST.log
59
+ - logs/root.GET.log
60
+ - tesla_api.gemspec
61
+ homepage: https://github.com/timdorr/model-s-api
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.2.2
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: A wrapper for the Tesla API
85
+ test_files: []