Smartcar Python SDK
Clone or download
Emre Sonmez
Emre Sonmez Merge pull request #46 from smartcar/test-mode-fix
Update e2e tests to use Tesla instead of mock
Latest commit 45499d5 Oct 30, 2018

README.md

Smartcar Python SDK Build Status PyPI version

Overview

The Smartcar API lets you read vehicle data (location, odometer) and send commands to vehicles (lock, unlock) to connected vehicles using HTTP requests.

To make requests to a vehicle from a web or mobile application, the end user must connect their vehicle using Smartcar's authorization flow. This flow follows the OAuth spec and will return a code which can be used to obtain an access token from Smartcar.

The Smartcar Python SDK provides methods to:

  1. Generate the link to redirect to for Smartcar's authorization flow.
  2. Make a request to Smartcar with the code obtained from this authorization flow to obtain an access and refresh token
  3. Make requests to the Smartcar API to read vehicle data and send commands to vehicles using the access token obtained in step 2.

Before integrating with Smartcar's SDK, you'll need to register an application in the Smartcar Developer portal. If you do not have access to the dashboard, please request access.

Installation

pip install smartcar

Running tests

make test

Running verbose tests

make test args="--verbose"

Overall Usage

Now that you have your id, secret and redirect URI, here's a simple overall idea of how to use the SDK to authenticate and make requests with the Smartcar API.

  • Import the sdk import smartcar

  • Create a new smartcar client with smartcar.AuthClient(client_id, client_secret, redirect_uri, scope, test_mode)

  • Redirect the user to an OEM login page using the URL from client.get_auth_url()

  • The user will login, and then accept or deny the permissions in your scope

    • If the user is already connected to your application, they will not be shown the accept or deny dialog. However the application can force this dialog to be shown with client.get_auth_url(force=True)
    • If the user accepts, they will be redirected to your redirect_uri. The query field code will contain an authentication code. This is very important, so save it for later.
    • If the user denies, the query field code will equal "access_denied", so you should handle this somehow.
  • With your authentication code in hand, use client.exchange_code(authentication_code) to exchange your authentication code for an access object. This access object will look like this:

{
  "access_token": "...",
  "token_type": "Bearer",
  "expiration": "2018-05-02T18:04:25+00:00",
  "refresh_token": "...",
  "refresh_expiration": "2018-06-02T18:03:25+00:00",
  "expires_in": "..."
}
  • To make any vehicle data request to the Smartcar API, you'll need to give the SDK a valid access token. Access tokens will expire every 2 hours, so you'll need to constantly refresh them. To check if an access object is expired, use smartcar.expired(access['expiration']).

  • It was pretty hard getting that first access token, but from now on it's easy! Calling client.exchange_refresh_token(refresh_token) will return a new access object using a previous access object's refresh token. This means you can always have a fresh access token, by doing something like this:

def get_fresh_access():
    access = load_access_from_database()
    if smartcar.expired(access['expiration']):
        new_access = client.exchange_refresh_token(access['refresh_token'])
        put_access_into_database(new_access)
        return new_access
    else:
        return access

fresh_access_token = get_fresh_access()['access_token']
  • With your fresh access token in hand, use smartcar.get_vehicle_ids(access_token) to get a list of the user's vehicles. The response will look like this:
{
  "vehicles": [
    "uuid-of-first-vehicle",
    "...",
    "uuid-of-nth-vehicle"
  ],
  "paging": {
    "count": 10,
    "offset": 0
  }
}
  • Now with a vehicle id in hand, use smartcar.Vehicle(vehicle_id, access_token) to get a Vehicle object representing the user's vehicle.

  • Now you can ask the car to do things, or ask it for some data! For example:

vehicle = smartcar.Vehicle(vehicle_id, access_token)
odometer = vehicle.odometer()['data']['distance']

Handling Exceptions

  • Any time you make a request to the Smartcar API, something can go wrong. This means that you really should wrap each call to client.exchange_code, client.exchange_refresh_token, client.get_vehicle_ids, and any vehicle method with some exception handling code.

  • Fortunately for you, we've made this as easy as we can! Whenever a request through the SDK returns a non 200 status code, the SDK will throw a nicely named exception for you to handle.

status code exception name
400 smartcar.ValidationException
401 smartcar.AuthenticationException
403 smartcar.PermissionException
404 smartcar.ResourceNotFoundException
409 smartcar.StateException
429 smartcar.RateLimitingException
430 smartcar.MonthlyLimitExceeded
500 smartcar.ServerException
501 smartcar.NotCapableException
504 smartcar.GatewayTimeoutException

AuthClient

smartcar.AuthClient(self, client_id, client_secret, redirect_uri, scope=None, test_mode=False)

A client for accessing the Smartcar API

Arguments:

Parameter Type Description
client_id String Required Application clientId obtained from Smartcar Developer Portal. If you do not have access to the dashboard, please request access.
client_secret String Required Application clientSecret obtained from Smartcar Developer Portal. If you do not have access to the dashboard, please request access.
redirect_uri String Required RedirectURI set in application settings. Given URL must match URL in application settings.
scope String[] Optional List of permissions your application requires. This will default to requiring all scopes. The valid permission names are found in the API Reference.
test_mode Boolean Optional Launch the Smartcar auth flow in test mode.
development Boolean Optional DEPRECATED Launch the Smartcar auth flow in development mode to enable mock vehicle brands.

