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 emlong_value. Valores com sinal em um campo sem sinal são codificados em complemento de dois, então o decodificador precisa olhar odatatypepara 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_nullcomo 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:
- PropertySet. Uma lista de chaves e valores tipados anexada a uma métrica. A conhecida propriedade
Qualityusa 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. - DataSet. Uma pequena tabela com nomes de colunas, tipos de colunas e linhas. Útil para parâmetros de receita ou um lote de leituras.
- 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.
- 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.



