IoT industrial

Formato do Payload Sparkplug B: Métricas, Tipos de Dados e Protobuf

Payloads Sparkplug B são mensagens Protobuf compactas, e é por isso que parecem ilegíveis em um cliente MQTT comum. Este guia percorre cada campo, mostra um exemplo decodificado e explica como inspecionar payloads na prática.

Diagrama de um payload Sparkplug B desmembrado em timestamp, número de sequência e uma lista de métricas tipadas
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

Um payload Sparkplug B é uma mensagem codificada em Protobuf que carrega um timestamp, um número de sequência e uma lista de métricas tipadas. Ao final deste guia você vai saber o que significa cada campo, por que os bytes brutos parecem ilegíveis em um cliente MQTT comum e como inspecionar payloads rapidamente durante o comissionamento ou a depuração de um edge node.

Por que os payloads Sparkplug B parecem ilegíveis

Se você assinar spBv1.0/# com uma ferramenta genérica como o mosquitto_sub, vai ver uma mistura de nomes de tags legíveis cercados por caracteres estranhos. Isso não é corrupção. O Sparkplug B usa Google Protocol Buffers, um formato de serialização binária, então números de campo, comprimentos e valores numéricos são gravados como varints compactos e bytes de largura fixa, e não como texto.

Essa troca é proposital. Redes industriais costumam rodar sobre links celulares, backhaul via satélite ou Ethernet de planta congestionada, e um gateway pode publicar milhares de tags. Uma codificação binária mantém as mensagens pequenas, preserva os tipos numéricos exatos (um contador de 64 bits sem sinal continua sendo um contador de 64 bits sem sinal) e oferece o mesmo schema a todos os consumidores. O custo é que você precisa do schema, o arquivo sparkplug_b.proto, para transformar os bytes de volta em algo legível por humanos.

Experimente você mesmo com um subscriber genérico:

mosquitto_sub -h broker.connectmq.com -p 1883 -i payload-viewer-7f3a -t "spBv1.0/demo-7f3a/#" -v

Tudo o que um edge node Sparkplug publicar nesse grupo vai aparecer como texto parcialmente binário. Para entender o conteúdo, você precisa conhecer a estrutura por baixo.

A estrutura do payload Sparkplug B

O schema fica no projeto Eclipse Tahu, no arquivo sparkplug_b.proto. No nível mais alto existe uma única mensagem Payload:

message Payload {
    optional uint64 timestamp = 1;   // ms desde a época Unix, UTC
    repeated Metric metrics   = 2;   // os dados propriamente ditos
    optional uint64 seq       = 3;   // 0-255, volta ao início
    optional string uuid      = 4;   // identificador opcional do schema
    optional bytes  body      = 5;   // bytes opacos opcionais
}
Campo Tipo Finalidade Observações
timestamp uint64 Momento em que o payload foi criado Milissegundos desde a época, em UTC
metrics repeated Metric Os valores de tags reportados Pode conter uma métrica ou milhares
seq uint64 Número de sequência da mensagem De 0 a 255, depois volta a 0
uuid string Identificador opcional do schema do payload Raramente usado na prática
body bytes Bytes opcionais específicos da aplicação Não interpretados pelo Sparkplug

É o campo seq que permite a uma aplicação host detectar mensagens perdidas. O NBIRTH começa em 0 e cada mensagem seguinte do mesmo edge node o incrementa em um. Uma lacuna significa que algo se perdeu, o que normalmente dispara uma solicitação de rebirth. Esse fluxo de recuperação se chama rebirth.

Por dentro de uma métrica

A maior parte dos dados interessantes fica na mensagem Metric. Cada métrica é um único valor nomeado com metadados opcionais:

message Metric {
    optional string      name          = 1;
    optional uint64      alias         = 2;
    optional uint64      timestamp     = 3;
    optional uint32      datatype      = 4;
    optional bool        is_historical = 5;
    optional bool        is_transient  = 6;
    optional bool        is_null       = 7;
    optional MetaData    metadata      = 8;
    optional PropertySet properties    = 9;
    oneof value {
        uint32 int_value       = 10;
        uint64 long_value      = 11;
        float  float_value     = 12;
        double double_value    = 13;
        bool   boolean_value   = 14;
        string string_value    = 15;
        bytes  bytes_value     = 16;
        DataSet  dataset_value  = 17;
        Template template_value = 18;
        MetricValueExtension extension_value = 19;
    }
}

