tesla_api 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20e84c22651e2f1856d02fc5288277ec8ec512cc
4
- data.tar.gz: b4a0471a5d0ca51c0974071b0ef526d7603a531c
3
+ metadata.gz: 45741a5c5b2afc5cd2e0eb6b2ecafa1115847868
4
+ data.tar.gz: 79c210bf38a56293ff3fc7261780eb84fcd87684
5
5
  SHA512:
6
- metadata.gz: 6b0fc114f6cd257b6d52dbcc6aa6d3902a4241fd536cc39c75554ba96b5a88d56dc69e6076d15479c30e4133a1ca24573224daa054222dc04c7843a0a2f1ae17
7
- data.tar.gz: f6f63dc83fd699d418c3f2702cf612f772c16a6a4980765a57d254eded2ded59a6cd065b3ed70762dc589464844720a2859d48b861bfa9b1c6b6ffd1da7e4902
6
+ metadata.gz: aec12640955ab16d5a77611e4bb66d34ff3084b362caf572372d59c8a2a7b484d8a46224d0a4f2dff0360d912b1e49f5eaf6c99a7c31ac4e4204814e10b207a7
7
+ data.tar.gz: 87ae5a2fac0c7ade54796a83d0c0eb6b87a3eddc20415f2c67c2c3959dda4e08ae38abe64e4052be0f3f4d5ee9656659a4dbc63aad79f8a5744880c65232444e
data/.gitignore CHANGED
@@ -12,3 +12,6 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ .ruby-version
16
+ .ruby-gemset
17
+ .env
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format documentation
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.5
6
+ env:
7
+ global:
8
+ - TESLA_EMAIL=elon.musk@teslamotors.com
9
+ - TESLA_PASS=oilLOL
10
+ - TESLA_CLIENT_ID=1
11
+ - TESLA_CLIENT_SECRET=2
File without changes
data/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  [View Documentation](http://docs.timdorr.apiary.io/)
4
4
 
5
- This is unofficial documentation of the Tesla Model S JSON API used by the iOS and Android apps.
5
+ This is unofficial documentation of the Tesla JSON API used by the iOS and Android apps.
6
6
  The API provides functionality to monitor and control the Model S (and future Tesla vehicles) remotely.
7
7
  The project provides both a documention of the API and a Ruby library to for accessing it.
8
8
 
9
- ## Ruby Library
9
+ ## Ruby Gem [![Gem Version](https://img.shields.io/gem/v/tesla_api.svg)](http://rubygems.org/gems/tesla_api) [![Build Status](https://img.shields.io/travis/timdorr/model-s-api/master.svg)](https://travis-ci.org/timdorr/model-s-api)
10
10
 
11
11
  This gem provides a basic wrapper around the API to easily query and command the car remotely.
12
12
  It also provides access to the streaming API and a means to process data coming from it.
@@ -30,8 +30,8 @@ Here's a quick example:
30
30
  ```ruby
31
31
  require 'tesla_api'
32
32
 
33
- tesla_api = TeslaApi.new(email, password, client_id, client_secret)
34
- model_s = tesla_api.vehicles.first
33
+ tesla_api = TeslaApi::Client.new(email, password, client_id, client_secret)
34
+ model_s = tesla_api.vehicles.first # => <TeslaApi::Vehicle>
35
35
 
36
36
  model_s.wake_up
37
37
  model_s.auto_conditioning_start unless model_s.climate_state["is_auto_conditioning_on"]
@@ -44,3 +44,8 @@ puts "Your Model S is #{charge_state["charging_state"]} " +
44
44
  "with a SOC of #{charge_state["battery_level"]}% " +
45
45
  "and an estimate range of #{charge_state["est_battery_range"]} miles"
46
46
  ```
47
+
48
+ ## Copyright
49
+
50
+ Ruby portions are Copyright (c) 2014 Tim Dorr. Released under the terms of the
51
+ MIT license. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,2 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
2
3
 
4
+ RSpec::Core::RakeTask.new(:spec) do |task|
5
+ task.rspec_opts = ['--color', '--format', 'documentation', '--require', 'spec_helper']
6
+ end
7
+
8
+ task default: :spec
data/lib/tesla_api.rb CHANGED
@@ -1,172 +1,6 @@
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
1
+ require "httparty"
2
+ require "em-http-request"
82
3
 
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
4
+ require "tesla_api/version"
5
+ require "tesla_api/client"
6
+ require "tesla_api/vehicle"
@@ -0,0 +1,28 @@
1
+ module TeslaApi
2
+ class Client
3
+ include HTTParty
4
+ base_uri "https://owner-api.teslamotors.com/api/1"
5
+ format :json
6
+
7
+ attr_reader :email
8
+
9
+ def initialize(email, password, client_id, client_secret)
10
+ @email = email
11
+ response = self.class.post(
12
+ "https://owner-api.teslamotors.com/oauth/token",
13
+ body: {
14
+ "grant_type" => "password",
15
+ "client_id" => client_id,
16
+ "client_secret" => client_secret,
17
+ "email" => email,
18
+ "password" => password
19
+ }
20
+ )
21
+ self.class.headers "Authorization" => "Bearer #{response["access_token"]}"
22
+ end
23
+
24
+ def vehicles
25
+ self.class.get("/vehicles")["response"].map { |v| Vehicle.new(self.class, email, v["id"], v) }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,145 @@
1
+ module TeslaApi
2
+ class Vehicle
3
+ attr_reader :api, :email, :id, :vehicle
4
+
5
+ def initialize(api, email, id, vehicle)
6
+ @api = api
7
+ @email = email
8
+ @id = id
9
+ @vehicle = vehicle
10
+ end
11
+
12
+ def [](key)
13
+ vehicle[key]
14
+ end
15
+
16
+ # State
17
+
18
+ def mobile_enabled
19
+ api.get("/vehicles/#{id}/mobile_enabled")["response"]
20
+ end
21
+
22
+ def charge_state
23
+ api.get("/vehicles/#{id}/data_request/charge_state")["response"]
24
+ end
25
+
26
+ def climate_state
27
+ api.get("/vehicles/#{id}/data_request/climate_state")["response"]
28
+ end
29
+
30
+ def drive_state
31
+ api.get("/vehicles/#{id}/data_request/drive_state")["response"]
32
+ end
33
+
34
+ def gui_settings
35
+ api.get("/vehicles/#{id}/data_request/gui_settings")["response"]
36
+ end
37
+
38
+ def vehicle_state
39
+ api.get("/vehicles/#{id}/data_request/vehicle_state")["response"]
40
+ end
41
+
42
+ # Commands
43
+
44
+ def wake_up
45
+ api.post("/vehicles/#{id}/wake_up")
46
+ end
47
+
48
+ def charge_port_door_open
49
+ api.post("/vehicles/#{id}/command/charge_port_door_open")
50
+ end
51
+
52
+ def charge_standard
53
+ api.post("/vehicles/#{id}/command/charge_standard")
54
+ end
55
+
56
+ def charge_max_range
57
+ api.post("/vehicles/#{id}/command/charge_max_range")
58
+ end
59
+
60
+ def set_charge_limit(percent)
61
+ api.post("/vehicles/#{id}/command/set_charge_limit", query: {state: "set", percent: percent})
62
+ end
63
+
64
+ def charge_start
65
+ api.post("/vehicles/#{id}/command/charge_start")
66
+ end
67
+
68
+ def charge_stop
69
+ api.post("/vehicles/#{id}/command/charge_stop")
70
+ end
71
+
72
+ def flash_lights
73
+ api.post("/vehicles/#{id}/command/flash_lights")
74
+ end
75
+
76
+ def honk_horn
77
+ api.post("/vehicles/#{id}/command/honk_horn")
78
+ end
79
+
80
+ def door_unlock
81
+ api.post("/vehicles/#{id}/command/door_unlock")
82
+ end
83
+
84
+ def door_lock
85
+ api.post("/vehicles/#{id}/command/door_lock")
86
+ end
87
+
88
+ def set_temps(driver_temp, passenger_temp)
89
+ api.post("/vehicles/#{id}/command/set_temps", query: {driver_temp: driver_temp, passenger_temp: passenger_temp})
90
+ end
91
+
92
+ def auto_conditioning_start
93
+ api.post("/vehicles/#{id}/command/auto_conditioning_start")
94
+ end
95
+
96
+ def auto_conditioning_stop
97
+ api.post("/vehicles/#{id}/command/auto_conditioning_stop")
98
+ end
99
+
100
+ def sun_roof_control(state)
101
+ api.post("/vehicles/#{id}/command/sun_roof_control", query: {state: state})
102
+ end
103
+
104
+ def sun_roof_move(percent)
105
+ api.post("/vehicles/#{id}/command/sun_roof_control", query: {state: "move", percent: percent})
106
+ end
107
+
108
+ # Streaming
109
+
110
+ def stream(&reciever)
111
+ EventMachine.run do
112
+ request = EventMachine::HttpRequest.new(
113
+ "https://streaming.vn.teslamotors.com/stream/#{self["vehicle_id"]}/" +
114
+ "?values=speed,odometer,soc,elevation,est_heading,est_lat,est_lng,power")
115
+
116
+ http = request.get(
117
+ head: {
118
+ "authorization" => [
119
+ email,
120
+ self["tokens"].first
121
+ ]
122
+ },
123
+ inactivity_timeout: 15)
124
+
125
+ http.stream do |chunk|
126
+ attributes = chunk.split(",")
127
+ reciever.call({
128
+ time: DateTime.strptime((attributes[0].to_i/1000).to_s, "%s"),
129
+ speed: attributes[1].to_f,
130
+ odometer: attributes[2].to_f,
131
+ soc: attributes[3].to_f,
132
+ elevation: attributes[4].to_f,
133
+ est_heading: attributes[5].to_f,
134
+ est_lat: attributes[6].to_f,
135
+ est_lng: attributes[7].to_f,
136
+ power: attributes[8].to_f
137
+ })
138
+ end
139
+
140
+ http.callback { EventMachine.stop }
141
+ http.errback { EventMachine.stop }
142
+ end
143
+ end
144
+ end
145
+ end
@@ -1,3 +1,3 @@
1
1
  module TeslaApi
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,48 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://owner-api.teslamotors.com/oauth/token
6
+ body:
7
+ encoding: UTF-8
8
+ string: grant_type=password&client_id=<TESLA_CLIENT_ID>&client_secret=<TESLA_CLIENT_SECRET>&email=<TESLA_EMAIL>&password=<TESLA_PASS>
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx
23
+ Date:
24
+ - Mon, 15 Dec 2014 03:09:22 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Status:
32
+ - 200 OK
33
+ Cache-Control:
34
+ - no-store
35
+ Pragma:
36
+ - no-cache
37
+ X-Ua-Compatible:
38
+ - IE=Edge,chrome=1
39
+ X-Request-Id:
40
+ - 349d563d345a9694c610770b743d3006
41
+ X-Runtime:
42
+ - '0.416152'
43
+ body:
44
+ encoding: UTF-8
45
+ string: '{"access_token":"1cba4845a8653d4b731440e9911d84304a179bd16a9ecbc9b649f2d8e0f6947e","token_type":"bearer","expires_in":7776000}'
46
+ http_version:
47
+ recorded_at: Mon, 15 Dec 2014 03:09:22 GMT
48
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,89 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://owner-api.teslamotors.com/oauth/token
6
+ body:
7
+ encoding: UTF-8
8
+ string: grant_type=password&client_id=<TESLA_CLIENT_ID>&client_secret=<TESLA_CLIENT_SECRET>&email=<TESLA_EMAIL>&password=<TESLA_PASS>
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx
23
+ Date:
24
+ - Mon, 15 Dec 2014 03:28:30 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Status:
32
+ - 200 OK
33
+ Cache-Control:
34
+ - no-store
35
+ Pragma:
36
+ - no-cache
37
+ X-Ua-Compatible:
38
+ - IE=Edge,chrome=1
39
+ X-Request-Id:
40
+ - 2716f7fd5f4ee1239d044ddfba838d70
41
+ X-Runtime:
42
+ - '0.372092'
43
+ body:
44
+ encoding: UTF-8
45
+ string: '{"access_token":"53514fcfea416c9dd77b50d0a1c1dc681960002d23c22b1a9cf2681e8cbec8da","token_type":"bearer","expires_in":7776000}'
46
+ http_version:
47
+ recorded_at: Mon, 15 Dec 2014 03:28:30 GMT
48
+ - request:
49
+ method: get
50
+ uri: https://owner-api.teslamotors.com/api/1/vehicles
51
+ body:
52
+ encoding: US-ASCII
53
+ string: ''
54
+ headers:
55
+ Authorization:
56
+ - Bearer 53514fcfea416c9dd77b50d0a1c1dc681960002d23c22b1a9cf2681e8cbec8da
57
+ response:
58
+ status:
59
+ code: 200
60
+ message: OK
61
+ headers:
62
+ Server:
63
+ - nginx
64
+ Date:
65
+ - Mon, 15 Dec 2014 03:28:30 GMT
66
+ Content-Type:
67
+ - application/json; charset=utf-8
68
+ Content-Length:
69
+ - '446'
70
+ Connection:
71
+ - keep-alive
72
+ Status:
73
+ - 200 OK
74
+ X-Ua-Compatible:
75
+ - IE=Edge,chrome=1
76
+ Etag:
77
+ - '"4a35974adbecef7554d775e098548913"'
78
+ Cache-Control:
79
+ - max-age=0, private, must-revalidate
80
+ X-Request-Id:
81
+ - 59523c1d2611a93fa82e277ae4d97e87
82
+ X-Runtime:
83
+ - '0.289093'
84
+ body:
85
+ encoding: UTF-8
86
+ string: '{"response":[{"color":null,"display_name":"Nikola","id":1514029006966957156,"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,COUS","vehicle_id":490215852,"vin":"5YJSA1CN5CFP01657","tokens":["74bd32f47d3c8d9e","c244a90fbad06a65"],"state":"online","remote_start_enabled":true,"calendar_enabled":true,"notifications_enabled":true}],"count":1}'
87
+ http_version:
88
+ recorded_at: Mon, 15 Dec 2014 03:28:30 GMT
89
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe TeslaApi::Client do
4
+ subject(:tesla_api) { TeslaApi::Client.new(ENV["TESLA_EMAIL"], ENV["TESLA_PASS"], ENV["TESLA_CLIENT_ID"], ENV["TESLA_CLIENT_SECRET"]) }
5
+
6
+ describe "#initialize", vcr: { cassette_name: "client-initialize" } do
7
+ it { is_expected.to be_a(TeslaApi::Client) }
8
+
9
+ it "logs into the API" do
10
+ base_uri = URI.parse(tesla_api.class.base_uri)
11
+ expect(a_request(:post, "https://#{base_uri.host}/oauth/token")).to have_been_made.once
12
+ end
13
+
14
+ it "sets a Bearer token" do
15
+ expect(tesla_api.class.headers).to include({"Authorization" => /Bearer [a-z0-9]{32}/})
16
+ end
17
+ end
18
+
19
+ describe "#vehicles", vcr: {cassette_name: "client-vehicles"} do
20
+ it "lists the vehicles on the account" do
21
+ expect(tesla_api.vehicles).to include(TeslaApi::Vehicle)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require 'dotenv'
2
+ require 'vcr'
3
+ require 'webmock/rspec'
4
+
5
+ require 'tesla_api'
6
+
7
+ Dotenv.load
8
+
9
+ VCR.configure do |c|
10
+ c.cassette_library_dir = "spec/cassettes"
11
+ c.hook_into :webmock
12
+ c.default_cassette_options = {:record => :once}
13
+ c.configure_rspec_metadata!
14
+
15
+ c.define_cassette_placeholder("<TESLA_EMAIL>") { CGI::escape(ENV["TESLA_EMAIL"]) }
16
+ c.define_cassette_placeholder("<TESLA_PASS>") { ENV["TESLA_PASS"] }
17
+ c.define_cassette_placeholder("<TESLA_CLIENT_ID>") { ENV["TESLA_CLIENT_ID"] }
18
+ c.define_cassette_placeholder("<TESLA_CLIENT_SECRET>") { ENV["TESLA_CLIENT_SECRET"] }
19
+ end
20
+
21
+ RSpec.configure do |config|
22
+ config.expect_with :rspec do |expectations|
23
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
24
+ end
25
+
26
+ config.mock_with :rspec do |mocks|
27
+ mocks.verify_partial_doubles = true
28
+ end
29
+
30
+ config.disable_monkey_patching!
31
+ config.order = :random
32
+ Kernel.srand config.seed
33
+ end
data/tesla_api.gemspec CHANGED
@@ -17,6 +17,13 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.add_dependency "httparty"
21
+ spec.add_dependency "em-http-request"
22
+
20
23
  spec.add_development_dependency "bundler", "~> 1.7"
21
24
  spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.1"
26
+ spec.add_development_dependency "vcr", "~> 2.9"
27
+ spec.add_development_dependency "webmock", "~> 1.20"
28
+ spec.add_development_dependency "dotenv", "~> 1.0"
22
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tesla_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Dorr
@@ -10,6 +10,34 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2014-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: em-http-request
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +66,62 @@ dependencies:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
68
  version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: vcr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.9'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.20'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.20'
111
+ - !ruby/object:Gem::Dependency
112
+ name: dotenv
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
41
125
  description: Check the state of your Tesla Model S and issue basic commands. Stream
42
126
  data from the car's telematics system.
43
127
  email:
@@ -47,16 +131,21 @@ extensions: []
47
131
  extra_rdoc_files: []
48
132
  files:
49
133
  - ".gitignore"
134
+ - ".rspec"
135
+ - ".travis.yml"
50
136
  - Gemfile
51
- - LICENSE.txt
137
+ - LICENSE
52
138
  - README.md
53
139
  - Rakefile
54
140
  - apiary.apib
55
141
  - lib/tesla_api.rb
142
+ - lib/tesla_api/client.rb
143
+ - lib/tesla_api/vehicle.rb
56
144
  - lib/tesla_api/version.rb
57
- - logs/login.GET.log
58
- - logs/login.POST.log
59
- - logs/root.GET.log
145
+ - spec/cassettes/client-initialize.yml
146
+ - spec/cassettes/client-vehicles.yml
147
+ - spec/lib/tesla_api/client_spec.rb
148
+ - spec/spec_helper.rb
60
149
  - tesla_api.gemspec
61
150
  homepage: https://github.com/timdorr/model-s-api
62
151
  licenses:
@@ -78,8 +167,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
167
  version: '0'
79
168
  requirements: []
80
169
  rubyforge_project:
81
- rubygems_version: 2.2.2
170
+ rubygems_version: 2.4.3
82
171
  signing_key:
83
172
  specification_version: 4
84
173
  summary: A wrapper for the Tesla API
85
- test_files: []
174
+ test_files:
175
+ - spec/cassettes/client-initialize.yml
176
+ - spec/cassettes/client-vehicles.yml
177
+ - spec/lib/tesla_api/client_spec.rb
178
+ - spec/spec_helper.rb
data/logs/login.GET.log DELETED
@@ -1,44 +0,0 @@
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
-
data/logs/login.POST.log DELETED
@@ -1,29 +0,0 @@
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 DELETED
@@ -1,50 +0,0 @@
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
-