Os tipos de dados do Sparkplug B definem exatamente como cada valor de métrica é codificado, de um inteiro de 8 bits com sinal até uma tabela inteira de linhas e colunas. Esta referência lista todos os códigos de datatype com o campo Protobuf que cada um usa, explica as propriedades de métricas e os códigos de qualidade e mostra exemplos decodificados para que você reconheça cada tipo ao inspecionar tráfego real.
Por que o Sparkplug tem os seus próprios tipos de dados
O JSON tem números, strings e booleanos. Sistemas industriais precisam de mais precisão do que isso. Um registrador de CLP pode ser um inteiro de 16 bits sem sinal, um contador pode ser um valor de 64 bits sem sinal e um timestamp não pode ser confundido com um número comum. O Sparkplug B atribui a cada métrica um código datatype explícito para que uma aplicação host do outro lado do mundo interprete o valor exatamente como o edge node pretendia.
O datatype é declarado para cada métrica nas mensagens de birth. As mensagens de dados podem omiti-lo, e é por isso que os consumidores armazenam os datatypes a partir dos births, como descrito no nosso guia de payload Sparkplug B.
Tipos de dados escalares do Sparkplug B
| Código | Nome | Campo de valor Protobuf | Observações |
|---|---|---|---|
| 0 | Unknown | nenhum | Marcador, não deve aparecer em métricas válidas |
| 1 | Int8 | int_value | Com sinal, complemento de dois em um campo sem sinal |
| 2 | Int16 | int_value | Com sinal, complemento de dois |
| 3 | Int32 | int_value | Com sinal, complemento de dois |
| 4 | Int64 | long_value | Com sinal, complemento de dois em uint64 |
| 5 | UInt8 | int_value | Sem sinal |
| 6 | UInt16 | int_value | Sem sinal |
| 7 | UInt32 | int_value | Sem sinal |
| 8 | UInt64 | long_value | Sem sinal |
| 9 | Float | float_value | IEEE 754 de 32 bits |
| 10 | Double | double_value | IEEE 754 de 64 bits |
| 11 | Boolean | boolean_value | true ou false |
| 12 | String | string_value | Texto UTF-8 |
| 13 | DateTime | long_value | Milissegundos desde a época Unix, UTC |
| 14 | Text | string_value | Texto mais longo, mesma codificação de String |
| 15 | UUID | string_value | UUID em forma de string |
| 16 | DataSet | dataset_value | Tabela de colunas e linhas tipadas |
| 17 | Bytes | bytes_value | Dados binários brutos |
| 18 | File | bytes_value | Conteúdo de arquivo, descrito por MetaData |
| 19 | Template | template_value | Tipo ou instância definido pelo usuário |
Os códigos 20 e 21 (PropertySet e PropertySetList) são usados para valores de propriedades, não para valores de métricas.
A armadilha dos inteiros com sinal
O bug de decodificação mais comum no Sparkplug é ler inteiros com sinal diretamente. Como int_value é um campo de 32 bits sem sinal, um Int32 de -5 chega como 4294967291, e um Int64 de -1 chega como 18446744073709551615 em long_value. O consumidor precisa aplicar o complemento de dois com base no datatype declarado. Os edge nodes precisam fazer o inverso ao codificar. Se um dashboard de repente mostrar uma temperatura de quatro bilhões de graus, quase sempre o motivo é este.
DateTime não é um número
Uma métrica DateTime e uma métrica Int64 usam o mesmo campo, mas significam coisas diferentes. Trate DateTime como milissegundos desde a época em UTC e converta-o para exibição. Nunca envie segundos e nunca envie horário local.
Tipos de dados array
O Sparkplug também define arrays de tipos escalares. Eles trafegam em bytes_value como valores compactados em little-endian, uma codificação que o Sparkplug 3.0 detalha com precisão (veja a nossa comparação do Sparkplug 3.0 para saber o que mais foi esclarecido).
| Código | Nome | Código | Nome |
|---|---|---|---|
| 22 | Int8Array | 29 | UInt64Array |
| 23 | Int16Array | 30 | FloatArray |
| 24 | Int32Array | 31 | DoubleArray |
| 25 | Int64Array | 32 | BooleanArray |
| 26 | UInt8Array | 33 | StringArray |
| 27 | UInt16Array | 34 | DateTimeArray |
| 28 | UInt32Array |
O suporte a arrays varia entre produtos. Se você depende de arrays entre fornecedores diferentes, teste cedo com as duas pontas conectadas ao mesmo broker.
Flags de métricas
Cada métrica pode carregar flags booleanas que mudam a forma como os consumidores a tratam:
| Flag | Significado | Comportamento do consumidor |
|---|---|---|
| is_null | A métrica existe, mas não tem valor | Exibir como nulo ou qualidade ruim, não substituir por zero |
| is_historical | O valor é do passado, por exemplo de store and forward | Armazenar, sem sobrescrever o valor ao vivo |
| is_transient | O valor não deve ser historiado | Exibir, sem armazenar |
As métricas também têm um timestamp opcional, separado do timestamp do payload. Use-o para registrar quando o valor foi amostrado na origem.
Propriedades de métricas
Uma métrica pode carregar um PropertySet: listas paralelas de chaves e valores tipados. Os valores de propriedades usam os mesmos códigos de datatype, mais PropertySet (20) e PropertySetList (21), que permitem aninhamento.
A propriedade Quality
A única propriedade à qual a especificação dá um significado definido é Quality, um Int32:
| Valor | Significado |
|---|---|
| 192 | Boa |
| 0 | Ruim |
| 500 | Desatualizada (stale) |
Um host que recebe uma métrica com Quality 0 deve exibi-la como ruim, mesmo que haja um valor presente. Muitas plataformas de borda definem Quality 500 quando perdem contato com o device subjacente, mas mantêm o node conectado.
Outras propriedades comuns
Unidades de engenharia, faixas, descrições e formatos de exibição costumam ser transportados como propriedades, mas os nomes das chaves são convenções de cada plataforma, e não parte da especificação. Combine um vocabulário de propriedades entre os seus edge nodes, ou a sua aplicação host verá o mesmo conceito sob chaves diferentes.
DataSets
Um DataSet é uma pequena tabela tipada dentro de uma única métrica. Ele tem um número de colunas, nomes de colunas, um código de datatype para cada coluna e uma lista de linhas. Cada valor de linha usa um conjunto restrito de campos: int, long, float, double, boolean ou string.
Decodificada, uma tabela de parâmetros de receita pode ficar assim:
{
"name": "Recipe/Steps",
"datatype": 16,
"datasetValue": {
"numOfColumns": 3,
"columns": ["Step", "Temperature", "Duration"],
"types": [3, 9, 7],
"rows": [
{ "elements": [{ "intValue": 1 }, { "floatValue": 180.0 }, { "intValue": 600 }] },
{ "elements": [{ "intValue": 2 }, { "floatValue": 220.0 }, { "intValue": 300 }] }
]
}
}
DataSets são úteis para lotes de valores relacionados que precisam ficar juntos. Para modelos estruturados de equipamentos, os templates costumam ser mais adequados; veja templates e UDTs do Sparkplug.
Exemplos decodificados
Este é um trecho de birth com vários tipos de dados e uma propriedade Quality, como você o veria depois de decodificado:
[
{ "name": "Pump/Running", "alias": 1, "datatype": 11, "booleanValue": true },
{ "name": "Pump/Speed", "alias": 2, "datatype": 9, "floatValue": 1475.0,
"properties": { "keys": ["Quality"], "values": [{ "type": 3, "intValue": 192 }] } },
{ "name": "Pump/StartCount", "alias": 3, "datatype": 8, "longValue": "18342" },
{ "name": "Pump/LastService", "alias": 4, "datatype": 13, "longValue": "1789000000000" },
{ "name": "Pump/Offset", "alias": 5, "datatype": 2, "intValue": 4294967286 },
{ "name": "Pump/Serial", "alias": 6, "datatype": 12, "stringValue": "P-0042" }
]
Repare no offset Int16: o valor bruto 4294967286 é -10 depois do complemento de dois. Repare também que algumas representações em JSON mostram valores de 64 bits como strings para evitar perda de precisão no JavaScript.
Verificando tipos de dados na prática
A forma mais rápida de verificar os datatypes é ler os births decodificados. O ConnectMQ decodifica Sparkplug B no topic explorer do portal, então você pode abrir um NBIRTH ou DBIRTH e conferir o datatype e o valor de cada métrica sem escrever código. Para verificações automatizadas, o decodificador do nosso tutorial sobre como decodificar Sparkplug B em Python mapeia códigos para nomes e trata a conversão de sinal.
Quando testar no servidor MQTT público, use um group ID aleatório e lembre-se de que tudo ali pode ser lido por qualquer pessoa.
Checklist de tipos de dados para configurar edge nodes
- Faça cada tipo Sparkplug corresponder ao tipo do registrador de origem; não converta tudo para Double.
- Use tipos sem sinal para contadores que nunca ficam negativos.
- Use DateTime para timestamps, sempre em milissegundos UTC.
- Defina Quality nas métricas cuja origem pode falhar independentemente do node.
- Use is_null em vez de zero quando um valor não estiver disponível.
- Marque os dados de store and forward como históricos.
- Combine os nomes das chaves de propriedades entre todos os edge nodes.
- Teste arrays, DataSets e templates de ponta a ponta antes da implantação.
Onde os tipos de dados se encaixam
Tipos de dados corretos são o que permite que os dados Sparkplug alimentem historians, SCADA, um Unified Namespace e um gêmeo digital sem correções tag a tag, seja numa usina, numa mineradora ou numa linha de manufatura. Para orientações de arquitetura, veja o guia de IoT Industrial com MQTT. Qualquer broker MQTT compatível transporta esses payloads; um broker MQTT gerenciado que também os decodifica torna a verificação muito mais rápida.
Comece com o ConnectMQ
Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito. Conecte o seu edge node e confira o datatype, o valor e a qualidade de cada métrica no topic explorer do ConnectMQ.
Perguntas frequentes
Quantos tipos de dados o Sparkplug B tem?
A especificação define tipos escalares com códigos de 1 a 19, tipos de property set 20 e 21 e tipos array de 22 a 34. O código 0 é Unknown.
Por que o meu valor negativo do Sparkplug aparece como um número enorme?
Inteiros com sinal são armazenados em campos Protobuf sem sinal. Aplique o complemento de dois com base no datatype declarado ou use um decodificador que faça isso por você.
O que significa Quality 192 no Sparkplug?
Significa qualidade boa. A propriedade Quality usa 192 para boa, 0 para ruim e 500 para desatualizada.
Os tipos de dados do Sparkplug são obrigatórios nas mensagens de dados?
Eles são obrigatórios nas mensagens de birth e opcionais em NDATA e DDATA. Os consumidores devem memorizar o datatype de cada métrica a partir do birth.



