Android SBeacon Framework Driving Behavior - scopetech/Mobile-Public GitHub Wiki

Driving Behavior Detection

The SBeacon SDK provides real-time detection of harsh driving events including acceleration, braking, cornering, and collision incidents.


Overview

The driving behavior feature uses the beacon's built-in accelerometer to detect when G-forces exceed configured thresholds. Events are:

  • Detected in real-time during active trips via notifications
  • Stored on the beacon (up to 80 events in circular buffer)
  • Retrievable on-demand for synchronization with your backend

Event Types

enum class DrivingBehaviorType(val rawValue: Int) {
    HARSH_ACCELERATION(4),  // Excessive forward G-force
    HARSH_BRAKING(5),       // Excessive backward G-force (deceleration)
    HARSH_CORNERING(6),     // Excessive lateral G-force
    ACCIDENT(8)             // G-forces exceeding accident threshold
}
Event Description Default Threshold
Harsh Acceleration Rapid speed increase 0.25g (250 milli-Gs)
Harsh Braking Rapid deceleration 0.40g (400 milli-Gs)
Harsh Cornering Sharp turns 0.45g (450 milli-Gs)
Accident Collision detection Configured separately

Prerequisites

Before using driving behavior detection:

  1. Beacon must be paired - See Beacon Pairing
  2. Beacon must be calibrated - See Calibration
  3. Feature must be enabled - Disabled by default

Enable/Disable Feature

val bleManager = BLEManager.retrieveInstance(context)

// Enable driving behavior detection with all filters
bleManager.enableDrivingBehavior(beaconMac)

// Disable driving behavior detection
bleManager.disableDrivingBehavior(beaconMac)

The enable command sets:

  • Driving Behavior: Enabled
  • High Pass Filter: Enabled (removes gravity offset)
  • Low Pass Filter: Enabled (smooths readings)

Configuration

Reading Current Configuration

bleManager.requestDrivingBehaviorConfig(beaconMac)

// Handle configuration response
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
    override fun onDrivingBehaviorConfigReceived(
        beaconMac: String,
        config: DrivingBehaviorConfig
    ) {
        Log.d("DB", """
            Enabled: ${config.enabled}
            High Pass Filter: ${config.highPassFilterEnabled}
            Low Pass Filter: ${config.lowPassFilterEnabled}
            Cornering Threshold: ${config.corneringThreshold} mG
            Braking Threshold: ${config.brakingThreshold} mG
            Acceleration Threshold: ${config.accelerationThreshold} mG
            Duration Threshold: ${config.durationThreshold} ms
        """.trimIndent())
    }
}

// Register in onResume
override fun onResume() {
    super.onResume()
    IBFHelper.registerEventsReceiver(requireContext(), eventsReceiver)
}

Setting Thresholds

Configure detection sensitivity using threshold values in milli-Gs (1000 mG = 1g):

// Configure all thresholds at once
bleManager.configureDrivingBehaviorThresholds(
    beaconMac = beaconMac,
    corneringThreshold = 450,      // 0.45g - lateral G-force
    brakingThreshold = 400,        // 0.40g - deceleration
    accelerationThreshold = 250,   // 0.25g - acceleration
    durationThreshold = 500        // 500ms minimum duration
)

// Or set individual thresholds
bleManager.setCorneringThreshold(beaconMac, 500)    // 0.50g
bleManager.setBrakingThreshold(beaconMac, 350)      // 0.35g
bleManager.setAccelerationThreshold(beaconMac, 300) // 0.30g
bleManager.setDurationThreshold(beaconMac, 400)     // 400ms

Threshold Ranges

Parameter Min Max Default Unit
Cornering 50 5000 450 milli-Gs
Braking 50 5000 400 milli-Gs
Acceleration 50 5000 250 milli-Gs
Duration 1 10000 500 milliseconds

Note: Lower threshold values = more sensitive detection. Higher values = less sensitive.

Using DrivingBehaviorConfig

For complete control, use the DrivingBehaviorConfig data class:

val config = DrivingBehaviorConfig(
    enabled = true,
    highPassFilterEnabled = true,
    lowPassFilterEnabled = true,
    corneringThreshold = 450,
    brakingThreshold = 400,
    accelerationThreshold = 250,
    durationThreshold = 500
)

// Validate before writing
if (config.isValid()) {
    bleManager.writeDrivingBehaviorConfig(beaconMac, config)
}

Real-Time Events

During an active trip, the beacon sends immediate notifications when harsh driving is detected:

private val eventsReceiver = object : IBFHelper.EventsReceiver() {
    override fun onRealTimeDrivingBehaviorEvent(
        beaconMac: String,
        eventType: DrivingBehaviorType,
        timestamp: Long
    ) {
        Log.d("DB", "Real-time event: $eventType at $timestamp")

        when (eventType) {
            DrivingBehaviorType.HARSH_ACCELERATION -> {
                showWarning("Harsh acceleration detected!")
            }
            DrivingBehaviorType.HARSH_BRAKING -> {
                showWarning("Harsh braking detected!")
            }
            DrivingBehaviorType.HARSH_CORNERING -> {
                showWarning("Sharp turn detected!")
            }
            DrivingBehaviorType.ACCIDENT -> {
                showAlert("Potential collision detected!")
            }
        }
    }
}

Real-Time Event Properties

