Programação Por Equipe DevBras

Capa do artigo: Integrar catraca e leitora ao seu sistema sem perder evento quando a rede cai

Integrar catraca e leitora ao seu sistema sem perder evento quando a rede cai

Ligue um sistema a equipamentos de controle de acesso: quem decide a liberação, como mapear a pessoa, como receber eventos sem duplicar e o que fazer quando a rede cai.

Uma academia com três catracas e 1.200 alunos integra o sistema de mensalidades às leitoras faciais. Funciona na demonstração. Na primeira queda de internet, a catraca libera todo mundo por quarenta minutos e, quando a conexão volta, o relatório de frequência mostra metade das entradas em dobro e a outra metade sumida. A resposta curta: integrar controle de acesso é combinar um contrato, não importar a tela do fabricante. Decida antes quem libera a passagem quando o servidor não responde, use o identificador do seu sistema como identificador da pessoa no equipamento, grave cada evento com uma chave única para não duplicar e guarde dois horários: o do equipamento e o da chegada no seu servidor.

Os nomes de endpoints, campos e modos variam por fabricante e por modelo. Este guia trata do desenho que vale para qualquer um; os detalhes do seu equipamento estão na documentação oficial dele, como a API de acesso indicada na fonte.

Como a integração funciona por dentro

Equipamentos de acesso costumam trabalhar em um de dois modos, e muitos oferecem os dois.

  • Decisão no equipamento: a leitora guarda localmente a lista de pessoas e regras, decide sozinha e depois informa o que aconteceu. Seu sistema mantém essa lista atualizada.
  • Decisão no servidor: a cada leitura, o equipamento pergunta ao seu sistema se libera ou não, e espera a resposta.

No primeiro modo, a catraca continua funcionando sem rede, mas com a lista que tinha no momento da queda: um aluno bloqueado há dez minutos ainda entra. No segundo, a regra é sempre a atual, mas sem rede a decisão depende do que o equipamento faz quando a pergunta não tem resposta. Nenhum dos dois é errado. Errado é não saber qual está configurado.

Os eventos fazem o caminho contrário. O equipamento pode enviá-los para uma URL do seu sistema assim que acontecem, ou guardá-los para que você os busque periodicamente. Nos dois casos, o mesmo evento pode chegar mais de uma vez: o equipamento reenvia porque não recebeu confirmação, ou a sua busca pega de novo um intervalo já lido.

Como integrar passo a passo

  1. Escreva a política de falha. Sem rede, a catraca da entrada libera ou nega? Quem pode liberar manualmente? Isso é decisão de quem opera o prédio, registrada por escrito, antes do código.
  2. Cadastre cada equipamento no seu banco, com um identificador, o local e as credenciais de acesso guardadas como segredo.
  3. Use o id da pessoa no seu sistema como id do usuário no equipamento. Nunca case evento com cadastro pelo nome.
  4. Sincronize as pessoas a partir do seu sistema, que é a fonte da verdade. Bloqueio por inadimplência gera uma tarefa de envio com nova tentativa em caso de falha.
  5. Receba eventos numa tabela com chave única por equipamento e identificador do evento.
  6. Guarde o horário do equipamento e o horário de recebimento, ambos em UTC.
  7. Reconcilie diariamente: compare a lista de pessoas no equipamento com a do seu sistema e busque eventos de períodos com falha.

O exemplo da academia

A tabela de eventos

CREATE TABLE eventos_acesso (
  id                BIGSERIAL PRIMARY KEY,
  equipamento_id    INT NOT NULL REFERENCES equipamentos(id),
  evento_externo_id TEXT NOT NULL,
  pessoa_id         INT NULL REFERENCES pessoas(id),
  resultado         TEXT NOT NULL CHECK (resultado IN ('liberado', 'negado', 'nao_identificado')),
  ocorrido_em       TIMESTAMPTZ NOT NULL,
  recebido_em       TIMESTAMPTZ NOT NULL DEFAULT now(),
  bruto             JSONB NOT NULL,
  UNIQUE (equipamento_id, evento_externo_id)
);

A restrição UNIQUE é o que torna a gravação idempotente: se o mesmo evento chegar duas vezes, a segunda gravação não cria linha nova. O campo bruto guarda o corpo original, como veio do fabricante, para que você possa reprocessar se descobrir um erro na sua tradução. A coluna pessoa_id aceita nulo porque leitura de rosto desconhecido também é evento, e a auditoria vai querer vê-la.

O endpoint que recebe os eventos

Em Node.js com Express e o driver pg, o recebimento fica assim. As funções autenticarEquipamento e normalizar são suas: a primeira confere a credencial que o equipamento envia, e a segunda traduz o formato do fabricante para os campos da tabela, conforme a documentação do modelo.

