Skip navigation links

Package com.tomtom.business.ubi.commons.api

This document describes the TomTom UBI Core component and the corresponding SDK.

See: Description

Package com.tomtom.business.ubi.commons.api Description

This document describes the TomTom UBI Core component and the corresponding SDK.

TomTom UBI

TomTom UBI is a comprehensive project about collecting and analyzing driving data from vehicles like cars or trucks. A hardware dongle installed in the vehicle collects the data through OBD. A service component on the smartphone connects to the dongle, communicates with it and sends back all collected data to the TomTom servers where they can be accessed via HTTP for further analysis.

The Core

The TomTom UBI Core is a component that handles the communication between the TomTom dongle (Bluetooth), all back-end systems (TCP and others) and the custom client application (IPC). It is implemented as an Android service that can be run in a remote service process independent from the client application or as service embedded in the client application.

Roles and Responsibilities

TomTom publishes and maintains the Core and the corresponding SDK. Using the SDK an external developer is able to develop a custom app. The SDK is either distributed as Android library and can be bundled internally with a client app or is distributed via Google Play as independent application.

Core Communication via Android Service Binding

See Core for more information. This approach lets a client deeply integrate with the Core component. A comprehensive API based on the Request/Reply pattern eases the integration. Multiple concurrent clients are not supported at the moment. A client-local service that binds to the Core can be used to keep the Core running without UI if background processing is desired.

Queuing

The Core stores any outgoing message, that is messages that are supposed to be send from the Core to either dongle or WEBFLEET or via end-to-end communication between the dongle and WEBFLEET, in a persistent queue. So if the user initiates the download of driving data the Core instructs the dongle to send all data. If at this moment the connection to WEBFLEET is interrupted the Core stores these messages containing the driving data persistently in a local storage. Note, however not all messages are stored forever. Mostly user initiated actions like starting the download are not persisted.

Connections

When the client connects to the Core the Core initiates connections to both sides dongle and WEBFLEET. As long as the client is bound to the Core and the Core is alive it will keep the connection open or try to establish it. If a number of attempts failed the Core gives up and retries upon next client-initiated action. So if the user drives into a underground parking lot he will likely lose Internet connection while keeping the Bluetooth connection. The user can then initiate the download and the Core will automatically try to reconnect to WEBFLEET.

Note: The Core doesn't automatically reconnect to either side upon Android's ConnectivityManager.CONNECTIVITY_ACTION broadcast. If desired a client has to catch this event and call ServiceClient.reconnectToDongle() and ServiceClient.reconnectToServer().

For testing purposes please use the following CoreBootParameters for the connection to WEBFLEET:

WEBFLEET Messaging Server Host Name: its-robin-gprs.business.tomtom.com
WEBFLEET Messaging Server Port: 443
WEBFLEET.connect Server Host Name: https://its-wfc.business.tomtom.com
WEBFLEET.connect API Key: UBI-ROBIN-SINGLEOBJECT

When you are done with testing and want to switch to production please use the following parameters:

WEBFLEET Messaging Server Host Name: robin-gprs.business.tomtom.com
WEBFLEET Messaging Server Port: 443
WEBFLEET.connect Server Host Name: https://csv.business.tomtom.com
WEBFLEET.connect API Key: This is handed to the developer on a per-company basis.

Concurrency

The client must be prepared to handle any callback method at any time. It can happen that multiple callbacks of the same type arrive at the same time. Therefore it is recommended to keep the state in the client app. ServiceClientCallback.onFirmwareUpdateAvailable(ServiceClientCallback.FirmwareUpdateAvailableResponse) is called the client should discard any further 'firmware-available' callbacks until the user has finally finished the update process, that is either the user declined the request for firmware update or the firmware update was eventually carried out no matter if successful or not.

Main Functions

Activation

The activation is the process of registering the dongle device with WEBFLEET. It is implicitly done when connecting to the Core by calling ServiceClient.bootCore(CoreBootParameter). Among others user name, password and a Bluetooth device (the dongle) are required when connecting. The Bluetooth device can be acquired using the recommendations regarding Bluetooth in the Android documentation. Upon successful initialization ServiceClientCallback.onCoreBooted() is called. After this callback the client can call arbitrary functions in the Core. Please note: The client may not call any other methods in the Core until ServiceClientCallback.onCoreBooted() was called. The 'core-booted' callback doesn't mean the activation was successful but only that all internal subsystems of the Core have properly been started. Depending on the current state of the activation internal communication takes place between dongle and WEBFLEET. Upon successful activation the Core calls ServiceClientCallback.onActivationFinished().

Once the activation was successfully finished and the client connects to the dongle no further internal communication takes place. To reset the Core's state and force an activation send the CoreBootParameter.reset flag with ServiceClient.bootCore(CoreBootParameter). Then the activation will be carried out from scratch. Please note: Any local data - even downloaded driving data - will be erased when the reset flag is sent!

