Comissionamento de portal Zebra
Como ligar um leitor fixo Zebra FX ao Gestão de Ativos, do cadastro do ponto de leitura até a movimentação aparecendo sozinha na tela de registros.
Este guia começa onde o Instalação e validação termina: o middleware já está instalado e no ar. Aqui o assunto é a integração entre os dois sistemas.
Fluxo verificado ponta a ponta em 10/09/2026, com Gestão de Ativos 1.1.10 sobre SQL Server 2019 (banco pré-criado, collation case-sensitive) e Middleware LITE 1.0.0 na mesma máquina.
A cadeia
O leitor não fala com o Gestão de Ativos. Ele abre um socket para o middleware, que junta as leituras em lote e faz uma única chamada HTTP por passagem.
Parte 1 — Preparar o Gestão de Ativos
A ordem importa: o endpoint que o middleware vai chamar só existe depois que o ponto de leitura foi criado, porque a chave é derivada do ID dele.
1. Criar o nível e o ponto de leitura do portal
Menu Níveis Orga.
Um nível é o local físico (fábrica, CD, filial). Dentro dele, cada ponto de leitura é um lugar por onde o ativo passa ou onde ele fica parado.
Crie o nível, depois adicione um ponto de leitura para a doca:
- Tipo de leitura:
Leitor Fixo Zebra— é o que habilita a geração da chave de API. - Status do ativo: o status que todo item recebe ao passar por aqui (ex.:
ativo). - Gerar alerta: ligue apenas se toda passagem tiver de virar alerta.
Crie também um segundo ponto de leitura comum (ex.: Estoque, tipo QR Code). Ele será o local de
origem dos itens e, se você usar o mapeamento de entrada/saída do passo 5, o local de trânsito.
2. Liberar os níveis do usuário "Dispositivo Fixo"
Menu Administração › Usuários
A instalação cria um usuário de sistema chamado Dispositivo Fixo (device@system.local). É a
identidade com que o portal grava as movimentações — é o nome que aparece na auditoria.
Ele nasce sem nenhum nível autorizado. Edite o usuário e marque o nível do portal (ou "ver todos os níveis").
Sem nível liberado, toda leitura volta 403 — Usuário não possui níveis autorizados. O sintoma
engana: o leitor lê, o middleware mostra a action disparando, e nada aparece no Gestão de Ativos.
3. Copiar o endpoint do portal
Menu Movimentação › Pontos de Leitura
A lista mostra os pontos de leitura com uma coluna Endpoint. No ponto marcado como
Leitor Fixo Zebra, clique no ícone de copiar. Vai para a área de transferência a URL completa, já
com a chave:
http://SERVIDOR:4001/movimentacao/itens/movimentar/2?apiKey=5dad1687dd76…9841
O número antes do ? é o ID do ponto de leitura. A chave é um HMAC de movimentacao:<id> assinado
com o JWT_SECRET da instalação, e vale só para esse ponto — ela não abre nenhuma outra rota da
API.
A chave é derivada do JWT_SECRET. Reinstalar por cima preserva o segredo e a URL continua válida.
Instalar do zero gera um segredo novo e invalida todas as URLs de portal — é preciso copiar de
novo e reconfigurar cada action.
4. Garantir que os ativos existem
Menu Etiquetas / Impressão
O portal movimenta ativos, não cria. Um EPC que não está cadastrado é ignorado, e a resposta lista
ele em epcsNaoEncontrados. Se nenhum EPC do lote for conhecido, a chamada volta 404.
Os ativos entram no sistema pelo fluxo de etiquetas: cadastre o produto, gere os itens de impressão e imprima. Antes de comissionar o portal, confirme que as tags do teste já aparecem em Ativos.
5. Ligar o mapeamento de entrada e saída (opcional)
Menu Administração › Configuração
Por padrão, toda passagem pelo portal registra uma movimentação para o próprio portal. Com o mapeamento ligado, o sistema passa a alternar o sentido a cada passagem e grava o tipo do evento:
- item parado no portal, lido de novo → saída, e ele vai para o local de trânsito;
- item em trânsito, lido no portal → entrada, e ele volta para o portal.
Configure nesta ordem, senão a segunda etapa é recusada:
- Escolha o local dos itens em trânsito e salve. Vale qualquer ponto de leitura ativo que não
seja um portal Zebra — use o
Estoquedo passo 1. - Ative a chave mapeamento de entrada e saída.
Para conferir: passe a mesma tag duas vezes pelo portal e abra Movimentação › Registros. Os dois lançamentos têm que sair com sentidos opostos.
Parte 2 — Conectar o leitor ao middleware
O leitor se anuncia sozinho assim que o agente embarcado sobe. Você não cadastra o leitor no painel — ele aparece.
6. Instalar o DA-APP com o endereço do middleware
No leitor Zebra FX
O DA-APP é o agente que roda dentro do FX e abre o socket para o servidor. Ele é gerado com o endereço já embutido, então informe no build:
| Parâmetro | Valor | Observação |
|---|---|---|
middlewareHost | 192.168.0.50 | IP ou DNS do servidor, alcançável da rede do leitor |
backendTcpPort | 5555 | socket do DA-APP |
backendHttpPort | 4141 | painel web |
readerUsername / readerPassword | admin / … | credenciais do próprio FX, usadas pelo agente nas APIs locais |
Rede: o leitor precisa alcançar SERVIDOR:5555, e o operador precisa alcançar SERVIDOR:4141. Em
servidor Windows, libere as duas portas na entrada do firewall; em nuvem, também no security group.
Não existe um .deb genérico: o IP e as portas são gravados no agente na hora do build. Um pacote por
site — ou por servidor de middleware.
Existe uma saída, se você precisar redirecionar um leitor já instalado sem regerar: as variáveis de
ambiente HIOT_SERVER_HOST e HIOT_SERVER_PORT vencem o valor gravado.
Como gerar o .deb
O gerador vive no repositório do middleware, em back/installer/da-app-builder-service. Ele monta o
agente, os scripts de start/stop e empacota com dpkg-deb — por isso precisa rodar em Linux
(no Windows, use WSL).
O README.md do diretório descreve subir um serviço HTTP numa VPS e pedir o build por token. Isso é
útil se você quiser que outras pessoas gerem pacotes sem acesso ao repositório, mas esse serviço não
está hospedado em lugar nenhum hoje — a URL padrão do cliente é um placeholder. Para uma implantação
pontual, chame o gerador direto.
Salve como gera-daapp.js na raiz de da-app-builder-service:
const path = require("path");
const fs = require("fs/promises");
const { buildDaAppPackage } = require("./src/package-builder");
const { normalizeBuildRequest } = require("./src/builder-utils");
// uso: node gera-daapp.js <IP_DO_MIDDLEWARE> <DIR_SAIDA> [porta_tcp] [porta_http]
(async () => {
const cfg = normalizeBuildRequest({
middlewareHost: process.argv[2],
backendTcpPort: Number(process.argv[4] || 5555),
backendHttpPort: Number(process.argv[5] || 4141),
readerUsername: process.env.FX_USER || "admin",
readerPassword: process.env.FX_PASS || "Change@123",
});
const built = await buildDaAppPackage(cfg);
await fs.mkdir(process.argv[3], { recursive: true });
const dest = path.join(process.argv[3], built.fileName);
await fs.copyFile(built.outputFile, dest);
await built.cleanup();
console.log("OK ->", dest);
})().catch((e) => { console.error("FALHOU:", e.message); process.exit(1); });
E rode:
node gera-daapp.js 192.168.0.50 ./dist
Não precisa de npm install: o package-builder só usa módulos nativos do Node. A única dependência
externa é o dpkg-deb, que já vem em qualquer Debian/Ubuntu.
Se as credenciais do leitor não forem as padrão, passe antes do comando:
FX_USER=operador FX_PASS='senha-real' node gera-daapp.js 192.168.0.50 ./dist
O agente usa usuário e senha para chamar as APIs locais do próprio leitor. Com credencial errada, o pacote instala, conecta no middleware e aparece no painel — mas falha na hora de comandar o rádio. O sintoma não aponta para a senha.
O que vem dentro
hiot-bridge-agent.js → o agente; vai para /apps/ no leitor
start_hiot-bridge-agent.sh → node /apps/hiot-bridge-agent.js &
stop_hiot-bridge-agent.sh
connect-scripts.txt → resumo da configuração embutida
O control do pacote traz APP_TYPE: DA: é um user app do Zebra IoT Connector, instalado pelo
console web do leitor. O procedimento de upload é o da própria Zebra —
packaging and deployment.
Para conferir um pacote antes de mandar para o cliente:
dpkg-deb -I pacote.deb # metadados, confirma APP_TYPE: DA
dpkg-deb -c pacote.deb # lista os arquivos
dpkg-deb -x pacote.deb /tmp/v && grep SERVER_HOST /tmp/v/hiot-bridge-agent.js
O último comando é o que importa: mostra o IP que realmente ficou gravado.
7. Conferir o leitor e definir o modo de leitura
Painel do middleware —
http://SERVIDOR:4141
Com o DA-APP rodando, o leitor aparece no menu lateral. Clique nele e confira que o rádio está
conectado e as antenas certas estão habilitadas com a potência desejada.
| Modo | Quando usar |
|---|---|
| Start e stop manual | comissionamento e testes — você controla pelo painel |
| Start por GPI e stop por GPI | portal com sensor de presença nas duas pontas |
| Start por GPI e stop por tempo | portal com um sensor só; a passagem tem duração previsível |
| Contínuo | leitura permanente, com envio em lote por intervalo |
Em portal de doca, o normal é GPI: o sensor dispara a leitura, e o lote é enviado quando ela termina.
O debounce evita que oscilação elétrica do sensor abra várias leituras.
Use Adicionar leitor simulador. Ele aceita uma lista de tags por antena e se comporta como um FX real — dispara as actions do mesmo jeito. Foi assim que este fluxo foi validado.
8. Cadastrar a action que movimenta
Painel do middleware — Cadastrar ações
Uma action é a chamada HTTP que o middleware dispara quando fecha um lote de leituras. Crie uma por portal:
| Campo | Valor |
|---|---|
| Nome | algo que identifique o portal, ex.: GA — Doca 01 |
| Método | POST |
| URL | a URL copiada no passo 3, com o IP no lugar de localhost |
| Estratégia de envio | lote — uma chamada por passagem, com todas as tags |
| Timeout | 10000 ms |
No corpo da requisição, monte uma lista de objetos com a chave leituras e três campos:
| Chave | Origem | Vira |
|---|---|---|
epc | EPC | o código da tag |
reads | SEEN_COUNT | quantas vezes foi vista |
antena | ANTENNA | antena que leu |
O middleware vai montar exatamente isto e postar na URL:
{
"leituras": [
{ "epc": "E28011700000021234500001", "reads": 6, "antena": 1 },
{ "epc": "E28011700000021234500002", "reads": 6, "antena": 1 }
]
}
Depois de salvar, volte à tela do leitor, encontre Associar action e escolha a action recém-criada. É esse vínculo que faz o lote sair.
Não use o modo de entrega "simples". Ele existe para integrações genéricas e manda um corpo com
batchId, macAddress e reads — formato que o Gestão de Ativos não entende. A movimentação só
funciona por action.
Não use localhost na URL, mesmo com os dois sistemas na mesma máquina. O middleware resolve
localhost para IPv6 e a API do Gestão de Ativos escuta em IPv4 — a action falha com
ECONNREFUSED ::1:4001. Use 127.0.0.1 ou o IP do servidor.
Parte 3 — Validar a passagem
9. Passar a tag e conferir os dois lados
- Inicie a leitura (pelo painel, ou passando pelo sensor) e encerre.
- No painel do leitor, abra o diagnóstico de entrega. Você deve ver
action-requestcom o corpo montado e, na sequência,action-responsecomstatus 200. - No Gestão de Ativos, abra Movimentação › Registros. Os lançamentos aparecem com usuário Dispositivo Fixo e destino no ponto do portal.
- Abra o ativo em Ativos e confirme que o local atual mudou para o portal.
O corpo da resposta do Gestão de Ativos é o melhor diagnóstico que existe — ele diz quantos processou e quais EPCs não conhecia:
{
"message": "Movimentações processadas com sucesso",
"processados": 3,
"epcsNaoEncontrados": [],
"movimentacoes": [
{ "epc": "E280…0001", "movimentacao_id": 7, "reads": 6, "antena": 1 }
]
}
10. Quando não funciona
| O que você vê | Causa | Correção |
|---|---|---|
| Leitor não aparece no painel | DA-APP não subiu, ou porta 5555 bloqueada | Confira o serviço no FX e libere a porta entre leitor e servidor |
| Leitor conecta, mas não obedece start/stop | Credenciais Local REST erradas no pacote | Passo 6 — regere o .deb com FX_USER/FX_PASS corretos |
| Leitor aponta para o servidor errado | IP compilado num .deb antigo | Regere, ou sobrescreva com HIOT_SERVER_HOST |
ECONNREFUSED ::1:4001 | localhost resolvendo para IPv6 | Troque por 127.0.0.1 ou pelo IP do servidor |
403 níveis autorizados | "Dispositivo Fixo" sem nível | Passo 2 — libere o nível do portal para o usuário |
401 Token inválido | Chave não bate com o JWT_SECRET atual | Copie a URL de novo no passo 3 e refaça a action |
404 nenhum EPC válido | Tags não cadastradas como ativos | Passo 4 — gere as etiquetas antes |
| Action dispara, nada é gravado | Modo de entrega "simples" em vez de action | Passo 8 — associe a action ao leitor |
422 processo de trânsito | Mapeamento ligado sem trânsito válido | Passo 5 — salve o trânsito antes de ativar a chave |
| Lê, grava, mas sem entrada/saída | Chave de mapeamento desligada | Passo 5 — o tipo do evento fica vazio sem ela |
Referência — contrato do endpoint
Útil se você for integrar outro leitor, ou depurar com curl antes de mexer no middleware.
A rota POST /movimentacao/itens/movimentar/<id> aceita o formato do middleware e também o formato
nativo do Zebra IoT Connector. O EPC é normalizado para maiúsculas nos dois casos.
// formato do middleware / mobile / web
{ "leituras": [ { "epc": "E280…0001", "reads": 2, "antena": 4,
"timestamp": "2026-09-10 09:30:00" } ] }
// formato nativo Zebra IoT Connector — array na raiz
[ { "data": { "idHex": "e280…0003", "reads": 7, "antenna": 2 },
"timestamp": "2026-09-10T12:31:00.000Z" } ]
A autenticação vale por ?apiKey= na query ou por Authorization: Bearer <chave>. Teste rápido de
linha de comando:
curl -X POST "http://192.168.0.50:4001/movimentacao/itens/movimentar/2?apiKey=SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{"leituras":[{"epc":"E28011700000021234500001","reads":1,"antena":1}]}'
Portas e caminhos
| Item | Padrão |
|---|---|
| API do Gestão de Ativos | :4001 |
| Front do Gestão de Ativos | :3000 |
| Painel do middleware | :4141 |
| Socket DA-APP | :5555 |
| Dados do middleware | C:\ProgramData\H1TECH-Middleware-LITE |
| Logs de serviço | …\service-logs |
| Instalação do Gestão de Ativos | C:\Program Files\H1Tech\GestaoAtivos |
| Log de instalação | C:\ProgramData\H1Tech\GestaoAtivos\logs |
O que foi e o que não foi validado
Verificado ponta a ponta: agregação do lote pelo middleware, montagem do corpo, autenticação por chave de dispositivo, gravação da movimentação no SQL Server e o mapeamento de entrada/saída alternando o sentido a cada passagem.
Não validado com hardware real: a instalação do DA-APP no FX físico e o disparo por GPI. O teste usou o leitor simulador, que dispara as actions exatamente do mesmo jeito, mas não substitui um FX na doca.