app.post('/integracoes/acesso/eventos', express.json({ limit: '64kb' }), async (req, res) => {
  const equipamento = await autenticarEquipamento(req)
  if (!equipamento) return res.sendStatus(401)

  const ev = normalizar(equipamento, req.body)
  if (!ev) return res.sendStatus(400)

  await pool.query(
    'INSERT INTO eventos_acesso ' +
      '(equipamento_id, evento_externo_id, pessoa_id, resultado, ocorrido_em, bruto) ' +
      'VALUES ($1, $2, $3, $4, $5, $6) ' +
      'ON CONFLICT (equipamento_id, evento_externo_id) DO NOTHING',
    [equipamento.id, ev.idExterno, ev.pessoaId, ev.resultado, ev.ocorridoEm, req.body]
  )

  res.sendStatus(200)
})

O endpoint responde 200 também quando o evento já existia. Para o equipamento, o recado é "recebido, pode parar de reenviar". Se você responder erro para duplicata, ele tenta de novo para sempre. Essa é a mesma lógica de idempotência no pagamento: repetir a mensagem não pode repetir o efeito.

O trabalho pesado, como recalcular frequência ou disparar mensagem para o aluno, fica fora desse caminho, numa rotina que lê a tabela depois. Responder rápido evita que o equipamento estoure o tempo de espera e reenvie. Se a comunicação for no sentido contrário, com o seu sistema chamando o equipamento, defina sempre um tempo limite, como explica o guia sobre timeout antes do infinito.

Os dois horários

O horário do equipamento diz quando a pessoa passou. O de recebimento diz quando você soube. Em operação normal, a diferença é de segundos. Depois de uma queda, eventos de uma hora atrás chegam juntos. E se o relógio do equipamento estiver errado, a diferença denuncia:

SELECT equipamento_id,
       round(avg(extract(epoch FROM recebido_em - ocorrido_em))) AS atraso_medio_s
FROM eventos_acesso
WHERE recebido_em > now() - interval '1 day'
GROUP BY equipamento_id
ORDER BY atraso_medio_s;

Um atraso médio negativo significa que o equipamento acha que está no futuro. Configure a sincronização de horário nele, se o modelo oferecer, e grave tudo em UTC, convertendo só na exibição, como em horário em UTC.

Segurança e rede

As credenciais do equipamento dão poder de abrir portas. Guarde-as como segredo, fora do código, e troque a senha padrão de fábrica no primeiro dia. Coloque os equipamentos numa rede separada, sem acesso direto pela internet, e permita que só o servidor de integração fale com eles. Se o equipamento envia eventos para uma URL sua, essa URL precisa autenticar quem chama: caso contrário, qualquer pessoa que descubra o endereço inventa entradas.

Há ainda uma camada que não é de software. Saídas de emergência e rotas de fuga seguem normas de segurança contra incêndio e acessibilidade, e a política "negar quando a rede cai" não pode prender ninguém do lado de dentro. Esse desenho deve ser validado com quem responde pela segurança do prédio. Este guia é técnico e não substitui um profissional habilitado nem as normas aplicáveis ao local.

Erros comuns

  • Casar evento com cadastro pelo nome. Dois "João Silva" dividem a mesma frequência, e uma correção de grafia cria um aluno novo.
  • Gravar evento sem chave única. Cada reenvio do equipamento vira uma entrada a mais no relatório.
  • Responder erro para evento repetido. O equipamento reenvia sem parar e enche a fila.
  • Guardar só o horário de recebimento. Depois de uma queda, todos os eventos parecem ter acontecido no mesmo minuto.
  • Não definir o comportamento sem rede. A catraca libera ou trava conforme a configuração de fábrica, e ninguém sabe qual.
  • Expor o equipamento na internet com a senha padrão. Qualquer um com o endereço consegue abrir a porta.

Checklist

  • A política de falha (liberar ou negar sem rede) está escrita e assinada por quem opera o local.
  • Cada pessoa no equipamento usa o id do seu sistema.
  • Bloqueios e desbloqueios são enviados com nova tentativa automática.
  • A tabela de eventos tem chave única por equipamento e evento.
  • Cada evento guarda o horário do equipamento e o de recebimento, em UTC.
  • O corpo original de cada evento é preservado.
  • Equipamentos estão numa rede separada, com senha trocada.
  • Uma reconciliação diária compara pessoas e busca eventos de períodos com falha.

Desligue o cabo de rede de uma catraca por cinco minutos em horário tranquilo e passe três vezes. Quando a rede voltar, quantas entradas aparecem no seu sistema?

Avalie este artigo

Referência: https://www.controlid.com.br/docs/access-api-pt/