Um sistema abrangente de testes .NET 8 para avaliação de operações de escrita em tags RFID utilizando o Impinj Octane SDK. Este projeto implementa múltiplas estratégias de teste para avaliar diferentes aspectos de performance, confiabilidade e funcionalidade de escrita em tags RFID.
Esta aplicação fornece um framework estruturado de testes para operações de escrita em tags RFID, implementando várias estratégias de teste usando o padrão Strategy para organizar diferentes cenários de teste. A arquitetura facilita a adição de novos casos de teste mantendo uma interface consistente.
- .NET 8.0 SDK
- Impinj Octane SDK (v5.0.0)
- LLRP SDK (incluído com o Octane SDK)
- Leitor RFID Impinj (hostname/endereço IP necessário)
- Docker (opcional, para execução containerizada)
Para compartilhar este repositório em um GitHub corporativo sem expor dados de clientes:
- Configuração sanitizada: o arquivo
OctaneTagWritingTest/config.example.jsoncontém apenas hostnames e identificadores fictícios. Copie-o localmente paraconfig.jsone preencha as informações reais fora do controle de versão. - Arquivos locais ignorados:
config.json,reader_settings.jsone a pastareader_settings/já estão listados no.gitignorepadrão. Valide que nenhuma variante com credenciais foi adicionada ao repositório antes de publicar. - Dados de amostra fictícios: as listas
epc_list.txtetid_list.txt, bem como as constantes de teste emTagUtils.Tests, utilizam valores claramente fictícios e anotados nos comentários. Mantenha esta distinção ao gerar novos conjuntos de teste. - Documentação neutra: substitua quaisquer referências a endereços IP ou infraestrutura cliente por placeholders (por exemplo,
detector.example.com). Os exemplos de CLI e Docker neste README já seguem este padrão. - Licenciamento corporativo: atualize o arquivo
LICENSEcom o texto aprovado pela empresa antes de abrir o código internamente.
OctaneTagWritingTest/
├── JobStrategies/
│ ├── JobStrategy0ReadOnlyLogging.cs # Logging apenas de leitura
│ ├── JobStrategy1SpeedStrategy.cs # Teste de velocidade de escrita
│ ├── JobStrategy2MultiAntennaWriteStrategy.cs # Escrita multi-antena
│ ├── JobStrategy3BatchSerializationPermalockStrategy.cs # Operações em lote
│ ├── JobStrategy4VerificationCycleStrategy.cs # Ciclo de verificação
│ ├── JobStrategy5EnduranceStrategy.cs # Teste de resistência
│ ├── JobStrategy6RobustnessStrategy.cs # Teste de robustez
│ ├── JobStrategy7OptimizedStrategy.cs # Estratégia otimizada
│ ├── JobStrategy8MultipleReaderEnduranceStrategy.cs # Resistência multi-leitor
│ └── JobStrategy9CheckBox.cs # Teste CheckBox
├── Helpers/
│ ├── EpcListManager.cs # Gerenciamento de listas EPC
│ ├── TagOpController.cs # Controle de operações de tags
│ ├── CommandLineParser.cs # Parser de linha de comando
│ └── InteractiveConfig.cs # Configuração interativa
├── BaseTestStrategy.cs # Classe base para estratégias
├── IJobStrategy.cs # Interface do padrão Strategy
├── JobManager.cs # Gerenciador de execução de testes
├── Program.cs # Ponto de entrada da aplicação
├── ApplicationConfig.cs # Configuração da aplicação
├── ReaderSettings.cs # Configurações do leitor
├── ReaderSettingsManager.cs # Gerenciador de configurações
└── Dockerfile # Configuração Docker
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
</Project>- OctaneSDK (v5.0.0)
- Newtonsoft.Json (v13.0.3)
- Microsoft.VisualStudio.Azure.Containers.Tools.Targets (v1.21.0)
- Apenas logging de operações de leitura
- Não realiza escrita, apenas monitora tags
- Otimizado para máxima velocidade de escrita
- Mede e registra timing das operações de escrita
- Resultados salvos em arquivo CSV
- Testa escrita através de múltiplas antenas
- Avalia coordenação e troca de antenas
- Testa operações de escrita em lote
- Avalia performance de serialização
- Inclui operações de permalock
- Implementa ciclos de escrita-verificação
- Garante integridade dos dados escritos
- Teste de resistência/durabilidade
- Executa múltiplos ciclos de escrita
- Teste de robustez com retry logic
- Implementa recuperação de erros
- Máximo de 5 tentativas por operação
- Estratégia otimizada para performance
- Configurações ajustadas para melhor throughput
- Estratégia avançada com múltiplos leitores
- Pode operar com qualquer combinação de leitores: detector, writer e verifier
- Detector: monitora tags no campo
- Writer: executa operações de escrita
- Verifier: verifica integridade dos dados escritos
- Suporte a GPI para sincronização
- Logging detalhado com timestamps e métricas
Esta estratégia agora permite executar o teste com 1, 2 ou 3 leitores. Basta informar os hostnames dos leitores desejados; leitores omitidos serão ignorados. Composições suportadas:
- detector + writer + verifier
- detector + writer
- detector + verifier
- writer + verifier
- apenas detector
- apenas writer
- apenas verifier
O comportamento do leitor verificador (verifier) ao detectar que o EPC lido nao corresponde ao EPC esperado agora e configuravel, permitindo operar mais rapido quando nao se deseja tentar reescrever a tag.
- VerifierRewriteOnMismatch: habilita tentativa de reescrita quando ha mismatch (padrao: true). Defina como false para apenas registrar o mismatch sem reescrever.
- VerifierEpcCompareMode: define como os EPCs sao comparados:
- "Full": compara o EPC completo
- "Offset": compara a partir de um deslocamento de caracteres (padrao)
- VerifierEpcCompareOffset: indice de inicio da comparacao quando em modo Offset (padrao: 13)
Exemplo (OctaneTagWritingTest/config.json):
{
"VerifierRewriteOnMismatch": false,
"VerifierEpcCompareMode": "Offset",
"VerifierEpcCompareOffset": 13
}
Observacoes:
- Os padroes preservam o comportamento anterior (reescrita habilitada, comparacao por offset em 13).
- A comparacao por offset reflete a logica previa que desconsiderava campos de cabecalho do EPC.
| Parâmetro | Descrição |
|---|---|
--detector <hostname> |
Hostname/IP do leitor detector. |
--writer <hostname> |
Hostname/IP do leitor writer. |
--verifier <hostname> |
Hostname/IP do leitor verifier. |
--desc <description> |
Descrição utilizada nos logs do teste. |
--sku <sku> |
SKU de 12 dígitos para codificação. |
--header <header> |
Cabeçalho EPC quando não utiliza SGTIN‑96. |
--code <code> |
Código de item EPC quando não utiliza SGTIN‑96. |
--quantity <number> |
Quantidade de EPCs a gerar. |
--detector-power <dbm> |
Potência de transmissão do detector. |
--writer-power <dbm> |
Potência de transmissão do writer. |
--verifier-power <dbm> |
Potência de transmissão do verifier. |
--use-gpi-verification <true/false> |
Habilita GPI para fase de verificação. |
--gpi-trigger-state <true/false> |
Estado do GPI que inicia a verificação. |
| `--gpi-port <1 | 2>` |
--gpo-pulse-port <n> |
Porta GPO utilizada para pulso. |
--gpo-static-port <n> |
Porta GPO utilizada de forma estática. |
--detector-antennas "port:power:maxRx:rxSens,..." |
Configuração das antenas do detector. |
--writer-antennas "port:power:maxRx:rxSens,..." |
Configuração das antenas do writer. |
--verifier-antennas "port:power:maxRx:rxSens,..." |
Configuração das antenas do verifier. |
--config <path> |
Carrega parâmetros de um arquivo JSON. |
--interactive |
Inicia modo de configuração interativo. |
--help |
Mostra mensagem de ajuda. |
Dica: informe apenas os parâmetros correspondentes aos leitores presentes. Se um hostname não for fornecido (ou estiver vazio), esse leitor será desconsiderado.
- Teste específico para funcionalidades CheckBox
- Validação de SKUs específicos
# Execução básica com dois leitores
OctaneTagWritingTest.exe [detector-hostname] [writer-hostname]
# Execução com três leitores (detector, writer, verifier)
OctaneTagWritingTest.exe [detector-hostname] [writer-hostname] [verifier-hostname]
# Modo interativo
OctaneTagWritingTest.exe --interactive
# Ajuda
OctaneTagWritingTest.exe --helpPara cenários de serialização rápida em que apenas um leitor writer está disponível, é possível carregar todas as informações
essenciais a partir do config.json e disparar a escrita diretamente com a antena 1. O exemplo abaixo utiliza os campos
EpcHeader e EpcPlainItemCode para definir um EPC plano, sem habilitar SGTIN‑96.
-
Copie
OctaneTagWritingTest/config.example.jsonparaOctaneTagWritingTest/config.jsone ajuste apenas os campos relevantes:{ "WriterHostname": "writer.local", "Sgtin96Enabled": false, "EpcHeader": "B6", "EpcPlainItemCode": "00000000012345", "Quantity": 10, "WriterAntennas": { "Antennas": [ { "Port": 1, "IsEnabled": true, "TxPowerInDbm": 27, "MaxRxSensitivity": true, "RxSensitivityInDbm": -70 } ] } }Os demais campos podem ser removidos ou deixados com valores fictícios; apenas o hostname do writer e a antena utilizada precisam refletir o ambiente real.
-
Execute o teste informando apenas o writer e o arquivo de configuração:
dotnet run --project OctaneTagWritingTest -- \ --writer writer.local \ --config OctaneTagWritingTest/config.json
O programa carregará o cabeçalho (
EpcHeader) e o código plano (EpcPlainItemCode) do arquivo de configuração e gerará os EPCs sequenciais necessários (Quantity) utilizando exclusivamente a porta 1 do writer.
Para operações que precisam validar cada EPC logo após a escrita, é possível orquestrar os três leitores (detector, writer e
verifier) operando com uma antena cada. O detector garante a presença da tag no campo, o writer executa a escrita e o verifier
confirma o EPC utilizando a porta GPI 1 para sincronizar o ciclo de verificação. O exemplo abaixo demonstra como carregar o
GTIN de origem pelo parâmetro Sgtin96SourceGtin no config.json e reutilizar as antenas padrão (porta 1) em cada leitor.
-
Copie
OctaneTagWritingTest/config.example.jsonparaOctaneTagWritingTest/config.jsone ajuste apenas os campos relevantes:{ "DetectorHostname": "detector.local", "WriterHostname": "writer.local", "VerifierHostname": "verifier.local", "UseGpiForVerification": true, "GpiPortToProcessVerification": 1, "GpiTriggerStateToProcessVerification": true, "Sgtin96Enabled": true, "Sgtin96SourceGtin": "01234567890123", "Quantity": 48, "DetectorAntennas": { "Antennas": [ { "Port": 1, "IsEnabled": true, "TxPowerInDbm": 25, "MaxRxSensitivity": true, "RxSensitivityInDbm": -65 } ] }, "WriterAntennas": { "Antennas": [ { "Port": 1, "IsEnabled": true, "TxPowerInDbm": 27, "MaxRxSensitivity": true, "RxSensitivityInDbm": -70 } ] }, "VerifierAntennas": { "Antennas": [ { "Port": 1, "IsEnabled": true, "TxPowerInDbm": 24, "MaxRxSensitivity": true, "RxSensitivityInDbm": -68 } ] } }Ajuste os hostnames e níveis de potência conforme a infraestrutura disponível. O uso de
Sgtin96SourceGtingera a sequência SGTIN-96 automaticamente para a quantidade configurada. -
Execute o programa informando os três leitores e o caminho para o arquivo de configuração:
dotnet run --project OctaneTagWritingTest -- \ --detector detector.local \ --writer writer.local \ --verifier verifier.local \ --config OctaneTagWritingTest/config.json
-
Selecione
[8] JobStrategy8MultipleReaderEnduranceStrategyquando o menu interativo aparecer. ComUseGpiForVerificationhabilitado eGpiPortToProcessVerificationdefinido como 1, o verifier aguardará o sinal GPI na porta 1 antes de efetuar a leitura de validação. Enquanto isso, o detector mantém o monitoramento da tag na antena 1, permitindo que o writer serialize rapidamente cada EPC e o verifier confirme o valor escrito.
Quando há necessidade de serializar tags com o máximo de cobertura física e controle por sensor, é possível operar apenas com o
leitor writer utilizando todas as quatro portas de antena e um sensor GPI para iniciar a rotina de leitura/gravação. O exemplo
abaixo aproveita o campo Sgtin96SourceGtin para gerar EPCs no formato SGTIN-96 diretamente a partir do config.json.
-
Copie
OctaneTagWritingTest/config.example.jsonparaOctaneTagWritingTest/config.jsone ajuste os campos relevantes para o seu ambiente:{ "WriterHostname": "writer.local", "UseGpiForVerification": true, "GpiPortToProcessVerification": 1, "GpiTriggerStateToProcessVerification": true, "GpiDebounceInMs": 50, "Sgtin96Enabled": true, "Sgtin96SourceGtin": "01234567890123", "Quantity": 96, "WriterAntennas": { "Antennas": [ { "Port": 1, "IsEnabled": true, "TxPowerInDbm": 27, "MaxRxSensitivity": true, "RxSensitivityInDbm": -70 }, { "Port": 2, "IsEnabled": true, "TxPowerInDbm": 27, "MaxRxSensitivity": true, "RxSensitivityInDbm": -70 }, { "Port": 3, "IsEnabled": true, "TxPowerInDbm": 27, "MaxRxSensitivity": true, "RxSensitivityInDbm": -70 }, { "Port": 4, "IsEnabled": true, "TxPowerInDbm": 27, "MaxRxSensitivity": true, "RxSensitivityInDbm": -70 } ] } }Ajuste o GTIN de origem (
Sgtin96SourceGtin), potência de transmissão e sensibilidade de acordo com a infraestrutura instalada. ComUseGpiForVerificationhabilitado, o programa aguardará o nível configurado na porta GPI 1 antes de iniciar a rodada de escrita/verificação. -
Execute o programa informando o hostname do writer e o caminho para o arquivo de configuração:
dotnet run --project OctaneTagWritingTest -- \ --writer writer.local \ --config OctaneTagWritingTest/config.json
-
No menu interativo exibido ao iniciar a aplicação, escolha a opção
[8] JobStrategy8MultipleReaderEnduranceStrategy. Esta estratégia suporta operar apenas com o writer e, com o GPI habilitado, aguarda o acionamento do sensor para disparar o ciclo de leitura/escrita e registrar os EPCs gerados.Conecte o sensor ao GPI indicado para que, ao atingir o estado configurado (
trueno exemplo), o reader inicie o processo de serialização utilizando as quatro antenas em sequência. O desligamento do sensor retorna o sistema ao estado de espera.
O aplicativo suporta configuração interativa quando executado sem parâmetros ou com a flag --interactive:
OctaneTagWritingTest.exe -iO sistema utiliza ApplicationConfig para gerenciar configurações centralizadas:
- DetectorHostname: Leitor responsável por detectar tags
- WriterHostname: Leitor responsável por operações de escrita
- VerifierHostname: Leitor responsável por verificação
Cada leitor pode ter configurações específicas:
- Potência de transmissão (TxPowerInDbm)
- Sensibilidade de recepção (RxSensitivityInDbm)
- Modo de busca (SearchMode)
- Sessão (Session)
- Modo RF (RfMode)
OctaneTagWritingTest/config.example.json: modelo com valores fictícios utilizado como referência.OctaneTagWritingTest/config.json: cópia local do modelo com hostnames e credenciais reais (não versionado).reader_settings/: diretório criado em tempo de execução contendo ajustes por leitor (não versionado).
Documente qualquer ajuste corporativo adicional no README.md antes de publicar para orientar outros times.
# Build para produção
docker build -t octane-tag-writing-test .
# Build para debug
docker build --build-arg BUILD_CONFIGURATION=Debug -t octane-tag-writing-test .# Execução em modo produção (preencha com hostnames internos)
docker run octane-tag-writing-test detector.example.com writer.example.com verifier.example.com
# Execução com dois leitores
docker run octane-tag-writing-test detector.example.com writer.example.comSubstitua os placeholders por hostnames internos resolvíveis. Evite publicar endereços reais na documentação corporativa.
O projeto inclui .dockerignore para otimizar o contexto de build:
- Artefatos de desenvolvimento (bin/, obj/)
- Arquivos de controle de versão (.git/, .gitignore)
- Arquivos de IDE (.vs/, .vscode/, *.user)
- Arquivos de configuração sensíveis
Cada estratégia de teste gera arquivos de log CSV com métricas relevantes:
- Timestamp: Data/hora da operação
- TID: Tag ID
- Previous_EPC: EPC anterior
- New_EPC/Expected_EPC: Novo EPC ou EPC esperado
- WriteTime_ms: Tempo de escrita em milissegundos
- VerifyTime_ms: Tempo de verificação em milissegundos
- Result: Resultado da operação (Success/Failure)
- RSSI: Força do sinal
- AntennaPort: Porta da antena utilizada
- ChipModel: Modelo do chip da tag
TestCase0_ReadOnlyLogging_Log-[description].csvTestCase1_Log-SpeedStrategy-[description].csvTestCase3_MultiAntenna_Log-[description].csvTestCase4_VerificationCycle_Log-[description].csvTestCase6_Robustness_Log-[description].csvTestCase7_Log-OptimizedStrategy-[description].csvTestCase8_Log-DualReaderEnduranceStrategy-[description].csvTestCase9_Log-CheckBox-[description].csv
IJobStrategy: Interface base para todas as estratégiasBaseTestStrategy: Classe base com funcionalidades comuns- Estratégias específicas implementam
IJobStrategy
ApplicationConfig: Configuração centralizada da aplicaçãoReaderSettings: Configurações específicas por leitorReaderSettingsManager: Singleton para gerenciar configurações
- Conexão e gerenciamento de leitores
- Configurações padrão otimizadas
- Relatórios de baixa latência
- Gerenciamento de listas EPC
- Logging estruturado em CSV
- Suporte a cancelamento via CancellationToken
- Crie uma nova classe na pasta
JobStrategies/ - Implemente a interface
IJobStrategy - Herde de
BaseTestStrategypara funcionalidades comuns - Implemente o método
RunJob(CancellationToken) - Registre a estratégia no
JobManager.cs
public class JobStrategyCustom : BaseTestStrategy
{
public JobStrategyCustom(string hostname, string logFile, Dictionary<string, ReaderSettings> readerSettings)
: base(hostname, logFile, readerSettings)
{
}
public override void RunJob(CancellationToken cancellationToken = default)
{
// Implementar lógica do teste
}
}O projeto suporta configuração automática em modo debug:
- Detecção automática de modo debug
- Configuração interativa quando sem argumentos
- Settings pré-configurados para desenvolvimento
Projeto auxiliar para utilitários de tags RFID, incluído como dependência do projeto principal.
Utilitário separado para geração de listas EPC, com seu próprio Dockerfile e configurações.
Esta estratégia implementa um sistema avançado com três leitores:
// Configuração da estratégia 8
strategies.Add("8", new JobStrategy8MultipleReaderEnduranceStrategy(
hostnameDetector, // Leitor detector
hostnameWriter, // Leitor writer
hostnameVerifier, // Leitor verifier
logFile,
readerSettings,
applicationConfig // Configuração centralizada
));- Detecção contínua: Leitor detector monitora tags no campo
- Escrita coordenada: Leitor writer executa operações de escrita
- Verificação automática: Leitor verifier valida dados escritos
- Sincronização GPI: Suporte a General Purpose Input para coordenação
- Retry automático: Re-escrita automática em caso de discrepância
- Métricas detalhadas: Logging completo de timing e resultados
Estratégias específicas suportam validação por SKU:
strategies.Add("9", new JobStrategy9CheckBox(hostname, logFile, readerSettings, sku));-
Conexão com leitor falha
- Verifique conectividade de rede
- Confirme hostname/IP do leitor
- Verifique se o leitor está configurado corretamente
-
Logs não são gerados
- Verifique permissões de escrita
- Confirme se o diretório de saída existe
-
Performance baixa
- Ajuste configurações de potência e sensibilidade
- Considere usar estratégias otimizadas (Strategy 7)
Execute em modo debug para informações detalhadas:
# No Visual Studio
F5 para debug com breakpoints
# Via linha de comando (se compilado em Debug)
OctaneTagWritingTest.exe --debug [argumentos][Especificar Licença]
Para contribuir com o projeto:
- Faça fork do repositório
- Crie uma branch para sua feature
- Implemente e teste suas mudanças
- Submeta um pull request
- Certifique-se da conectividade adequada do leitor antes de executar testes
- Revise a documentação individual de cada estratégia para requisitos específicos
- Verifique os arquivos de log CSV para resultados detalhados dos testes
- Use o modo interativo para configuração inicial e testes