Skip to content

iOS SBeacon Framework Driving Behavior

AigarsM edited this page Feb 2, 2026 · 1 revision

Driving Behavior

iOS SBeacon Framework v1.0.8

This guide covers driving behavior event detection, configuration, and data retrieval from SBeacon devices.


Overview

SBeacon devices can detect harsh driving events including acceleration, braking, cornering, and accidents. Events are stored in beacon memory (up to 80 events) and can be retrieved, configured, and cleared via BLE.


Prerequisites


Event Types

DrivingBehaviorEventType Enum

public enum DrivingBehaviorEventType: UInt8 {
    case acceleration = 4  // Harsh acceleration (forward)
    case braking = 5       // Harsh braking (deceleration)
    case cornering = 6     // Harsh cornering (lateral)
    case accident = 8      // Collision/impact
}

Detection Axes:

  • Acceleration/Braking: Y-axis (longitudinal, forward/backward)
  • Cornering: X-axis (lateral, side-to-side)
  • Accident: Any axis (resultant magnitude)

DrivingBehaviorEvent Model

public struct DrivingBehaviorEvent {
    let index: UInt8              // Record index (0-79)
    let eventType: DrivingBehaviorEventType
    let timestamp: UInt32         // Beacon timestamp (seconds)
    let duration: UInt16          // Event duration (milliseconds)
    let avgMagnitude: Float       // Average G-force
    let maxMagnitude: Float       // Maximum G-force
    let avgX: Float               // Average X-axis (G)
    let avgY: Float               // Average Y-axis (G)
    let avgZ: Float               // Average Z-axis (G)
    var actualTimestamp: Int64?   // Real-world time (ms)
    var actualDate: Date?         // Computed date
    var durationSeconds: TimeInterval // Duration in seconds
}

Retrieving Driving Behavior Events

Request All Events

import BLEFramework

func fetchDrivingBehaviorEvents(for beacon: SCPBeacon) {
    // Set callback
    SBeaconManager.shared.drivingBehaviorEventsReceived = { [weak self] events in
        print("Received \(events.count) driving behavior events")
        self?.processDrivingBehaviorEvents(events)
    }

    // Request events
    SBeaconManager.shared.requestDrivingBehaviorEvents(beacon: beacon)
}

private func processDrivingBehaviorEvents(_ events: [DrivingBehaviorEvent]) {
    for event in events {
        guard let date = event.actualDate else { continue }

        print("Event \(event.index): \(event.eventType.description)")
        print("  Date: \(date)")
        print("  Max G-force: \(String(format: "%.2f", event.maxMagnitude))G")
        print("  Duration: \(event.duration)ms")
        print("  Axis values: X=\(event.avgX), Y=\(event.avgY), Z=\(event.avgZ)")

        // Upload to server
        uploadEvent(event)
    }
}

Clearing Events

Clear Specific Event

// Clear event at index 5
SBeaconManager.shared.clearDrivingBehaviorEvent(index: 5, beacon: beacon)

Clear All Events

// Clear all stored events from beacon memory
SBeaconManager.shared.clearAllDrivingBehaviorEvents(beacon: beacon)

Best Practice: Clear events after successfully uploading to server to free beacon memory.


Real-Time Event Detection

Real-Time Callback

Events detected during active trips trigger instant notifications:

SBeaconManager.shared.realTimeDrivingBehaviorEventDetected = { [weak self] event in
    print("REAL-TIME EVENT: \(event.eventType.description)")
    print("Axis: \(event.axis.description)")

    // Show alert, play sound, update UI, etc.
    self?.handleRealTimeEvent(event)
}

RealTimeDrivingBehaviorEvent Model

public struct RealTimeDrivingBehaviorEvent {
    let eventType: DrivingBehaviorEventType
    let axis: DrivingBehaviorAxis  // x, y, z, or radial
    let flags: UInt8               // Additional flags
}

Configuration

Detection Thresholds

G-Force Thresholds

Configure sensitivity for each event type:

Event Type Range (mG) Range (G) Default
Cornering 50 - 5000 0.05 - 5.0 300 mG (0.3G)
Braking 50 - 5000 0.05 - 5.0 400 mG (0.4G)
Acceleration 50 - 5000 0.05 - 5.0 350 mG (0.35G)

Unit: Milli-G (1000 mG = 1 G)

Duration Threshold

Minimum event duration to record:

  • Range: 1 - 10000 milliseconds
  • Default: 500 ms
  • Purpose: Filter out brief vibrations/bumps

Set Individual Thresholds

// Set cornering threshold to 300 mG (0.3G)
SBeaconManager.shared.setCorneringThreshold(300, beacon: beacon)

// Set braking threshold to 400 mG (0.4G)
SBeaconManager.shared.setBrakingThreshold(400, beacon: beacon)

// Set acceleration threshold to 350 mG (0.35G)
SBeaconManager.shared.setAccelerationThreshold(350, beacon: beacon)

// Set minimum duration to 500 ms
SBeaconManager.shared.setDurationThreshold(500, beacon: beacon)

Batch Configuration

Apply complete configuration at once:

