Docs / igloohome / BLE SDK / Fingerprint
Fingerprint
Enroll and remove fingerprints on Igloohome locks.
addFingerprint
Opens a BLE fingerprint registration window and returns a Flow of scan events. The lock requires 3 good reads to enroll a fingerprint (60-second timeout).
On successful enrollment, the SDK registers the fingerprint on the server. If server registration fails, the SDK automatically removes the fingerprint from lock hardware.
Signature
fun addFingerprint(
deviceId: String,
key: String,
name: String,
accessToken: String,
): Flow<FingerprintScanEvent>
func addFingerprint(
deviceId: String,
key: String,
name: String,
accessToken token: String
) async -> AsyncStream<FingerprintScanEvent>
Parameters
| Name |
Type |
Required |
Description |
deviceId |
String |
Yes |
Bluetooth device name of the lock. |
key |
String |
Yes |
Guest key with ADD_FINGERPRINT permission. |
name |
String |
Yes |
User-assigned name for the fingerprint. |
accessToken |
String |
Yes |
Access token for server calls. |
Return Type — FingerprintScanEvent
sealed class FingerprintScanEvent {
/** Good read recorded. More reads needed. */
data class ScanProgress(val attempt: Int, val total: Int) : FingerprintScanEvent()
/** Bad read. Prompt user to try again. */
class ScanError : FingerprintScanEvent()
/** Enrollment completed and registered on server. */
data class Completed(val accessId: String, val name: String) : FingerprintScanEvent()
/** Enrollment failed. */
data class Failed(val error: IglooHomeException) : FingerprintScanEvent()
}
enum FingerprintScanEvent {
/// A scan was captured, the user should place their finger on the sensor again.
case scanProgress(attempt: Int, total: Int)
/// The lock failed to read the fingerprint, the enrollment is stopped.
case scanError
/// Enrollment succeeded and the access is registered on the Iglooworks server.
case completed(accessId: String, name: String)
/// Enrollment failed with the given error.
case failed(error: any Error)
}
| Event |
Description |
ScanProgress(attempt, total) |
A good fingerprint scan. attempt = reads so far, total = 3. |
ScanError |
Bad read — finger not positioned correctly. Prompt to retry. |
Completed(accessId, name) |
All 3 reads successful. Fingerprint registered on server. |
Failed(error) |
Enrollment failed (timeout, disconnect, etc.). |
Example
try {
sdk.addFingerprint(
deviceId = "IGM4-XXXX",
key = guestKey,
name = "Right Thumb",
accessToken = accessToken,
).collect { event ->
when (event) {
is FingerprintScanEvent.ScanProgress ->
showProgress("Scan ${event.attempt}/${event.total}")
is FingerprintScanEvent.ScanError ->
showWarning("Bad read — try again")
is FingerprintScanEvent.Completed ->
showSuccess("Fingerprint enrolled: ${event.accessId}")
is FingerprintScanEvent.Failed -> {
when (event.error) {
is IglooHomeException.TimeoutException ->
showError("Timed out — place finger on sensor and try again")
is IglooHomeException.ConnectionException ->
showError("unexpected bluetooth connection issue")
else -> showError("Failed: ${event.error.message}")
}
}
}
}
} catch (e: IglooHomeException.BluetoothException) {
showError("Please enable Bluetooth")
} catch (e: IglooHomeException) {
showError("Fingerprint enrollment failed: ${e.message}")
}
let stream = await sdk.addFingerprint(
deviceId: "IGM4-XXXX",
key: guestKey,
name: "Right Thumb",
accessToken: accessToken)
var lastAttemp = 0, lastTotal = 0
for await event in stream {
switch event {
case let .scanProgress(attempt, total):
showProgress(
"Add Fingerprint",
message: "Scanning \(attempt)/\(total) — place the finger on the reader",
status: .warning)
case .scanError:
showProgress("Add Fingerprint", message: "Scan error, please try again", status: .failure)
case let .completed(accessId, name):
showProgress(
"Add Fingerprint",
message: "Fingerprint '\(name)' added. Access ID: \(accessId)",
status: .success)
case let .failed(error):
showProgress("Add Fingerprint", message: error.localizedDescription, status: .failure)
@unknown default:
showProgress("Add Fingerprint", message: "Unknown event", status: .failure)
}
}
Notes
- The lock requires exactly 3 good reads to enroll a fingerprint.
- Bad reads don't count toward the total — the user just tries again.
- The entire flow times out after 60 seconds.
- Errors are emitted as
Failed events rather than thrown as exceptions.
deleteFingerprint
Removes a fingerprint from the lock and deletes the server record.
The SDK fetches the fingerprint UID from the server, removes it from lock hardware via BLE, then deletes the server record.
Signature
suspend fun deleteFingerprint(
deviceId: String,
key: String,
accessId: String,
accessToken: String,
)
func deleteFingerprint(
deviceId: String,
key: String,
accessId: String,
accessToken token: String
) async throws
Parameters
| Name |
Type |
Required |
Description |
deviceId |
String |
Yes |
Bluetooth device name of the lock. |
key |
String |
Yes |
Guest key with DELETE_FINGERPRINT_UID permission. |
accessId |
String |
Yes |
Server-assigned access ID of the fingerprint to delete. |
accessToken |
String |
Yes |
Access token for server calls. |
Error Codes
| Exception |
Code |
Description |
BluetoothException |
708 |
Bluetooth is off or unavailable. |
ConnectionException |
12 |
Device disconnected during deletion. |
TimeoutException |
703 |
BLE operation exceeded the timeout. |
ApiException |
varies |
Server deletion failed. |
Example
try {
sdk.deleteFingerprint(
deviceId = "IGM4-XXXX",
key = guestKey,
accessId = "access-789",
accessToken = accessToken,
)
showSuccess("Fingerprint removed")
} catch (e: IglooHomeException.ConnectionException) {
showError("unexpected bluetooth connection issue")
} catch (e: IglooHomeException.TimeoutException) {
showError("Timed out, try again")
} catch (e: IglooHomeException) {
showError("Failed: ${e.message}")
}
do {
try await sdk.deleteFingerprint(
deviceId: "IGM4-XXXX",
key: guestKey,
accessId: "access-789",
accessToken: accessToken)
showSuccess(message: "Fingerprint removed")
} catch {
showError(message: "Failed: \(error.localizedDescription)")
}
Notes
- Server deletion retries up to 3 times with 1-second delays.
LockUidNotFoundException (980) during BLE delete is non-fatal — server record is still removed.