Welcome! Sign in or Register to get your developer token and download the SDK.

iOS SDK

Quick Start Guide API Reference Delegate Reference Other Connection Method Installation

Android SDK

Quick Start Guide API Reference Callback Reference

Web API

Web API Overview Authentication BAC Readings

Quick Start Guide

Understanding the Sample Project

Your app will send commands to, and receive callbacks from, BACtrack devices. In order to do this, you must first initialize a BacTrackAPI object with the following command call: mBacTrack = [[BacTrackAPI alloc] initWithDelegate:<BacTrackAPIDelegate> AndAPIKey:@"insertAPIKeyStringHere"]; This initializer method sets the specified delegate and checks with our server whether the included API Key is valid. In case your app has not been approved to use our SDK, the callback (void)BacTrackAPIKpiKeyDeclined:(NSString *)errorMessage will be called and must be implemented.

Once you've initialized your BacTrackAPI object, you can establish a BTLE connection between your iOS device and a BACtrack by executing the following command call on the BacTrackAPI object: connectToNearestBreathalyzer

Tapping on the "Take Test" button calls startCountdown on the BacTrackAPI object and initiates a series of callbacks on the BacTrackAPIDelegate shown below.

Countdown Screen Blow Now Screen Keep Blowing Screen Analyzing Results Screen Results Screen

Starting a BAC test walks the user through 5 steps.

The test process consists of a series of five phases. At the start of every phase your <BacTrackAPIDelegate> receives the following callbacks:

  1. Warming up (void)BacTrackCountdown:(NSNumber *)seconds executionFailure:(BOOL)failure This callback is called many times and the <seconds> parameter is an estimated amount of seconds left until the next callback (BacTrackStart) is called.
  2. Begin Blowing (void)BacTrackStart
  3. Keep Blowing (void)BacTrackBlow This callback is called many times during the time that the user is blowing into the BACtrack.
  4. Analyzing (void)BacTrackAnalyzing When this callback is called, the user can stop blowing.
  5. Results (void)BacTrackResults:(CGFloat)bac

API Reference

Initialize class

-(id)initWithDelegate:(id<BacTrackAPIDelegate> )delegate AndAPIKey:(NSString*)api_key;

These methods represent the commands you can send to a BACtrack:

Methods Description
-(void)connectToNearestBreathalyzer NORMAL use case for connecting to a BACtrack. Connects to nearest to BACtrack.
-(void)startScan Scan for BACtracks within range. To be used with connectBreathalyzer:withTimeout.
-(void)connectBreathalyzer:(Breathalyzer*)breathalyzer
    withTimeout:(NSTimeInterval)timeout
ALTERNATE use case for connecting to a BACtrack. See below for explanation.
-(void)stopScan Stop scanning for BACtracks within range. To be used with startScan.
-(void)disconnect Disconnect from BACtrack
-(BOOL)startCountdown Start BACtrack countdown to take a BAC test.
-(void)getBreathalyzerBatteryLevel Request a callback with the current battery voltage and level.

Delegate Reference

These methods represent all the messages you might get from the BACtrack.

Required Methods Description
-(void)BacTrackAPIKeyDeclined:(NSString *)errorMessage Called if the passed in API Key is not valid.
Optional Methods Description
-(void)BacTrackAPIKeyAuthorized Called if the passed in API Key is valid.
-(void)BacTrackConnected Successfully connected to BACTrack and found services and characteristics.
-(void)BacTrackDisconnected Disconnected from BACTrack.
-(void)BacTrackConnectTimeout Attempting to connect to BACTrack timed out.
-(NSTimeInterval)BacTrackGetTimeout Asks for connection timeout when connecting to nearest BACtrack.
-(void)BacTrackCountdown:(NSNumber*)seconds
        executionFailure:(BOOL)error
Counting down to reading, number (a double) seconds left, error = TRUE if BAC sensor rejects request.
-(void)BacTrackStart Tell the user to start blowing.
-(void)BacTrackBlow Tell the user to keep blowing.
-(void)BacTrackAnalyzing BACtrack is analyzing the result.
-(void)BacTrackResults:(CGFloat)bac Result of the blow.
-(void)BacTrackFoundBreathalyzer:(Breathalyzer*)breathalyzer Found a BACtrack. Call comes in for every BACtrack found during scan.
-(void)BacTrackBatteryLevel:(NSNumber *)number Reports battery level in the XCode console. 0 is low (needs to be charged). 1 is medium, >=2 is high.