Connection States

The Core calls ServiceClientCallback.onConnectionStatusUpdate(ServiceClientCallback.ConnectionStatusResponse) on every change of the connection status to either WEBFLEET or dongle. Upon ServiceClient.bootCore(CoreBootParameter) the Core attempts to connect to both sides, dongle and WEBFLEET. The Core stops to connect if a defined number (10) of connection attempts failed and yields ConnectionStatus.CONNECTING_FINALLY_FAILED. Any further function call that requires a connection to either side will try to reconnect then again, so the user doesn't need to care for reconnection manually.

Automatic Disconnect

When the Core recognizes there is no communication ongoing - that is no message is sent for a certain period of time (3 minutes at the moment) - it will automatically disconnect from both end-points. This prevents the dongle from staying alive. For instance if the Core was started via Intent (see below) to transmit OBD real-time data silently and the driver of the car forgot his smartphone in the car the Bluetooth connection between Core and dongle will prevent the dongle from going to sleep. This may lead to draining the battery of the car. To avoid this the Core disconnects from the dongle and the server after a period of time if no message has been exchanged in this period.

Core State

If the client wants to know how the current Core state is it can call ServiceClient.requestCoreState(). The Core answers with ServiceClientCallback.onCoreState(ServiceClientCallback.CoreStateResponse) containing the current state of the Core.

Download

The download of driving data can be initiated using ServiceClient.startSync(). Before being able to download the driving data the dongle checks its local clock. If the clock in the dongle needs synchronization the Core calls ServiceClientCallback.onClockSyncReasonForDownloadRequired(). The client must then let the user enter a reason for the clock synchronisation and send this reason back to the Core via ServiceClient.sendClockSyncReasonForDownload(DisconnectReasonParameter). After that several callbacks (ServiceClientCallback.onDownloadStatusUpdate(ServiceClientCallback.DownloadStatusResponse)) indicating the current progress of the download are being called by the Core. It is recommendable to show the progress in the UI while downloading.

CAUTION

Keep the download process shielded from other processes! So in order to not interfere with the sensitive download process stop possibly running OBD real-time feeds or firmware updates or other long-running tasks. The download process informs you about all state changes and thus you can resume the other tasks once the download has completed.

Firmware Update

A firmware check is automatically done upon successful connection to the Core. The activation of the dongle must be finished and valid.


Firmware update state machine

It's recommended to use a state machine to handle the firmware update process properly (like the one above).
If a new firmware is available ServiceClientCallback.onFirmwareUpdateAvailable(ServiceClientCallback.FirmwareUpdateAvailableResponse) is triggered. The firmware file ID contained in this response should only be used once for the next firmware update. In case the update fails (for any reason) it's NOT recommended to restart the firmware update process, but to forget about the available firmware update and switch back to the "no update available" state. It's recommended to give the user the possibility to accept or decline the firmware update once it was announced by the SDK instead of running the update in background.
As soon as the update has been started (from blue state - see above) via ServiceClient.updateFirmware(FirmwareUpdateParameter) a FirmwareUpdateStatus.DOWNLOAD_STARTED is sent via ServiceClientCallback.onFirmwareUpdateStatusUpdate(ServiceClientCallback.FirmwareUpdateStatusResponse). This status contains the max. progress for the download process and can be used for progress indicators in the app as the current download progress is reported via FirmwareUpdateStatus.DOWNLOAD_PROGRESS status updates. The same applies to the upload process where the FirmwareUpdateStatus.UPLOAD_STARTED status update contains the max. progress for the whole upload procedure of the firmware to the dongle.
After the firmware has been transferred to the dongle all remaining collected driving data on the dongle is automatically transmitted to WEBFLEET via smartphone. All messages described under Download may be sent by the dongle before actually starting to update the firmware. When sending of the messages is done the firmware is finally being installed on the dongle. A restart of the dongle is necessary for the new firmware to take effect. When a restart of the dongle took place the dongle tries to reconnect to the last known bluetooth address. Thus as soon as the dongle has been reconnected the firmware update process is finished.

CAUTION

Keep the firmware update process shielded from other processes! So in order to not interfere with the sensitive firmware update process stop possibly running OBD real-time feeds or continuous downloads from the Dongle or other long-running tasks. The firmware update process informs you about all state changes and thus you can resume the other tasks once the firmware update has been carried out.

OBD Real-Time Transmission

The transmission of real-time OBD data can be started by calling ServiceClient.startObdRealtimeTransmission(). After this message N ServiceClientCallback.onObdRealTimeDatagram(ServiceClientCallback.ObdRealTimeDatagramResponse) are triggered periodically if a dongle is currently connected. These callbacks contain various OBD data that can be processed as required. If the client wants to stop the transmission it can call ServiceClient.stopObdRealtimeTransmission(). Please note: To have the transmission of real-time OBD data fully functional and running - even when the device falls asleep, that is the screen is switched off - the use of a partial wake lock is recommended (acquire the partial wake lock before starting real-time transmission and release it after real-time transmission has been stopped). However, not all devices directly fall asleep when switching off the device. Note that keeping a wake lock may drain the battery when poorly implemented, so be cautious here.

