Asset Tracking

Using the SDKs

This topic explains how to get started using the Ably Asset Tracking SDKs.

Supported platforms

There are two Asset Tracking SDKs, one for publishing and one for subscribing. The following platforms are supported:

  • Android (Java and Kotlin) – publisher and subscriber SDK
  • iOS (Objective-C and Swift) – publisher and subscriber SDK
  • Web (JavaScript, with first class TypeScript support) – subscriber SDK

SDK repositories

The SDKs can be found in the following GitHub repositories:

Prerequisites

You need to have a suitable development environment installed, for example:

  • Android – Android Studio or Gradle (requires Android SDK to be installed)
  • iOS – Xcode
  • JavaScript – any suitable environment of your choice

You also need to have suitable credentials for the various SDK components:

  • ABLY_API_KEY – Your Ably API key
  • MAPBOX_ACCESS_TOKEN – Mapbox public key
  • MAPBOX_DOWNLOADS_TOKEN – Mapbox private key

On Android development systems you can set these values in your ~/.gradle/gradle.properties file.

Installing the SDK

You can find information on installing the Ably Asset Tracking SDKs in the following resources:

Authentication

The client requires authentication in order to establish a connection with Ably. There are three methods that can be used:

1. Basic Authentication
2. Token Authentication
3. JWT Authentication

Usually a client will use either token or JWT authentication, as Basic Authentication would require exposing the API keys on the client.

Examples of establishing a connection using the three methods are given in the following sections. While the examples shown are for the publishing SDK, the code equally applies to establishing a connection using the Subscribing SDK.

Basic Authentication

The following example demonstrates establishing a connection using Basic Authentication:

val publisher = Publisher.publishers() // get the Publisher builder in default state
    .connection(ConnectionConfiguration(Authentication.basic(CLIENT_ID, ABLY_API_KEY)))

This method should not be used on a client however, as it exposes the API key.

You can read more about Token Authentication in our documentation.

Token Authentication

The following example demonstrates establishing a connection using Token Authentication:

val publisher = Publisher.publishers() // get the Publisher builder in default state
    .connection(ConnectionConfiguration(Authentication.tokenRequest(CLIENT_ID) { requestParameters ->
        // get TokenRequest from your server
        getTokenRequestFromAuthServer(requestParameters); // customer implements this function
        }))

You can read more about Token Authentication in our documentation.

JWT Authentication

The following example demonstrates establishing a connection using JWT Authentication:

val publisher = Publisher.publishers() // get the Publisher builder in default state
    .connection(ConnectionConfiguration(Authentication.jwt(CLIENT_ID) { tokenParameters ->
        // get JWT from your server
        getJWTFromAuthServer(tokenParameters); // customer implements this function
        }))

You can read more about Token Authentication in our documentation.

Using the publishing SDK

Common operations you need to carry out on the publisher include:

  • Initialize the publisher.
  • Start tracking an asset.
  • Stop tracking an asset.
  • Set the resolution constraints on an asset.

Initializing the Publisher

During initialization of the publisher various methods can be called to configure the Publisher.

The required methods are:

connection
Called to provide Ably connection information, such as API keys, and any other configuration parameters as needed.
map
Called to provide Mapbox configuration, such as API keys, any other configuration parameters as needed.
resolutionPolicy
Sets the policy factory to be used to define the target resolution for publishers created from this builder.
androidContext
Called to provide the Android runtime context (on Android only).

The optional methods are:

profile
Called to set the means of transport being used for the initial state of publishers created from this builder. If not set then the default value is RoutingProfile.DRIVING.
locationSource
Sets the location source to be used instead of the GPS. The location source provides location updates for the Publisher.

The following code example creates some example resolution constraints:

 
// Prepare Resolution Constraints for an asset that will be used in the Resolution Policy
val exampleConstraints = DefaultResolutionConstraints(
    DefaultResolutionSet( // this constructor provides one Resolution for all states
        Resolution(
            accuracy = Accuracy.BALANCED,
            desiredInterval = 1000L,
            minimumDisplacement = 1.0
        )
    ),
    proximityThreshold = DefaultProximity(spatial = 1.0),
    batteryLevelThreshold = 10.0f,
    lowBatteryMultiplier = 2.0f
)

