SwiftOBD2

repository·main·Indexed 41 days ago

https://github.com/kkonteh97/swiftobd2

A Swift package for iOS and macOS applications to communicate with vehicles via ELM327 OBD2 adapters over Bluetooth or Wi-Fi. It provides tools for real-time sensor monitoring using OBDService, scanning for Diagnostic Trouble Codes (DTCs), and retrieving vehicle status. The library utilizes Combine for continuous data updates and supports the OBDCommand and OBDServiceDelegate abstractions for managing the connection lifecycle and ECU requests.

Tokens
1.8K
Snippets
3
Records
10
Agent score
1%

What's inside SwiftOBD2

  1. How OBDService, OBDServiceDelegate, and OBDCommand work together

    main

    SwiftOBD2 is built around three core abstractions:

    • OBDService: The central engine of the package. It manages the connection lifecycle (Bluetooth or Wi-Fi), handles adapter initialization, and processes vehicle data.
    • OBDServiceDelegate: A protocol used to receive lifecycle events and updates regarding the connection state (e.g., transitioning from disconnected to connectedToAdapter or connectedToVehicle).
    • OBDCommand: Represents specific requests sent to the vehicle's ECU (Engine Control Unit). These commands (like .mode1(.rpm)) are used to request specific Parameter IDs (PIDs).
  2. Important Implementation Considerations

    main

    When integrating SwiftOBD2 into your application, keep these requirements in mind:

    • Hardware: You must have a compatible ELM327 OBD2 adapter.
    • Permissions: If using Bluetooth, your app must request Bluetooth permissions from the user.
    • Error Handling: Implement robust error handling to manage potential communication issues between the app, adapter, and vehicle.
    • Background Updates: If your app requires OBD2 data updates while in the background, you must implement iOS background fetch capabilities and tune your app/library usage accordingly.
  3. Install SwiftOBD2 via Swift Package Manager

    main

    To use SwiftOBD2 in your Xcode project, add it as a dependency using the following URL:

    1. In Xcode, go to File > Add Packages...
    2. Enter the repository URL: https://github.com/kkonteh97/SwiftOBD2/
    3. Select your desired dependency rule (version, branch, or commit).
    https://github.com/kkonteh97/SwiftOBD2/
  4. Implement a ViewModel for OBD2 data

    main

    When building a SwiftUI application, it is recommended to use an ObservableObject ViewModel to manage the OBDService and its data.

    Key patterns include:

    1. Observing Connection State: Use Combine to bind obdService.$connectionState to a @Published property in your ViewModel.
    2. Managing Updates: Use startContinuousUpdates(_:) which returns a Combine publisher. Store the resulting subscription in a Set<AnyCancellable>.
    3. Dynamic PID Management: Use addPID(command:) to add new PIDs to the polling cycle after the initial connection is established.
    class ViewModel: ObservableObject {
        @Published var measurements: [OBDCommand: MeasurementResult] = [:]
        @Published var connectionState: ConnectionState = .disconnected
        var cancellables = Set<AnyCancellable>()
    
        let obdService = OBDService(connectionType: .bluetooth)
    
        init() {
            obdService.$connectionState
                .assign(to: &$connectionState)
        }
    
        func startContinousUpdates() {
            obdService.startContinuousUpdates([.mode1(.rpm)])
                .sink { completion in
                    print(completion)
                } receiveValue: { measurements in
                    self.measurements = measurements
                }
                .store(in: &cancellables)
        }
    
        func addPID(command: OBDCommand) {
            obdService.addPID(command)
        }
    
        func startConnection() async throws {
            let obd2info = try await obdService.startConnection(preferedProtocol: .protocol6)
            print(obd2info)
        }
    
        func stopConnection() {
            obdService.stopConnection()
        }
    }
  5. Quick Start: Connect and retrieve real-time data

    main

    You can get started quickly by initializing an OBDService with a connection type, starting the connection, and subscribing to continuous updates using Combine.

    import SwiftOBD2
    
    let obdService = OBDService(connectionType: .bluetooth)
    let obd2Info = try await obdService.startConnection()
    
    // Get real-time data for RPM and Speed
    obdService.startContinuousUpdates([.mode1(.rpm), .mode1(.speed)])
        .sink { measurements in
            print("RPM: \(measurements[.mode1(.rpm)]?.value ?? 0)")
            print("Speed: \(measurements[.mode1(.speed)]?.value ?? 0)")
        }
  6. Configure Bluetooth permissions for SwiftOBD2

    main

    If your application uses Bluetooth to connect to an OBD2 adapter, you must configure the following in your Xcode project:

    1. Info.plist: Add the NSBluetoothAlwaysUsageDescription key with a description explaining why your app requires Bluetooth access.
    2. Signing & Capabilities:
      • Add the Background Modes capability.
      • Enable the Uses Bluetooth LE Accessories option.
  7. Troubleshoot Bluetooth and Data connection issues

    main

    If you encounter issues while using SwiftOBD2, check the following common scenarios:

    Bluetooth Connection Failures

    • Ensure Bluetooth permissions are granted in iOS Settings.
    • Verify your ELM327 adapter is in pairing mode.
    • Try restarting Bluetooth on your device.

    No Data Received from Vehicle

    • Confirm the vehicle is OBD2 compatible (1996+ in US).
    • Ensure the ELM327 adapter is properly connected to the OBD2 port.
    • Verify the vehicle is running (some data requires the engine to be on).

    App Crashes on Connection

    • Update to the latest version of SwiftOBD2.
    • Ensure you have added the required Bluetooth permissions to your project's Info.plist.
  8. Retrieve vehicle diagnostics and status

    main

    Beyond real-time sensor data, OBDService provides methods for vehicle health diagnostics:

    • scanForTroubleCodes(): Retrieves Diagnostic Trouble Codes (DTCs) stored in the vehicle's OBD-II system.
    • getStatus(): Retrieves the overall status of the vehicle's onboard systems (specifically status since the last DTC clear).
  9. Verify Hardware Compatibility

    main

    SwiftOBD2 is designed to work with ELM327 adapters.

    Tested ELM327 Adapters:

    • BAFX Products Bluetooth OBD2
    • OBDLink MX+ Bluetooth
    • VEEPEAK Mini WiFi OBD2

    Known Limitations:

    • Cheap ELM327 clones may experience connectivity issues.
    • WiFi adapters require specific network configuration.