Docs / igloohome / BLE SDK / Sync
Sync
Synchronize device state via Bluetooth.
sync
Syncs the lock via Bluetooth: sets the lock's internal clock, retrieves battery level, uploads activity logs, and updates the device on the server.
Signature
suspend fun sync(
deviceId: String,
key: String,
timeInSeconds: Long? = null,
getDeviceToken: String,
storeLogsToken: String,
updateDeviceToken: String,
operationId: Int? = null,
): SyncResult
@available(*, deprecated, message: "Use `syncWithStatus` instead")
func sync(
_ deviceId: String,
key: String,
getDeviceToken deviceToken: String,
storeLogsToken storeToken: String,
updateDeviceToken updateToken: String,
timeInSeconds time: Int? = nil
) async throws -> SyncResult
Parameters
| Name |
Type |
Required |
Description |
deviceId |
String |
Yes |
Bluetooth device name of the lock. |
key |
String |
Yes |
Guest key with GET_TIME, SET_TIME, GET_BATTERY_LEVEL, GET_LOGS permissions. |
timeInSeconds |
Long? |
No |
Unix timestamp (seconds) to set on the lock. If omitted, SDK uses last server time. |
getDeviceToken |
String |
Yes |
OAuth access token for fetching device info. |
storeLogsToken |
String |
Yes |
OAuth access token for uploading activity logs. |
updateDeviceToken |
String |
Yes |
OAuth access token for updating device state on the server. |
operationId |
Int? |
No |
Operation ID for tracking. |
Return Type
data class SyncResult(val batteryLevel: Int)
public struct SyncResult: Sendable {
public let batteryLevel: Int
}
| Field |
Description |
batteryLevel |
Battery level as percentage (0-100). |
Error Codes
| Exception |
Code |
Description |
BluetoothException |
708 |
Bluetooth is off or unavailable. |
ConnectionException |
12 |
Device disconnected during sync. |
TimeoutException |
703 |
BLE operation exceeded the timeout. |
ApiException |
varies |
Activity log upload or device update failed. |
Example
try {
val result = sdk.sync(
deviceId = "IGM4-XXXX",
key = guestKey,
getDeviceToken = accessToken,
storeLogsToken = accessToken,
updateDeviceToken = accessToken,
)
println("Battery: ${result.batteryLevel}%")
} catch (e: IglooHomeException.ConnectionException) {
showError("unexpected bluetooth connection issue")
} catch (e: IglooHomeException.TimeoutException) {
showError("Timed out, try again")
} catch (e: IglooHomeException) {
showError("Sync failed: ${e.message}")
}
// Deprecated on iOS — prefer syncWithStatus below.
do {
let result = try await sdk.sync(
"IGM4-XXXX",
key: guestKey,
getDeviceToken: accessToken,
storeLogsToken: accessToken,
updateDeviceToken: accessToken)
print("Battery: \(result.batteryLevel)%")
} catch {
showError(message: "Sync failed: \(error.localizedDescription)")
}
Notes
- Sync reads all pending activity logs from the lock in a loop until no more remain.
- Logs are stored in a local database first, then batch-uploaded to the server.
- If
timeInSeconds is omitted and no cached server time is available, the lock time is not updated.
- The three token parameters (
getDeviceToken, storeLogsToken, updateDeviceToken) can be the same token if it has all required scopes, or different tokens with scoped permissions.
syncWithStatus
Syncs the lock via Bluetooth and emits granular status updates for each sync operation. Useful for showing per-step progress in the UI.
Signature
fun syncWithStatus(
deviceId: String,
key: String,
timeInSeconds: Long? = null,
getDeviceToken: String,
storeLogsToken: String,
updateDeviceToken: String,
operationId: Int? = null,
): Flow<SyncResultStatus>
func syncWithStatus(
_ deviceId: String,
key: String,
getDeviceToken deviceToken: String,
storeLogsToken storeToken: String,
updateDeviceToken updateToken: String,
timeInSeconds time: Int? = nil
) -> AsyncStream<SyncResultStatus>
Parameters
| Name |
Type |
Required |
Description |
deviceId |
String |
Yes |
Bluetooth device name of the lock. |
key |
String |
Yes |
Guest key with GET_TIME, SET_TIME, GET_BATTERY_LEVEL, GET_LOGS permissions. |
timeInSeconds |
Long? |
No |
Unix timestamp (seconds) to set on the lock. If omitted, SDK uses last server time. |
getDeviceToken |
String |
Yes |
OAuth access token for fetching device info. |
storeLogsToken |
String |
Yes |
OAuth access token for uploading activity logs. |
updateDeviceToken |
String |
Yes |
OAuth access token for updating device state on the server. |
operationId |
Int? |
No |
Operation ID for tracking. |
Return Type
data class SyncResultStatus(
val operation: Operation,
val isSuccess: Boolean,
val error: IglooHomeException?,
) {
enum class Operation {
SET_TIME,
GET_BATTERY_LEVEL,
SYNC_ACTIVITY_LOGS,
}
}
public struct SyncResultStatus: Sendable {
public enum Operation: Sendable {
case SET_TIME
case GET_BATTERY_LEVEL
case SYNC_ACTIVITY_LOGS
}
public let operation: SyncResultStatus.Operation
public let isSuccess: Bool
public let error: Error?
}
| Field |
Description |
operation |
The sync sub-operation that completed. |
isSuccess |
true if the operation succeeded. |
error |
The exception if the operation failed, null on success. |
Example
try {
sdk.syncWithStatus(
deviceId = "IGM4-XXXX",
key = guestKey,
getDeviceToken = accessToken,
storeLogsToken = accessToken,
updateDeviceToken = accessToken,
).collect { status ->
val label = when (status.operation) {
SyncResultStatus.Operation.SET_TIME -> "Set time"
SyncResultStatus.Operation.GET_BATTERY_LEVEL -> "Battery level"
SyncResultStatus.Operation.SYNC_ACTIVITY_LOGS -> "Activity logs"
}
if (status.isSuccess) {
println("$label: OK")
} else {
println("$label: FAILED — ${status.error?.message}")
}
}
} catch (e: IglooHomeException.ConnectionException) {
showError("unexpected bluetooth connection issue")
} catch (e: IglooHomeException.BluetoothException) {
showError("Please enable Bluetooth")
} catch (e: IglooHomeException) {
showError("Sync failed: ${e.message}")
}
for await status in sdk.syncWithStatus(
"IGM4-XXXX",
key: guestKey,
getDeviceToken: accessToken,
storeLogsToken: accessToken,
updateDeviceToken: accessToken
) {
let label: String
switch status.operation {
case .SET_TIME: label = "Set time"
case .GET_BATTERY_LEVEL: label = "Battery level"
case .SYNC_ACTIVITY_LOGS: label = "Activity logs"
}
if status.isSuccess {
print("\(label): OK")
} else {
print("\(label): FAILED — \(status.error?.localizedDescription ?? "unknown")")
}
}
Notes
- Each
SyncResultStatus emission represents one completed sub-operation.
- Unlike
sync(), individual operation failures do not throw — they are reported via isSuccess = false and error.
- The flow emits one status per operation in order:
SET_TIME, GET_BATTERY_LEVEL, SYNC_ACTIVITY_LOGS.
- Use this method when you need to show per-step progress or handle partial sync failures gracefully.
- iOS doc comment notes: the stream finishes on the first failure, and battery level is not pushed to the server for Switch-type devices.