iOS SDK: Getting started
This guide explains how to install the Cartrack BLE Lock SDK for iOS and run the basic connection flow against a compatible BLE terminal.
Installation
- Add the CartrackBleLock.xcframework folder to your Xcode project.
- In Project Settings → Frameworks, Libraries, and Embedded Content, set CartrackBleLock.xcframework to Embed & Sign.
Overview
The Cartrack BLE Lock SDK provides a simple and secure way to:
- Connect to BLE-enabled vehicle terminals
- Lock and unlock vehicles remotely
- Control vehicle features (headlights, horn)
- Monitor vehicle status and statistics
- Receive real-time connection and signal strength updates
Core Components
BleService
The entry point for the SDK. Use BleService.getTerminal(terminalID:) to obtain a BleTerminal instance for interacting with a specific vehicle terminal.
BleTerminal
Provides direct interaction with a BLE terminal. Handles connection management, authentication, and command execution.
BleTerminalDelegate
Protocol for receiving callbacks from BLE terminal events, including connection state changes, action results, and vehicle statistics updates.
VehicleStats
Data model containing comprehensive vehicle statistics including odometer, fuel level, door states, and more.
Quick Start
All examples require
import CartrackBleLockSDKin the source file.Before connecting, initialize
BleTerminaland save the authentication key.Your class must conform to
BleTerminalDelegateto receive callbacks.
1. Initialize BleTerminal
Initialize BleTerminal variable to get an instance of BleTerminal and set the delegate:
var bleTerminal: BleTerminal
bleTerminal = BleService.getTerminal(terminalID: "SBS1234X")
bleTerminal.delegate = self
2. Save Authentication Key
Save the authentication key with BleTerminal.saveAuthKey(authKey:):
bleTerminal?.saveAuthKey(authKey: "<Authentication Key>")
The authentication key is saved in the keychain.
IMPORTANT: The authentication key must be saved before connecting to the BLE terminal.
The response for BleTerminal.saveAuthKey(authKey:) will be in BleTerminalDelegate.bleTerminalDidSavedKey(terminal:error:):
func bleTerminalDidSavedKey(terminal: BleTerminal, error: BleError?) {
if let error = error {
self.showMessage(title: "Save Key Failed", message: "\(error.errorCode) \(error.localizedDescription)")
} else {
self.showMessage(title: "Save Key Successful", message: "Successful save authentication key!")
}
}
3. Check Authentication Key
Check whether an authentication key exists in the keychain with BleTerminal.hasKey:
bleTerminal?.hasKey
Output:
trueorfalse
4. Get Authentication Key
Get the authentication key from the keychain with BleTerminal.authKey:
bleTerminal?.authKey
Output:
<Authentication Key>ornil
5. Connect to Ble Terminal
Connect to Ble Terminal with BleTerminal.connect():
bleTerminal?.connect()
By default
timeoutinBleTerminal.connect(timeout:)is 10 sec.
Alternatively, if you want to extend the timeout:
bleTerminal?.connect(timeout: 20)
BleTerminal.connect()andBleTerminal.connect(timeout:)are the same function. If the key exists in the keychain, the SDK sends the connect command to the terminal; otherwise it returnsBleError.keyNotFound.
The response for BleTerminal.connect(timeout:) will be in BleTerminalDelegate.bleTerminalDidConnect(terminal:error:):
func bleTerminalDidConnect(terminal: BleTerminal, error: BleError?) {
if let error = error {
showMessage(title: "Failed to connect", message: "\(error.errorCode) \(error.localizedDescription)")
} else {
showMessage(title: "Connect Successful", message: "")
}
}
6. Disconnect from Ble Terminal
Disconnect from Ble Terminal with BleTerminal.disconnect():
bleTerminal?.disconnect()
This function will send a disconnect command to the terminal.
The response for BleTerminal.disconnect() will be in BleTerminalDelegate.bleTerminalDisconnected(terminal:):
func bleTerminalDisconnected(terminal: BleTerminal) {
showMessage(title: "", message: "Disconnected")
}
7. Terminal Signal Update
Called periodically to update the BLE signal strength to Ble Terminal:
func bleTerminalSignalUpdate(rssi: Int, strength: BleSignalStrength) {
rssiLabel.text = "RSSI: \(rssi) dBm (\(strength))"
}
8. Remove Authentication Key
Remove the authentication key in the keychain with BleTerminal.removeAuthKey():
bleTerminal?.removeAuthKey()
Call this function when vehicle rental is done.
The authentication key in the keychain will be removed.
9. Send Ble Action to Terminal
Send lock action to terminal:
bleTerminal?.sendAction(.lock)
Send unlock action to terminal:
bleTerminal?.sendAction(.unlock)
Send headlight action to terminal:
bleTerminal?.sendAction(.headlight)
Send horn action to terminal:
bleTerminal?.sendAction(.horn)
Get the current state of vehicle's lock status - possible value - locked/unlocked:
bleTerminal?.sendAction(.lockState)
The default value of
BleTerminal.lockStateisLockState.unknown, sendBleAction.lockStateaction to refresh the state.
Send unlock with no key fob action to terminal:
bleTerminal?.sendAction(.unlockNoKeyFob)
Get the current state of vehicle's ignition status - possible value - on/off:
bleTerminal?.sendAction(.ignitionState)
The default value of
BleTerminal.ignitionStateisIgnitionState.unknown, sendBleAction.ignitionStateaction to refresh the state.
The response for all BleAction will be in BleTerminalDelegate.bleTerminalDidAction(terminal:action:error:):
func bleTerminalDidAction(terminal: BleTerminal, action: BleAction, error: BleError?) {
if let error = error {
showMessage(title: "Action Failed", message: "[\(error.actionCode)] get vehicle stats Failed\nReason: [\(error.errorCode)] \(error.localizedDescription)")
} else {
switch action {
case .lock:
showMessage(title: "Action", message: "Lock Action Success\nLock state: [\(terminal.lockState)]")
case .unlock:
showMessage(title: "Action", message: "Unlock Action Success\nLock state: [\(terminal.lockState)]")
case .horn:
showMessage(title: "Action", message: "Horn Action Success")
case .headlight:
showMessage(title: "Action", message: "Headlight Action Success")
case .lockState:
showMessage(title: "Action", message: "Vehicle's door is \(terminal.lockState)")
case .unlockNoKeyFob:
showMessage(title: "Action", message: "Unlock with No Key Fob Action Success\nLock state: [\(terminal.lockState)]")
case .ignitionState:
showMessage(title: "Action", message: "Vehicle's ignition state is \(terminal.ignitionState)")
@unknown default:
break
}
}
}
10. Get Vehicle Stats from Terminal
Send vehicle stats to Terminal:
bleTerminal?.getVehicleStats()
The response for BleTerminal.getVehicleStats() will be in BleTerminalDelegate.bleTerminalDidGetVehicleStats(terminal:vehicleStats:error:):
func bleTerminalDidGetVehicleStats(terminal: BleTerminal, vehicleStats: VehicleStats?, error: BleError?) {
if let error = error {
showMessage(title: "Action Failed", message: "[\(error.errorCode)] get vehicle stats Failed\nReason: \(error.localizedDescription)")
} else {
print(vehicleStats?.odometer)
print(vehicleStats?.fuelLevel)
}
}
API Reference
Core Classes
- BleService - SDK entry point
- BleTerminal - Terminal interaction interface
- VehicleStats - Vehicle statistics data model
Protocols
- BleTerminalDelegate - Event handling protocol
Enumerations
- BleAction - Available terminal actions
- BleConnectionState - Connection states
- BleSignalStrength - Signal strength levels
- BleError - Error types
- CtgError - Terminal-specific errors
- LockState - Vehicle lock states
- IgnitionState - Vehicle ignition states
- IndicatorState - Vehicle indicator states
Best Practices
Connection Management
- Always check
hasKeybefore attempting to connect - Use appropriate timeout values (default 10 seconds recommended)
- Handle disconnection events gracefully
Signal Strength Monitoring
- Monitor signal strength via
bleTerminalSignalUpdatedelegate method - Avoid sending actions when signal is
.weak - Prompt users to move closer to the vehicle when signal is poor
Error Handling
- Always handle errors in delegate callbacks
- Check for specific error types to provide better user feedback
- Use
error.localizedDescriptionfor user-facing error messages
Resource Cleanup
- Call
removeAuthKey()when rental period ends - Call
disconnect()when done with terminal interaction - Properly manage delegate lifecycle to avoid memory leaks
Next Steps
- Review the BleService documentation for SDK initialization
- Learn about BleTerminal methods and properties
- Understand BleTerminalDelegate callbacks
- Explore BleError handling strategies