igloo
Docs / igloohome / BLE SDK / Linking

Linking

Link and unlink accessories (Keypads, Key Fobs, Bridges) to Igloohome locks.


Links an accessory to a lock. The SDK orchestrates server registration, cipher resolution, and BLE link command. If the BLE step fails, the server link is automatically rolled back.

Signature

suspend fun link(
    accessoryDeviceId: String,
    accessoryGuestKey: String,
    lockDeviceId: String,
    accessToken: String,
): LinkResult
func link(
    accessoryDeviceId: String,
    accessoryGuestKey: String,
    lockBluetoothDeviceName: String,
    accessToken token: String
) async throws -> LinkResult

Parameters

Name Type Required Description
accessoryDeviceId String Yes Bluetooth device name of the accessory (e.g. "EK1-XXXX").
accessoryGuestKey String Yes BLE key for the accessory. Keypad: ekey with ADD_LOCK permission. Fob: admin key.
lockDeviceId String Yes Bluetooth device ID of the lock to link to (e.g. "IGM4-XXXX").
accessToken String Yes Access token for server calls.

Return Type

data class LinkResult(
    val accessoryId: String,
    val lockId: String,
    val linkedAt: String,
)
public struct LinkResult {
    public let accessoryId: String
    public let lockId: String
    public let linkedAt: String
}

Error Codes

Exception Code Description
BluetoothException 708 Bluetooth is off or unavailable.
ConnectionException 12 Device disconnected during linking.
TimeoutException 703 BLE operation exceeded the timeout.
BridgeOfflineException 406 Bridge is offline (bridge link path).
ApiException varies Server API call failed.

Example

try {
    val result = sdk.link(
        accessoryDeviceId = "EK1-XXXX",
        accessoryGuestKey = ekeyWithAddLock,
        lockDeviceId = "IGM4-XXXX",
        accessToken = accessToken,
    )
    showSuccess("Linked ${result.accessoryId} to ${result.lockId}")
} catch (e: IglooHomeException.ConnectionException) {
    showError("unexpected bluetooth connection issue")
} catch (e: IglooHomeException.TimeoutException) {
    showError("Timed out, try again")
} catch (e: IglooHomeException) {
    showError("Link failed: ${e.message}")
}
do {
    let result = try await sdk.link(
        accessoryDeviceId: "EK1-XXXX",
        accessoryGuestKey: ekeyWithAddLock,
        lockBluetoothDeviceName: "IGM4-XXXX",
        accessToken: accessToken)
    showSuccess(message: "Linked \(result.accessoryId) to \(result.lockId)")
} catch {
    showError(message: "Link failed: \(error.localizedDescription)")
}

Unlinks an accessory from a lock. The SDK removes the link via BLE, then deletes the server record.

BLE errors 890 (PinNotFoundException) and 980 (LockUidNotFoundException) are treated as "already unlinked on the accessory side" — the SDK continues to remove the server link.

Signature

suspend fun unlink(
    accessoryDeviceId: String,
    accessoryGuestKey: String,
    lockDeviceId: String,
    accessToken: String,
)
func unlink(
    accessoryDeviceId: String,
    accessoryGuestKey: String,
    lockBluetoothDeviceName: String,
    accessToken token: String
) async throws

Parameters

Name Type Required Description
accessoryDeviceId String Yes Bluetooth device name of the accessory.
accessoryGuestKey String Yes BLE key for the accessory. Keypad: ekey with DELETE_LOCK permission. Fob: admin key.
lockDeviceId String Yes Bluetooth device ID of the lock to unlink from (e.g. "IGM4-XXXX").
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 unlinking.
TimeoutException 703 BLE operation exceeded the timeout.
BridgeOfflineException 406 Bridge is offline (bridge unlink path).
ApiException varies Server API call failed.

Example

try {
    sdk.unlink(
        accessoryDeviceId = "EK1-XXXX",
        accessoryGuestKey = ekeyWithDeleteLock,
        lockDeviceId = "IGM4-XXXX",
        accessToken = accessToken,
    )
    showSuccess("Accessory unlinked")
} catch (e: IglooHomeException.ConnectionException) {
    showError("unexpected bluetooth connection issue")
} catch (e: IglooHomeException.TimeoutException) {
    showError("Timed out, try again")
} catch (e: IglooHomeException) {
    showError("Unlink failed: ${e.message}")
}
do {
    try await sdk.unlink(
        accessoryDeviceId: "EK1-XXXX",
        accessoryGuestKey: ekeyWithDeleteLock,
        lockBluetoothDeviceName: "IGM4-XXXX",
        accessToken: accessToken)
    showSuccess(message: "Accessory unlinked")
} catch IgloohomeError.bridgeOffline {
    showError(message: "Bridge is offline — try again once it's back online")
} catch {
    showError(message: "Unlink failed: \(error.localizedDescription)")
}

Notes

  • Always unlink accessories before unpairing the lock — unpair() will throw HasLinkedDeviceException (Android) / IgloohomeError.hasLinkedDevice (iOS) if linked devices exist.
  • The accessory key type depends on the accessory type:
    • Keypad (EK1, EK2): Generate an ekey with appropriate permission via the ekey API.
    • Key Fob (IEF): Use the admin key from GET /devices/{device_id}/admin-key.
  • Bridge accessories ("EB1" prefix) are dispatched to a server-job link/unlink flow instead of a BLE flow — link/unlink work for Bridges, throwing BridgeOfflineException (Android) / IgloohomeError.bridgeOffline (iOS) if the Bridge is offline.