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.