API v1

Checklist Sistemico

Android: FragmentSistemicList · FragmentSistemicSchedule · FragmentCadSistemic

Módulo de inspeção sistemica de equipamentos eletrônicos instalados nos veículos. Diferente do checklist veicular comum, opera sobre itens rastreadores/dispositivos IoT com estados binários lidos diretamente do backend. Exclusivo Android na versão atual.

Distinção: O Checklist Sistemico (/ui/sistemic/) é independente do Checklist Veicular (/ui/checklist/). Usa os mesmos endpoints /v1/checklist mas com filtro origin=sistemic implícito e modelo de dados diferente.

Fluxo de Navegação

1

FragmentSistemicList — nav_sistemic_list

Lista todos os checklists sistemicos com chips de filtro por status. Suporta retry automático com backoff exponencial para HTTP 429 (via SistemicHttpUtils.kt).

2

FragmentSistemicSchedule — nav_sistemic_schedule

Agendamento de novos checklists sistemicos. Permite selecionar veículo e data/hora de execução.

3

FragmentCadSistemic — nav_sistemic_cad

Visualização e execução do checklist. Exibe contagem regressiva ao vivo, métricas de progresso, filtros por estado dos itens e botão de ação contextual (Iniciar / Finalizar).

Máquina de Estado do Checklist

StatusLabelCorAção disponível
PPendenteOrangeIniciar (requer perm 423)
IIniciadoAzulFinalizar (qualquer usuário autenticado)
FFinalizadoVerdeSomente leitura
CCanceladoVermelhoSomente leitura

Estados dos Itens

stateLabelToneDescrição
"" (vazio)Aguardando leiturawarning / orangeItem ainda não avaliado — conta como pending nas métricas
"0"Com Problemadanger / redFalha genérica detectada
"1"Não Instaladowarning / orangeDispositivo não encontrado no veículo
"2"Com Problemadanger / redFalha com tipo específico (stateType)
"3"OKsuccess / greenItem verificado e aprovado
"4"Análise Humanainfo / azulRequer revisão manual por inspetor
"5"Não Verificadoneutral / cinzaFora do escopo desta inspeção
"9"Não AplicadoinfoItem não se aplica ao veículo

Tipos de problema para state = "2"

stateTypeLabel
"0"Ausência de Alerta
"1"Alerta Contínuo
"2"Falha Comunicação
"3"Não Atua

Lógica de Contagem Regressiva

Visível apenas para status P e I. O prazo (deadline) é calculado assim:

// Status P — prazo para iniciar
deadline = scheduleDatetime + 86400  // +24 horas

// Status I — prazo para concluir
deadline = startDatetime + 2400      // +40 minutos
         ?: scheduleDatetime + 86400 // fallback se startDatetime == null

O timer atualiza a cada segundo no UI thread via Handler(Looper.getMainLooper()). Quando remaining < 0 o contador exibe tempo expirado e o label muda para EXPIRADO.

Métricas de Progresso

Calculadas em computeMetrics() em SistemicModels.kt:

data class SistemicChecklistMetrics(
    val total: Int,
    val ok: Int,           // state == "3"
    val problem: Int,      // state in ["0", "2"]
    val notInstalled: Int, // state == "1"
    val notVerified: Int,  // state == "5"
    val notApplied: Int,   // state == "9"
    val pending: Int,      // state == "" (vazio)
)

val done  = ok + problem + notInstalled + notVerified + notApplied
val pct   = if (total > 0) done * 100 / total else 0
Atenção: Itens com state == "" (vazio) contam como pending e não entram no numerador done. O progresso só avança quando o item recebe qualquer estado explícito.

Permissões

CódigoAção protegida
423Iniciar checklist sistemico (botão "Iniciar" visível apenas com esta permissão)
// Leitura em SharedPreferences "DATA", chave "perms_user"
val permissionsJson = dataPrefs.getString("perms_user", "[]") ?: "[]"
hasPerm423 = permissionsJson.contains("423")

Filtros e Busca nos Itens

O SistemicItemAdapter.filter() aceita dois parâmetros combinados:

ChipstateFilterStates mapeados
OK"ok""3"
Pendente"pending""" (vazio)
Problema"problem""0", "2"
Análise"analysis""4"
(nenhum)nullTodos

A busca textual (etSearchItem) filtra pelo campo item.name com ignoreCase = true e é combinada com o filtro de chip em tempo real via TextWatcher.

Modelos de Dados

data class SistemicChecklist(
    val id: String,
    val plate: String,           // placa do veículo
    val status: String,          // "P" | "I" | "F" | "C"
    val statusLabel: String,
    val origin: String,
    val nameDoer: String,        // executor
    val nameApplicant: String,   // solicitante
    val scheduleDatetime: Long?, // Unix epoch (segundos)
    val startDatetime: Long?,
    val endDatetime: Long?,
    val registrationDatetime: Long?,
    val canStart: Boolean,
    val resultChecklist: List<SistemicChecklistItem>,
)

data class SistemicChecklistItem(
    val id: String,
    val name: String,
    val state: String,           // "" | "0".."9"
    val stateLabel: String,
    val stateTone: String,       // "success" | "danger" | "warning" | "neutral" | "info"
    val stateType: String,       // relevante apenas quando state == "2"
    val stateTypeLabel: String,
    val statusOn: Long?,         // Unix epoch (segundos)
    val statusOff: Long?,
    val acessorio: Boolean?,
    val datetime: Long?,         // última verificação
)
Timestamps: Todos os campos de data/hora são Unix epoch em segundos (Long). Converter para milissegundos ao usar Date(epochSeconds * 1000).

Endpoints

GET /v1/checklist
Lista checklists sistemicos. Filtrar por origin quando necessário. ViewModel aplica retry com backoff exponencial (1s → 2s → 4s, máx 30s) para HTTP 429.
GET /v1/checklist/{id}
Busca checklist sistemico por ID. Chamado em fetchChecklistById(id, token) em SistemicCadViewModel. Retorna o SistemicChecklist completo com resultChecklist preenchido.
POST /v1/checklist/{id}/start
Inicia o checklist (status P → I). Exige permissão 423. Exibe AlertDialog de confirmação antes de chamar viewModel.startChecklist(id, token).
POST /v1/checklist/{id}/finalize
Finaliza o checklist (status I → F). Após sucesso o fragment recarrega os dados automaticamente via fetchChecklistById.

Retry e Rate Limiting

A classe SistemicHttpUtils.kt implementa retry com backoff exponencial para absorver respostas HTTP 429 do backend:

// Sequência de delays: 1s → 2s → 4s → ...
// Máximo: 30 segundos de espera acumulada
// Máximo de tentativas: configurável no ViewModel
Padrão de chamadas paralelas: O módulo sistemico pode gerar múltiplas requisições simultâneas (lista + detalhes). Use o mecanismo de retry centralizado em SistemicHttpUtils — não implemente retry manual nos ViewModels.

Expand/Collapse de Itens

Cada item do RecyclerView é expansível. O estado é mantido em expandedIds: MutableSet<String> no adapter. Ao expandir, exibe:

  • Status On — momento em que o dispositivo ficou ativo
  • Status Off — momento em que o dispositivo ficou inativo
  • ResultadostateLabel com pill colorido
  • DetalhestateTypeLabel (relevante para state = "2")