import BLEFramework

let config = DrivingBehaviorConfig(
    corneringThreshold: 300,     // 0.3G
    brakingThreshold: 400,        // 0.4G
    accelerationThreshold: 350,   // 0.35G
    durationThreshold: 500,       // 500ms
    enableFlagsValue: DrivingBehaviorConfig.enableAllValue
)

SBeaconManager.shared.applyDrivingBehaviorConfig(config, beacon: beacon)

Enable/Disable Detection

// Enable all driving behavior detection
SBeaconManager.shared.enableDrivingBehavior(true, beacon: beacon)

// Disable all driving behavior detection
SBeaconManager.shared.enableDrivingBehavior(false, beacon: beacon)

Read Current Configuration

// Read enable flags
SBeaconManager.shared.drivingBehaviorEnableFlagsReceived = { enableFlags in
    print("Cornering enabled: \(enableFlags.corneringEnabled)")
    print("Braking enabled: \(enableFlags.brakingEnabled)")
    print("Acceleration enabled: \(enableFlags.accelerationEnabled)")
}

SBeaconManager.shared.readDrivingBehaviorEnableFlags(beacon: beacon)

// Read individual thresholds
SBeaconManager.shared.readCorneringThreshold(beacon: beacon)
SBeaconManager.shared.readBrakingThreshold(beacon: beacon)
SBeaconManager.shared.readAccelerationThreshold(beacon: beacon)
SBeaconManager.shared.readDurationThreshold(beacon: beacon)

Complete Example

import SwiftUI
import BLEFramework

class DrivingBehaviorViewModel: ObservableObject {
    @Published var events: [DrivingBehaviorEvent] = []
    @Published var corneringThreshold: UInt16 = 300
    @Published var brakingThreshold: UInt16 = 400
    @Published var accelerationThreshold: UInt16 = 350
    @Published var isEnabled = false

    private let beacon: SCPBeacon

    init(beacon: SCPBeacon) {
        self.beacon = beacon
        setupCallbacks()
    }

    func setupCallbacks() {
        SBeaconManager.shared.drivingBehaviorEventsReceived = { [weak self] events in
            self?.events = events
        }

        SBeaconManager.shared.realTimeDrivingBehaviorEventDetected = { [weak self] event in
            self?.handleRealTimeEvent(event)
        }

        SBeaconManager.shared.drivingBehaviorEnableFlagsReceived = { [weak self] enableFlags in
            self?.isEnabled = enableFlags.enabled
        }
    }

    func fetchEvents() {
        SBeaconManager.shared.requestDrivingBehaviorEvents(beacon: beacon)
    }

    func clearAllEvents() {
        SBeaconManager.shared.clearAllDrivingBehaviorEvents(beacon: beacon)
        events.removeAll()
    }

    func applyConfiguration() {
        let config = DrivingBehaviorConfig(
            corneringThreshold: corneringThreshold,
            brakingThreshold: brakingThreshold,
            accelerationThreshold: accelerationThreshold,
            durationThreshold: 500,
            enableFlagsValue: isEnabled ? DrivingBehaviorConfig.enableAllValue : 0
        )

        SBeaconManager.shared.applyDrivingBehaviorConfig(config, beacon: beacon)
    }

    func toggleEnabled() {
        isEnabled.toggle()
        SBeaconManager.shared.enableDrivingBehavior(isEnabled, beacon: beacon)
    }

    private func handleRealTimeEvent(_ event: RealTimeDrivingBehaviorEvent) {
        // Show notification, play sound, etc.
        print("REAL-TIME: \(event.eventType.description) on \(event.axis.description)")
    }

    deinit {
        SBeaconManager.shared.drivingBehaviorEventsReceived = nil
        SBeaconManager.shared.realTimeDrivingBehaviorEventDetected = nil
        SBeaconManager.shared.drivingBehaviorEnableFlagsReceived = nil
    }
}

Best Practices

  1. Always Calibrate First: Uncalibrated beacons produce inaccurate G-force readings
  2. Set Appropriate Thresholds: Too sensitive = false positives, too high = missed events
  3. Clear After Upload: Free beacon memory by clearing synced events
  4. Handle Real-Time Events: Provide immediate feedback to drivers
  5. Batch Configuration: Use applyDrivingBehaviorConfig() for multiple settings
  6. Validate Thresholds: Framework validates range (50-5000 mG)
  7. Monitor Battery: Frequent event detection drains battery faster

Troubleshooting

No Events Detected

Solutions:

  • Ensure beacon is calibrated (beacon.isCalibrated == true)
  • Check detection is enabled
  • Verify thresholds aren't too high
  • Confirm beacon is mounted correctly in vehicle

Inaccurate G-Force Values

Solutions:

  • Recalibrate beacon on flat surface
  • Check beacon mounting orientation (ISO8855 standard)
  • Verify beacon isn't loose/vibrating

Events Not Retrieved

Solutions:

  • Check beacon is connected
  • Verify drivingBehaviorEventsReceived callback is set
  • Ensure beacon has events (check count first)

Related Pages

Clone this wiki locally