tesla_api 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/Rakefile +1 -1
- data/docs/vehicle/optioncodes.md +54 -26
- data/lib/tesla_api.rb +7 -2
- data/lib/tesla_api/autopark.rb +8 -10
- data/lib/tesla_api/client.rb +50 -51
- data/lib/tesla_api/stream.rb +28 -21
- data/lib/tesla_api/vehicle.rb +9 -9
- data/lib/tesla_api/version.rb +1 -1
- data/spec/lib/tesla_api/client_spec.rb +1 -10
- data/tesla_api.gemspec +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 310c9a551e9ace78ebf8eeee97d301ef30421545f0c0a876532653bad401d00f
|
4
|
+
data.tar.gz: 01344c140bec766dd95697124888b9b860d8a1a3028811d64ec41e15ff5f4adf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b5c85dfc21d90bb311b8818d636d2e320aff0ca5fd5da3d6a99046c717dd91cd7b0d1ba0404d130aec49f55904442776cf1df3b78e3dfd5661aa6f92c92bfbd
|
7
|
+
data.tar.gz: 8f5bf9d04e7ee75980510f5705ecc8d1530086798a858c9a65744ac2eeb346173bbaa290898dd649c1e666e4f2b6df2f92a533f059e7f60adcbaf82afd9cb0e6
|
data/README.md
CHANGED
@@ -36,8 +36,11 @@ Here's a quick example:
|
|
36
36
|
```ruby
|
37
37
|
require 'tesla_api'
|
38
38
|
|
39
|
-
tesla_api = TeslaApi::Client.new(email, client_id, client_secret)
|
40
|
-
tesla_api.login!(password)
|
39
|
+
tesla_api = TeslaApi::Client.new(email: email, client_id: client_id, client_secret: client_secret)
|
40
|
+
tesla_api.login!(password)
|
41
|
+
# Or if you have an access token:
|
42
|
+
tesla_api = TeslaApi::Client.new(access_token: access_token)
|
43
|
+
|
41
44
|
model_s = tesla_api.vehicles.first # => <TeslaApi::Vehicle>
|
42
45
|
|
43
46
|
model_s.wake_up
|
data/Rakefile
CHANGED
data/docs/vehicle/optioncodes.md
CHANGED
@@ -30,7 +30,7 @@ appreciated!_
|
|
30
30
|
| AD09 | Adapter, Swiss (1 phase, 10A) | |
|
31
31
|
| AD10 | Adapter, Denmark (1 phase, 13A) | |
|
32
32
|
| AD11 | Adapter, Italy (1 phase, 13A) | |
|
33
|
-
| AD15 |
|
33
|
+
| AD15 | Adapter | J1772 |
|
34
34
|
| ADPX2 | Type 2 Public Charging Connector | |
|
35
35
|
| ADX4 | No European 3-Phase | |
|
36
36
|
| ADX5 | European 3-Phase, IT | |
|
@@ -38,7 +38,7 @@ appreciated!_
|
|
38
38
|
| ADX7 | No - 3-ph Red IEC309 (3 phase, 16A) | |
|
39
39
|
| ADX9 | No - Adapter, Swiss (1 phase, 10A) | |
|
40
40
|
| ADX8 | Blue IEC309 (1 phase, 230V 32A) | |
|
41
|
-
| AF00 | No HEPA Filter | |
|
41
|
+
| AF00 | No HEPA Filter | Standard air filter, no air ionizer |
|
42
42
|
| AF02 | HEPA Filter | |
|
43
43
|
| AH00 | No Accessory Hitch | |
|
44
44
|
| APE1 | Enhanced Autopilot | |
|
@@ -55,17 +55,19 @@ appreciated!_
|
|
55
55
|
| APPB | Enhanced Autopilot | |
|
56
56
|
| AU00 | No Audio Package | |
|
57
57
|
| AU01 | Ultra High Fidelity Sound | |
|
58
|
+
| AU3P | Sound Studio Package | Premium audio package |
|
58
59
|
| BC0B | Black Brake Calipers | |
|
59
60
|
| BC0R | Red Brake Calipers | |
|
60
61
|
| BC3B | Black Brake Calipers, Model 3 | |
|
61
62
|
| BCMB | Black Brake Calipers | |
|
62
63
|
| BCYR | Performance Brakes | |
|
64
|
+
| BG30 | No Badge | Model 3 |
|
63
65
|
| BP00 | No Ludicrous | |
|
64
66
|
| BP01 | Ludicrous Speed Upgrade | |
|
65
67
|
| BR00 | No Battery Firmware Limit | |
|
66
68
|
| BR03 | Battery Firmware Limit (60kWh) | |
|
67
69
|
| BR05 | Battery Firmware Limit (75kWh) | |
|
68
|
-
| BS00 |
|
70
|
+
| BS00 | Blind Spot Sensor Package | |
|
69
71
|
| BS01 | Special Production Flag | |
|
70
72
|
| BT37 | 75 kWh (Model 3) | |
|
71
73
|
| BT40 | 40 kWh | |
|
@@ -85,7 +87,7 @@ appreciated!_
|
|
85
87
|
| CF00 | High Power Charger | |
|
86
88
|
| CF01 | 48amp charger | |
|
87
89
|
| CH00 | Standard Charger (40 Amp) | |
|
88
|
-
| CH01 | Dual Chargers (80 Amp) | |
|
90
|
+
| CH01 | Dual Chargers (80 Amp) | Twin 10kW charge config |
|
89
91
|
| CH04 | 72 Amp Charger (Model S/X) | |
|
90
92
|
| CH05 | 48 Amp Charger (Model S/X) | |
|
91
93
|
| CH07 | 48 Amp Charger (Model 3) | |
|
@@ -96,32 +98,38 @@ appreciated!_
|
|
96
98
|
| COUS | Country: United States | |
|
97
99
|
| CONL | Country: Netherlands | |
|
98
100
|
| CPW1 | 20" Performance Wheels | |
|
99
|
-
| CW00 | No Cold Weather Package |
|
100
|
-
| CW02 | Subzero Weather Package |
|
101
|
+
| CW00 | Weather Package | No Cold Weather Package |
|
102
|
+
| CW02 | Weather Package | Subzero Weather Package |
|
101
103
|
| DA00 | No Autopilot | |
|
102
|
-
| DA01 | Active Safety (ACC,LDW,SA) | |
|
104
|
+
| DA01 | Active Safety (ACC,LDW,SA) | Drivers Assistance Package |
|
103
105
|
| DA02 | Autopilot Convenience Features | |
|
104
106
|
| DCF0 | Autopilot Convenience Features (DCF0) | |
|
105
107
|
| DRLH | Left Hand Drive | |
|
106
108
|
| BC3R | Performance Brakes | Model 3 |
|
107
109
|
| DRRH | Right Hand Drive | |
|
108
|
-
| DSH5 | PUR
|
110
|
+
| DSH5 | Dashboard | PUR Dashboard Pad |
|
109
111
|
| DSH7 | Alcantara Dashboard Accents | |
|
110
112
|
| DSHG | PUR Dash Pad | |
|
111
113
|
| DU00 | Drive Unit - IR | |
|
112
114
|
| DU01 | Drive Unit - Infineon | |
|
113
115
|
| DV2W | Rear-Wheel Drive | |
|
114
116
|
| DV4W | All-Wheel Drive | |
|
117
|
+
| FC3P | Front Console Front Console (Premium) | Model 3 |
|
115
118
|
| FG00 | No Exterior Lighting Package | |
|
116
|
-
| FG01 | Exterior Lighting Package |
|
117
|
-
| FG02 |
|
119
|
+
| FG01 | Fog Lamps | Exterior Lighting Package |
|
120
|
+
| FG02 | Fog Lamps | Fog Lamps |
|
121
|
+
| FG31 | Fog Lamps | Premium Fog Lights (Model 3) |
|
122
|
+
| FM3B | Performance Package (Model 3) | |
|
118
123
|
| FMP6 | FMP6 | |
|
119
124
|
| FR01 | Base Front Row | |
|
120
125
|
| FR02 | Ventilated Front Seats | |
|
121
126
|
| FR03 | FR03 | |
|
122
127
|
| FR04 | FR04 | |
|
128
|
+
| GLFR | Assembly | Final Assembly Fremont |
|
123
129
|
| HC00 | No Home Charging installation | |
|
124
130
|
| HC01 | Home Charging Installation | |
|
131
|
+
| HM31 | Teck Package - Homelink | Homelink |
|
132
|
+
| HL31 | Head Lamp (Model 3) | Uplevel Headlamps |
|
125
133
|
| HP00 | No HPWC Ordered | |
|
126
134
|
| HP01 | HPWC Ordered | |
|
127
135
|
| ID3W | (Model 3) Wood Decor | |
|
@@ -132,7 +140,7 @@ appreciated!_
|
|
132
140
|
| IDOM | Matte Obeche Wood Decor | |
|
133
141
|
| IDOG | Gloss Obeche Wood Decor | |
|
134
142
|
| IDLW | Lacewood Decor | |
|
135
|
-
| IDPB | Piano Black Decor | |
|
143
|
+
| IDPB | Piano Black Decor | |
|
136
144
|
| IN3BB | All Black Partial Premium Interior | |
|
137
145
|
| IN3PB | All Black Premium Interior | |
|
138
146
|
| INBBW | White | |
|
@@ -145,6 +153,7 @@ appreciated!_
|
|
145
153
|
| INWPT | Tan Interior | |
|
146
154
|
| INYPB | All Black Premium Interior | |
|
147
155
|
| INYPW | Black and White Premium Interior | |
|
156
|
+
| IL31 | Interior Ambient Lighting | |
|
148
157
|
| IVBPP | All Black Interior | |
|
149
158
|
| IVBSW | Ultra White Interior | |
|
150
159
|
| IVBTB | All Black Interior | |
|
@@ -153,10 +162,11 @@ appreciated!_
|
|
153
162
|
| IX01 | Extended Nappa Leather Trim | |
|
154
163
|
| LLP1 | LLP1 | |
|
155
164
|
| LLP2 | LLP2 | |
|
156
|
-
|
|
165
|
+
| LP00 | Lighting Package | No Lighting Package |
|
166
|
+
| LP01 | Lighting Package | Premium Interior Lighting |
|
157
167
|
| LT00 | Vegan interior | |
|
158
168
|
| LT01 | Standard interior | |
|
159
|
-
| LT1B |
|
169
|
+
| LT1B | Lower Trim | Lower Trim |
|
160
170
|
| LT3W | LT3W | |
|
161
171
|
| LT4B | LT4B | |
|
162
172
|
| LT4C | LT4C | |
|
@@ -166,11 +176,13 @@ appreciated!_
|
|
166
176
|
| LT6P | LT6P | |
|
167
177
|
| LTPB | Lower Trim PUR Black | |
|
168
178
|
| ME01 | Memory Seats | |
|
169
|
-
| ME02 | Memory
|
179
|
+
| ME02 | Seat Memory | Seat Memory LHD Driver |
|
170
180
|
| MI00 | 2015 Production Refresh | |
|
181
|
+
| MI00 | Project/Program Code M3 | Base Manufacturing Intro Code |
|
171
182
|
| MI01 | 2016 Production Refresh | |
|
172
183
|
| MI02 | 2017 Production Refresh | |
|
173
184
|
| MI03 | 201? Production Refresh | Found on Model X ordered 11/2018 delivered 3/2019 |
|
185
|
+
| MR31 | Tech Package - Mirror -YES | Uplevel Mirrors |
|
174
186
|
| MT300 | Standard Range Rear-Wheel Drive | |
|
175
187
|
| MT301 | Standard Range Plus Rear-Wheel Drive | |
|
176
188
|
| MT302 | Long Range Rear-Wheel Drive | |
|
@@ -192,7 +204,7 @@ appreciated!_
|
|
192
204
|
| PF01 | Performance Legacy Package | |
|
193
205
|
| PI00 | No Premium Interior | |
|
194
206
|
| PI01 | Premium Upgrades Package | |
|
195
|
-
| PK00 |
|
207
|
+
| PK00 | Parking Sensors | |
|
196
208
|
| PMAB | Anza Brown Metallic Color | |
|
197
209
|
| PMBL | Obsidian Black Multi-Coat Color | |
|
198
210
|
| PMMB | Monterey Blue Metallic Color | |
|
@@ -206,6 +218,7 @@ appreciated!_
|
|
206
218
|
| PPSR | Signature Red Color | |
|
207
219
|
| PPSW | Pearl White Multi-Coat Color | |
|
208
220
|
| PPTI | Titanium Metallic Color | |
|
221
|
+
| PL30 | No Aluminum Pedal | |
|
209
222
|
| PL31 | Performance Pedals | Model 3 |
|
210
223
|
| PRM30 | Partial Premium Interior | |
|
211
224
|
| PRM31 | Premium Interior | |
|
@@ -213,6 +226,7 @@ appreciated!_
|
|
213
226
|
| PRMY1 | Premium Interior | |
|
214
227
|
| PS00 | No Parcel Shelf | |
|
215
228
|
| PS01 | Parcel Shelf | |
|
229
|
+
| RS3H | Second Row Seat Rear Seats (Heated) | Model 3 |
|
216
230
|
| PX00 | No Performance Plus Package | |
|
217
231
|
| PX01 | Performance Plus | |
|
218
232
|
| PX6D | Zero to 60 in 2.5 sec | |
|
@@ -242,32 +256,40 @@ appreciated!_
|
|
242
256
|
| RCX0 | No Rear Console | |
|
243
257
|
| RF3G | Model 3 Glass Roof | |
|
244
258
|
| RFBK | Black Roof | |
|
245
|
-
| RFBC | Body Color Roof | |
|
259
|
+
| RFBC | Body Color Roof | Roof |
|
246
260
|
| RFFG | Glass Roof | |
|
247
261
|
| RFP0 | All Glass Panoramic Roof | |
|
248
262
|
| RFP2 | Sunroof | |
|
249
263
|
| RFPX | Model X Roof | |
|
264
|
+
| S02B | Seat | BLK Leather |
|
250
265
|
| S02P | S02P | |
|
251
266
|
| S31B | S31B | |
|
252
267
|
| S32C | S32C | |
|
253
268
|
| S32P | S32P | |
|
254
269
|
| S32W | S32W | |
|
270
|
+
| S3PB | Seat Black PUR Premium Seats | |
|
255
271
|
| SC00 | No Supercharging | |
|
256
272
|
| SC01 | Supercharging Enabled | |
|
257
273
|
| SC04 | Pay Per Use Supercharging | |
|
258
274
|
| SC05 | Free Supercharging | |
|
275
|
+
| SLR0 | No Rear Spoiler | |
|
259
276
|
| SP00 | No Security Package | |
|
260
|
-
| SR01 | Standard 2nd row | |
|
277
|
+
| SR01 | Standard 2nd row | Second Row Seat |
|
261
278
|
| SR06 | Seven Seat Interior | |
|
262
279
|
| SR07 | Standard 2nd row | |
|
263
280
|
| ST00 | Non-leather Steering Wheel | |
|
264
281
|
| ST01 | Non-heated Leather Steering Wheel | |
|
282
|
+
| ST31 | Steering Wheel | Premium Steering Wheel |
|
283
|
+
| STCP | Steering Wheel | Steering Column (Power) |
|
265
284
|
| STY5S | Five Seat Interior | |
|
266
285
|
| STY7S | Seven Seat Interior | |
|
267
286
|
| SU00 | Standard Suspension | |
|
268
287
|
| SU01 | Smart Air Suspension | |
|
269
|
-
|
|
270
|
-
|
|
288
|
+
| SU3C | Suspension | Coil spring suspension |
|
289
|
+
| T3MA | Tires M3 | 18 Michelin All Season, Square |
|
290
|
+
| TIC4 | Tires | All-Season Tires |
|
291
|
+
| TIMP | Tires | Michelin Primacy 19" Tire |
|
292
|
+
| TM00 | Model Trim | General Production Series Vehicle |
|
271
293
|
| TM02 | General Production Signature Trim | |
|
272
294
|
| TM0A | ALPHA PRE-PRODUCTION NON-SALEABLE | |
|
273
295
|
| TM0B | BETA PRE-PRODUCTION NON-SALEABLE | |
|
@@ -275,22 +297,28 @@ appreciated!_
|
|
275
297
|
| TP01 | Tech Package - No Autopilot | |
|
276
298
|
| TP02 | Tech Package with Autopilot | |
|
277
299
|
| TP03 | Tech Package with Enhanced Autopilot | |
|
278
|
-
| TR00 | No
|
300
|
+
| TR00 | No Rear Facing Seats |
|
279
301
|
| TR01 | Third Row Seating | |
|
280
302
|
| TRA1 | Third Row HVAC | |
|
281
|
-
|
|
303
|
+
| TW00 | No Tow Package | |
|
304
|
+
| TW01 | Tow Package | |
|
282
305
|
| UM01 | Universal Mobile Charger - US Port (Single) | |
|
306
|
+
| UT3P | Suede Grey Premium Headliner | |
|
283
307
|
| UTAB | Black Alcantara Headliner | |
|
284
308
|
| UTAW | Light Headliner | |
|
309
|
+
| UTMF | Headliner | |
|
285
310
|
| UTPB | Dark Headliner | |
|
286
311
|
| UTSB | Dark Headliner | |
|
287
312
|
| UTZW | Light Headliner | |
|
313
|
+
| USSB | Safety | Safety US Black |
|
288
314
|
| SLR1 | Carbon Fibre Spoiler | Model 3 |
|
289
315
|
| SPT31 | Performance Upgrade | Model 3 |
|
290
316
|
| SPTY1 | Performance Upgrade | Model Y |
|
291
317
|
| W32P | 20" Performance Wheels | Model 3 |
|
292
318
|
| W38B | 18" Aero Wheels | For the Model 3 and Model Y |
|
293
319
|
| W39B | 19" Sport Wheels | |
|
320
|
+
| WR00 | No Wrap | |
|
321
|
+
| WT19 | 19" Wheels | |
|
294
322
|
| WT20 | 20" Silver Slipstream Wheels | |
|
295
323
|
| WT22 | 22" Silver Turbine Wheels | |
|
296
324
|
| WTAB | 21" Black Arachnid Wheels | |
|
@@ -338,14 +366,14 @@ appreciated!_
|
|
338
366
|
| X014 | Override: No Satellite Radio | |
|
339
367
|
| X019 | Carbon Fiber Spoiler | |
|
340
368
|
| X020 | No Performance Exterior | |
|
341
|
-
| X021 | No Spoiler | |
|
369
|
+
| X021 | No Rear Carbon Fiber Spoiler | |
|
342
370
|
| X024 | Performance Package | |
|
343
|
-
| X025 |
|
344
|
-
| X027 | Lighted Door Handles | |
|
345
|
-
| X028 | Battery Badge | |
|
371
|
+
| X025 | Performance Powertrain | |
|
372
|
+
| X027 | Lighted Door Handles | Light handle |
|
373
|
+
| X028 | Battery Badge | Normal Badging |
|
346
374
|
| X029 | Remove Battery Badge | |
|
347
375
|
| X030 | Override: No Passive Entry Pkg | |
|
348
|
-
| X031 | Keyless Entry | |
|
376
|
+
| X031 | Keyless Entry | Passive Entry Pkg |
|
349
377
|
| X037 | Powerfolding Mirrors | |
|
350
378
|
| X039 | DAB Radio | |
|
351
379
|
| X040 | No DAB Radio | |
|
data/lib/tesla_api.rb
CHANGED
data/lib/tesla_api/autopark.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
require 'faye/websocket'
|
2
|
-
|
3
1
|
module TeslaApi
|
4
2
|
module Autopark
|
5
3
|
def start_autopark(&handler)
|
6
4
|
EventMachine.run do
|
7
|
-
|
5
|
+
autopark_socket.on(:message) do |event|
|
8
6
|
message = if event.data.is_a?(Array)
|
9
7
|
JSON.parse(event.data.map(&:chr).join)
|
10
8
|
else
|
@@ -15,8 +13,8 @@ module TeslaApi
|
|
15
13
|
handler.call(message.delete('msg_type'), message)
|
16
14
|
end
|
17
15
|
|
18
|
-
|
19
|
-
@
|
16
|
+
autopark_socket.on(:close) do |_|
|
17
|
+
@autopark_socket = nil
|
20
18
|
@heartbeat && @heartbeat.cancel
|
21
19
|
EventMachine.stop
|
22
20
|
end
|
@@ -34,14 +32,14 @@ module TeslaApi
|
|
34
32
|
msg_type: 'autopark:heartbeat_app',
|
35
33
|
timestamp: Time.now.to_i
|
36
34
|
}
|
37
|
-
|
35
|
+
autopark_socket.send(beat.to_json)
|
38
36
|
end
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
42
|
-
def
|
43
|
-
@
|
44
|
-
|
40
|
+
def autopark_socket
|
41
|
+
@autopark_socket ||= Faye::WebSocket::Client.new(
|
42
|
+
autopark_socket_endpoint,
|
45
43
|
nil,
|
46
44
|
{
|
47
45
|
headers: {
|
@@ -55,7 +53,7 @@ module TeslaApi
|
|
55
53
|
Base64.strict_encode64("#{email}:#{self['tokens'].first}")
|
56
54
|
end
|
57
55
|
|
58
|
-
def
|
56
|
+
def autopark_socket_endpoint
|
59
57
|
"wss://streaming.vn.teslamotors.com/connect/#{self['vehicle_id']}"
|
60
58
|
end
|
61
59
|
end
|
data/lib/tesla_api/client.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
module TeslaApi
|
2
2
|
class Client
|
3
|
-
|
4
|
-
base_uri 'https://owner-api.teslamotors.com/api/1'
|
5
|
-
headers 'User-Agent' => "github.com/timdorr/tesla-api v:#{VERSION}"
|
6
|
-
format :json
|
7
|
-
raise_on [401]
|
3
|
+
attr_reader :api, :email, :access_token, :access_token_expires_at, :refresh_token, :client_id, :client_secret
|
8
4
|
|
9
|
-
|
5
|
+
BASE_URI = 'https://owner-api.teslamotors.com/api/1'
|
10
6
|
|
11
7
|
def initialize(
|
12
8
|
email: nil,
|
@@ -21,59 +17,54 @@ module TeslaApi
|
|
21
17
|
@client_id = client_id
|
22
18
|
@client_secret = client_secret
|
23
19
|
|
24
|
-
self.update_token(
|
25
|
-
access_token: access_token,
|
26
|
-
access_token_expires_at: access_token_expires_at,
|
27
|
-
refresh_token: refresh_token
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
def update_token(access_token:, access_token_expires_at:, refresh_token:)
|
32
20
|
@access_token = access_token
|
33
21
|
@access_token_expires_at = access_token_expires_at
|
34
22
|
@refresh_token = refresh_token
|
35
|
-
self.class.headers 'Authorization' => "Bearer #{access_token}" if access_token
|
36
23
|
|
37
|
-
|
24
|
+
@api = Faraday.new(
|
25
|
+
BASE_URI,
|
26
|
+
headers: { 'User-Agent' => "github.com/timdorr/tesla-api v:#{VERSION}" }
|
27
|
+
) do |conn|
|
28
|
+
conn.request :json
|
29
|
+
conn.response :json
|
30
|
+
conn.response :raise_error
|
31
|
+
conn.adapter Faraday.default_adapter
|
32
|
+
end
|
38
33
|
end
|
39
34
|
|
40
35
|
def refresh_access_token
|
41
|
-
response =
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
refresh_token: response['refresh_token']
|
55
|
-
)
|
36
|
+
response = api.post(
|
37
|
+
'https://owner-api.teslamotors.com/oauth/token',
|
38
|
+
{
|
39
|
+
grant_type: 'refresh_token',
|
40
|
+
client_id: client_id,
|
41
|
+
client_secret: client_secret,
|
42
|
+
refresh_token: refresh_token
|
43
|
+
}
|
44
|
+
).body
|
45
|
+
|
46
|
+
@access_token = response['access_token']
|
47
|
+
@access_token_expires_at = Time.at(response['created_at'].to_f + response['expires_in'].to_f).to_datetime
|
48
|
+
@refresh_token = response['refresh_token']
|
56
49
|
|
57
50
|
response
|
58
51
|
end
|
59
52
|
|
60
53
|
def login!(password)
|
61
|
-
response =
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
refresh_token: response['refresh_token']
|
76
|
-
)
|
54
|
+
response = api.post(
|
55
|
+
'https://owner-api.teslamotors.com/oauth/token',
|
56
|
+
{
|
57
|
+
grant_type: 'password',
|
58
|
+
client_id: client_id,
|
59
|
+
client_secret: client_secret,
|
60
|
+
email: email,
|
61
|
+
password: password
|
62
|
+
}
|
63
|
+
).body
|
64
|
+
|
65
|
+
@access_token = response['access_token']
|
66
|
+
@access_token_expires_at = Time.at(response['created_at'].to_f + response['expires_in'].to_f).to_datetime
|
67
|
+
@refresh_token = response['refresh_token']
|
77
68
|
|
78
69
|
response
|
79
70
|
end
|
@@ -83,12 +74,20 @@ module TeslaApi
|
|
83
74
|
access_token_expires_at <= DateTime.now
|
84
75
|
end
|
85
76
|
|
86
|
-
def
|
87
|
-
|
77
|
+
def get(url)
|
78
|
+
api.get(url.sub(/^\//, ''), nil, { 'Authorization' => "Bearer #{access_token}" }).body
|
88
79
|
end
|
89
80
|
|
90
|
-
|
81
|
+
def post(url, body: nil)
|
82
|
+
api.post(url.sub(/^\//, ''), body, { 'Authorization' => "Bearer #{access_token}" }).body
|
83
|
+
end
|
91
84
|
|
92
|
-
|
85
|
+
def vehicles
|
86
|
+
get('/vehicles')['response'].map { |v| Vehicle.new(self, email, v['id'], v) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def vehicle(id)
|
90
|
+
Vehicle.new(self, email, id, self.class.get("/vehicles/#{id}")['response'])
|
91
|
+
end
|
93
92
|
end
|
94
93
|
end
|
data/lib/tesla_api/stream.rb
CHANGED
@@ -2,10 +2,19 @@ module TeslaApi
|
|
2
2
|
module Stream
|
3
3
|
def stream(&receiver)
|
4
4
|
EventMachine.run do
|
5
|
-
|
6
|
-
attributes = chunk.split(",")
|
5
|
+
socket = create_streaming_socket
|
7
6
|
|
8
|
-
|
7
|
+
socket.on(:open) do |event|
|
8
|
+
socket.send(JSON.generate(stream_connect_message))
|
9
|
+
end
|
10
|
+
|
11
|
+
socket.on(:message) do |event|
|
12
|
+
data = JSON.parse(event.data.pack('c*'))
|
13
|
+
|
14
|
+
if data['msg_type'] == 'data:update'
|
15
|
+
attributes = data['value'].split(',')
|
16
|
+
|
17
|
+
receiver.call({
|
9
18
|
time: DateTime.strptime((attributes[0].to_i/1000).to_s, '%s'),
|
10
19
|
speed: attributes[1].to_f,
|
11
20
|
odometer: attributes[2].to_f,
|
@@ -19,35 +28,33 @@ module TeslaApi
|
|
19
28
|
range: attributes[10].to_f,
|
20
29
|
est_range: attributes[11].to_f,
|
21
30
|
heading: attributes[12].to_f
|
22
|
-
|
31
|
+
})
|
32
|
+
end
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
|
35
|
+
socket.on(:close) do |event|
|
36
|
+
EventMachine.stop
|
37
|
+
end
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
41
|
private
|
31
42
|
|
32
|
-
def
|
33
|
-
|
34
|
-
"#{stream_endpoint}/stream/#{self['vehicle_id']}/?values=#{stream_params}")
|
35
|
-
end
|
36
|
-
|
37
|
-
def http
|
38
|
-
request.get(
|
39
|
-
head: {
|
40
|
-
'authorization' => [email, self['tokens'].first]
|
41
|
-
},
|
42
|
-
inactivity_timeout: 15)
|
43
|
+
def create_streaming_socket
|
44
|
+
Faye::WebSocket::Client.new(streaming_endpoint)
|
43
45
|
end
|
44
46
|
|
45
|
-
def
|
46
|
-
'
|
47
|
+
def streaming_endpoint
|
48
|
+
'wss://streaming.vn.teslamotors.com/streaming/'
|
47
49
|
end
|
48
50
|
|
49
|
-
def
|
50
|
-
|
51
|
+
def stream_connect_message
|
52
|
+
{
|
53
|
+
msg_type: 'data:subscribe',
|
54
|
+
token: Base64.strict_encode64("#{email}:#{self['tokens'].first}"),
|
55
|
+
value: 'speed,odometer,soc,elevation,est_heading,est_lat,est_lng,power,shift_state,range,est_range,heading',
|
56
|
+
tag: self['vehicle_id'].to_s,
|
57
|
+
}
|
51
58
|
end
|
52
59
|
end
|
53
60
|
end
|
data/lib/tesla_api/vehicle.rb
CHANGED
@@ -2,10 +2,10 @@ module TeslaApi
|
|
2
2
|
class Vehicle
|
3
3
|
include Stream
|
4
4
|
include Autopark
|
5
|
-
attr_reader :api, :email, :id, :vehicle
|
5
|
+
attr_reader :client, :api, :email, :id, :vehicle
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(client, email, id, vehicle)
|
8
|
+
@client = client
|
9
9
|
@email = email
|
10
10
|
@id = id
|
11
11
|
@vehicle = vehicle
|
@@ -28,15 +28,15 @@ module TeslaApi
|
|
28
28
|
# State
|
29
29
|
|
30
30
|
def data
|
31
|
-
|
31
|
+
client.get("/vehicles/#{id}/data")['response']
|
32
32
|
end
|
33
33
|
|
34
34
|
def mobile_enabled
|
35
|
-
|
35
|
+
client.get("/vehicles/#{id}/mobile_enabled")['response']
|
36
36
|
end
|
37
37
|
|
38
38
|
def nearby_charging_sites
|
39
|
-
|
39
|
+
client.get("/vehicles/#{id}/nearby_charging_sites")['response']
|
40
40
|
end
|
41
41
|
|
42
42
|
def gui_settings
|
@@ -62,7 +62,7 @@ module TeslaApi
|
|
62
62
|
# Commands
|
63
63
|
|
64
64
|
def wake_up
|
65
|
-
@vehicle =
|
65
|
+
@vehicle = client.post("/vehicles/#{id}/wake_up")['response']
|
66
66
|
end
|
67
67
|
|
68
68
|
def set_valet_mode(on, password=nil)
|
@@ -197,11 +197,11 @@ module TeslaApi
|
|
197
197
|
private
|
198
198
|
|
199
199
|
def data_request(name)
|
200
|
-
|
200
|
+
client.get("/vehicles/#{id}/data_request/#{name}")
|
201
201
|
end
|
202
202
|
|
203
203
|
def command(name, body: nil)
|
204
|
-
|
204
|
+
client.post("/vehicles/#{id}/command/#{name}", body: body)
|
205
205
|
end
|
206
206
|
end
|
207
207
|
end
|
data/lib/tesla_api/version.rb
CHANGED
@@ -19,12 +19,7 @@ RSpec.describe TeslaApi::Client do
|
|
19
19
|
|
20
20
|
it 'logs into the API' do
|
21
21
|
tesla_api.login!(ENV['TESLA_PASS'])
|
22
|
-
expect(a_request(:post, "https://#{URI.parse(
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'sets a Bearer token header' do
|
26
|
-
tesla_api.login!(ENV['TESLA_PASS'])
|
27
|
-
expect(tesla_api.class.headers).to include({'Authorization' => /Bearer [a-z0-9]{32}/})
|
22
|
+
expect(a_request(:post, "https://#{URI.parse(TeslaApi::Client::BASE_URI).host}/oauth/token")).to have_been_made.once
|
28
23
|
end
|
29
24
|
|
30
25
|
it 'obtains a Bearer token' do
|
@@ -63,10 +58,6 @@ RSpec.describe TeslaApi::Client do
|
|
63
58
|
it 'is not expired' do
|
64
59
|
expect(tesla_api.expired?).to eq(false)
|
65
60
|
end
|
66
|
-
|
67
|
-
it 'sets a Bearer token header' do
|
68
|
-
expect(tesla_api.class.headers).to include({'Authorization' => "Bearer #{access_token}"})
|
69
|
-
end
|
70
61
|
end
|
71
62
|
|
72
63
|
describe '#refresh_access_token', vcr: {cassette_name: 'client-refresh'} do
|
data/tesla_api.gemspec
CHANGED
@@ -14,9 +14,9 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
15
15
|
spec.require_paths = ['lib']
|
16
16
|
|
17
|
-
spec.add_dependency '
|
17
|
+
spec.add_dependency 'faraday'
|
18
|
+
spec.add_dependency 'faraday_middleware'
|
18
19
|
spec.add_dependency 'faye-websocket'
|
19
|
-
spec.add_dependency 'em-http-request'
|
20
20
|
|
21
21
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
22
22
|
spec.add_development_dependency 'rake', '~> 12.0'
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tesla_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Dorr
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: faraday
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: faraday_middleware
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: faye-websocket
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|