Skip to main content

iOS SDK: Troubleshooting

Each entry starts from what your app sees, then gives the cause and what to do. The Getting started guide describes the normal flow. To compare your app's behaviour with a known-good one, run the same steps in the demo app from the SDK package: its event list shows every SDK callback with its error code.

The app stops on the first call to the SDK​

Symptom: the app ends the first time it calls BleService.getTerminal(terminalID:), with a message about privacy-sensitive data in the Xcode console.

Cause: that first call creates the SDK's Bluetooth manager, and iOS stops an app that uses Bluetooth without a usage description.

What to do: add NSBluetoothAlwaysUsageDescription to the app's Info.plist, with a sentence that tells the user why the app needs Bluetooth.

The terminal is not found although it is next to the phone​

Symptom: bleTerminalDidConnect(terminal:error:) reports terminalNotFound (7) once the timeout has passed, with the vehicle in range.

Cause and what to do:

  • The Bluetooth permission has not been answered yet (3.0.2 and earlier). Until the user answers the system prompt, iOS gives the app no Bluetooth at all, and the attempt waits out its timeout. From 3.0.4 such an attempt reports bluetoohUnauthorized (1) instead: see below. Connect once CBCentralManager.authorization is .allowedAlways.
  • The app is not on screen. The SDK looks for every Bluetooth device nearby, which iOS only allows in the foreground. Start the connection from a visible screen, for example when the user opens the vehicle screen. From 3.0.4 an app that declares bluetooth-central in UIBackgroundModes can also connect from the background, to a terminal that advertises the MiKey service.
  • Another phone is connected to the terminal. A terminal does not advertise while a phone is connected to it. Disconnect or close the other app.
  • The name does not match. The name passed to BleService.getTerminal(terminalID:) is trimmed, upper-cased and then compared exactly with the name the terminal advertises.
  • The timeout is too short for the scan to see the terminal. Keep the default of 10 seconds or more.

Connecting reports a Bluetooth permission the user never refused​

Symptom: from 3.0.4, bleTerminalDidConnect(terminal:error:) reports bluetoohUnauthorized (1) once the timeout has passed, although the user did not refuse Bluetooth.

Cause: the system's Bluetooth permission prompt was still unanswered when the attempt timed out. Until it is answered, iOS does not let the SDK look for the terminal.

What to do: ask the user to answer the prompt, then call connect() again. To avoid it, connect once CBCentralManager.authorization is .allowedAlways.

Lock succeeds, but the lock state still reads unlocked​

Symptom: bleTerminalDidAction(terminal:action:error:) reports .lock without an error, and terminal.lockState is still .unlocked, or the other way round.

Cause: the terminal accepted the command. Before answering, the SDK reads the lock state, which comes from an input of the vehicle: it can lag the command, and on some installations it is not wired at all.

What to do: treat a lock or unlock without an error as accepted by the terminal. To refresh the state, send .lockState again a moment later.

The connection reports an error while connected​

Symptom: bleTerminalDidConnect(terminal:error:) is called with ctgError(45, 23) well after the connection was reported, and bleTerminalDisconnected(terminal:) follows.

Cause: the SDK keeps the connection alive by asking the terminal every 7 seconds, and the terminal refused: the connection is over.

What to do: call connect() again.

No key on a new phone​

Symptom: connect() reports keyNotFound (5) after the user moved to a new phone or restored one from a backup.

Cause: from 3.0.2, the key never leaves the phone it was saved on, so backups do not carry it.

What to do: fetch the key from the Fleet API again and save it with saveAuthKey(authKey:).

A command reports a timeout​

Symptom: bleTerminalDidAction(terminal:action:error:) or bleTerminalDidGetVehicleStats(terminal:vehicleStats:error:) reports ctgError(actionCode, 22).

Cause: the terminal did not answer within the timeout passed to connect(timeout:), usually because the phone is moving out of range.

What to do: check the signal in bleTerminalSignalUpdate(rssi:strength:) and ask the user to move closer when it is .weak, then send the command again.