Alguns pontos que costumam confundir:

  • name versus alias. As mensagens de birth precisam incluir o nome completo da métrica, como Line1/Spindle/Speed. Se o edge node atribuir um alias, as mensagens NDATA e DDATA seguintes podem enviar apenas o alias numérico para economizar bytes. Um decodificador que não viu o birth não consegue mapear o alias de volta para um nome.
  • datatype é um número. O campo datatype é um código inteiro, como 3 para Int32, 9 para Float ou 12 para String. Ele indica como interpretar o slot de valor. A lista completa está na nossa referência de tipos de dados do Sparkplug B.
  • O slot de valor depende do tipo. De Int8 a UInt32 os valores trafegam em int_value; Int64, UInt64 e DateTime em long_value. Valores com sinal em um campo sem sinal são codificados em complemento de dois, então o decodificador precisa olhar o datatype para recuperar corretamente um número negativo.
  • is_null é explícito. Uma métrica pode existir sem valor atual. Em vez de enviar zero, o nó define is_null como true, o que é importante para consumidores que levam a qualidade em conta.
  • is_historical e is_transient. Métricas históricas carregam dados retroativos que não devem sobrescrever o valor ao vivo. Métricas transitórias devem ser exibidas, mas não armazenadas por um historian.

Um exemplo decodificado

Veja como fica um payload DDATA típico de uma máquina CNC depois de decodificado, apresentado em JSON para facilitar a leitura:

{
  "timestamp": 1792137600123,
  "seq": 42,
  "metrics": [
    { "alias": 3, "timestamp": 1792137600120, "datatype": 9, "floatValue": 1487.5 },
    { "alias": 4, "timestamp": 1792137600120, "datatype": 11, "booleanValue": true },
    { "alias": 7, "timestamp": 1792137600121, "datatype": 3, "intValue": 4294967291 }
  ]
}

Repare em dois detalhes. Primeiro, as métricas têm aliases, mas não têm nomes, então você precisa do DBIRTH para saber que o alias 3 é a velocidade do spindle. Segundo, a métrica Int32 mostra 4294967291 no campo bruto sem sinal. Interpretado como inteiro de 32 bits com sinal, o valor é -5. É exatamente o tipo de coisa que um decodificador ingênuo erra.

O DBIRTH correspondente conteria as definições completas:

{
  "timestamp": 1792137590000,
  "seq": 1,
  "metrics": [
    { "name": "Spindle/Speed", "alias": 3, "datatype": 9, "floatValue": 0.0 },
    { "name": "Spindle/Running", "alias": 4, "datatype": 11, "booleanValue": false },
    { "name": "Axis/X/Offset", "alias": 7, "datatype": 3, "intValue": 0 }
  ]
}

Properties, DataSets e Templates

Além de escalares simples, o payload Sparkplug B pode carregar estruturas mais ricas:

  1. PropertySet. Uma lista de chaves e valores tipados anexada a uma métrica. A conhecida propriedade Quality usa 192 para bom, 0 para ruim e 500 para desatualizado (stale). Unidades de engenharia, faixas e descrições também podem ser anexadas como propriedades.
  2. DataSet. Uma pequena tabela com nomes de colunas, tipos de colunas e linhas. Útil para parâmetros de receita ou um lote de leituras.
  3. Template. Um tipo definido pelo usuário, semelhante a um UDT em um CLP. A definição do template é declarada uma vez no NBIRTH e as instâncias fazem referência a ela. Os templates são a forma como o Sparkplug modela bombas, motores e outros equipamentos repetidos.
  4. MetaData. Informações para métricas de bytes e de arquivo, como tipo de conteúdo, tamanho, MD5 e nome do arquivo.

A maioria dos sistemas em produção usa escalares com uma propriedade Quality. DataSets e templates são poderosos, mas acrescentam complexidade, então adote-os só quando uma lista plana de métricas ficar difícil de gerenciar.

Lendo payloads Sparkplug B na prática

Você tem três opções práticas para transformar dados binários do Sparkplug em algo legível.

Decodificar com o seu próprio código

Compile o sparkplug_b.proto para a sua linguagem e faça o parse de cada mensagem. Essa é a escolha certa para consumidores em produção, e em Python bastam poucas linhas. Nosso tutorial sobre como decodificar Sparkplug B em Python mostra um subscriber completo, incluindo resolução de aliases e tratamento de inteiros com sinal.

Usar as bibliotecas de referência do Tahu