get_auth_url(self, force=False, state=None)

Generate an OAuth authentication URL

Arguments

Parameter Type Description
force Boolean Optional Setting forcePrompt to true will show the permissions approval screen on every authentication attempt, even if the user has previously consented to the exact scope of permissions.
state String Optional OAuth state parameter passed to the redirectUri. This parameter may be used for identifying the user who initiated the request.

Return

Type Description
String Smartcar OAuth authentication URL

Example

'https://connect.smartcar.com/oauth/authorize?response_type=token...'

exchange_code(code)

Exchange an authentication code for an access dictionary

Arguments

Parameter Type Description
code String Authorization code to exchange with Smartcar for an access_token.

Return

Type Description
Dictionary Dictionary containing the access and refresh token
Dictionary.access_token A string representing an access token used to make requests to the Smartcar API.
Dictionary.expiration A datetime of the expiration of the access_token
Dictionary.refresh_token A string representing a refresh token, which is used to renew access when the current access token expires. The refresh token expires in 60 days.
Dictionary.refresh_expiration A datetime of the expiration of the refresh_token
Dictionary.token_type Always set to Bearer . Token type is used in forming the Authorization header used by the Smartcar API in the following step.

exchange_refresh_token(token)

Exchange a refresh token for a new access dictionary

Arguments

Parameter Type Description
token String Refresh token to exchange with Smartcar for an access_token.

Return

Type Description
Dictionary Dictionary containing the access and refresh token
Dictionary.access_token A string representing an access token used to make requests to the Smartcar API.
Dictionary.expiration A datetime of the expiration of the access_token
Dictionary.refresh_token A string representing a refresh token, which is used to renew access when the current access token expires. The refresh token expires in 60 days.
Dictionary.refresh_expiration A datetime of the expiration of the refresh_token
Dictionary.token_type Always set to Bearer . Token type is used in forming the Authorization header used by the Smartcar API in the following step.

Vehicle

After receiving an access_token from the Smartcar Auth flow, your application may make requests to the vehicle using the access_token and the Vehicle class.

smartcar.Vehicle(self, vehicle_id, access_token, unit_system='metric')

Initializes a new Vehicle to use for making requests to the Smartcar API.

Arguments

Parameter Type Description
vehicle_id String Required the vehicle's unique identifier
access_token String Required a valid access token
unit_system String Optional the unit system to use for vehicle data. Defaults to metric.

set_unit_system(self, unit_system)

Update the unit system to use in requests to the Smartcar API.

Arguments

Parameter Type Description
unit_system String the unit system to use (metric/imperial)

permissions(self)

Returns a paged list of all permissions currently associated with this vehicle.

Return

Type Description
List[String] An array of permissions.

info(self)

Returns a single vehicle object, containing identifying information.

Return

Type Description
Dictionary vehicle's info
Dictionary.id A vehicle ID (UUID v4).
Dictionary.make The manufacturer of the vehicle.
Dictionary.model The model of the vehicle.
Dictionary.year The model year.

vin(self)

Returns the vehicle's manufacturer identifier.

Return

Type Description
String The manufacturer unique identifier.

location(self)

Returns the location of the vehicle in geographic coordinates.

Return

Type Description
Dictionary vehicle's location
Dictionary.data.latitude The latitude (in degrees).
Dictionary.data.longitude The longitude (in degrees).
Dictionary.age A datetime for the age of the data

odometer(self)

Returns the vehicle's current odometer reading.

Return

Type Description
Dictionary vehicle's odometer
Dictionary.data.odometer The current odometer of the vehicle
Dictionary.unit_system the unit system of the odometer data
Dictionary.age A datetime for the age of the data

disconnect(self)

Disconnect this vehicle from the connected application.

Note: Calling this method will invalidate your access token and you will have to have the user reauthorize the vehicle to your application if you wish to make requests to it

unlock(self)

Unlock the vehicle.

lock(self)

Lock the vehicle.

Static Methods

smartcar.is_expired(expiration)

Check if an expiration is expired

Arguments

Parameter Type Description
expiration DateTime Required expiration datetime

Returns

Type Description
Boolean true if expired

smartcar.get_vehicle_ids(access_token, limit=10, offset=0)

Get a list of the user's vehicle ids

Arguments

Parameter Type Description
access_token String Required A valid access token from a previously retrieved access object
limit Integer Optional The number of vehicle ids to return
offset Integer Optional The index to start the vehicle list at

Returns

Type Description
Dictionary response containing the list of vehicle ids and paging information
Dictionary.vehicles An array of vehicle IDs.
Dictionary.paging.count The total number of elements for the entire query (not just the given page).
Dictionary.paging.offset The current start index of the returned list of elements.

smartcar.get_user_id(access_token)

Retrieve the userId associated with the access_token

Arguments

Parameter Type Description
access_token String Required A valid access token from a previously retrieved access object

Returns

Type Description
String the user id