CAUTION

Since the firmware update process or the download of driving data from the dongle are sensitive processes stop possibly running OBD real-time feeds as long as there are long-running tasks to do.

Device Status

The current device status can be queried by calling ServiceClient.requestDeviceStatus(). The Core will answer with ServiceClientCallback.onDeviceStatus(ServiceClientCallback.DeviceStatusResponse). At the moment the device status consists of information about the current number and duration of disconnected periods of the dongle from the vehicle and the virtual odometer provided by the dongle. It is recommended to request the vehicle's odometer from the user when the dongle was disconnected. The vehicle could have moved without the dongle installed and so both odometer values from car and dongle might diverge quickly.

Setting the Odometer

To set the odometer call ServiceClient.changeOdometer(OdometerValueParameter) with a proper odometer value set. Note: Setting the odometer requires a WEBFLEET connection. A ServiceClientCallback.onOdometerChange(ServiceClientCallback.OdometerChangeResponse) is sent back by the dongle upon completion containing the result of the change request.

Push Notifications

WEBLFEET sends push notifications (PN) to the Core to inform the client about an overdue download of driving data, for example. In order to get PNs the client app needs to send the token received from the GCM to WEBFLEET via ServiceClient.sendGcmRegistrationToken(GcmRegistrationParameter) and register a GcmListenerService in its manifest (for more information on this topic please refer to the Android GCM client documentation). The intent that is sent from WEBFLEET via PN contains an extra (key = 'action', value = 'uploadHint').

Error Handling

Upon each error ServiceClientCallback.onError(ServiceClientCallback.UbiErrorCodeResponse) is called by the Core. It returns an UbiErrorCode and an optional ServiceClientCallback.UbiErrorCodeResponse.errorCodeDescription.

Shutdown

When the client unbinds from the service or the service is stopped in an other way the Core is shut down and the communication and all connections with WEBFLEET and dongle are terminated.

Wake-up via Dongle

The dongle periodically attempts to connect to the smartphone it was connected to lastly and validly activated with. At the moment the interval is 1 minute. If the dongle recognizes a stable Bluetooth connection from the smartphone to the dongle it stops connecting. The custom app can capture these connection requests from the dongle registering a BroadcastReceiver that filters on android.bluetooth.device.action.ACL_CONNECTED. See the following example from an Android manifest:

  <receiver android:name="com.business.app.DongleWakeupReceiver">
      <intent-filter><action android:name="android.bluetooth.device.action.ACL_CONNECTED"/></intent-filter>
  </receiver>
 
The BroadcastReceiver also returns within the extra's of the Intent the Bluetooth address of the dongle that attempts to connect. The client app can look up this Bluetooth address in its local storage and retrieve the corresponding user credentials. These credentials can then be used to start the Core, initiate the download of driving data and stop the Core if done. The client app can either start an client-local service upon capturing the Intent mentioned above and bind to the Core and control it the normal way or it can use a simple Intent-based interface. Please note, the calls to the BroadcastReceiver listening for android.bluetooth.device.action.ACL_CONNECTED may happen quite frequently. To avoid repeatedly booting the Core and running into concurrency issues the BroadcastReceiver should track the last start time of the Core and reject further connection requests if the Core was just started. Otherwise the Core would stop and restart itself each time upon each new call to boot. It is also possible to trigger another connection attempt using ServiceClient.reconnectToDongle() or ServiceClient.reconnectToServer().

Intent-based interface

The Intent-based interface currently supports booting the Core, downloading the driving data and starting and stopping the real-time transmission of OBD data. Please note: The Core can either be started by starting it via Intent or via binding to it. Binding to the Core - that is a client component like an activity or a service binds to the Core - has always higher priority. So in case there is already a client bound to the Core it is not possible to start the Core via Intent at the same time. If the Core was started via Intent and another component is trying to bind to it the Core will be automatically be rebooted with the new parameters given in the bind request.

Be sure to always stop the Core if it was started before via Intent - even if an other component bound to it later. The Core can be stopped via Context.stopService(Intent).

Versioning

The API of the Core and the SDK will always be backward compatible. Any changes to external interfaces may only be additive. Internal changes must and will always obey the functional definitions of the API. User implementations must always code against the specification of the API. An erroneous internal implementation is subject to be fixed if it doesn't match the API definition. Before a new version of the Core is released any involved integrators will be informed about the new release and get a new build up front.
Copyright 2013 - 2016 TomTom Telematics
Skip navigation links