Using the SDK

A few general notes:

  • Customers should avoid using TripDetector directly; to ensure proper functionality, customers should only use the public class TripDetectionManager;

  • TripDetectionManager can be accidentally initialised multiple times; this got fixed and we print a warning for this now.

  • Show thread name in log file (“main” or “other”).

  • Log current thread on Common.initialize and TripDetectionManager.enable; initialising the SDK and enabling trip detection outside of main thread may cause issues for trip detection.

Device Activation (aka Phone Registration)

The user's phone must be registered through the Portal before trips recorded on that phone can be uploaded. Depending on the activation method, as selected by the host app, the device may only require one activation.

There is currently a limit of one registered phone per user account. If the same user logs in and registers a second phone, trips from the first phone will no longer get uploaded to the server.

Use the DeviceService to activate the device (register the phone) before you start recording trips.

let deviceService = DeviceService(identity: identity)
deviceService.activate(then: { result in
    guard let device = result.value else {
        print("Something went wrong.")
        return
    }
    // Additional activation for the device.
})

Control Trip Detection and Recording

To utilize trip detection, recording, and uploading features, it is essential to initialize the trip detection manager. We highly advise performing this initialization process upon application launch. Once the trip detection manager is initialized, you will have access to enable and disable functionalities.

To activate trip detection, recording, and file upload, utilize the enable function. Additionally, there are two callback functions available: tripStartHandler, which triggers when a trip starts, and tripEndHandler, which is called upon trip ends.

Use the disable function to stop, such as when the user logs out.

Note that once trip detection is enabled, it remains enabled even if the application restarts or the phone reboots. You only need to explicitly re-enable it if you previously disabled it.

// Enable Trip Detection
tripDetectionManager?.enable(tripStartHandler: { date in
    // Do something with the trip start date ...
}, tripEndHandler: { date in
    // Do something with the trip end date ...
})

// Disable Trip Detection
tripDetectionManager?.disable()
tripDetectionManager?.enable method has first argument powerMode: PowerMode = .high which is deprecated in SDK 1.16.0 version.

Manual Trip Recording and Uploading

Trip detecting, recording, and uploading will be performed automatically once the enable function is called. If you prefer manual control over recording and uploading trips, you can use the following functions:

  • Use beginTripRecording to start trip recording

// Start recording the trip manually
tripDetectionManager?.beginTripRecording()
  • Use endTripRecording to stop trip recording

// Stop recording the trip manually
tripDetectionManager?.endTripRecording()
  • Use uploaAll to upload all the trip data

// Upload all trip data
tripDetectionManager?.uploadAll()
  • Use tripsToUplaod to see the number of trips that are ready to upload. Note the this number will be increased when a trip is recorded without a network connection.

// see the number of trips that are ready to upload
tripDetectionManager?.tripsToUplaod()

Bluetooth Trip Detection

How it works

The Bluetooth Trip Detection (BTD thereafter) uses pending connections to Bluetooth LE devices to wake-up the trip detection. The BTD acts as a wake-up trigger, which kick-starts the trip detection. The first implementation is neither required, nor sufficient to start a trip on its own. A trip can still be started without any bluetooth device being detected, and the trip detection is still required to confirm the validity of a trip.

Bluetooth vs Bluetooth LE vs Bluetooth beacon

BTD supports both Bluetooth and Bluetooth LE technology. BTD does not support Bluetooth beacon, although these can be used via the Bluetooth LE features (beacon features are not used in the current implementation) BTD makes use of the "Bluetooth classic" as defined in Apple's WWDC 2019. Not all Bluetooth devices support this feature. BTD makes use of the AudioManager to try to infer the presence of regular Bluetooth devices, such as a car infotainment system.

Starting and Stopping the Bluetooth Trip

Once a Bluetooth device is added to the list of known devices, the Bluetooth trip detection will start detecting automatically.

Built-in Bluetooth device list

To reduce issues related to device support, the SDK provides a list of devices that can be directly used for trip detection. The list is built using the same technologies used by the SDK for the detection, and insure a higher success rate by not showing devices known to not be compatible with the current implementation. The list can be accessed via

bluetoothManager.availableBluetoothDevices(callback: { device in
    // update your UI based on this
})

BluetoothDevice's can be used in place of CBPeripherals when adding/removing devices.

Adding / removing devices

In order to add a Bluetooth device to the list of known Bluetooth devices you need to call:

TripManager.shared.bluetoothTripDetector()?.availableBluetoothDevices(callback: { device in
    print("Discovered a new device \(device)")
})

This does not show any audio devices.

Then one needs to access the trip detection component 'BluetoothTripDetector' (name subject to change for final release). This component includes all the required methods to add or remove Bluetooth devices to and from the list. The list of devices is backed up by the SDK itself in order to provide the simplest implementation. When using the TripUmbrella, a default implement exists and can be used as follows

TripManager.shared.bluetoothTripDetector()?.registerBluetoothDevice(withBluetoothDevice: TripDetection.BluetoothDevice)

In the same fashion, it is possible to remove a Bluetooth device.

TripManager.shared.bluetoothTripDetector()?.unregisterBluetoothDevice((withIdentifier: String)

NOTE: For a full implementation example, check out the Sample App.

Controlling how the files are uploaded

At the time of SDK initialization, if the host app wants it can select the upload route for uploading the trip files to the DriveSync server.

SDK has two upload routes host app can choose:

  • .wifiOnly: Upload data only when connected to a WiFi network.

  • .anyNetwork: Upload data when connected to any network.

If the host app doesn't pass the upload route, the SDK will choose .anyNetwork by default for uploading the trip files.

See below example for passing the upload route:

let manager = TripDetectionManager(identity: Identity,
                                    uploadRoute: .wifiOnly,
                                    telemetryEvents: Set,TelemetryEvent>,
                                    externalRecordProviders: [Factory<ExternalRecordProvider>],
                                    features: [Feature])

Also, after initialization the upload route settings can be changed.

See below example:

manager.uploadRoute = .wifiOnly

Logging the message

The log function will log the message into SDK log file. Please make sure to import the Common framework. There are 4 levels for the log message, which are debug, info, warning and error.

import Common

// Debug level
log.d("Debug message")

// Info level
log.i("Info message")

// Warning level
log.w("Warning message")

// Error level
log.e("Error message")

The format of the log message will be:

[Local Time] [Log Level] [Thread] [File Name] [Function Name]:[Line] - [Message]

Here is an example of the log

2023-11-02T15:30:42.508-04:00 [INFO] <0x700380 (MAIN)> ContentView.swift - logMessageFunction():26 -message

All the logs will be stored in the log directory under the app directory. You can use the app directory, which from initializing sdk, to get the log directory.

// this directory is created when initializing the sdk
let sdkDirectory = Directories(root:
                                try! FileManager.default.url(
                                    for: .documentDirectory,
                                    in: .userDomainMask,
                                    appropriateFor: nil,
                                    create: true).appendingPathComponent("SDK"))

// get the log directory path using the sdk directory
let logURL = sdkDirectory.logs

do {
    // get all files from log directory
    let logFiles = try FileManager.default.contentsOfDirectory(at: logUrl, includingPropertiesForKeys: nil)
    for file in logFiles {
        // do something with log files
    }
} catch {
    print("Error")
}

Last updated