igloo
Docs / iglooworks / 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? = null,
): 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? OAuth only OAuth 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: IglooWorksException) : FingerprintScanEvent()
}
public enum FingerprintScanEvent {
    case scanProgress(attempt: Int, total: Int)
    case scanError
    case completed(accessId: String, name: String)
    case failed(error: 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",
    ).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 IglooWorksException.TimeoutException ->
                        showError("Timed out — place finger on sensor")
                    is IglooWorksException.ConnectionException ->
                        showError("unexpected bluetooth connection issue")
                    else -> showError("Failed: ${event.error.message}")
                }
            }
        }
    }
} catch (e: IglooWorksException.BluetoothException) {
    showError("Please enable Bluetooth")
} catch (e: IglooWorksException) {
    showError("Fingerprint enrollment failed: ${e.message}")
}
let stream = await sdk.addFingerprint(
    deviceId: "IGM4-XXXX",
    key: guestKey,
    name: "Right Thumb",
    accessToken: accessToken)
for await event in stream {
    switch event {
    case let .scanProgress(attempt, total):
        showProgress(message: "Scanning \(attempt)/\(total) — place the finger on the reader")
    case .scanError:
        showWarning(message: "Bad read — try again")
    case let .completed(accessId, name):
        showSuccess(message: "Fingerprint '\(name)' enrolled: \(accessId)")
    case let .failed(error):
        showError(message: error.localizedDescription)
    }
}

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? = null,
)
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? OAuth only OAuth 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",
    )
    showSuccess("Fingerprint removed")
} catch (e: IglooWorksException.ConnectionException) {
    showError("unexpected bluetooth connection issue")
} catch (e: IglooWorksException.TimeoutException) {
    showError("Timed out, try again")
} catch (e: IglooWorksException) {
    showError("Delete 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, Android) / IglooworksError.lockUidNotFound (iOS) during BLE delete is non-fatal — server record is still removed.