Other Connection Method

You can connect to a BACtrack manually

Normally, an app will set up a BTLE connection with the nearest BACtrack using the connectToNearestBreathalyzer command call. However, your app might want to connect with a selected BACtrack. To enable this functionality, you need to scan for nearby BACtracks using the startScan command call. The scan runs indefinitely until the command stopScan is called. During the scan, everytime your iOS device finds a BACtrack, the callback (void)BacTrackFoundBreathalyzer:(Breathalyzer*)breathalyzer is called. Our sample app implements this by adding the breathalyzer to a breathalyzers array, which is then used as the data source for a table view that lists all the nearby breathalyzers.

Launch Screen Connect Screen

A list of nearby BACtracks in the Sample App

You can distinguish between BACtracks with the following attributes:

After isolating the Breathalyzer object that you want, you can connect with it by providing the Breathalyzer object as an argument to the following command call: (void)connectBreathalyzer:(Breathalyzer*)breathalyzer withTimeout:(NSTimeInterval)timeout

Installation

The BACtrack API consists of a static library (.a file) and a header file (.h file). To use the SDK, your app must link with our static library.

Add a library

Add the .a library file in build phases.

Lastly, in Build Settings > Linking > Other Linker Flags, add the following flags:

Linker Flags

Quick Start Guide (Android)

Your app will send commands, and recieve callbacks from your BACtrack device. In order to do this, you must first create a BacTrackAPI object with the following constructor: mAPI = new BACtrackAPI(this, mCallbacks, apiKey);. This constructor creates a BACtrackAPI object with the passed in callbacks and also checks with our server whether the included API Key is valid. In case your app has not been approved to use our SDK, the callback void BACtrackAPIKeyDeclined(String errorMessage) will be called and must be implemented.

Once you've created your BacTrackAPI object, you can establish a BTLE connection between your Android device and your BACtrack by executing the following command call on the BACtrackAPI object: public void connectToNearestBreathalyzer()

Tapping on the "Take Test" button calls public boolean startCountdown() on the BacTrackAPI object and initiates a series of callbacks on the BacTrackAPIDelegate shown below.

Countdown Screen Blow Now Screen Keep Blowing Screen Analyzing Results Screen Results Screen

The test process consists of a series of five phases. At the start of every phase your <BacTrackAPIDelegate> receives the following callbacks:

  1. Warming up void BACtrackCountdown(int currentCountdownCount) This callback is called many times and the <currentCountdownCount> parameter is an estimated amount of seconds left until the next callback (BacTrackStart) is called.
  2. Begin Blowingvoid BACtrackStart()
  3. Keep Blowingvoid BACtrackBlow() This callback is called many times during the time that the user is blowing into the BACtrack.
  4. Analyzingvoid BACtrackAnalyzing() When this callback is called, the user can stop blowing.
  5. Resultsvoid BACtrackResults(float measuredBac)

API Reference (Android)

Constructor to be used with the public SDK.

public BACtrackAPI(Context context, final BACtrackAPICallbacks bacTrackAPICallbacks, String apiKey)

These methods represent the commands you can send to the BACtrack.

Methods Description
public void connectToNearestBreathalyzer() Connect to the nearest BACtrack device.
public void connectToNearestBreathalyzerWithTimeout() Connect to the nearest BACtrack device.
public void startScan() Scans for BACtracks within range. Continues until stopScan() is called
public void connectToDevice(BluetoothDevice breathalyzer) ALTERNATE use case for connecting to a breathalyzer. Use arraylist returned in stopScan to get breathalyzer.
public ArrayList<BluetoothDevice> stopScan() Stop scanning and return array of breathalyzers found.
public void disconnect() Disconnect from the currently-connected BACtrack device.
public boolean startCountdown() Start BACtrack countdown to take a BAC test.
public boolean getBreathalyzerBatteryVoltage() Request the device's battery voltage. Will trigger BACtrackBatteryVoltage and BACtrackBatteryLevel on successful read.

Callback Reference (Android)

These methods represent all the messages you might get from the BACtrack.