O projeto Eclipse Tahu fornece o arquivo proto canônico e implementações de referência em várias linguagens. É um bom ponto de partida quando você está construindo um edge node ou uma aplicação host e quer um comportamento alinhado à especificação.

Usar um broker que decodifica para você

Durante o comissionamento, você não quer escrever código só para verificar se uma tag está publicando. O ConnectMQ detecta topics Sparkplug B, decodifica payloads Protobuf (e Sparkplug codificado em JSON) e os exibe de forma legível no topic explorer do portal. Ele também pode republicar dados Sparkplug em topics ISA-95, de modo que spBv1.0/factory1/DDATA/line1/cnc1 fica disponível como connectmq/factory1/production/line1/cnc1/telemetry para ferramentas que não falam Protobuf. Se você hospeda o seu próprio broker, precisaria de um serviço de decodificação separado para ter a mesma visão.

Armadilhas comuns com payloads

Sintoma Causa provável Solução
Métricas mostram números em vez de nomes O decodificador perdeu a mensagem de birth Solicite um rebirth ou inicie o consumidor antes do nó
Valores negativos aparecem como números enormes Tipo com sinal lido de um campo sem sinal Aplique complemento de dois com base no datatype
Timestamps parecem ser do ano 50000 Confusão entre segundos e milissegundos Timestamps Sparkplug são sempre em milissegundos
DecodeError no parser O payload não é Sparkplug B ou a versão do proto está errada Verifique se o topic começa com spBv1.0 e use o proto do Tahu
O seq salta inesperadamente Mensagens perdidas ou dois nós com o mesmo ID Garanta IDs de edge node únicos e use o QoS adequado

A maioria desses problemas aparece durante o comissionamento. Manter uma visão decodificada ao vivo aberta enquanto você coloca um novo gateway em operação economiza muito trabalho de adivinhação.

Como o payload se encaixa no quadro geral

O payload é só metade do Sparkplug. A outra metade é o namespace de topics do Sparkplug e as regras de estado construídas em torno dos certificados de birth e death. Juntos, eles tornam os dados autodescritivos e conscientes de estado, e é por isso que o Sparkplug é popular como transporte para um Unified Namespace. Para a visão de arquitetura, leia MQTT, Sparkplug B e o Unified Namespace e o nosso guia principal de IoT Industrial com MQTT.

Qualquer broker MQTT compatível com o padrão pode transportar Sparkplug B, porque o broker nunca precisa interpretar o payload para roteá-lo. O que um broker com suporte a Sparkplug acrescenta é visibilidade: visões decodificadas, republicação legível e detecção da estrutura de topics, que tornam os dados binários acessíveis para toda a equipe.

Comece com o ConnectMQ

Aponte um edge node ou simulador Sparkplug para o servidor MQTT público usando um group ID exclusivo e apenas dados de teste, e depois migre para o seu próprio broker MQTT gerenciado quando precisar de credenciais e isolamento. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, e veja seus payloads Sparkplug B decodificados ao vivo no topic explorer do ConnectMQ.

Perguntas frequentes

Um payload Sparkplug B é sempre Protobuf?

A especificação define Protobuf como a codificação do Sparkplug B. Algumas ferramentas também geram uma representação JSON da mesma estrutura para depuração ou integração, e o ConnectMQ consegue decodificar as duas formas.

Por que minhas métricas têm aliases, mas não têm nomes?

O edge node enviou os nomes completos apenas no seu certificado de birth e passou a usar aliases numéricos depois para economizar banda. O seu consumidor precisa armazenar o mapeamento nome-alias do NBIRTH ou DBIRTH, ou solicitar um rebirth para obtê-lo de novo.

Qual é o tamanho máximo de um payload Sparkplug B?

O próprio Sparkplug não define um limite pequeno, mas o seu broker define. No broker público do ConnectMQ as mensagens são limitadas a 64 KB, e os planos Serverless permitem 256 KB (gratuito) ou 1 MB (pago).

Preciso do arquivo proto para ler dados Sparkplug?

Sim, a menos que uma ferramenta decodifique para você. O arquivo sparkplug_b.proto do Eclipse Tahu é o schema canônico, e todo decodificador Sparkplug é construído sobre ele.

Artigos relacionados

Cliente MQTT no CODESYS: Publicando Variáveis do CLP em um Broker

Configure a biblioteca IIoT MQTT Client do CODESYS para publicar variáveis do CLP em JSON, verifique-as no servidor MQTT público broker.connectmq.com e depois migre para um broker privado com credenciais e TLS.

8 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.