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
- 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.
- Cadastre cada equipamento no seu banco, com um identificador, o local e as credenciais de acesso guardadas como segredo.
- Use o id da pessoa no seu sistema como id do usuário no equipamento. Nunca case evento com cadastro pelo nome.
- 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.
- Receba eventos numa tabela com chave única por equipamento e identificador do evento.
- Guarde o horário do equipamento e o horário de recebimento, ambos em UTC.
- 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?
Referência: https://www.controlid.com.br/docs/access-api-pt/