Property Type Description
beaconMac String MAC address of reporting beacon
eventType DrivingBehaviorType Type of event detected
timestamp Long Client timestamp (milliseconds)

Retrieving Stored Events

The beacon stores up to 80 driving behavior events in a circular buffer. Retrieve them for detailed analysis:

// Request stored events
bleManager.requestDrivingBehaviorEvents(beaconMac)

// Handle response
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
    override fun onDrivingBehaviorEventsReceived(
        beaconMac: String,
        events: ArrayList<DrivingBehaviorEvent>
    ) {
        Log.d("DB", "Received ${events.size} stored events")

        events.forEach { dbEvent ->
            Log.d("DB", """
                Index: ${dbEvent.recordIndex}
                Type: ${dbEvent.eventType}
                Time: ${Date(dbEvent.timestamp)}
                Duration: ${dbEvent.durationMs}ms
                Avg Magnitude: ${dbEvent.averageMagnitude}g
                Max Magnitude: ${dbEvent.maxMagnitude}g
                Avg X (lateral): ${dbEvent.averageX}g
                Avg Y (longitudinal): ${dbEvent.averageY}g
                Avg Z (vertical): ${dbEvent.averageZ}g
            """.trimIndent())
        }
    }
}

DrivingBehaviorEvent Properties

Property Type Description
recordIndex Int Buffer index (0-79)
eventType DrivingBehaviorType Event classification
timestamp Long Unix timestamp (milliseconds)
durationMs Int Event duration in milliseconds
averageMagnitude Float Average G-force magnitude
maxMagnitude Float Peak G-force magnitude
averageX Float Lateral G-force (side-to-side)
averageY Float Longitudinal G-force (forward/back)
averageZ Float Vertical G-force (up/down)
beaconMacAddress String Source beacon MAC

Clearing Events

After syncing events to your backend, clear them from the beacon:

// Clear all events
bleManager.clearAllDrivingBehaviorEvents(beaconMac)

// Or clear a specific event by index
bleManager.clearDrivingBehaviorEvent(beaconMac, index = 5)

// Handle confirmation
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
    override fun onDrivingBehaviorEventsClearConfirmed(
        beaconMac: String,
        clearedIndex: Int
    ) {
        if (clearedIndex == 0xFF) {
            Log.d("DB", "All events cleared")
        } else {
            Log.d("DB", "Event $clearedIndex cleared")
        }
    }
}

Axis Reference

The accelerometer measures G-forces on three axes:

Axis Direction Positive Value Example
X Lateral Right turn Sharp right corner
Y Longitudinal Forward Hard acceleration
Z Vertical Upward Speed bump

Note: The beacon must be properly calibrated for accurate axis measurements. See Calibration.


Best Practices

  1. Always calibrate first - Uncalibrated beacons produce inaccurate readings
  2. Start with default thresholds - Adjust based on real-world testing
  3. Consider vehicle type - Sports cars may need higher thresholds than sedans
  4. Enable both filters - High-pass removes gravity, low-pass smooths noise
  5. Clear events after sync - Prevent buffer overflow and duplicate processing
  6. Handle events gracefully - Real-time events may arrive rapidly during aggressive driving

Complete Example

class DrivingBehaviorFragment : Fragment() {

    private val bleManager by lazy { BLEManager.retrieveInstance(requireContext()) }
    private var currentBeaconMac: String? = null

    private val eventsReceiver = object : IBFHelper.EventsReceiver() {

        override fun onRealTimeDrivingBehaviorEvent(
            beaconMac: String,
            eventType: DrivingBehaviorType,
            timestamp: Long
        ) {
            // Handle real-time harsh driving alert
            Log.w("DB", "Alert: $eventType")
            showWarning(eventType)
        }

        override fun onDrivingBehaviorEventsReceived(
            beaconMac: String,
            events: ArrayList<DrivingBehaviorEvent>
        ) {
            // Process and sync events to backend
            lifecycleScope.launch {
                uploadToServer(events)
                // Clear after successful sync
                bleManager.clearAllDrivingBehaviorEvents(beaconMac)
            }
        }

        override fun onDrivingBehaviorConfigReceived(
            beaconMac: String,
            config: DrivingBehaviorConfig
        ) {
            Log.d("DB", "Config: $config")
            updateUI(config)
        }
    }

    override fun onResume() {
        super.onResume()
        IBFHelper.registerEventsReceiver(requireContext(), eventsReceiver)
    }

    override fun onPause() {
        super.onPause()
        IBFHelper.unregisterEventsReceiver(requireContext(), eventsReceiver)
    }

    fun setupDrivingBehavior(beaconMac: String) {
        currentBeaconMac = beaconMac

        // Enable feature with custom thresholds
        bleManager.enableDrivingBehavior(beaconMac)
        bleManager.configureDrivingBehaviorThresholds(
            beaconMac = beaconMac,
            corneringThreshold = 400,
            brakingThreshold = 350,
            accelerationThreshold = 300,
            durationThreshold = 500
        )
    }

    private fun showWarning(eventType: DrivingBehaviorType) {
        // Show UI alert
    }

    private suspend fun uploadToServer(events: ArrayList<DrivingBehaviorEvent>) {
        // Upload events to your backend
    }

    private fun updateUI(config: DrivingBehaviorConfig) {
        // Update UI with config
    }
}

Related Pages