1Fontes de Dados
Omnilink
Rastreador telemétrico instalado fisicamente em cada veículo. Gera automaticamente um registro por ciclo contendo: data e hora (DD/MM/AAAA HH:MM:SS), velocidade instantânea (km/h), latitude e longitude (WGS-84). Os dados são transmitidos ao servidor Omnilink e exportados para planilha eletrônica sem intervenção humana — cada linha representa um evento real gerado pelo hardware embarcado.
TMS
Sistema de Gestão de Transportes da empresa. Registra cada viagem com: filial emissora, número do MDF-e (Manifesto Eletrônico de Documentos Fiscais — SEFAZ), motorista, placa do veículo de tração, UF de carregamento, UF de descarregamento, peso total da carga (kg), valor total da mercadoria (R$) e valor do frete (R$). Os registros TMS são cruzados com os dados GPS para confirmar o trajeto real declarado fiscalmente.
Planilha Google Sheets
Cada aba segue o padrão PLACA MêsPorExtenso Ano (ex: NWM2G94 Janeiro 2025). O backend detecta e processa automaticamente todas as abas neste formato — nenhuma configuração é necessária ao adicionar novos meses ou novas placas. Uma aba separada chamada TMS armazena os dados de viagem do sistema de gestão.
2Arquitetura do Sistema
O sistema é composto por duas camadas independentes e auditáveis:
Backend — Google Apps Script (Code.gs)
Script publicado como Web App no Google Workspace, executado nos servidores do Google. Lê a planilha Omnilink diretamente, processa todos os registros GPS, aplica os algoritmos de classificação de jornada e retorna um objeto JSON estruturado via requisição HTTP. O endpoint principal retorna dados agregados por placa e dia; o endpoint ?action=posicoes retorna as coordenadas brutas para visualização no mapa.
Frontend — HTML/CSS/JavaScript (arquivo único)
Dashboard executado no navegador, sem servidor próprio. Carrega os dados do Apps Script via fetch() assíncrono e renderiza os gráficos, tabelas e mapas localmente. Bibliotecas utilizadas: Chart.js 4.4 (gráficos de barras empilhadas e linhas), Leaflet.js 1.9.4 (mapa de rota GPS interativo com OpenStreetMap), fontes Manrope e JetBrains Mono via Google Fonts. Em caso de falha de conectividade, o sistema opera em modo demonstrativo com dados embutidos, garantindo funcionamento offline.
3Detecção de Movimento — Método Timestamp + Coordenada
O Omnilink pode registrar velocidade = 0 km/h mesmo quando o veículo está em deslocamento — falha de transmissão documentada no modelo utilizado. Para eliminar esta inconsistência, o sistema abandona o campo velocidade como critério primário de classificação e utiliza exclusivamente a combinação de timestamp + coordenadas GPS, que são gerados diretamente pelo receptor GNSS do hardware e não estão sujeitos à mesma falha.
Para cada par de registros consecutivos (A → B):
Δt = tB − tA // tempo real entre registros (minutos)
Δd = haversine(latA, lonA, latB, lonB) // distância real percorrida (km)
velts = Δd ÷ (Δt ÷ 60) // velocidade média auditável do trecho (km/h)
Δd ≥ 150 m → todo o intervalo Δt é classificado como movimento, com velocidade média velts. Este dado é irrefutável: decorre diretamente das coordenadas e do relógio do hardware, independentemente do campo velocidade registrado.
Δd < 150 m → todo o intervalo Δt é classificado como parado. O GPS confirma imobilidade independentemente do valor no campo velocidade. O limiar de 150 m é conservador e filtra o drift estático normal do sinal GNSS em condições de repouso (tipicamente 5–30 m).
Quando velts indica movimento mas o Omnilink havia registrado velocidade = 0, o campo gpsEstimado = true é marcado no dia, sinalizando a correção aplicada.
4Cálculo de Distância — Fórmula de Haversine
Distância geodésica entre dois pontos na superfície terrestre, considerando a curvatura do elipsoide WGS-84. Utilizada em 100% dos cálculos de Δd deste sistema. A precisão é da ordem de metros para as distâncias típicas do transporte rodoviário nacional (50–1500 km), tornando o erro geodésico desprezível para fins trabalhistas.
a = sin²(Δlat/2) + cos(latA) · cos(latB) · sin²(Δlon/2)
c = 2 · atan2(√a, √(1−a))
d = R · c // R = 6.371 km — raio médio da Terra (WGS-84)
5Tratamento de Lacunas de Sinal
Quando o intervalo entre dois pings consecutivos supera 30 minutos — limiar configurável via LACUNA_MINUTOS — o intervalo é tratado como lacuna de cobertura (área sem sinal celular, dispositivo temporariamente desligado ou falha de transmissão). A mesma regra do Δd é aplicada:
Δd < 150 m → o veículo permaneceu no mesmo ponto durante toda a lacuna: 100% do intervalo = parado.
Δd ≥ 150 m → GPS confirma deslocamento durante a lacuna. O tempo de movimento é estimado usando a mediana das velts reais do mesmo corredor de rota (cache histórico — ver item 6). Na ausência de histórico do corredor, usa-se a mediana das velts registradas no próprio dia. O tempo restante é classificado como parado — critério conservador que não infla o tempo de trabalho.
Dias com lacuna recebem o indicador LACUNA na aba Jornada por Dia e o campo temLacuna = true no JSON exportado, garantindo rastreabilidade completa.
6Cache de Velocidades por Corredor de Rota
Para resolver lacunas com deslocamento confirmado, o sistema aprende automaticamente a velocidade média real de cada corredor geográfico a partir dos dados do próprio veículo. Cada segmento normal (Δt ≤ 30 min, Δd ≥ 150 m, velts entre 5 e 150 km/h) alimenta um cache indexado por grade geográfica de 1° (~110 km) — suficiente para identificar o corredor viário sem revelar o trajeto exato.
chave = ⌊latA⌉, ⌊lonA⌉ → ⌊latB⌉, ⌊lonB⌉ // grade de 1° arredondada
cache[chave].push(velts) // acumula amostras reais
vel_ref = mediana(cache[chave]) // robusta a outliers
A mediana é preferida à média aritmética por ser robusta a outliers (congestionamentos esporádicos, paradas imprevistas). O cache completo é exportado no JSON sob a chave rotasAprendidas, com número de amostras, mediana, velocidade mínima e máxima de cada corredor — permitindo auditoria pericial independente.
7Apuração do Período Noturno
O adicional noturno incide sobre os minutos de movimento classificados entre 22h00 e 05h00, conforme Art. 73 da CLT. O cálculo utiliza a hora exata de cada registro Omnilink — sem estimativas — por meio de função analítica de complexidade O(1) que computa os minutos noturnos em qualquer intervalo sem iterar minuto a minuto.
Segmentos que cruzam a meia-noite (23h→01h, por exemplo) são divididos por dia calendário antes do cômputo, garantindo que os minutos noturnos sejam corretamente atribuídos a cada dia. Cada dia exibe o total acumulado na coluna H.Noturno da aba Jornada por Dia.
8Apuração CLT — Jornada, Extras e Intervalo Intrajornada
CLT
Os seguintes artigos da Consolidação das Leis do Trabalho são aplicados automaticamente sobre os dados GPS de cada dia, com base nos minutos de movimento apurados:
Art. 58 — Jornada normal máxima de 8h (480 min) por dia. Base de comparação para apuração de excedentes e cálculo do índice de conformidade exibido na Análise Geral.
Art. 59 — Horas extras: minutos de movimento acima de 480 min/dia. Sinalizados como +HE na aba Jornada por Dia. O limite legal de 2h extras/dia (120 min) e o acréscimo mínimo de 50% sobre a hora normal são referências para quantificação do passivo trabalhista.
Art. 71 — Intervalo intrajornada: jornada superior a 6h exige pausa contínua mínima de 1h (60 min). O sistema detecta automaticamente, para cada dia, se houve ao menos uma parada ininterrupta de 60 min. Dias sem pausa suficiente são sinalizados como INT.SUP (intervalo suprimido).
Art. 73 — Adicional noturno de 20% sobre as horas efetivamente trabalhadas no período de 22h às 5h, com hora noturna reduzida de 52min30s.
Ao final do processamento, cada dia é normalizado para exatamente 1.440 minutos (24h). Dias com total diferente de 1.440 min — decorrentes de registros esparsos ou lacunas — têm seus valores proporcionalmente ajustados, preservando a distribuição relativa entre movimento e parado e garantindo consistência nos totalizadores mensais.
9Integridade e Valor Probatório
Os dados brutos do Omnilink são lidos diretamente da planilha exportada pelo sistema de rastreamento, sem edição manual em nenhuma etapa da cadeia. O backend (Apps Script) não modifica os registros originais — apenas os lê, processa e agrega.
Ao carregar, o sistema gera um hash de autenticidade do conjunto de dados, exibido na barra superior do dashboard. Qualquer alteração posterior nos dados produziria um hash distinto, evidenciando adulteração — o hash funciona como lacre digital do conjunto probatório.
Cada dia processado expõe os seguintes campos de rastreabilidade no JSON e na aba Jornada por Dia:
gpsEstimado — indica que o GPS detectou movimento em um dia onde o Omnilink havia registrado velocidade = 0, e o campo velocidade foi desconsiderado em favor das coordenadas.
temLacuna — indica que houve intervalo sem sinal superior a 30 min no dia, e que parte da jornada foi estimada por inferência conservadora.
rotasAprendidas — documenta os corredores geográficos aprendidos automaticamente, com número de amostras e estatísticas de velts (mediana, mínima, máxima), permitindo auditoria pericial independente da metodologia de estimativa.
O juízo pode verificar, dia a dia, exatamente qual metodologia foi aplicada em cada registro — eliminando qualquer "caixa-preta" no processo de apuração.