Navegação

    Fórum Técnico Insoft4

    • Login
    • Pesquisar
    • Categorias
    • Recente
    • Tags
    • Popular
    • Usuários
    • Grupos

    Documentação Técnica - Parte 1

    Documentações
    doc-tecnica doc-for-devs-and-sup
    1
    1
    3
    Carregando Mais Posts
    • Mais Antigo para Mais Recente
    • Mais Recente para Mais Antigo
    • Mais Votados
    Responder
    • Responder como tópico
    Entre para responder
    Este tópico foi deletado. Apenas usuários com privilégios de moderação de tópico podem vê-lo.
    • G
      Gilberto Júnior Equipamentos última edição por Gilberto Júnior

      📚 Documentação Técnica — Insoft Readers App

      Versão: 1.0.0
      Data: Abril de 2026
      Plataforma: Windows (x64)
      Público: Equipe de Suporte Técnico · Desenvolvedores


      📌 1. VISÃO GERAL DO SISTEMA

      Objetivo do Sistema

      O Insoft Readers App é uma aplicação desktop para Windows que gerencia leitores de cartões RFID/Mifare (modelo Digicon DG-710) e expõe uma API local para que outros sistemas possam receber e processar os dados de leitura.

      Problema que Resolve

      Empresas que utilizam leitores de cartão de proximidade precisam integrar essas leituras a outros softwares (sistemas de ponto, acesso, automação etc.). O Insoft Readers App resolve isso ao:

      1. Detectar automaticamente o leitor físico conectado ao computador
      2. Ler os cartões aproximados ao leitor em tempo real
      3. Enviar o código do cartão lido automaticamente para qualquer campo de texto ativo em qualquer aplicativo (como um teclado virtual)
      4. Disponibilizar uma API local REST para que outros sistemas consumam os eventos de leitura

      Público-alvo

      Perfil Uso
      Usuário final Vê o ícone na bandeja do sistema; o cartão é automaticamente "digitado" na aplicação aberta
      Analista de Suporte Monitora status dos leitores, diagnostica falhas de conexão e configuração
      Desenvolvedor Integra o sistema via API HTTP local, configura parâmetros de leitura

      Principais Funcionalidades

      • ✅ Leitura automática de cartões Mifare/RFID via leitor Digicon DG-710
      • ✅ Auto-paste: cola o código do cartão no campo de texto ativo do Windows
      • ✅ API REST local (porta 3791) para integração com outros sistemas
      • ✅ Stream de eventos em tempo real (SSE) para consumo live dos cartões lidos
      • ✅ Interface gráfica (dashboard) para monitoramento e configuração
      • ✅ Ícone na bandeja do sistema (system tray) com notificações
      • ✅ Configuração de prefixo/sufixo, intervalo de polling e modo contínuo
      • ✅ Suporte a execução como Serviço do Windows (via NSSM)
      • ✅ Modo mock (sem hardware): simula leituras para desenvolvimento/testes

      🏗️ 2. ARQUITETURA DO SISTEMA

      Visão Macro

      O sistema é composto por três camadas independentes que se comunicam via HTTP local:

      ┌─────────────────────────────────────────────────────────────────┐
      │                        HARDWARE                                  │
      │              Leitor Digicon DG-710 (USB/Serial)                  │
      │              DG710Facade.dll (DLL nativa Windows)                │
      └──────────────────────────┬──────────────────────────────────────┘
                                 │ FFI (koffi)
      ┌──────────────────────────▼──────────────────────────────────────┐
      │                    BACKEND API (@insoft/backend)                  │
      │           Express HTTP · porta 3791 · Node.js / TypeScript        │
      │    Gerencia leitores · processa eventos · persiste configurações  │
      └────────────┬──────────────────────────────────────┬─────────────┘
                   │ REST + SSE (HTTP)                     │ HTTP POST /notify
                   │                                       │
      ┌────────────▼──────────────┐          ┌────────────▼─────────────┐
      │   FRONTEND (@insoft/      │          │  ELECTRON (@insoft/       │
      │   frontend)               │          │  electron)                │
      │   React · Vite · Zustand  │◄─────────│  Processo principal       │
      │   Interface de usuário    │   IPC     │  porta control: 3792      │
      │   porta dev: 5173         │          │  System Tray · Auto-paste │
      └───────────────────────────┘          └──────────────────────────┘
      

      Como os Componentes se Comunicam

      De Para Protocolo Finalidade
      Frontend (React) Backend API HTTP REST (axios) Listar leitores, controlar conexão, buscar configurações
      Frontend (React) Backend API SSE (EventSource) Receber eventos de cartão em tempo real
      Electron (main) Backend API HTTP REST (fetch) Garantir que a API está rodando, reconectar leitores
      Electron (main) Backend API SSE (fetch + stream) Escutar eventos de cartão para auto-paste
      Backend API Electron (main) HTTP POST porta 3792 Enviar notificações para a interface
      Frontend Electron (main) IPC (contextBridge) Controle de janela, tema, cache de settings
      Electron (main) Sistema Windows VBScript (wscript.exe) Simular Ctrl+V no aplicativo ativo

      Tecnologias Utilizadas

      Tecnologia Versão Uso
      Node.js ≥ 20 Runtime do Backend e Electron
      TypeScript 5.8 Linguagem principal (todos os módulos)
      Electron 35 Aplicação desktop (janela, tray, IPC)
      Express 4.21 Servidor HTTP da API REST
      React 18.3 Interface gráfica do usuário
      Vite 6.2 Bundler do frontend
      Zustand 5.0 Gerenciamento de estado do frontend
      Zod 3.24 Validação de dados (backend e frontend)
      koffi 2.13 FFI: chama funções da DLL nativa Digicon
      pino 9.6 Logging estruturado no backend
      Tailwind CSS 3.4 Estilos do frontend
      Flowbite React 0.10 Componentes UI
      axios 1.8 Cliente HTTP do frontend
      electron-builder 25 Empacotamento do instalador
      NSSM — Gerenciador de Serviço Windows (externo)

      📁 3. ESTRUTURA DE PASTAS E COMPONENTES

      O projeto é um monorepo npm workspaces com três pacotes independentes:

      insoft-readers-app/                ← Raiz do monorepo
      ├── package.json                   ← Workspace root (scripts globais)
      ├── insoft-readers-api/            ← Pacote: @insoft/backend
      └── insoft-readers-app/
          ├── electron/                  ← Pacote: @insoft/electron
          └── frontend/                  ← Pacote: @insoft/frontend
      

      📂 insoft-readers-api/ — Backend API

      Descrição funcional (para suporte):

      É o "motor" do sistema. Fica rodando em segundo plano, se comunica com o hardware do leitor e disponibiliza um servidor web local para que a interface e outros sistemas possam receber os dados dos cartões. Roda na porta 3791.

      Responsabilidades técnicas:

      • Gerenciar o ciclo de vida dos leitores de cartão (inicializar, conectar, desconectar, iniciar/parar polling)
      • Processar eventos de leitura aplicando formatação (prefixo/sufixo)
      • Manter histórico dos últimos 50 cartões lidos
      • Persistir configurações de runtime em arquivo JSON
      • Emitir eventos SSE para clientes conectados
      • Garantir que somente uma instância está rodando (single-instance check)

      📂 src/server.ts — Ponto de entrada do Backend

      Descrição funcional:

      Inicializa tudo ao ser executado: verifica se já existe uma API rodando, registra os leitores, monta o servidor HTTP e começa a escutar na porta 3791.

      Descrição técnica:

      • Executa ensureSingleApiInstance(): verifica via /health se já existe instância; se sim, encerra com process.exit(0); se a porta estiver ocupada por outro processo, encerra com process.exit(1)
      • Instancia ReaderRegistry, DeviceManager, CardService, CardEventBroker, AppProcessManager
      • Monta rotas Express: /health, /readers, /cards, /settings
      • Configura middleware: cors, express.json(), pinoHttp (logging HTTP)
      • Tratamento global de erros: ZodError → HTTP 400; erros Digicon conhecidos → HTTP 503; outros → HTTP 500
      • Inicia timer de manutenção (maintainReaders) a cada 1.500ms
      • Registra handlers de SIGINT/SIGTERM para shutdown gracioso

      📂 src/core/ — Núcleo da Aplicação

      ReaderRegistry.ts

      Descrição funcional:

      Um catálogo que registra quais tipos de leitores o sistema conhece. Funciona como uma "fábrica" de leitores.

      Descrição técnica:

      • Padrão de projeto: Registry + Factory
      • register(key, factory): registra uma função construtora associada a uma chave única (ex: "digicon-dg710")
      • create(key): chama a factory correspondente, retornando uma nova instância de ICardReader
      • Lança Error se a chave já existe (prevent duplicates) ou se a chave não foi registrada

      DeviceManager.ts

      Descrição funcional:

      O gerente dos leitores físicos. Agrupa todos os leitores e permite operações em batch (inicializar todos, descobrir todos, aplicar configurações em todos).

      Descrição técnica:

      • Estende EventEmitter do Node.js
      • Mantém um Map<string, ICardReader> internamente
      • addReader(reader): adiciona o leitor ao mapa e registra o callback onCardRead para reemitir o evento "cardRead" no próprio DeviceManager
      • initializeAll(): chama reader.initialize() em cada leitor; falhas são logadas mas não interrompem a inicialização dos demais
      • discoverAll(): chama reader.discover() opcionalmente (método opcional na interface)
      • applyReaderSettings(settings): propaga as configurações de runtime para todos os leitores que implementam applySettings
      • onCardRead(listener): atalho para escutar o evento "cardRead" do EventEmitter

      ReaderSettingsStore.ts

      Descrição funcional:

      Salva e carrega as configurações de como o leitor deve funcionar (ex: intervalo de leitura, prefixo/sufixo do cartão). As configurações ficam gravadas no arquivo reader-runtime-settings.json.

      Descrição técnica:

      • Lê/escreve o arquivo reader-runtime-settings.json (caminho configurável via READER_SETTINGS_FILE)
      • load(): carrega do disco; se o arquivo não existir ou for inválido, usa defaultReaderRuntimeSettings
      • get(): retorna as configurações em memória
      • update(next): mescla com as configurações atuais, valida/normaliza via normalizeSettings() e persiste em disco
      • normalizeSettings(): garante que intervalMs está entre 50ms e 10.000ms, prefixo/sufixo têm no máximo 32 chars

      CardService.ts

      Descrição funcional:

      O cérebro do sistema. Orquestra tudo: recebe as leituras do hardware, aplica formatação, guarda o histórico, distribui para os ouvintes e controla individualmente cada leitor.

      Descrição técnica:

      • Injeta DeviceManager (obrigatório) e ReaderSettingsStore (opcional, cria instância padrão)
      • No construtor: registra listener em deviceManager.onCardRead para:
        1. Aplicar prefixo/sufixo ao cardId via applyRuntimeSettingsToEvent()
        2. Prepend no array recentReads (máximo 50 itens via splice)
        3. Notificar todos os listeners registrados em this.listeners
      • initializeRuntimeSettings(): carrega settings do disco e aplica nos leitores
      • maintainReaders(): para cada leitor, se desconectado tenta connect(); se conectado mas não escutando tenta startListening() — usado pelo timer de manutenção do servidor
      • applyRuntimeSettingsToEvent(event): retorna novo objeto com cardId = prefix + cardId + suffix

      logger.ts

      Descrição funcional:

      Responsável por gerar os logs do sistema. Em produção, escreve JSON puro; em desenvolvimento, exibe logs coloridos e formatados no terminal.

      Descrição técnica:

      • Usa biblioteca pino com nível configurável via variável de ambiente LOG_LEVEL (padrão: "info")
      • Em NODE_ENV !== "production": ativa pino-pretty com cores e timestamp legível
      • Exporta instância singleton logger usada em todo o backend

      AppProcessManager.ts

      Descrição funcional:

      Permite que a API avise a interface gráfica quando um cartão é lido. Se a interface não estiver aberta, ela é iniciada automaticamente só para exibir a notificação.

      Descrição técnica:

      • notifyApiUsage(payload): verifica se o AppControlServer (porta 3792) está vivo via /health; se não, executa o .exe da interface com flag --tray; aguarda 1.200ms; tenta novamente; se disponível, faz POST /notify
      • launchAppTray(): usa spawn com detached: true para iniciar o processo filho sem bloquear a API
      • getExecutablePath(): resolve o caminho do executável da interface nos cenários dev e produção (via process.pkg para binário compilado com pkg)

      📂 src/api/routes/ — Rotas HTTP

      GET /health

      Retorna { "status": "ok" }. Usado por health checks de todas as camadas.

      GET /readers

      Chama service.getReaders() → deviceManager.discoverAll() + retorna lista de ReaderInfo[].

      GET /readers/status

      Retorna ReaderStatus[] com status atual de conexão/escuta de cada leitor.

      POST /readers/connect · POST /readers/disconnect

      Body: { "key": "digicon-dg710" } — conecta ou desconecta o leitor identificado pela chave.

      POST /readers/start · POST /readers/stop

      Inicia ou para o polling de leitura no leitor identificado.

      GET /cards/recent

      Retorna os últimos 50 cartões lidos em memória.

      GET /cards/events

      Abre uma conexão SSE (Server-Sent Events). O cliente recebe:

      • Evento connected ao conectar
      • Evento card-read a cada cartão detectado (payload: CardReadEvent)

      GET /settings/reader

      Retorna as configurações de runtime atuais.

      PUT /settings/reader

      Body: ReaderRuntimeSettings — valida via Zod, salva no disco e propaga para os leitores.


      📂 src/api/sse/CardEventBroker.ts

      Descrição funcional:

      Mantém abertas as conexões dos clientes que querem receber cartões em tempo real e distribui cada evento para todos ao mesmo tempo.

      Descrição técnica:

      • Mantém Set<Response> de conexões HTTP ativas
      • attachClient(res): configura headers SSE, envia evento connected, registra listener res.on("close") para remoção automática
      • broadcast(event): serializa CardReadEvent como SSE e escreve em todos os clientes conectados

      📂 src/devices/digicon/ — Implementação do Hardware

      DigiconDG710Reader.ts

      Descrição funcional:

      É o "driver" do leitor Digicon DG-710. Faz a comunicação com o hardware e gera um evento toda vez que um cartão é detectado.

      Descrição técnica:

      • Implementa ICardReader (interface contratual de todos os leitores)
      • Chave única: "digicon-dg710"
      • Usa DigiconFacade para todas as chamadas à DLL nativa
      • Polling por timeout: usa setTimeout recursivo com intervalo configurável (padrão 1.000ms)
      • Lógica de detecção:
        • continuousRead = false (padrão): só dispara evento na transição ausente→presente (wasCardPresent)
        • continuousRead = true: dispara em todo tick enquanto o cartão estiver presente
      • applySettings(settings): atualiza pollingMs e continuousRead; reinicia o loop se estiver ativo
      • Estados internos: connected, listening, handle, serial, lastError
      • Formato do evento emitido:
        {
          "readerKey": "digicon-dg710",
          "cardId": "12345678",
          "rawHex": "BC614E",
          "protocol": "mifare",
          "timestamp": "2026-04-02T10:00:00.000Z"
        }
        

      DigiconFacade.ts

      Descrição funcional:

      Camada que conversa diretamente com a DLL DG710Facade.dll do fabricante Digicon. É a ponte entre o código TypeScript e o hardware físico.

      Descrição técnica:

      • Usa koffi para FFI (Foreign Function Interface) — chama funções C da DLL sem Node addons
      • Mock mode: se a DLL não for encontrada ou não carregar, opera em modo simulação:
        • getChannels() retorna [710]
        • isCardPresent() simula presença de cartão em intervalos aleatórios (a cada ~5 segundos)
        • readMifareCard() retorna cardId aleatório
      • resolveDllPath(): busca DG710Facade.dll em ~9 caminhos candidatos; configurável via DIGICON_DLL_PATH
      • initializeRegistry(): inicia o registro Digicon (necessário antes de qualquer operação); idempotente
      • readMifareCard(handle): lê 4 bytes em little-endian → converte para hex big-endian → converte BigInt para decimal (10 dígitos)
      • Detecta incompatibilidade de arquitetura (x86 vs x64) e loga mensagem específica

      📂 src/interfaces/ — Contratos de Dados

      Interface Campos
      ICardReader key, getInfo(), getStatus(), initialize(), connect(), disconnect(), startListening(), stopListening(), onCardRead(), discover?(), applySettings?()
      CardReadEvent readerKey, cardId, protocol, timestamp, rawHex?
      ReaderInfo key, name, manufacturer, model, connected, listening, serial?, capabilities[]
      ReaderStatus key, connected, listening, lastError?
      ReaderRuntimeSettings prefix, suffix, intervalMs, appendNewLine, continuousRead

      📂 insoft-readers-app/electron/ — Processo Principal Electron

      Descrição funcional:

      É o "casca" desktop da aplicação. Cria a janela, o ícone na bandeja do sistema, garante que a API está rodando e implementa o auto-paste (cola o cartão no aplicativo ativo).


      📂 electron/main/main.ts — Ponto de Entrada do Electron

      Responsabilidades:

      • Garantir instância única da aplicação (app.requestSingleInstanceLock)
      • Chamar apiProcessManager.ensureApiRunning() antes de criar a janela
      • Criar e gerenciar BrowserWindow (frameless, 1200×820)
      • Iniciar subscrição SSE aos eventos de cartão (startCardEvents)
      • Implementar handleCardRead():
        • Se a janela estiver em foco: envia evento IPC card:read para a UI
        • Se a janela estiver em background: executa pasteToExternalFocusedApp()
      • pasteToExternalFocusedApp(): escreve o cardId na área de transferência + executa VBScript pré-gerado para simular Ctrl+V (com ou sem {ENTER} conforme appendNewLine)
      • Manter cache local de runtimeSettingsCache (atualizado a cada 1.200ms)
      • Registrar handlers IPC: window:minimize, window:maximize-toggle, window:close, window:get-state, reader-runtime-settings:update-cache
      • Gerenciar AppControlServer (porta 3792) e pendingNotifications

      📂 electron/main/services/ApiProcessManager.ts

      Descrição funcional:

      Garante que a API backend está rodando. Verifica se já está ativa, tenta iniciar como Serviço Windows, e se nada funcionar, inicia como processo filho.

      Descrição técnica:

      • ensureApiRunning() — fluxo de tentativas em ordem:
        1. Verifica /health → se OK, retorna
        2. Verifica se serviço Windows está instalado → tenta nssm start
        3. Aguarda health check (12 tentativas × 800ms = ~9,6s)
        4. Se ainda falhou: chama spawnApiProcess()
        5. Aguarda health check final → se falhar, lança Error
      • Em desenvolvimento: executa npm run dev:once -w @insoft/backend
      • Em produção: executa insoft-reader-api.exe da pasta resources/api/

      📂 electron/main/services/AppControlServer.ts

      Descrição funcional:

      Um mini servidor HTTP interno (porta 3792) que recebe notificações da API backend e as repassa para a interface gráfica.

      Descrição técnica:

      • Servidor HTTP puro (node:http) sem dependências externas
      • Rotas: GET /health → { status: "ok" } | POST /notify → dispara onNotification(payload)
      • onNotification é um callback injetado no construtor que envia mainWindow.webContents.send("app:notification", payload)

      📂 electron/main/services/HealthCheckService.ts

      Descrição funcional:

      Verifica se a API está "viva" fazendo uma requisição ao endpoint /health.

      Descrição técnica:

      • isHealthy(url): GET com timeout de 1.500ms; verifica response.ok e payload.status === "ok"
      • waitForHealthy(url, retries, delayMs): loop com tentativas e espera

      📂 electron/main/services/WindowsServiceManager.ts

      Descrição funcional:

      Verifica e inicia o serviço Windows da API usando as ferramentas sc e nssm.

      Descrição técnica:

      • isInstalled(name): executa sc query <name>; considera instalado se o comando retornar código 0 ou se a saída não contiver "does not exist"
      • start(name): executa nssm start <name>; retorna true se código de saída for 0
      • Funciona apenas em win32; retorna false em outras plataformas

      📂 electron/main/tray.ts

      Descrição funcional:

      Cria o ícone na bandeja do sistema (canto inferior direito da tela) com um menu de contexto.

      Menu disponível:

      • Abrir interface — exibe e foca a janela principal
      • Reconectar leitores — chama performReconnectReaders()
      • Sair — encerra o aplicativo

      📂 electron/main/uiActions.ts

      Descrição funcional:

      Gerencia o tema visual (dark/light) persistindo em arquivo de preferências do usuário.

      Descrição técnica:

      • Arquivo: %APPDATA%\Insoft Readers App\preferences.json
      • Handlers IPC: theme:get e theme:set
      • Aplica o tema ao sistema operacional via nativeTheme.themeSource

      📂 electron/ipc/reader.ipc.ts

      Descrição funcional:

      Implementa o comando "Reconectar Leitores" que faz disconnect + connect + start em todos os leitores de uma vez.

      Descrição técnica:

      • performReconnectReaders(): GET /readers → para cada leitor: POST /readers/disconnect → POST /readers/connect → POST /readers/start
      • Registra handler IPC reader:reconnect que chama a função acima

      📂 electron/preload/preload.ts

      Descrição funcional:

      Ponte segura entre o código da interface (React) e o Electron. Expõe apenas as funções necessárias para a UI, sem dar acesso completo ao Node.js.

      APIs expostas via contextBridge:

      Namespace Métodos
      window.readerApi reconnectReaders(), syncRuntimeSettings(settings), onCardRead(callback)
      window.appWindow getState(), onStateChange(callback)
      window.appTheme get(), set(theme)
      window.electron minimizeApp(), maximizeRestoreApp(), closeApp(), getWindowState(), onWindowStateChange(callback)
      window.appNotifications onNotify(callback)

      📂 insoft-readers-app/frontend/ — Interface Gráfica (React)

      Descrição funcional:

      A tela do sistema. Exibe o status dos leitores, os cartões lidos, permite configurar o comportamento do leitor e monitorar eventos em tempo real.


      📂 src/store/reader.store.ts — Estado Global

      Descrição técnica:

      • Usa Zustand (store reativo sem Context API do React)
      • Estado: readers[], statuses[], recentCards[], activeReaderKey
      • prependCard(event): adiciona na frente e mantém máximo 50 itens
      • setRecentCards(events): limita a 50 itens

      📂 src/hooks/ — Hooks React

      useReaders.ts

      • Busca dados do backend a cada chamada de refresh(): fetchReaders(), fetchReaderStatus(), fetchRecentCards() em paralelo
      • Expõe: loading, error, connect(key?), disconnect(key?), start(key?), stop(key?), refresh()
      • Usa activeReaderKey do store quando key não for informado

      useCardEvents.ts

      • Abre conexão EventSource para GET /cards/events
      • Escuta evento card-read e chama prependCard() no store
      • Fecha a conexão no useEffect cleanup

      📂 src/services/api.ts — Cliente HTTP

      • Instância axios com baseURL = VITE_BACKEND_URL ?? "http://127.0.0.1:3791" e timeout de 5s
      • Funções exportadas: fetchReaders, fetchReaderStatus, fetchRecentCards, connectReader, disconnectReader, startReader, stopReader, fetchReaderSettings, saveReaderSettings, buildCardEventsUrl

      📂 src/pages/ — Páginas da Interface

      Página Rota interna Descrição
      Dashboard dashboard Visão geral: 4 cards de estatística, tabela de status, ações rápidas
      Readers readers Gerencia leitores: seleção, connect/disconnect/start/stop
      CardMonitoring monitoring Stream ao vivo de eventos SSE, métricas de cartões únicos
      DeviceLogs logs Painel de logs baseado nos dados de status e eventos recentes
      Settings settings Formulário de configurações de runtime do leitor

      📂 src/components/settings/SettingsForm.tsx

      Descrição funcional:

      Formulário para configurar como o leitor funciona: intervalo de leitura, prefixo/sufixo do código, modo contínuo, nova linha.

      Descrição técnica:

      • Usa react-hook-form + zodResolver para validação
      • No load: busca GET /settings/reader e popula o formulário com reset(settings)
      • No submit: chama PUT /settings/reader + window.readerApi?.syncRuntimeSettings(updated) para sincronizar o cache do processo Electron

      🔄 4. FLUXOS PRINCIPAIS DO SISTEMA

      🔹 Fluxo 1: Inicialização do Sistema

      Explicação simplificada (Suporte):

      Quando o usuário abre o Insoft Readers App, o programa verifica se a API está funcionando. Se não estiver, ele a inicia automaticamente. Depois cria a janela e começa a escutar os cartões.

      Explicação técnica (Dev):

      app.on("ready")
        │
        ├─► apiProcessManager.ensureApiRunning()
        │     ├─ GET /health → OK? → continua
        │     ├─ Não OK → verifica serviço Windows (sc query)
        │     │     ├─ Instalado → nssm start → aguarda health (12×800ms)
        │     │     └─ Não instalado → spawnApiProcess() → aguarda health
        │     └─ Falha total → app.quit()
        │
        ├─► createMainWindow(startInTray)
        │     ├─ BrowserWindow frameless 1200×820
        │     ├─ Carrega frontend (URL dev ou arquivo dist)
        │     ├─ registerReaderIpc(ipcMain)
        │     └─ createAppTray(...)
        │
        ├─► initializeUIActions()
        │     └─ Lê preferences.json → aplica tema
        │
        ├─► appControlServer.start() (porta 3792)
        │
        └─► startCardEvents()
              ├─ refreshRuntimeSettings() (busca /settings/reader)
              ├─ setInterval(refreshRuntimeSettings, 1200ms)
              └─ connectCardEvents() → GET /cards/events (SSE stream)
      

      🔹 Fluxo 2: Leitura de um Cartão — Ponta a Ponta

      Explicação simplificada (Suporte):

      O usuário aproxima o cartão do leitor. O hardware detecta, o sistema processa e automaticamente cola o número do cartão no campo ativo do Windows. Se a janela estiver aberta, aparece uma janela popup com o número.

      Explicação técnica (Dev):

      [Hardware DG-710]
        │  Cartão aproximado
        ▼
      DigiconFacade.isCardPresent(handle) → true
        │
      DigiconFacade.readMifareCard(handle)
        │  rawHex = bytes[3..0] em hex big-endian
        │  cardId = BigInt(0x{rawHex}).toString(10)
        │  Exemplo: bytes = [0x4E, 0x61, 0xBC, 0x00]
        │           rawHex = "00BC614E"
        │           cardId = "12345678"
        ▼
      DigiconDG710Reader.runPollingTick()
        │  continuousRead=false: só dispara na transição
        │  continuousRead=true: dispara a cada tick
        ▼
      DeviceManager.emit("cardRead", rawEvent)
        ▼
      CardService.onCardRead listener
        │  applyRuntimeSettingsToEvent(rawEvent)
        │  cardId = prefix + "12345678" + suffix
        │  recentReads.unshift(processedEvent)  ← histórico in-memory (max 50)
        ▼
      CardEventBroker.broadcast(processedEvent)  ← notifica clientes SSE
        │
      AppProcessManager.notifyApiUsage(...)      ← notifica interface
        │
        ├─► [Clientes SSE do frontend React]
        │     useCardEvents → prependCard(event) → store atualizado → UI re-renderiza
        │
        └─► [Electron main process — SSE stream]
              handleCardRead(event)
                ├─ janela em foco? → ipcMain.send("card:read", event) → CardReadModal abre
                └─ janela em background?
                     ├─ clipboard.writeText(cardId)
                     └─ spawn("wscript", ["//B", vbsPaste]) → Ctrl+V no app ativo
      

      A documentação continua na parte 2, através da seguinte URL:

      Documentação Técnica - Parte 2

      1 Resposta Última resposta Responder Citar 0
      • Primeiro post
        Último post
      Powered by NodeBB | Contributors