Required Methods Description
void BACtrackAPIKeyDeclined(String errorMessage) Called if the passed in API Key is not valid.
Optional Methods Description
void BACtrackAPIKeyAuthorized() Called if the passed in API Key is valid.
void BACtrackConnected(BACTrackDeviceType bacTrackDeviceType) Called after the BACtrack is connected and services are discovered.
void BACtrackDidConnect(String breathalyzerAdvertisedName) Called after the BACtrack is connected but before services are discovered.
void BACtrackDisconnected() Called when the BACtrack disconnects from the Android device.
void BACtrackConnectionTimeout() Called if the connection to the BACtrack times out.
void BACtrackFoundBreathalyzer(BluetoothDevice breathalyzer) Called whenever a BACtrack device is found while scanning for a device.
void BACtrackCountdown(int currentCountdownCount) Called when the BACtrack is counting down to the "Blow Now" state. currentCountdownCount is the estimated time until BACtrackStart() is called.
void BACtrackStart() Called when the device wants the user to start blowing.
void BACtrackBlow() Tell the user to keep blowing. Continu
void BACtrackAnalyzing() Called while the BACtrack is analyzing the blow results.
void BACtrackResults(float measuredBac) Called when the BACtrack is finished analyzing the blow results.
void BACtrackFoundBreathalyzer(BluetoothDevice breathalyzer) Called whenever a BACtrack device is found while scanning for a device.
void BACtrackBatteryVoltage(float voltage)/code> Called when the BACtrack responds with its battery voltage.
void BACtrackBatteryLevel(int level) Called when the BACtrack responds with its battery level. 0 is low (needs to be charged). 1 is medium, >=2 is high.
void BACtrackError(int errorCode) Called when an error occurs. The code of the error. Codes can be looked up in Constants/ControlBytes * prefixed by "ERROR_".

Web API Overview

BACtrack users have store hundreds of thousands of BAC readings to the cloud. BAC readings contain rich metadata like location, photos, and notes. Many users opt in to allow readings to be viewed anonymously. This unique dataset can be accessed by developers for use in statistcal analysis, data mashups, or use in your app. You can view some examples of the data in action at the BACtrack Consumption Report and BACtrack WorldView. In your own app, you can authentice users to let them view their account data.

Authentication

The BACtrack data API uses OAuth 1.0a. OAuth is a protocol that allows the user grant your app access to our web service on his behalf without telling you his login credentials. OAuth defines a workflow that allows the user to log in to our site at your request to create an access token that will allow you to request data from the service on his behalf.

OAuth Signing

These docs don't describe how to sign each request. There is a description of the process at http://oauth.net/core/1.0a/#signing_process. However, most developers do not implement OAuth signing themselves since there are several available libraries. In python, people typically use OAuth2 (In spite of its name, this library is for OAuth 1.0a).

Steps to Obtain an Access Token

As you read the overview of the OAuth authentication protocol below, it might help to follow along on this diagram from oauth.net: http://oauth.net/core/diagram.png

  1. The Consumer (your app) requests a Request Token from the Provider (our service) at http://mobile.bactrack.com/oauth/request_token/. The Consumer's request must be signed with a valid Consumer Secret (see above for a discussion of signing). The request does not need to include any oauth_token in the header. The response will consist of a Request Token and a Request Token Secret.
  2. The Consumer requests (and shows to the user) the login (authorization) page at http://mobile.bactrack.com/oauth/authorize/. The request for this page should use the Request Token as its oauth_token and compute the oauth_signature using the Request Token Secret.
  3. After the user has logged in and authorized the Consumer, the Consumer can now use the validated Request Token to request an Access Token at http://mobile.bactrack.com/oauth/access_token/. This request should be signed using the Request Token Secret. The response will consist of an Access Token and Access Token Secret.

For all of these steps and for general API usage, the oauth parameters should be passed via the HTTP Authorization header. If the HTTP Authorization header is not available, we also accept these parameters as url-encoded query string parameters. The parameter names are as follows:

