Documentação Técnica App + API REST - Parte 1
-
Documentação Técnica — Insoft QFace AppVersão: 1.0.0
Empresa: Insoft4 Informática LTDA
Plataforma: Windows (x64 / ia32)
Data: Abril de 2026
1. VISÃO GERAL DO SISTEMAO que é este sistema?
O Insoft QFace App é um software desktop para Windows desenvolvido pela Insoft4 Informática. Ele serve como interface gráfica e gerenciador de um leitor biométrico facial da linha QFace (Digicon/Suprema).
Problema que resolve
Empresas que utilizam leitores biométricos faciais QFace precisam:
- Cadastrar imagens faciais de colaboradores no dispositivo
- Converter imagens (JPEG/PNG) em templates biométricos (dados compactados que representam o rosto da pessoa)
- Capturar fotos ao vivo usando a câmera do dispositivo QFace
- Gerenciar o serviço de API que realiza estas operações
- Monitorar o status da API e do dispositivo em tempo real
Público-alvo
Público Uso principal Administradores de TI Instalar, configurar e gerenciar o serviço Operadores Monitorar conversões e capturas em andamento Desenvolvedores Integrar sistemas externos via REST API Suporte Técnico Diagnosticar falhas e consultar logs Principais funcionalidades
Conversão de imagens faciais em templates biométricos (via QFace SDK)
Captura ao vivo pela câmera do dispositivo QFace
Dashboard de monitoramento (status da API e do dispositivo)
Gerenciamento do serviço Windows (insoft-qface-win-api)
Configuração de conexão com o dispositivo (IP, porta)
Suporte a SSL/TLS para a API REST
Integração com API externa (webhook de saída configurável)
Histórico de conversões realizadas
Logs de operação em arquivo
️ 2. ARQUITETURA DO SISTEMAVisão simplificada (para Suporte)
O sistema é composto por dois programas que trabalham juntos:
┌──────────────────────────────────────────────┐ │ INSOFT QFACE APP (.exe) │ │ Interface gráfica + Gerenciador (Electron) │ │ │ │ ┌──────────────────┐ │ │ │ React (UI) │ ← Usuário interage │ │ └────────┬─────────┘ │ │ │ IPC (comunicação interna) │ │ ┌────────▼─────────┐ │ │ │ Electron Main │ ← Controla tudo │ │ └────────┬─────────┘ │ └────────────┼─────────────────────────────────┘ │ WebSocket (porta 3133) │ HTTP REST (porta 3333) ┌────────────▼─────────────────────────────────┐ │ INSOFT QFACE WIN API (.exe) │ │ Servidor REST + Integração com SDK │ │ │ │ ┌──────────────────┐ │ │ │ Express Server │ ← Recebe requisições │ │ └────────┬─────────┘ │ │ │ │ │ ┌────────▼─────────┐ │ │ │ QFace SDK │ ← Fala com o leitor │ │ │ (DLL nativa) │ │ │ └──────────────────┘ │ └──────────────────────────────────────────────┘ │ │ TCP/IP (porta 12120) ▼ ┌─────────────────┐ │ Dispositivo │ │ QFace (leitor) │ │ Digicon/Suprema│ └─────────────────┘Arquitetura técnica
O projeto utiliza uma arquitetura em camadas com separação clara de responsabilidades:
Camada Tecnologia Responsabilidade UI (Frontend) React + TypeScript + Tailwind CSS Interface visual do usuário Desktop Shell Electron (Node.js + Chromium) Janela nativa Windows, IPC, gerenciamento de sistema API REST Express.js + TypeScript Endpoints HTTP para operações biométricas SDK Wrapper Koffi (FFI) + DLL nativa Comunicação com o hardware QFace via DLL C/C++ Serviço Windows NSSM (Non-Sucking Service Manager) Execução do API como serviço do Windows Comunicação em tempo real Socket.IO Notificações de eventos entre API e interface Como os componentes se comunicam
React UI │ ├─── contextBridge (window.electron.*) ──► Preload.ts ──► ipcMain (IPC canais) │ │ │ main.ts / ipc/index.ts │ │ │ ┌────────────────┼─────────────────┐ │ │ │ │ │ HTTP Requests WebSocket Client Windows SC │ │ │ │ insoft-qface-win-api │ │ │ │ │ Express Routes Socket.IO Server │ │ (porta 3133) │ Controller │ │ │ QFace SDK (DLL) │ │ └──────────────────────── Dispositivo QFace (IP:12120)Tecnologias utilizadas
insoft-qface-app(Frontend + Electron)Tecnologia Versão Finalidade Electron ^30.0.1 Shell desktop nativo React ^18.3.1 Interface do usuário TypeScript ^5.2.2 Tipagem estática Vite ^5.1.4 Build do frontend Tailwind CSS ^3.4.3 Estilização Flowbite React 0.12.9 Componentes UI Socket.IO Client ^4.8.1 Comunicação em tempo real com a API React Router ^6.26.2 Navegação entre telas React Hook Form ^7.56.2 Formulários Zod ^3.24.4 Validação de schemas electron-log ^5.2.4 Logs persistentes electron-store ^9.0.0 Armazenamento local insoft-qface-win-api(API Backend)Tecnologia Versão Finalidade Node.js 18 (target) Runtime Express ^5.1.0 Servidor HTTP TypeScript ^5.2.2 Tipagem estática Koffi ^2.8.0 Binding FFI para DLL nativa Socket.IO ^4.8.1 Eventos em tempo real Helmet ^8.1.0 Segurança HTTP Morgan ^1.10.1 Logs de requisições pkg ^5.8.1 Empacotamento em .exe standalone
3. ESTRUTURA DE PASTAS E COMPONENTES
Raiz do Monorepo (insoft-qface-global-app/)insoft-qface-global-app/ ├── insoft-qface-app/ ← Aplicativo Electron (Desktop) ├── insoft-qface-win-api/ ← Servidor REST API (Windows) └── shared/ └── i18n/ ← Mensagens e códigos internacionalizados
insoft-qface-app/— Aplicativo DesktopDescrição funcional (para Suporte):
Este é o programa principal que o usuário vê e usa. Ele exibe a interface gráfica, controla o serviço de API em segundo plano e se comunica com a janela do Windows.
Descrição técnica (para Devs):
insoft-qface-app/ ├── electron/ │ └── main/ │ ├── main.ts ← Ponto de entrada do processo principal do Electron │ ├── preload.ts ← Bridge segura entre Renderer (React) e Main process │ ├── CertificateStore.ts ← Gerenciamento de certificado SSL no Windows │ ├── types.d.ts ← Tipos TypeScript globais │ ├── i18n/ │ │ └── messages.ts ← Constantes de mensagens (códigos i18n) │ ├── ipc/ │ │ ├── index.ts ← Handlers IPC para Dashboard, Device, API management │ │ └── ui-actions.ts ← Handlers IPC para ações de UI (janela, tema) │ └── utils/ │ ├── logger.ts ← Configuração do electron-log │ ├── nssm-manager.ts ← Operações com NSSM (install/start/stop/status) │ └── windows-service-manager.ts ← Wrapper para gerenciar serviços Windows ├── src/ │ ├── App.tsx ← Componente raiz React │ ├── routes/ │ │ ├── AppRoutes.tsx ← Definição de todas as rotas da aplicação │ │ ├── ContextRoutes.tsx ← Wrapper de rotas com contexto (MainView) │ │ └── NavigationListener.tsx ← Escuta eventos de navegação do IPC │ ├── context/ │ │ ├── ConfigContext.tsx ← Contexto global de configurações │ │ └── ThemeContext.tsx ← Contexto de tema (dark/light) │ ├── hooks/ │ │ ├── useApiServiceStatus.ts ← Hook para status do serviço Windows │ │ ├── useCamera.ts ← Hook para acesso à câmera │ │ └── useDarkMode.ts ← Hook para alternância de tema │ ├── mappings/ │ │ ├── AppSettings.ts ← Interface TypeScript das configurações │ │ └── types.ts ← Tipos compartilhados do frontend │ ├── views/ │ │ ├── StartApp/ ← Tela inicial (verificação de serviço) │ │ ├── Dashboard/ ← Painel de monitoramento │ │ ├── ApiManagement/ ← Gerenciamento da API e fluxo de conversão/captura │ │ ├── DeviceManagement/ ← Gerenciamento do dispositivo QFace │ │ ├── Settings/ ← Configurações do sistema │ │ └── MainView/ ← Layout principal (menu lateral + header) │ ├── components/ ← Componentes reutilizáveis (Button, Card, Modal, etc.) │ └── utils/ ← Utilitários (captureFrame, getQualityStyle, etc.) ├── config/ │ └── application.json ← Arquivo de configuração principal (editável) ├── nssm/ │ ├── win32/ ← NSSM para x86 │ └── win64/ ← NSSM para x64 ├── cert_app/ ← Certificado digital da aplicação └── electron-builder.json ← Configurações de build/empacotamento
insoft-qface-win-api/— API REST WindowsDescrição funcional (para Suporte):
Este é o "motor" que faz as operações reais com o leitor QFace. Ele fica rodando em segundo plano como um Serviço do Windows (similar ao antivírus), recebe comandos da interface gráfica e se comunica diretamente com o hardware biométrico.
Descrição técnica (para Devs):
insoft-qface-win-api/ ├── src/ │ ├── start.ts ← Ponto de entrada do servidor │ ├── server/ │ │ ├── index.ts ← Configuração Express, Socket.IO, HTTPS/HTTP, Mutex │ │ ├── routes.ts ← Agregador de rotas (picture + device) │ │ └── eventQueue.ts ← Fila de eventos para comunicação com Electron │ ├── routes/ │ │ ├── pictureRoutes.ts ← Rotas: /v1/foto/converter, /v1/foto/capturar, /internal/* │ │ └── deviceRoutes.ts ← Rotas: /v1/qfaceInfo, /device/* │ ├── controller/ │ │ ├── biometricTemplateController.ts ← Lógica de conversão e captura biométrica │ │ ├── deviceController.ts ← Lógica de controle do dispositivo QFace │ │ └── pendingRequests.ts ← Map de requisições de captura pendentes │ ├── sdk/ │ │ └── qface-sdk.ts ← Wrapper TypeScript para a DLL QFM_SDK_DLL.dll │ ├── config/ │ │ └── configManager.ts ← Leitura/escrita do application.json │ ├── middleware/ │ │ └── auth.ts ← Middleware de autenticação Bearer (preparado) │ ├── i18n/ │ │ └── messages.ts ← Importa códigos de mensagem do shared/i18n │ └── utils/ │ ├── logger.ts ← Configuração de logger │ └── cameraDeviceName.ts ← Detecção de câmera no Windows ├── dlls/ ← DLLs nativas do QFace SDK ├── config/ │ └── application.json ← Configuração compartilhada └── scripts/ └── copy-dlls.js ← Script de build: copia DLLs para pasta de output
shared/i18n/— Mensagens InternacionalizadasDescrição funcional (para Suporte):
Contém todas as mensagens do sistema traduzidas. Se uma mensagem de erro aparecer com o código
repp.message.XXX, consulte este arquivo para ver o texto correspondente.Descrição técnica (para Devs):
Arquivo Conteúdo message-codes.jsonMapeamento de constantes → códigos (ex: "FAILED_CONNECT_DEVICE": "repp.message.24")en-US.jsonTraduções em Inglês pt-BR.jsonTraduções em Português validate-i18n.mjsScript de validação de consistência entre arquivos de tradução As mensagens são traduzidas automaticamente no
preload.tsantes de chegar ao frontend (padrão regex/^repp\.message\.\d+$/).
4. FLUXOS PRINCIPAIS DO SISTEMA
Fluxo 1: Inicialização do SistemaExplicação simplificada (Suporte):
Quando o usuário abre o aplicativo, ele automaticamente tenta iniciar o serviço da API em segundo plano. Se o serviço já estiver instalado e rodando, conecta a ele. Se não, tenta iniciá-lo.
Explicação técnica (Dev):
1. Electron inicia (main.ts) ├── Lê config/application.json ├── Aplica flags de linha de comando (MediaFoundation, autoplay) ├── Instala certificado digital via CertificateStore.ensureInstalled() ├── Cria BrowserWindow com preload.ts ├── Carrega o React (hash router: /#/) └── Chama startApiServer() 2. startApiServer() ├── Sonda a API (HTTP GET em /insoft-qface-win-api/v1/health) │ ├── Se responder → registra como running, conecta WebSocket │ └── Se não responder → │ ├── [Windows Prod] Verifica serviço Windows (sc qc insoft-qface-win-api) │ │ ├── Instalado → startWindowsService() → espera healthcheck (até 15s) │ │ └── Não instalado → exibe erro │ └── [Dev] Procura .exe e executa via spawn() 3. connectWebSocket() └── Conecta Socket.IO ao localhost:3133 com reconexão infinita
Fluxo 2: Conversão de Imagens em Templates BiométricosExplicação simplificada (Suporte):
Um sistema externo (ou o próprio usuário) envia imagens faciais para a API. O sistema conecta no leitor QFace, converte cada imagem em um "código biométrico" (template) e retorna esses dados. Durante o processo, a tela do aplicativo abre automaticamente para mostrar o progresso.
Fluxo detalhado:
Sistema Externo │ │ POST /v1/foto/converter │ Body: { "pictures": [{ "personId": 123, "image": "<base64>" }] } │ ▼ insoft-qface-win-api (Express) │ ├── pictureRoutes → convertBiometricTemplate() │ ├── [1] Adquire mutex (garante que apenas 1 conversão ocorre por vez) │ ├── [2] Conecta ao dispositivo QFace via SDK (initSocket) │ ├── [3] Emite evento WebSocket → api:convert:start │ └─► Electron main.ts (recebe via Socket.IO) │ └─► mainWindow.webContents.send('api:convert:start') │ └─► React (navega para /api/convert) │ ├── [4] QF_DeleteAll() — apaga templates existentes no dispositivo │ ├── [5] Para cada imagem (sequencial): │ ├── Decodifica base64 → Buffer │ ├── QF_EnrollImage(userID, imageBuffer) — envia imagem ao dispositivo │ ├── QF_ReadTemplate(userID) — lê o template gerado │ ├── Converte buffer → string hexadecimal │ ├── Salva imagem em imagens/face_<id>.jpeg │ ├── Salva template em templates/bio_<id>.tmp │ ├── Salva metadados em templates/capture_<id>.json │ └── Emite evento WebSocket → api:convert:item (status individual) │ ├── [6] Fecha conexão com dispositivo (closeSocket) │ ├── [7] Emite evento WebSocket → api:convert:done (resultados finais) │ └── [8] Retorna HTTP 200 com array de resultados
Fluxo 3: Captura de Foto ao Vivo (QFace Camera)Explicação simplificada (Suporte):
Um sistema externo solicita a captura de uma foto usando a câmera do leitor QFace. O aplicativo abre automaticamente a tela de captura, aciona o leitor, o usuário deve ficar na frente do leitor para a foto ser tirada. Quando capturada, o resultado é retornado para o sistema solicitante.
Fluxo detalhado:
Sistema Externo │ │ POST /v1/foto/capturar │ Body: { "personId": 123 } │ ▼ insoft-qface-win-api ├── [1] Valida personId/employeeId ├── [2] Sonda disponibilidade do QFace (probeQFaceDeviceAvailability) │ └─► Se indisponível → retorna 503 imediatamente │ ├── [3] Gera requestId único ├── [4] Emite evento WebSocket → api:capture:start { requestId, personId } │ └─► Electron main.ts │ ├─► bringWindowToFront() — traz janela para frente │ ├─► navega para /api/capture │ └─► 100ms depois → mainWindow.webContents.send('api:capture:start') │ ├── [5] Registra request em pendingCaptureRequests (Map com Response + timeout) │ └── [6] Aguarda resposta do Electron (timeout configurável, padrão ~60s) │ ▼ React (PictureCapture View) ├── Aciona câmera/dispositivo QFace ├── Usuário posiciona rosto ├── Captura template via qface:captureTemplate (IPC) └── Chama electron.dashboard.completeCaptureRequest(requestId, template) │ ▼ IPC → capture:completeCaptureRequest │ ▼ POST /internal/capture/complete { requestId, template, quality, imageBase64 } │ ▼ completeCaptureFromElectron() └─► Resolve response pendente → HTTP 200 para sistema externo
Fluxo 4: Gerenciamento do Serviço WindowsExplicação simplificada (Suporte):
O usuário pode instalar, iniciar, parar e desinstalar o serviço da API diretamente pela tela de Gerenciamento do Dashboard. O sistema usa o NSSM (ferramenta especial) para registrar o .exe da API como um serviço do Windows.
Explicação técnica (Dev):
React (Dashboard) → window.electron.dashboard.installService(name, displayName, apiPath) │ ▼ IPC: dashboard:installService │ ▼ windows-service-manager.ts → installWindowsService() ├── Resolve caminho do nssm.exe (win32/ ou win64/) ├── Executa: nssm install <serviceName> <exePath> ├── Configura: nssm set <serviceName> AppDirectory <dir> ├── Configura: nssm set <serviceName> AppEnvironmentExtra CONFIG_PATH=... QFACE_DLL_PATH=... └── Executa: nssm start <serviceName>
Fluxo 5: Configuração e TemaExplicação simplificada (Suporte):
As configurações são salvas em um arquivo
application.jsontanto na pasta do aplicativo quanto na pasta do serviço de API. Quando o usuário altera as configurações, ambos são atualizados ao mesmo tempo.Explicação técnica (Dev):
React ConfigContext ├── loadConfig() → IPC:loadConfig → main.ts lê config/application.json ├── saveConfig(updates) → IPC:saveConfig → main.ts escreve config/application.json │ → HTTP POST /internal/config/update (API sincroniza) └── LocalStorage como cache temporário (chave: 'qface-app-config')
️ 5. ROTINAS E MÉTODOS IMPORTANTES
convertBiometricTemplateDescrição simplificada:
Recebe um conjunto de imagens, conecta no leitor QFace e gera os templates biométricos correspondentes.
Descrição técnica:
- Localização: insoft-qface-win-api/src/controller/biometricTemplateController.ts
- Rota:
POST /v1/foto/converter
Parâmetros (Request Body):
{ "pictures": [ { "personId": 123, "image": "<base64 da imagem facial>" } ] }Retorno (HTTP 200):
{ "success": true, "pictures": [ { "personId": 123, "template": "4A1B2C...", "quality": 85 } ] }Regras de negócio:
- Usa
QFaceMutexpara garantir que apenas uma conversão ocorra por vez (DLL não é thread-safe) - Processa imagens sequencialmente (não em paralelo)
- Apaga todos os templates do dispositivo antes de iniciar (
QF_DeleteAll) - Salva imagens em
imagens/face_<personId>.jpeg - Salva templates em
templates/bio_<personId>.tmp - O campo
imageno retorno é removido para evitar overflow de memória
Possíveis erros:
Código Significado repp.message.22picturesnão é um array válidorepp.message.24Falha ao conectar no dispositivo QFace repp.message.25Falha ao apagar templates existentes repp.message.27Imagem inválida para template facial repp.message.47Falha ao ler template gerado
capturePictureDescrição simplificada:
Inicia uma captura ao vivo usando a câmera do QFace. A requisição fica "suspensa" aguardando o usuário posicionar o rosto na frente do leitor.
Descrição técnica:
- Localização: insoft-qface-win-api/src/controller/biometricTemplateController.ts
- Rota:
POST /v1/foto/capturar
Parâmetros (Request Body):
{ "personId": 123, "includeBase64": false }Comportamento:
- Verifica disponibilidade do QFace antes de iniciar (fail-fast)
- Armazena a resposta HTTP pendente em
pendingCaptureRequests(Map) - O timeout padrão evita que a requisição fique aberta indefinidamente
- A resolução ocorre via chamada interna do Electron:
POST /internal/capture/complete
startApiServerDescrição simplificada:
Tenta iniciar o servidor da API usando o método mais adequado disponível (serviço Windows, .exe, ou API já rodando).
Descrição técnica:
- Localização: insoft-qface-app/electron/main/main.ts
- Chamado por: IPC
dashboard:startApi, e na inicialização do app
Lógica de decisão:
1. API já está acessível via HTTP healthcheck? → Registra como running 2. Serviço Windows instalado? ├── Rodando? → Healthcheck → Registra └── Parado? → sc start → Aguarda healthcheck (15s) 3. Em produção sem serviço → Retorna erro 4. Em desenvolvimento → Tenta spawn do .exe diretamente
connectWebSocketDescrição simplificada:
Cria uma conexão em tempo real entre o aplicativo e o servidor de API, para receber notificações imediatas sobre conversões e capturas.
Descrição técnica:
- Localização: insoft-qface-app/electron/main/main.ts
- Conecta em
http://localhost:3133(Socket.IO) - Reconexão automática infinita com backoff exponencial (1s → 5s)
- Ouve eventos:
api:convert:start,api:convert:item,api:convert:done,api:capture:start - Cada evento é repassado via IPC para o frontend React
QFaceSDK.initSocketDescrição simplificada:
Conecta o software ao leitor QFace pela rede local.
Descrição técnica:
- Localização: insoft-qface-win-api/src/sdk/qface-sdk.ts
- Chama
QF_InitSocket(deviceIp, devicePort, asciiMode)na DLL nativa via Koffi (FFI) asciiMode = false→ protocolo binário (padrão)- Retorna
trueseQF_SUCCESS (0),falsecaso contrário - Mapeia todos os códigos de erro da DLL (de
-1a-304)
Principais erros da DLL:
Código Significado -302QF_ERR_CANNOT_OPEN_SOCKET— IP errado ou dispositivo offline-303QF_ERR_CANNOT_CONNECT_SOCKET— Porta bloqueada ou firewall-305QF_ERR_READ_SOCKET_TIMEOUT— Dispositivo não respondeu
QFaceMutex.runExclusiveDescrição simplificada:
Garante que apenas uma operação de conversão aconteça por vez, evitando travamentos na DLL.
Descrição técnica:
- Localização: insoft-qface-win-api/src/server/index.ts
- Implementação de mutex assíncrono com fila (FIFO)
- Motivo: A DLL
QFM_SDK_DLL.dllnão é thread-safe — chamadas concorrentes causam crash - Todas as operações que acessam a DLL devem usar
qfaceMutex.runExclusive()
CertificateStore.ensureInstalledDescrição simplificada:
Instala automaticamente o certificado digital do aplicativo no Windows para reduzir bloqueios por antivírus ao acessar a câmera.
Descrição técnica:
- Localização: insoft-qface-app/electron/main/CertificateStore.ts
- Verifica se o certificado
Insoft4 QFace Appjá está emLocalMachine\Root - Se não estiver, executa
certutil -addstore Root <certPath> - Chamado automaticamente na inicialização do Electron
normalizeIpcPayload(Preload)Descrição simplificada:
Traduz automaticamente os códigos de mensagem (
repp.message.X) para texto legível em Português antes de mostrar no frontend.Descrição técnica:
- Localização: insoft-qface-app/electron/main/preload.ts
- Percorre recursivamente o payload de qualquer chamada IPC
- Identifica strings que correspondem ao padrão
/^repp\.message\.\d+$/ - Faz lookup no catálogo
pt-BR.json(carregado uma vez e cacheado) - Aplica a tradução antes de retornar ao React
A documentação continua na parte 2, através da seguinte URL:
Documentação Técnica App + API REST - Parte 2