Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚗 Intelbras LPR Webhook

🇧🇷 Português · 🇺🇸 English

Desenvolvi este projeto para consolidar minha experiência com integrações de webhook: recebo leituras LPR de uma câmera Intelbras, persisto os dados em PostgreSQL e exponho um painel web + API REST para acompanhar as entradas em tempo real.


⚡ Início rápido

git clone https://github.com/lucas-hochmann-rosa/intelbras-lpr-webhook.git
cd intelbras-lpr-webhook
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env    # edite as variáveis de ambiente (PostgreSQL é obrigatório)
python main.py

Detalhes de cada passo nas seções abaixo.


📌 Visão Geral

O intelbras-lpr-webhook recebe eventos POST enviados pela função Push de uma câmera Intelbras LPR, valida e deduplica as leituras, salva os metadados e a imagem da captura em PostgreSQL, e disponibiliza tudo por uma API REST e um dashboard web responsivo (tema claro/escuro).


✨ Principais Funcionalidades

  • Recebimento do webhook LPR - aceita os dois prefixos de rota citados na documentação oficial da câmera (/NotificationInfo/... e /Notification/...), evitando 404 independente do firmware.
  • Persistência em PostgreSQL via SQLAlchemy.
  • Deduplicação de leituras repetidas da mesma placa em uma janela de 30 segundos.
  • Armazenamento das imagens de captura em disco, com limpeza automática das mais antigas.
  • API REST para consulta do histórico de entradas (/api/records) com filtros por placa e período.
  • Dashboard web com filtros, tabela em tempo real, preview de imagem e indicador de entradas não lidas.
  • Controle de acesso por IP para o dashboard.
  • Terminal organizado com Rich: banner, resumo de configuração e URLs de acesso ao subir o servidor; log estruturado em JSON Lines gravado em disco.

🧭 Sumário


🏗️ Arquitetura

intelbras-lpr-webhook/
├── main.py                         # Ponto de entrada: carrega .env, inicializa banco e sobe o servidor
├── requirements.txt
├── .env.example
├── docs/
│   └── intelbras-lpr-push-webhook.md  # Referência técnica dos payloads da câmera
├── scripts/
│   └── send_test_plate.py          # Simulador de webhook para testes locais
└── src/
    └── lpr_webhook/
        ├── app.py                  # Application factory (Flask + CORS + blueprints)
        ├── config.py               # Leitura e validação das variáveis de ambiente
        ├── logging_setup.py        # Console colorido (Rich) + arquivo JSON Lines
        ├── terminal.py              # Banner, resumo de configuração e URLs (Rich)
        ├── database.py              # Engine PostgreSQL (sem fallback local)
        ├── models.py                 # Modelo ORM (PlateReading)
        ├── repository.py             # Consultas de leitura sobre o histórico
        ├── network.py                 # IP local, IP do cliente e allowlist
        ├── services/
        │   ├── plate_capture.py        # Valida, deduplica e persiste uma leitura
        │   └── image_cleanup.py        # Limpeza de imagens de captura antigas
        ├── routes/
        │   ├── camera.py                # Endpoints chamados pela câmera (webhook)
        │   ├── api.py                    # API REST de consulta (/api/records)
        │   └── web.py                     # Dashboard e favicon
        ├── templates/
        │   └── index.html                 # Dashboard web
        └── static/
            ├── camera.png                  # Favicon do painel
            └── captures/                    # Imagens salvas das leituras (execução)

Organização

  • main.py: bootstrap do serviço - carrega ambiente, conecta ao PostgreSQL e sobe o servidor Waitress.
  • src/lpr_webhook/app.py: application factory, monta o Flask com CORS e registra as blueprints.
  • src/lpr_webhook/routes/: camada HTTP, dividida por responsabilidade (câmera, API, web).
  • src/lpr_webhook/services/: regras de negócio (captura de leitura, limpeza de imagens).
  • src/lpr_webhook/database.py + models.py + repository.py: camada de persistência.
  • src/lpr_webhook/logging_setup.py + terminal.py: observabilidade - logs estruturados e saída de terminal.

🧰 Tecnologias utilizadas

Runtime: Python 3.10+

Web: Flask, Flask-CORS, Waitress (servidor WSGI de produção)