The next step is create a default resolution to be used:

// Prepare the default resolution for the Resolution Policy
val defaultResolution = Resolution(Accuracy.BALANCED, desiredInterval = 1000L, minimumDisplacement = 1.0)

Once these are created you can then initialize the publisher with the constraints and default resolution, and start the publisher:

// Initialize and Start the Publisher
val publisher = Publisher.publishers() // get the Publisher builder in default state
    .connection(ConnectionConfiguration(Authentication.basic(CLIENT_ID, ABLY_API_KEY))) // provide Ably configuration with credentials
    .map(MapConfiguration(MAPBOX_ACCESS_TOKEN)) // provide Mapbox configuration with credentials
    .androidContext(this) // provide Android runtime context
    .resolutionPolicy(DefaultResolutionPolicyFactory(defaultResolution, this)) // provide either the default resolution policy factory or your custom implementation
    .profile(RoutingProfile.DRIVING) // provide mode of transportation for better location enhancements
    .start()

Start tracking

You can start tracking an asset by calling the track method of the publisher. You need to supply the tracking identifier of the asset to be tracked, and optionally any resolution constraints that need to be applied.

The following code example demonstrates how to start tracking an asset:

// Start tracking an asset
publisher.track(
    Trackable(
        trackingId, // provide a tracking identifier for the asset
        constraints = exampleConstraints // provide a set of Resolution Constraints
    )
)
// handle asset tracking started successfully
...

Stop tracking

You can stop tracking a trackable (asset) that is registered with the publisher using the remove method, as shown in the following code:

publisher.remove(trackable)

Using the Subscribing SDK

Common operations you will need to carry out on the subscriber include:

  • Initialize the subscriber.
  • Listen for location updates sent from from the publisher.
  • Listen for asset status updates sent from the publisher.
  • Request a different resolution to be sent from the publisher.

Initializing the Subscriber

During initialization of the subscriber various methods can be called to configure the Subscriber.

The required methods are:

connection
Called to provide Ably connection information, such as API keys, and any other configuration parameters as needed.
trackingId
Sets the asset to be tracked, using the unique tracking identifier of the asset.

The optional methods are:

resolution
Request a specific resolution of updates to be requested from the remote publisher.

The following code example demonstrates initializing and starting the subscriber:

// Initialize and Start the Subscriber
val subscriber = Subscriber.subscribers() // Get an AssetSubscriber
    .connection(ConnectionConfiguration(Authentication.basic(CLIENT_ID, ABLY_API_KEY))) // provide Ably configuration with credentials
    .resolution(Resolution(Accuracy.MAXIMUM, desiredInterval = 1000L, minimumDisplacement = 1.0)) // request a specific resolution to be considered by the publisher
    .trackingId(trackingId) // provide the tracking identifier for the asset that needs to be tracked
    .start() // start listening for updates

Subscribe to updates

You can subscribe to updates from the publisher, specifying a function that is called when each update is received. This is shown in the following example:

// Listen for location updates
subscriber.locations
    .onEach { } // provide a function to be called when enhanced location updates are received
    .launchIn(scope) // coroutines scope on which the locations are received

Subscribe to asset state changes

You can subscribe to asset state changes from the publisher, specifying a function that is called when each state change is received. This is shown in the following example:

// Listen for asset state changes
subscriber.trackableStates
    .onEach { } // provide a function to be called when the asset changes its state
    .launchIn(scope) // coroutines scope on which the statuses are received

Request a different resolution

The subscriber can always request a different resolution preference by calling the resolutionPreference method, passing in the required Resolution. This is shown in the following example:

// Request a different resolution when needed.
subscriber.resolutionPreference(Resolution(Accuracy.MAXIMUM, desiredInterval = 100L, minimumDisplacement = 2.0))
// change request submitted successfully
...

See also


API reference
Documentation

Need help?

If you need any help with your implementation or if you have encountered any problems, do get in touch. You can also quickly find answers from our knowledge base, and blog.