> For the complete documentation index, see [llms.txt](https://datamob.gitbook.io/doc-locator/TQfkVhcPsZiXIvXxq8Bv/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://datamob.gitbook.io/doc-locator/TQfkVhcPsZiXIvXxq8Bv/english/service.md).

# Reference

[< Voltar](https://github.com/ProcessosDatamob/Locator/blob/main/docs/en/README.md)

`LocatorService` é a **interface principal** do SDK Locator exposta para o APP e para bridges de WebView. Tudo que o APP precisa fazer com o SDK passa, direta ou indiretamente, por aqui.

***

## 4.1 Visão Geral

O `LocatorService` encapsula:

* Ciclo de vida do SDK (start, stop, destroy)
* Estado interno (modo, sessão, configuração atual)
* Sincronização com backend (config, grupos, features, cercas, scopes)
* Envio de dados (localizações e eventos)
* Execução de comandos (recebidos de APP, servidor, FCM, MQTT)
* Gerenciamento de permissões (o SDK sabe o que está pendente)

Fluxo macro esperado:

1. App cria/obtém uma instância concreta do SDK (`LocatorService`).
2. App registra uma implementação de `LocatorIntegration`.
3. App configura o SDK (license, URLs, etc) usando `setConfig`.
4. App chama `start()` para iniciar o SDK.
5. SDK sincroniza tudo (`syncAll` ou métodos de sync específicos).
6. SDK começa a coletar localizações, enviar dados e processar comandos.

***

## 4.2 Interface Completa

```ts
export interface LocatorService {
  // Integração
  registerIntegration(integration: LocatorIntegration): void;

  // Consultas (somente leitura)
  getConfig(): LocatorConfig;
  getGroups(): LocatorGroups;
  getFeatures(): LocatorFeatures;
  getGeofences(): LocatorGeofences;
  getState(): LocatorState;
  getSdkMode(): LocatorSdkMode;
  getSession(): LocatorSession;
  getVersion(): string;
  getJwtToken(): string;
  pendingPermissions(): LocatorPermission[];

  // Ciclo de vida
  start(correlation?: Record<string, string>): Promise<void>;
  stop(): Promise<void>;
  destroy(): Promise<void>;

  // Mutação de estado/configuração
  setConfig(config: LocatorConfig): void;
  setState(state: LocatorState, correlation?: Record<string, string>): void;
  setSdkMode(mode: LocatorSdkMode, correlation?: Record<string, string>): void;
  setGroups(groups: LocatorGroups): void;
  setFeatures(features: LocatorFeatures): void;
  setGeofences(geofences: LocatorGeofences, correlation?: Record<string, string>): void;

  // Sincronização com backend
  syncConfig(correlation?: Record<string, string>): Promise<void>;
  syncScopes(correlation?: Record<string, string>): Promise<void>;
  syncGroups(correlation?: Record<string, string>): Promise<void>;
  syncFeatures(correlation?: Record<string, string>): Promise<void>;
  syncGeofences(correlation?: Record<string, string>): Promise<void>;
  syncAll(correlation?: Record<string, string>): Promise<void>;

  // Envio de dados & comandos
  sendEvents(data: LocatorEventPackage, correlation?: Record<string, string>): Promise<void>;
  sendLocations(data: LocatorCollectPackage, correlation?: Record<string, string>): Promise<void>;
  execute(command: LocatorCommand, correlation?: Record<string, string>): Promise<LocatorCommandResult>;
}
```

#### 🟩 **Kotlin (Android)**

```kotlin
interface LocatorService {
    fun registerIntegration(integration: LocatorIntegration)
    
    fun getConfig(): LocatorConfig
    fun getGroup(): LocatorGroups
    fun getFeatures(): LocatorFeatures
    fun getGeofences(): LocatorGeofences
    fun getState(): LocatorState
    fun getSdkMode(): LocatorSdkMode
    fun getVersion(): String
    fun getSession(): LocatorSession
    fun getJwtToken(): String
    fun getJwtToken(correlation: Map<String, String>?): String
    fun pendingPermissions(): List<LocatorPermission>
    
    fun start()
    fun start(correlation: Map<String, String>?)
    fun stop()
    fun stop(correlation: Map<String, String>?)
    fun destroy()
    fun destroy(correlation: Map<String, String>?)
    
    fun setConfig(config: LocatorConfig)
    fun setConfig(config: LocatorConfig, correlation: Map<String, String>?)
    fun setState(state: LocatorState)
    fun setState(state: LocatorState, correlation: Map<String, String>?)
    fun setSdkMode(mode: LocatorSdkMode)
    fun setSdkMode(mode: LocatorSdkMode, correlation: Map<String, String>?)
    fun setGroup(groups: LocatorGroups)
    fun setGroup(groups: LocatorGroups, correlation: Map<String, String>?)
    fun setFeatures(features: LocatorFeatures)
    fun setGeofences(geofences: LocatorGeofences)
    fun setGeofences(geofences: LocatorGeofences, correlation: Map<String, String>?)
    
    fun syncConfig()
    fun syncConfig(correlation: Map<String, String>?)
    fun syncScopes()
    fun syncGroup()
    fun syncGroup(correlation: Map<String, String>?)
    fun syncFeatures()
    fun syncGeofences()
    fun syncGeofences(correlation: Map<String, String>?)
    fun syncAll()
    fun syncAll(correlation: Map<String, String>?)
    
    fun sendEvents(data: LocatorEventPackage)
    fun sendLocations(data: LocatorCollectPackage)
    fun execute(command: LocatorCommand): LocatorCommandResult
    
    fun setLogLevel(level: LocatorLogLevel, customTag: String? = null)
}
```

#### 🟧 **Swift (iOS)**

```swift
protocol LocatorService {
    // MARK: - Integração
    func registerIntegration(integration: LocatorIntegration)

    // MARK: - Consultas (somente leitura)
    func getConfig() -> LocatorConfig
    func getGroup() -> LocatorGroups
    func getFeatures() -> LocatorFeatures
    func getGeofences() -> LocatorGeofences
    func getState() -> LocatorState
    func getSdkMode() -> LocatorSdkMode
    func getVersion() -> String
    func getSession() -> LocatorSession
    func getJwtToken() -> String
    func pendingPermissions() -> [LocatorPermission]

    // MARK: - Ciclo de vida
    func start(correlation: [String: String]?) async throws
    func stop() async throws
    func destroy() async throws

    // MARK: - Sincronização com backend
    func syncConfig(correlation: [String: String]?) async throws
    func syncScopes(correlation: [String: String]?) async throws
    func syncGroups(correlation: [String: String]?) async throws
    func syncFeatures(correlation: [String: String]?) async throws
    func syncGeofences(correlation: [String: String]?) async throws
    func syncAll(correlation: [String: String]?) async throws

    // MARK: - Mutação de estado/configuração
    func setConfig(_ config: LocatorConfig)
    func setState(_ state: LocatorState, correlation: [String: String]?)
    func setSdkMode(_ mode: LocatorSdkMode, correlation: [String: String]?)
    func setGroups(_ groups: LocatorGroups)
    func setFeatures(_ features: LocatorFeatures)
    func setGeofences(_ geofences: LocatorGeofences, correlation: [String: String]?) async

    // MARK: - Envio de dados & comandos
    func sendEvents(_ data: LocatorEventPackage, correlation: [String: String]?) async throws
    func sendLocations(_ data: LocatorCollectPackage, correlation: [String: String]?) async throws
    func execute(_ command: LocatorCommand, correlation: [String: String]?) async throws -> LocatorCommandResult?

    // MARK: - Logging
    func setLogLevel(level: LocatorLogLevel)
}
```

> 💡 **iOS:** every method that takes `correlation: [String: String]?` ships with a **default overload** without the parameter (which internally calls the variant with `correlation: nil`). Existing call sites keep compiling untouched — adopt the `correlation:` variant only when you want to propagate distributed correlation context.

***

## 4.2.1 Correlation (Distributed Tracing)

As of version **1.2.7 (iOS)**, `LocatorService` accepts an optional `correlation: [String: String]?` parameter (`Map<String, String>?` on Android, `Record<string, string>` on TS) on every method that triggers backend traffic.

`correlation` is an **arbitrary dictionary** defined by the host APP (`{ "traceId": "...", "spanId": "...", "userJourney": "sos-button-tap" }`) that the SDK propagates **without interpreting** it:

| Channel                       | How `correlation` travels                                                                                                                                                                       |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **HTTP (LocatorIntegration)** | Included on the `correlation` field of the `LocatorRequestApi<T>` payload sent to `/cert`, `/token`, `/scopes`, `/config`, `/features`, `/groups`, `/geofences`, `/audio`.                      |
| **MQTT publish**              | JSON-encoded and attached as MQTT v5 **`correlationData`** property on `locator/collect/...`, `locator/event/...` and `locator/command/response/...` topics.                                    |
| **MQTT receive**              | The SDK reads `correlationData` from the incoming MQTT message and propagates it through the command pipeline. The MQTT response published by the command result reuses the same `correlation`. |

**When to use:**

* End-to-end tracking of a user journey (e.g. SOS button tap → audio upload → command acknowledgement).
* Joining logs from the APP, SDK, HTTP backend and MQTT broker under a single `traceId`.
* Carrying tracing context (W3C Trace Context, OpenTelemetry, Datadog APM, etc).

**When NOT to use:**

* To identify the request itself — that is what `id` (request id) and `sessionId` inside `LocatorRequestApi` are for.
* To carry sensitive data (PII, tokens) — `correlation` is only propagated, and may show up in logs.

***

## 4.3 Ciclo de Vida do SDK

### 4.3.1 `registerIntegration(integration: LocatorIntegration): void`

Registra a implementação de `LocatorIntegration` usada pelo SDK para acessar o backend.

* **Quem chama:** APP na inicialização.
* **Quando chamar:** antes de qualquer `start()` ou `sync*()`.

**Comportamento esperado:**

* Substitui qualquer implementação anterior.
* Não dispara chamadas de rede por si só.
* Pode validar minimamente a instância (ex: não aceitar `undefined`).

***

### 4.3.2 `start(correlation?): Promise<void>`

Inicia o SDK, incluindo:

* inicialização de sessão (`LocatorSession`)
* validação de permissões mínimas
* configuração de timers/foreground service (Android)
* conexão inicial com MQTT/WSS (conforme config)
* opcionalmente, um `syncAll()` (dependendo da implementação)

**Parâmetros:**

* `correlation` *(opcional, iOS 1.2.7+)* — dicionário propagado em todas as chamadas HTTP de inicialização (`getCert`, `getApiToken`, `getMqttToken`, `getWssToken`, `getConfig`, `getGeofences`) e em quaisquer mudanças de `state`/`mode` disparadas internamente. Ver [§4.2.1 Correlation](#421-correlation-distributed-tracing).

**Pré-requisitos recomendados:**

* `registerIntegration()` chamado
* `setConfig()` já configurado com `license`, `api`, `mqtt`, etc
* Permissões mínimas resolvidas (ou o SDK retorna em `pendingPermissions()` o que falta)

**Eventos esperados:**

* Pode disparar `SDKSTATE_CHANGED`
* Pode disparar `SDKMODE_CHANGED` (se modo default definido)
* Pode disparar eventos de erro se algo bloqueante falhar (ex: `PERMISSION_ERROR`)

***

### 4.3.3 `stop(): Promise<void>`

Para a coleta ativa e operações de rede, mas **mantém cache e certificados**.

* Desconecta de MQTT/WSS.
* Cancela timers de coleta / flush.
* Mantém:
  * certificados mTLS
  * tokens (até expirar)
  * configurações / caches locais

***

### 4.3.4 `destroy(): Promise<void>`

Desativa completamente o SDK para a licença corrente:

* Chama internamente um `stop()`.
* Remove:
  * certificados
  * tokens
  * caches de config, grupos, features, cercas
  * sessão ativa

Use quando:

* Usuário faz logout global
* Licença não é mais válida para aquele device
* APP precisa resetar estado

***

## 4.4 Leitura de Estado & Configurações

### 4.4.1 `getConfig(): LocatorConfig`

Retorna a última `LocatorConfig` conhecida pelo SDK.

* Fonte: `setConfig()` ou `syncConfig()`.
* Pode estar **desatualizada** se o app nunca sincronizou.

**Uso típico:**

* Mostre ao desenvolvedor / devtools.
* Para debug: inspecionar intervalos e política de coleta.

***

### 4.4.2 `getGroups(): LocatorGroups`

Retorna:

* `admin[]`: grupos com permissão elevada.
* `all[]`: todos os grupos que impactam visibilidade/coleta.

Fonte: `setGroups()` ou `syncGroups()`.

***

### 4.4.3 `getFeatures(): LocatorFeatures`

Lista de features habilitadas para a licença no dispositivo.

* Cada `LocatorFeature` pode conter `scopes`.
* O SDK **não deve ativar** features que exijam scopes não presentes.

***

### 4.4.4 `getGeofences(): LocatorGeofences`

Retorna todas as cercas conhecidas pelo SDK.

* Não significa que todas estão ativas — depende dos `groups`.
* Atualizado via `setGeofences()` ou `syncGeofences()`.

***

### 4.4.5 `getState(): LocatorState`

Estado atual do SDK:

* `DEFAULT`, `IDLE`, `COLLECTING`, `PAUSED`, `STOPPED`.

**Diferença chave:**

* `STOPPED`: pós-`stop()`, sem coleta.
* `PAUSED`: SDK ativo, mas coleção inibida temporariamente.
* `COLLECTING`: coleta ativa e agendada.

***

### 4.4.6 `getSdkMode(): LocatorSdkMode`

Modo de operação atual, ex:

* `DEFAULT`: modo normal
* `OBSERVED`: foco em rastreio, mais agressivo
* `SOS`: modo de emergência
* `ALERT`: modo de atenção

O modo afeta:

* Intervalo de coleta e envio
* Política de bateria
* Critérios de retenção offline

***

### 4.4.7 `getSession(): LocatorSession`

Sessão atual do SDK:

```ts
export interface LocatorSession {
  id: string;
  startAt: number;
  endAt?: number;
}
```

#### 🟩 **Kotlin (Android)**

```kotlin
data class LocatorSession(
    val id: String,
    val startAt: Long, // epoch ms
    val endAt: Long? = null // epoch ms
)
```

#### 🟧 **Swift (iOS)**

```swift
struct LocatorSession {
    let id: String
    let startAt: Int64
    let endAt: Int64?
}
```

* `id`: identificador único por ciclo de `start()`.
* `endAt`: preenchido em `stop()`/`destroy()`.

Pode ser usado para:

* Correlacionar eventos/locais no backend.
* Auditoria/telemetria.

***

### 4.4.8 `getVersion(): string`

Versão do SDK em execução.

* Ex: `"1.2.3"` ou `"1.2.3-android"`.

Ideal para:

* Logging no app
* Envio de metadata para ferramentas de crash

***

### 4.4.9 `getJwtToken(): string`

Retorna o **último JWT válido** conhecido pelo SDK.

* Normalmente JWT\_API.
* Pode ser usado por WebViews ou módulos externos que precisem do token gerenciado pelo SDK.

⚠️ Cuidados:

* Use apenas se o contrato do produto permitir o compartilhamento.
* Renove token via `LocatorIntegration.getToken()` quando necessário (SDK pode cuidar disso internamente).

***

### 4.4.10 `pendingPermissions(): LocatorPermission[]`

Retorna a lista de permissões **ainda não concedidas**, segundo os requisitos do SDK.

Possíveis valores (sob `LocatorPermission`):

* `location_fine`
* `location_coarse`
* `location_background`
* `activity_recognition`
* `body_sensors`
* `battery_optimization`

#### 🟩 **Kotlin (Android)**

```kotlin
  LOCATION_FINE = "location_fine",
  LOCATION_COARSE = "location_coarse",
  LOCATION_BACKGROUND = "location_background",
  ACTIVITY_RECOGNITION = "activity_recognition",
  BODY_SENSORS = "body_sensors",
  BATTERY_OPTIMIZATION = "battery_optimization",
  FOREGROUND_SERVICE = "foreground_service"
  FOREGROUND_SERVICE_LOCATION = "foreground_service_location"
  ACCESS_NETWORK_STATE = "access_network_state"
```

#### 🟧 **Swift (iOS)**

```swift
CRITICAL_ALERT = "critical_alert"
LOCATION = "location"
LOCATION_BACKGROUND = "location_background"
MICROPHONE_ACCESS = "microphone_access"
POST_NOTIFICATIONS = "post_notifications"
```

**Uso sugerido:**

* Antes de chamar `start()`, pergunte ao SDK.
* Se a lista **não estiver vazia**, o app deve abrir o fluxo de permissão.

***

## 4.5 Mutação de Estado & Configuração

### 4.5.1 `setConfig(config: LocatorConfig): void`

Aplica a configuração do SDK para a licença nesta instância.

**Responsabilidades:**

* Salvar `config` em storage interno.
* Comparar `revision` (se existente) para identificar alteração.
* Reconfigurar:
  * MQTT (broker, clientId, username, etc)
  * Política de coleta (intervalos, batch size)
  * Política de retry

**Momento recomendado de uso:**

* Na ativação, após `getConfig()` via backend.
* Quando backend informar nova `revision`.

***

### 4.5.2 `setState(state, correlation?): void`

Força mudança de estado operacional do SDK.

**Parâmetros:**

* `state` — novo estado (`COLLECTING`, `PAUSED`, `STOPPED`, etc).
* `correlation` *(opcional, iOS 1.2.7+)* — propagado para os eventos MQTT disparados pela mudança de estado (ex.: quando o SDK ao entrar em `COLLECTING` aciona internamente `ModeManager.start`, que dispara um publish MQTT).

Exemplos de uso:

* `IDLE` quando usuário está logado mas sem coleta ativa.
* `PAUSED` quando usuário pausa temporariamente localização.
* `COLLECTING` quando app quer garantir coleta imediata.

***

### 4.5.3 `setSdkMode(mode, correlation?): void`

Altera o **modo lógico** do SDK (observed, SOS, alert, etc).

**Parâmetros:**

* `mode` — novo modo do SDK.
* `correlation` *(opcional, iOS 1.2.7+)* — propagado para todos os efeitos colaterais do modo (publishes MQTT, requests internas). Em modo `SOS`, é o `correlation` que viaja com o upload de áudio para `/audio` e com as respostas MQTT de comandos do fluxo de SOS.

Impactos típicos:

* `SOS`: coleta com intervalos menores, prioridade alta.
* `POWER_SAVER` (via `LocatorPowerMode`) pode combinar com certos modos.

**O SDK deve**:

* Ajustar timers de coleta/envio de acordo com o modo.
* Disparar `LocatorEventType.SDKMODE_CHANGED`.

***

### 4.5.4 `setGroups(groups: LocatorGroups): void`

Aplica a lista de grupos no SDK, impactando:

* Tópicos MQTT monitorados
* Geofences ativas (somente de grupos presentes)
* Regras de visibilidade

***

### 4.5.5 `setFeatures(features: LocatorFeatures): void`

Aplica features, considerando:

* `feature.feature` (identificador)
* `feature.scopes` (se presentes)

O SDK deve:

* Verificar se os scopes exigidos estão presentes (`getScopes()` / cache interno).
* Ativar/desativar internamente o código associado.

***

### 4.5.6 `setGeofences(geofences: LocatorGeofences): void`

Atualiza a lista de cercas conhecida pelo SDK.

* Deve registrar/desregistrar monitoramento de geofences nativas (OS).
* Considerar `groupId` + `LocatorGroups` para determinar quais cercas ativar.

***

### 4.5.7 `setLogLevel(level: LocatorLogLevel): void`

Configures the minimum log level emitted by the SDK at runtime. The SDK starts in `LocatorLogLevel.NONE` (silent) until the integrator opts in.

**Signatures:**

* **🟦 TypeScript:** `setLogLevel(level: LocatorLogLevel): void` *(if exposed on the bridge)*
* **🟩 Kotlin (Android):** `fun setLogLevel(level: LocatorLogLevel, customTag: String? = null)` — optional `customTag` overrides the default logcat tag.
* **🟧 Swift (iOS, 1.2.7+):** `func setLogLevel(level: LocatorLogLevel)`

**Behavior:**

* Inclusive filter: a call with `WARN` emits `WARN` and `ERROR` only; `INFO` and `DEBUG` are suppressed.
* `NONE` silences everything (default).
* Idempotent — safe to call multiple times across the SDK lifecycle (even before `start()`).
* Local-only configuration: nothing is sent to the backend, no MQTT publish, no correlation propagation.

**iOS specifics:**

* Levels are mapped to Apple Unified Logging (`os.log`) via the subsystem `br.com.vivo.locator`, with one `OSLog` category per level (`Debug`, `Info`, `Warn`, `Error`, `None`).
* The same level is forwarded to the embedded MQTT client (`MQTT.Logger.level`), so MQTT diagnostics follow the configured verbosity.
* Visible via Console.app, `log stream --subsystem br.com.vivo.locator`, or attached via Xcode debugger.

**Android specifics:**

* Defaults to logcat under the SDK tag, or to `customTag` when provided.
* `ERROR` callsites that pass a `Throwable` emit the stacktrace via `Log.e(tag, msg, t)`.

**Recommended usage:**

```swift
// iOS — enable verbose logging during development
locator.setLogLevel(level: .debug)

// Silence everything in production (default, no-op call)
locator.setLogLevel(level: .none)
```

```kotlin
// Android — verbose with a custom tag during QA
locator.setLogLevel(level = LocatorLogLevel.DEBUG, customTag = "LocatorQA")
```

> ⚠️ Avoid leaving `DEBUG` enabled in release builds: payload/config dumps may include sensitive data (tokens, license, geofence coordinates).

***

## 4.6 Sincronização com Backend

### 4.6.1 `syncConfig(correlation?): Promise<void>`

**Parâmetros:**

* `correlation` *(opcional, iOS 1.2.7+)* — propagado para a chamada `LocatorIntegration.getConfig` e para o payload HTTP correspondente.

Fluxo típico:

1. SDK monta `LocatorRequestApiConfig` com:
   * `license`
   * `sessionId`
   * `sdkVersion`
   * `osPlatform`
   * `timestamp`
2. Chama `LocatorIntegration.getConfig`.
3. Recebe `LocatorResponseApiConfig`.
4. Chama internamente `setConfig()`.

***

### 4.6.2 `syncScopes(): Promise<void>`

Assíncrono, mas fundamental para RBAC.

* SDK chama `LocatorIntegration.getScopes`.
* Atualiza cache de scopes.
* Revalida features ativas (`setFeatures` interno).

***

### 4.6.3 `syncGroups(): Promise<void>`

* Atualiza `LocatorGroups` via `getGroups()`.
* Ajusta tópicos MQTT e geofences ativas.

***

### 4.6.4 `syncFeatures(): Promise<void>`

* Chama `getFeatures()`.
* Aplica features novas.
* Desativa features removidas.

***

### 4.6.5 `syncGeofences(): Promise<void>`

* Chama `getGeofences()`.
* Atualiza monitoramento de geofences.

***

### 4.6.6 `syncAll(correlation?): Promise<void>`

**Parâmetros:**

* `correlation` *(opcional, iOS 1.2.7+)* — propagado para **todas** as chamadas HTTP encadeadas pelo sync completo. Útil para juntar a janela de sincronização inteira sob um único `traceId`.

Sincronização completa em ordem controlada, por exemplo:

1. `syncConfig()`
2. `syncScopes()`
3. `syncGroups()`
4. `syncFeatures()`
5. `syncGeofences()`

Deve:

* Tratar erro parcial.
* Aplicar backoff quando necessário.
* Disparar eventos `*_SYNCED`:
  * `CONFIGS_SYNCED`
  * `SCOPES_SYNCED`
  * `GROUPS_SYNCED`
  * `FEATURES_SYNCED`
  * `GEOFENCES_SYNCED`

***

## 4.7 Envio de Dados

### 4.7.1 `sendEvents(data, correlation?): Promise<void>`

Envia um pacote de eventos para o backend via MQTT (ou outro canal interno).

**Parâmetros:**

* `data` — `LocatorEventPackage` contendo os eventos.
* `correlation` *(opcional, iOS 1.2.7+)* — anexado ao publish MQTT como propriedade `correlationData` (MQTT v5). Ver [§4.2.1](#421-correlation-distributed-tracing).

`LocatorEventPackage`:

```ts
export interface LocatorEventPackage extends LocatorPackage<LocatorEvent> {}
```

#### 🟩 **Kotlin (Android)**

```kotlin
TODO
```

#### 🟧 **Swift (iOS)**

```swift
TODO
```

**Responsabilidades do SDK:**

* Garantir preenchimento de:
  * `id` (pacote)
  * `license`
  * `sessionId`
  * `connectivity`
  * `network`
  * `osPlatform`
  * `sdkVersion`
  * `timestamp`
* Enfileirar caso offline (respeitando `offlineRetentionDays`).
* Tratar `retryPolicy`.

***

### 4.7.2 `sendLocations(data, correlation?): Promise<void>`

Semelhante a `sendEvents`, mas para localizações (`LocatorCollect`).

**Parâmetros:**

* `data` — `LocatorCollectPackage`.
* `correlation` *(opcional, iOS 1.2.7+)* — anexado ao publish MQTT do tópico `locator/collect/...` como `correlationData`.

**Idealmente:**

* O APP não chama isso diretamente, é responsabilidade interna do SDK.
* Caso seja exposto, é para casos avançados de manual send / flush forçado.

***

## 4.8 Execução de Comandos

### 4.8.1 `execute(command, correlation?): Promise<LocatorCommandResult>`

Executa um comando enviado por:

* APP (chamada direta)
* FCM (payload interpretado pelo APP → SDK)
* MQTT (comandos recebidos de backend e repassados internamente)

**Parâmetros:**

* `command` — `LocatorCommand` a ser executado.
* `correlation` *(opcional, iOS 1.2.7+)* — propagado para todas as chamadas HTTP/MQTT geradas durante a execução do comando. Quando o comando chega via MQTT, o SDK extrai automaticamente o `correlationData` da mensagem recebida e usa esse valor no publish da `LocatorCommandResult`.

`LocatorCommand`:

* `type`: `LocatorCommandType`
* `requiresInternet`: se `true`, não executa offline
* `priority`: `LocatorPriority`
* `expiresAt`: TTL do comando

**Exemplos de tipos:**

* `SET_SDK_MODE`
* `SET_POWER_MODE`
* `START_SDK`
* `STOP_SDK`
* `SYNC_*`
* `KEEP_ALIVE`

**Responsabilidades do SDK:**

* Validar `expiresAt` (não executar comando expirado).
* Respeitar `requiresInternet`.
* Tratar idempotência se necessário (via `command.id`).
* Retornar `LocatorCommandResult` com:
  * `status`: `SUCCESS | FAILED | ERROR`
  * `errorCode` se aplicável
  * `attempts`, `startAt`, `endAt`, `timestamp`

**Exemplo: comportamento típico de alguns comandos**

* `SET_SDK_MODE` → chama internamente `setSdkMode()`.
* `SYNC_CONFIG` → chama `syncConfig()`.
* `SYNC_ALL` (se existir no futuro) → chama `syncAll()`.

***

## 4.9 Fluxo típico de uso (APP)

### 4.9.1 Ativação da licença

1. APP obtém `license` e JWT inicial.
2. APP cria `LocatorIntegrationImpl`.
3. APP chama `locatorService.registerIntegration(integration)`.
4. APP chama `locatorService.syncAll()` ou:
   * `syncConfig`
   * `syncGroups`
   * `syncFeatures`
   * `syncGeofences`
5. APP chama `locatorService.start()`.

***

## 4.10 Exemplos de Uso — TypeScript (React Native/Web)

```ts
import {
  LocatorService,
  LocatorIntegration,
  LocatorConfig,
  LocatorSdkMode,
} from "./locator-sdk";

const locatorService: LocatorService = createLocatorService(); // implementação concreta

class MyLocatorIntegration implements LocatorIntegration {
  async getCert(p) {
    /* ... */
  }
  async getToken(p) {
    /* ... */
  }
  async getScopes(p) {
    /* ... */
  }
  async getFeatures(p) {
    /* ... */
  }
  async getConfig(p) {
    /* ... */
  }
  async getGroups(p) {
    /* ... */
  }
  async getGeofences(p) {
    /* ... */
  }
}

export async function initLocator() {
  const integration = new MyLocatorIntegration();
  locatorService.registerIntegration(integration);

  // Sync inicial
  await locatorService.syncAll();

  // Start SDK
  await locatorService.start();

  // Verificar permissões
  const pending = locatorService.pendingPermissions();
  if (pending.length > 0) {
    // abrir telas de permissão no app
  }

  // Mudar modo para observado
  locatorService.setSdkMode(LocatorSdkMode.OBSERVED);
}
```

***

## 4.11 Exemplos de Uso — Kotlin (Android)

```kotlin
class AppLocatorManager(
    private val locator: LocatorService,
    private val integration: LocatorIntegration
) {

    suspend fun initialize() {
        locator.registerIntegration(integration)

        // Sincronização inicial
        locator.syncAll()

        val pending = locator.pendingPermissions()
        if (pending.isNotEmpty()) {
            // abrir UI pedindo permissões
        }

        // Start do SDK
        locator.start()
    }

    suspend fun enableSosMode() {
        locator.setSdkMode(LocatorSdkMode.SOS)
    }

    suspend fun pauseTracking() {
        locator.setState(LocatorState.PAUSED)
    }

    suspend fun fullStop() {
        locator.stop()
    }

    suspend fun logoutAndDestroy() {
        locator.destroy()
    }
}
```

***

## 4.12 Exemplos de Uso — Swift (iOS)

```swift
final class LocatorManager {

    private let locator: LocatorService
    private let integration: LocatorIntegration

    init(locator: LocatorService, integration: LocatorIntegration) {
        self.locator = locator
        self.integration = integration
    }

    func initialize() async throws {
        locator.registerIntegration(integration)

        try await locator.syncAll()
        try await locator.start()

        let pending = locator.pendingPermissions()
        if !pending.isEmpty {
            // apresentar telas de permissão
        }
    }

    func setObservedMode() {
        locator.setSdkMode(.OBSERVED)
    }

    func stopSdk() async throws {
        try await locator.stop()
    }

    func destroySdk() async throws {
        try await locator.destroy()
    }
}
```

***

## 4.13 Resumo da Parte 4

Nesta parte documentamos completamente:

* Todos os métodos do `LocatorService`
* Como cada método se relaciona com:
  * ciclo de vida
  * sincronização
  * envio de dados
  * execução de comandos
  * permissões
* Fluxos típicos de uso (ativação, modo SOS, pausa, logout)
* Exemplos em TypeScript, Kotlin e Swift

## Correlation (`correlation` parameter)

The 13 methods with remote side-effects accept `correlation: Map<String, String>? = null` (Kotlin) / `Record<string, string>?` (TypeScript) / `[String: String]?` (Swift) as an optional final parameter.

### Methods that accept correlation

`setConfig`, `setSdkMode`, `setGroup`, `setGeofences`, `setState`, `getJwtToken`, `start`, `stop`, `destroy`, `syncConfig`, `syncGroup`, `syncGeofences`, `syncAll`.

### Methods that do NOT accept correlation

* `registerIntegration`, `getConfig`, `getGroup`, `getFeatures`, `getGeofences`, `getState`, `getSdkMode`, `getVersion`, `getSession`, `pendingPermissions`, `setFeatures`, `setLogLevel` — local read or local config, no remote emit.
* `syncScopes`, `syncFeatures` — deprioritized in BTC-1938 matrix (do not emit to BE currently).
* `sendEvents`, `sendLocations`, `execute` — correlation travels via MQTT 5 `correlationData` (not in payload). No facade parameter.

### Semantics

* `correlation = null` (default): publish/request goes **without** correlation; field omitted from wire (MQTT 5 property omitted; HTTP `Data.correlation` absent).
* `correlation = emptyMap()` (`mapOf()`): publish/request goes with **empty object** (`{}` UTF-8 bytes in MQTT; `Data.correlation = {}` in HTTP). Distinguishable from `null`.
* `correlation = mapOf("k" to "v", ...)`: keys are sorted alphabetically during serialization (deterministic — same Map produces identical bytes).

### No ambient fallback (G5)

Correlation only travels when explicitly passed by the caller. **No snapshot** of "session" or "active operation". Internal workers always emit without correlation.

### Java legacy compatibility

Android SDK methods have explicit overloads without the `correlation` parameter to preserve Java ABI. Existing callers continue to compile unchanged.

Starting in **v2.2.0**, the non-`correlation` overloads of the 13 public methods (introduced in 2.1.2) were declared **explicitly on the `LocatorService` interface**. This ensures Java callers can call both `service.setSdkMode(LocatorSdkMode.SOS)` and `sdk.setSdkMode(LocatorSdkMode.SOS)` without casting and without any changes to pre-existing code.

Before v2.2.0, the non-`correlation` overload existed only as a shim on the concrete `LocatorSDK` class — Java callers holding a reference typed as `LocatorService` would need to cast to the concrete type or pass `null` explicitly. This ABI gap is now closed.

Kotlin callers are unaffected (Kotlin already resolved the default argument).

### `registerServiceErrorListener(listener: (Exception) -> Unit)`

> Available from **v2.2.0**. This method belongs to the `LocatorSDK` class (not the `LocatorService` interface) — invoke it via the concrete instance returned by `LocatorSDK.initialize(...)` or `LocatorSDK.getInstance()`.

Registers a listener for **asynchronous** errors during the SDK lifecycle. Useful for capturing failures that do not reach the caller via exception (because they happen inside the SDK's internal coroutines).

Covered cases:

* Failure to fetch the certificate during `start()` — when `LocatorSDKCertificateNotReadyException` (code `LOC_SDK_105`) is thrown inside `sdkScope.scopedLaunch`, the listener receives the exception.
* Failure to initialize `LocationForegroundService` (e.g., eligibility gate denied, Android 14+ FGS-BG-start restriction).
* Other asynchronous failures reported via `LocatorSDK.notifyServiceError(error)` internally.

#### Signature

```kotlin
fun registerServiceErrorListener(listener: (Exception) -> Unit)
```

#### Example

```kotlin
val sdk = LocatorSDK.initialize(context = applicationContext)
sdk.registerServiceErrorListener { error ->
    Log.e("App", "SDK async error: ${error.message}", error)
    // e.g., surface to crash reporter, retry start(), etc.
}
sdk.setConfig(config = config)
sdk.start()
```

### Exceptions

| Class                                        | Code              | When it is thrown                                                                                                                                                                                |
| -------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `LocatorSDKNotInitializedException`          | LOC\_SDK\_101     | `getInstance()` called before `initialize()`.                                                                                                                                                    |
| `LocatorSDKNoConfigSetException`             | LOC\_SDK\_102     | `start()` called without a prior `setConfig()` (blank license).                                                                                                                                  |
| `LocatorSDKMissingPermissionsException`      | LOC\_SDK\_103     | `start()` called without the main location permissions.                                                                                                                                          |
| `LocatorSDKMissingAudioPermissionsException` | LOC\_SDK\_104     | `setSdkMode(SOS)` when RECORD\_AUDIO (and/or FOREGROUND\_SERVICE\_MICROPHONE on API 34+) is not granted.                                                                                         |
| **`LocatorSDKCertificateNotReadyException`** | **LOC\_SDK\_105** | **(new in 2.2.0)** `start()` called, but the certificate is not available within the 15 s timeout. Also reported to `registerServiceErrorListener` when thrown inside the SDK's coroutine scope. |
| `LocatorSDKGetFeaturesException`             | —                 | `getFeatures()` fails when querying the integrator.                                                                                                                                              |
| `LocatorSDKGetGeofencesException`            | —                 | `getGeofences()` fails when querying the local repository.                                                                                                                                       |

[< Voltar](https://github.com/ProcessosDatamob/Locator/blob/main/docs/en/README.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://datamob.gitbook.io/doc-locator/TQfkVhcPsZiXIvXxq8Bv/english/service.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