Persistência: SQLAlchemy + psycopg2-binary (PostgreSQL)

Observabilidade: Rich (console colorido e tracebacks legíveis) + logging estruturado em JSON Lines

Configuração: python-dotenv

Frontend: HTML + CSS puro (fonte Inter via Google Fonts), sem framework JS - servido pelo próprio Flask via Jinja


📡 Como funciona o webhook

A câmera Intelbras usa a função Push: ao detectar uma leitura, ela mesma envia um POST com o payload em JSON para o endpoint configurado nela - a aplicação atua de forma passiva, apenas recebendo e respondendo HTTP 200.

A documentação oficial é inconsistente quanto ao prefixo das rotas: os exemplos de código usam /NotificationInfo/..., mas as tabelas de glossário registram /Notification/... (sem o sufixo "Info"). Este projeto registra os dois prefixos para os três endpoints, para não depender de qual forma o firmware da câmera realmente usa:

  1. POST /NotificationInfo/TollgateInfo (e /Notification/TollgateInfo) - evento principal, com os dados da placa, do veículo e (opcionalmente) o snapshot em base64.
  2. POST /NotificationInfo/KeepAlive (e /Notification/KeepAlive) - heartbeat periódico do dispositivo.
  3. POST /NotificationInfo/DeviceInfo (e /Notification/DeviceInfo) - metadados do dispositivo.

As respostas seguem o contrato oficial da câmera (objeto plano com Result/DeviceID/PlateNumber no TollgateInfo, corpo vazio no KeepAlive). Veja docs/intelbras-lpr-push-webhook.md para o detalhamento completo dos payloads, incluindo autenticação HTTP Digest e o modo alternativo Subscribe.


🖥️ Logging e terminal

  • Console: RichHandler colore por nível (INFO/WARNING/ERROR) e formata tracebacks de forma legível; o boot do servidor imprime um banner, um resumo da configuração carregada e uma tabela com as URLs prontas para uso.
  • Arquivo: cada evento é gravado como uma linha JSON em logs/app.jsonl (rotação automática em 5 MB, até 5 arquivos), fácil de buscar (grep), parsear ou enviar para uma ferramenta de observabilidade.
  • O nível (INFO/WARNING/ERROR) e o nome do logger (LPR_WEBHOOK.database, por exemplo) seguem o padrão em inglês do próprio módulo logging; a mensagem em si - o texto explicando o que está acontecendo, tipo "Conectando ao PostgreSQL..." - fica em português, igual à UI do dashboard.

📐 Regras da construção do projeto

  • Identificadores, funções e estrutura de arquivos ficam em inglês.
  • Mensagens de log ficam em português (nível e nome do logger seguem o inglês padrão do módulo logging); a resposta da câmera (Result/DeviceID/PlateNumber) segue o contrato oficial, em inglês, por ser um protocolo externo.
  • Comentários no código ficam em português, reservados para decisões não óbvias - o "porquê", não o "o quê".
  • Toda interação com a câmera fica isolada em src/lpr_webhook/routes/camera.py e src/lpr_webhook/services/plate_capture.py.
  • Nenhuma credencial é versionada: .env fica de fora do repositório, só .env.example é versionado.

⚙️ Requisitos

  • Python >= 3.10
  • PostgreSQL ativo e acessível - obrigatório, não há fallback local

Sem PostgreSQL configurado ou acessível, o servidor não sobe: main.py falha rápido com uma mensagem clara em vez de continuar em um estado degradado.


🔧 Instalação

Windows (PowerShell ou CMD)

git clone https://github.com/lucas-hochmann-rosa/intelbras-lpr-webhook.git
cd intelbras-lpr-webhook
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env

Linux / macOS

git clone https://github.com/lucas-hochmann-rosa/intelbras-lpr-webhook.git
cd intelbras-lpr-webhook
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

No Linux, psycopg2-binary costuma exigir as bibliotecas de desenvolvimento do PostgreSQL para compilar dependências nativas (libpq). Se a instalação falhar, instale primeiro: Debian/Ubuntu sudo apt install libpq-dev python3-dev; Fedora sudo dnf install libpq-devel python3-devel; Arch sudo pacman -S postgresql-libs.