Parameter Description
oauth_consumer_key The public key for your app. This is different than your hardware API Key. Please contact developer@bactrack.com to get a Web API Key
oauth_nonce A one time random string that you generate per request. This protects against replay attacks. Nonce stands for "number used once".
oauth_signature Signature for the request. Signed with the appropriate secret key using the technique from http://oauth.net/core/1.0a/#signing_process. It is probably easiest to find a library to do this signing for you.
oauth_signature_method Must be HMAC-SHA1. We do not support plaintext signing.
oauth_timestamp Must be a recent timestamp in seconds since the epoch. In python this is found with import time; timestamp = time.time().
oauth_token The appropriate token (depending on which leg of the auth procedure you're performing).
oauth_version Must be 1.0

Note: In OAuth jargon, a key is like a username, and a secret is the corresponding password. Important: You must set the content-type to json in the header of every request: Content-Type: application/json.
Alternatively, you can add ?format=json to all requests.

BAC Readings

Readings are the backbone of the BACtrack data API. They provide insight into user activity and contain a variety of interesting data sets.

User Readings

User readings are readings that belong to a particular users. These readings may or may not be publicly shared by the user. To access the private readings for a user, you must sign the request with a validated Access Token.

GET http://mobile.bactrack.com/v1/users/id/readings/

Query String Filter Parameters:

Parameter Description
lat_center The latitudinal center to query for readings from. Expressed in degrees.
lng_center The longitudinal center to query for readings from. Expressed in degrees.
radius_meters The radius in meters from the center latitude / longitude to limit to return of readings to.
timestamp__gte Limit the results to readings timestamped after this value. Expressed in ISO-8601.
timestamp__lte Limit the results to readings timestamped before this value. Expressed in ISO-8601.
offset Offset of the results as an integer. Default is 0.
limit Limit the number of results as an integer. Default is 100.

Sample Request with Timestamp Filters

Content-Type: application/json; charset=utf-8
Authorization: {oauth header goes here}
GET http://mobile.bactrack.com/v1/users/1/readings/timestamp__gte=2010-11-16 14:17:00&timestamp__lte=2010-11-16 14:22:00

Sample Response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  count:1,
  readings:
   [
      {
        "id": 123,
        "date": "2010-11-16 14:18:00",
        "location": [47.123, 128.112],
        "bac": 0.021,
        "verified", false,
        "drinks":
         [
           "martini",
           "bourbon"
         ],
        "notes":
        [
          "Love whiskey"
        ],
        "photos":
        [
        ]
     }
   ]
}

Sample Request with Center and Radius Filter

Content-Type: application/json; charset=utf-8
Authorization: {oauth header goes here}
GET http://mobile.bactrack.com/v1/users/{id}/readings?lat_center=47.123&lng_center=128.112&radius_meters=100

Sample Response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  count:1,
  readings:
   [
      {
        "id": 123,
        "date": "2010-11-16 14:18:00",
        "location": [47.123, 128.112],
        "bac": 0.021,
        "verified", false,
        "drinks":
         [
           "martini",
           "bourbon"
         ],
        "notes":
        [
          "Love whiskey"
        ],
        "photos":
        [
        ]
     }
   ]
}

Public Readings

Note: Since these resources give you readings that users have made public, you don't need to sign these requests with a validated Access Token. You can just sign them with your Consumer Key and Secret (like when you're requesting a request token).

GET http://mobile.bactrack.com/v1/readings

Query String Filter Parameters:

Parameter Description
lat_center The latitudinal center to query for readings from. Expressed in degrees.
lng_center The longitudinal center to query for readings from. Expressed in degrees.
radius_meters The radius in meters from the center latitude / longitude to limit to return of readings to.
timestamp__gte Limit the results to readings timestamped after this value. Expressed in ISO-8601.
timestamp__lte Limit the results to readings timestamped before this value. Expressed in ISO-8601.
offset Offset of the results as an integer. Default is 0.
limit Limit the number of results as an integer. Default is 100.

Sample Request with Location Filter

Content-Type: application/json; charset=utf-8
Authorization: {oauth header goes here}
GET http://mobile.bactrack.com/v1/readings?lat_center=47.123&lng_center=128.112&radius_meters=100

Sample Response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  count:1,
  readings:
   [
      {
        "id": 123,
        "date": "2010-11-16 14:18:00",
        "location": [47.123, 128.112],
        "bac": 0.021,
        "verified", false,
        "drinks":
         [
           "martini",
           "bourbon"
         ],
        "notes":
        [
          "Love whiskey"
        ],
        "photos":
        [
        ]
     }
   ]
}

Return a Single Public Reading

GET http://mobile.bactrack.com/v1/readings/id

Sample Request

Content-Type: application/json; charset=utf-8
Authorization: {oauth header goes here}
GET http://mobile.bactrack.com/v1/readings/123

Sample Response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

  {
    "id": 123,
    "date": "2010-11-16 14:18:00",
    "location": [47.123, 128.112],
    "bac": 0.021,
    "verified", false,
    "drinks":
     [
       "martini",
       "bourbon"
     ],
    "notes":
    [
      "Love whiskey"
    ],
    "photos":
    [
    ]
 }

Photos are requested via a normal GET request that does not need to be signed with OAuth. The URLs for the photos are available in "photos" section of any Reading resource.