Repository navigation
Android SBeacon Framework Trip Management
SBeacon SDK v1.6.13
This guide covers trip lifecycle management, status monitoring, and retrieving trip data from SBeacon devices.
Trips are automatically detected by the SBeacon based on motion detection. The trip status transitions through these states:
| Status | Description |
|---|---|
IDLE |
No trip in progress, beacon stationary |
START |
Trip starting, motion detected |
ACTIVE |
Trip in progress |
END |
Trip ending, motion stopped |
TIMEOUT |
Trip timed out |
UNKNOWN |
Status not yet determined |
Trip Flow: IDLE → START → ACTIVE → END → IDLE
Important: Fetch trip data only when transitioning from END to IDLE. Track the previous trip status to detect this transition and avoid fetching data on repeated IDLE events. Fetching trip records before the status transitions back to IDLE may result in incomplete data.
private var lastTripStatus: TripStatus? = null
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
override fun onTripStatusChanged(status: String) {
lifecycleScope.launch(Dispatchers.Main) {
val tripStatus = TripStatus.valueOf(status)
updateTripStatusUI(tripStatus)
// Fetch trip data only when transitioning from END to IDLE
if (tripStatus == TripStatus.IDLE && lastTripStatus == TripStatus.END) {
syncCompletedTripData()
}
lastTripStatus = tripStatus
}
}
}Request current trip status and unsynced data counts:
private fun requestTripInformation(beaconMac: String) {
lifecycleScope.launch(Dispatchers.IO) {
try {
BLEManager.retrieveInstance(requireContext())
.requestTripInformation(beaconMac)
// Responses arrive via events:
// - TripStatusChanges (trip status)
// - UnsyncedDataCounts (unsynced counts)
} catch (e: Exception) {
Timber.e(e, "Failed to request trip info")
}
}
}override fun onUnsyncedDataCounts(
beaconMac: String,
unsyncedTripCount: Int,
unsyncedIncidentCount: Int,
unsyncedDrivingBehaviorCount: Int
) {
lifecycleScope.launch(Dispatchers.Main) {
updateUnsyncedCounts(unsyncedTripCount, unsyncedIncidentCount, unsyncedDrivingBehaviorCount)
}
}Retrieve historical trip data stored on the beacon:
private fun requestTripRecords(beaconMac: String) {
lifecycleScope.launch(Dispatchers.IO) {
try {
BLEManager.retrieveInstance(requireContext())
.requestTripRecords(beaconMac)
// Response arrives via TripRecordsReceived event
} catch (e: Exception) {
Timber.e(e, "Failed to request trip records")
}
}
}override fun onTripRecordsReceived(beaconMac: String, trips: ArrayList<TripRecord>) {
trips.forEach { trip ->
Timber.i("Trip ${trip.recordIndex}:")
Timber.i(" Start: ${Date(trip.startTimestamp)}")
Timber.i(" End: ${Date(trip.endTimestamp)}")
Timber.i(" Duration: ${trip.durationSeconds} seconds")
}
lifecycleScope.launch(Dispatchers.Main) {
displayTripRecords(trips)
}
}Retrieve accident/collision records from the beacon:
private fun requestTripIncidents(beaconMac: String) {
lifecycleScope.launch(Dispatchers.IO) {
try {
BLEManager.retrieveInstance(requireContext())
.requestTripIncidents(beaconMac)
// Response arrives via TripIncidentsReceived event
} catch (e: Exception) {
Timber.e(e, "Failed to request incidents")
}
}
}override fun onTripIncidentsReceived(beaconMac: String, incidents: ArrayList<IncidentRecord>) {
incidents.forEach { incident ->
Timber.i("Incident ${incident.id} at ${Date(incident.timestamp)}")
Timber.i(" Samples: ${incident.samples}")
Timber.i(" Max vector: ${incident.maximumResultantVector}")
}
lifecycleScope.launch(Dispatchers.Main) {
displayIncidents(incidents)
}
}By default, incidents are not automatically fetched when trip information is received. You can enable automatic fetching:
// Enable auto-fetch of incidents when trip info indicates unsynced incidents
BLEManager.retrieveInstance(context).setAutoFetchIncidentsOnTripInfo(true)
// Or disable (default)
BLEManager.retrieveInstance(context).setAutoFetchIncidentsOnTripInfo(false)data class TripRecord(
val recordIndex: Int, // Index in beacon's circular buffer (0-99)
val startTimestamp: Long, // Unix timestamp (ms) when trip started
val endTimestamp: Long, // Unix timestamp (ms) when trip ended
val beaconMacAddress: String // MAC address of the source beacon
) {
val durationMs: Long // Trip duration in milliseconds
val durationSeconds: Long // Trip duration in seconds
fun isValid(): Boolean // True if timestamps are valid
}data class IncidentRecord(
var id: Int, // Incident identifier
var timestamp: Long, // Recording timestamp
var actualIncidentTimestamp: Long, // When incident occurred
var samples: Int, // Number of samples
var vectorValues: ArrayList<Vector>, // G-force samples
var averageVector: Vector, // Average G-force
var averageResultantVector: Long, // Average magnitude
var maximumResultantVector: Long // Peak magnitude
)
data class Vector(
var x: Int, // X-axis (lateral)
var y: Int, // Y-axis (longitudinal)
var z: Int // Z-axis (vertical)
)When syncing all data from a beacon:
suspend fun syncBeaconData(beaconMac: String) {
val bleManager = BLEManager.retrieveInstance(context)
// 1. Get current status and counts
bleManager.requestTripInformation(beaconMac)
delay(500)
// 2. Get trip records
bleManager.requestTripRecords(beaconMac)
delay(500)
// 3. Get incidents
bleManager.requestTripIncidents(beaconMac)
delay(500)
// 4. Get driving behavior events
bleManager.requestDrivingBehaviorEvents(beaconMac)
}Due to BLE buffer limits, large trip histories may require multiple calls:
// The beacon stores up to 100 trip records (indices 0-99)
// Records are returned in batches based on BLE MTU size- Driving Behavior - Configure and monitor driving behavior events
- Calibration - Calibrate for accurate detection
- Event Handling - Complete event reference
Consolidated SDK
SmartDrive
PortalApiBase
PortalApiClient
Wellness
SBeacon
- Overview
- Installation
- Initialization
- Beacon Scanning
- Beacon Pairing
- Trip Management
- Driving Behavior
- Calibration
- Event Handling
- Data Models
- API Reference
Consolidated SPM
SDApiManager
CCFrameworkOpen
SmartDrive
SBeacon