Skip to content

Commit

Permalink
Revamp Client.
Browse files Browse the repository at this point in the history
Use keyword args for initialization. Add access token refreshing. Better handle auth failures.
  • Loading branch information
timdorr committed Sep 23, 2019
1 parent b550a5f commit af6e585
Show file tree
Hide file tree
Showing 24 changed files with 200 additions and 108 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ env:
- TESLA_PASS=oilLOL
- TESLA_CLIENT_ID=1
- TESLA_CLIENT_SECRET=2
- TESLA_API_TOKEN=3
- TESLA_ACCESS_TOKEN=3
- TESLA_REFRESH_TOKEN=4
before_install:
- gem update --system
- gem install bundler
Expand Down
73 changes: 51 additions & 22 deletions lib/tesla_api/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,57 @@ class Client
base_uri 'https://owner-api.teslamotors.com/api/1'
headers 'User-Agent' => "github.com/timdorr/tesla-api v:#{VERSION}"
format :json
raise_on [401]

attr_reader :email, :token, :refresh_token, :client_id, :client_secret
attr_reader :email, :access_token, :access_token_expires_at, :refresh_token, :client_id, :client_secret

def initialize(email, client_id = ENV['TESLA_CLIENT_ID'], client_secret = ENV['TESLA_CLIENT_SECRET'])
def initialize(
email: nil,
access_token: nil,
access_token_expires_at: nil,
refresh_token: nil,
client_id: ENV['TESLA_CLIENT_ID'],
client_secret: ENV['TESLA_CLIENT_SECRET']
)
@email = email

@client_id = client_id
@client_secret = client_secret
end

def token=(token)
@token = token
self.class.headers 'Authorization' => "Bearer #{token}"
self.update_token(
access_token: access_token,
access_token_expires_at: access_token_expires_at,
refresh_token: refresh_token
)
end

def expires_in=(seconds)
@expires_in = seconds.to_f
end
def update_token(access_token:, access_token_expires_at:, refresh_token:)
@access_token = access_token
@access_token_expires_at = access_token_expires_at
@refresh_token = refresh_token
self.class.headers 'Authorization' => "Bearer #{access_token}" if access_token

def created_at=(timestamp)
@created_at = Time.at(timestamp.to_f).to_datetime
access_token
end

def expired_at
return nil unless defined?(@created_at)
(@created_at.to_time + @expires_in.to_f).to_datetime
end
def refresh_access_token
response = self.class.post(
'https://owner-api.teslamotors.com/oauth/token',
body: {
grant_type: 'refresh_token',
client_id: client_id,
client_secret: client_secret,
refresh_token: refresh_token
}
)

def expired?
return true unless defined?(@created_at)
expired_at <= DateTime.now
self.update_token(
access_token: response['access_token'],
access_token_expires_at: Time.at(response['created_at'] + response['expires_in']).to_datetime,
refresh_token: response['refresh_token']
)

response
end

def login!(password)
Expand All @@ -48,10 +69,18 @@ def login!(password)
}
)

self.expires_in = response['expires_in']
self.created_at = response['created_at']
self.token = response['access_token']
self.refresh_token = response['refresh_token']
self.update_token(
access_token: response['access_token'],
access_token_expires_at: Time.at(response['created_at'] + response['expires_in']).to_datetime,
refresh_token: response['refresh_token']
)

response
end

def expired?
return true if access_token_expires_at.nil?
access_token_expires_at <= DateTime.now
end

def vehicles
Expand Down
51 changes: 51 additions & 0 deletions spec/cassettes/client-refresh.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-activate_speed_limit.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-cancel_software_update.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-charge_port_door_close.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-clear_speed_limit_pin.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-data.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-deactivate_speed_limit.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-navigation_request.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-nearby_charging_sites.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-open_frunk.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-open_trunk.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-reset_valet_pin.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-schedule_software_update.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions spec/cassettes/vehicle-seat_heater_request.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit af6e585

Please sign in to comment.