Depois de instalar (em qualquer sistema), edite o .env recém-criado com as credenciais do seu PostgreSQL antes de seguir para a seção Configuração de Ambiente.


🔐 Configuração de Ambiente

Crie .env com base em .env.example:

DATABASE_URL=
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=intelbras_lpr_webhook
POSTGRES_USER=postgres
POSTGRES_PASSWORD=senha_aqui

WEBHOOK_PORT=8000
WEBHOOK_HOST=127.0.0.1

FRONTEND_ALLOWED_IPS=127.0.0.1,::1
Variável Padrão Para que serve
DATABASE_URL - URL completa do PostgreSQL; se definida, tem prioridade sobre as variáveis POSTGRES_*
POSTGRES_HOST / POSTGRES_PORT / POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD - Credenciais do PostgreSQL. Obrigatório (via essas variáveis ou via DATABASE_URL)
WEBHOOK_PORT - Porta HTTP do servidor. Obrigatório
WEBHOOK_HOST 127.0.0.1 Host informativo usado nos logs
FRONTEND_ALLOWED_IPS vazio IPs/redes com acesso ao dashboard, separados por vírgula. Vazio libera todo mundo

Importante: não publique o arquivo .env com credenciais reais - o .gitignore já o ignora.


▶️ Execução

python main.py
  • Dashboard: http://localhost:WEBHOOK_PORT/
  • API: http://localhost:WEBHOOK_PORT/api/records
  • Webhook: http://localhost:WEBHOOK_PORT/NotificationInfo/TollgateInfo (e demais rotas da câmera)

📡 Endpoints Principais

Método Rota Descrição
GET / Dashboard web de monitoramento
POST /NotificationInfo/TollgateInfo, /Notification/TollgateInfo Endpoint principal para eventos da câmera
POST /NotificationInfo/KeepAlive, /Notification/KeepAlive Keep-alive da câmera
POST /NotificationInfo/DeviceInfo, /Notification/DeviceInfo Informações do dispositivo
GET /api/records Lista leituras, com filtros plate, start_date e end_date

Resposta ao TollgateInfo (contrato oficial da câmera):

{"Result": true, "DeviceID": "1c11c9c4-8dbc-4391-0dd7-56764ba18dbc", "PlateNumber": "ABC1234"}

🧪 Testes Locais Rápidos

Para simular entradas da câmera e validar o dashboard sem depender do hardware:

python scripts/send_test_plate.py

🔒 Segurança

  • FRONTEND_ALLOWED_IPS restringe o acesso ao dashboard por IP/rede; deixe vazio apenas em ambientes de teste.
  • Nenhuma credencial fica hardcoded - tudo vem do .env, que nunca é versionado.
  • O servidor falha rápido (não sobe) se o PostgreSQL não estiver configurado/acessível, evitando operar num estado inconsistente.

🧯 Quando parar de funcionar

Sintoma Causa provável
WEBHOOK_PORT não definido no .env Configure a porta no .env antes de iniciar
Servidor não inicia com erro de PostgreSQL Verifique POSTGRES_*/DATABASE_URL no .env e se o PostgreSQL está acessível
Dashboard retorna Acesso negado Seu IP não está em FRONTEND_ALLOWED_IPS
Leituras não aparecem no dashboard Confira se a câmera está configurada para enviar Push para /NotificationInfo/TollgateInfo (ou /Notification/TollgateInfo) na porta correta

Logs completos ficam em logs/app.jsonl (JSON Lines, um evento por linha).


⚠️ Avisos

Projeto pessoal construído para consolidar experiência prática com integrações de webhook e persistência de dados em ambiente real. Adapte os endpoints e o payload conforme o modelo exato da sua câmera Intelbras - consulte o manual técnico do fabricante em conjunto com docs/intelbras-lpr-push-webhook.md.


👨‍💻 Autor

Lucas Hochmann Rosa


📄 Licença

Licenciado sob MIT. Você pode usar, modificar e distribuir, mantendo o aviso de copyright e atribuindo crédito a Lucas Hochmann Rosa.


About

Dashboard para câmeras Intelbras LPR que recebe leituras via webhook, armazena os dados em PostgreSQL e disponibiliza uma API REST para atualização dos registros em tempo real na interface.

Topics

Resources

Stars

Watchers

Forks

Releases

Contributors

Languages