Add SparkplugB dissector
Add a dissector for SparkplugB as a heuristic subdissector of MQTT and which calls protobuf to dissect the messages payload.
This commit is contained in:
parent
2c62e2eb3f
commit
f6ad4812a2
|
@ -2274,6 +2274,23 @@ add_custom_command(
|
||||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
file(GLOB _protobuf_src_files RELATIVE "${CMAKE_SOURCE_DIR}" protobuf/*.proto)
|
||||||
|
set (_protobuf_data_files)
|
||||||
|
foreach(_data_file ${_protobuf_src_files})
|
||||||
|
list(APPEND _protobuf_data_files "${DATAFILE_DIR}/${_data_file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${_protobuf_data_files}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${DATAFILE_DIR}/protobuf"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${_protobuf_src_files}"
|
||||||
|
"${DATAFILE_DIR}/protobuf"
|
||||||
|
VERBATIM
|
||||||
|
DEPENDS ${_protobuf_src_files}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
file(GLOB _profiles_src_files RELATIVE "${CMAKE_SOURCE_DIR}" profiles/*/*)
|
file(GLOB _profiles_src_files RELATIVE "${CMAKE_SOURCE_DIR}" profiles/*/*)
|
||||||
set (_profiles_data_files)
|
set (_profiles_data_files)
|
||||||
foreach(_data_file ${_profiles_src_files})
|
foreach(_data_file ${_profiles_src_files})
|
||||||
|
@ -2290,6 +2307,7 @@ list(APPEND copy_data_files_depends
|
||||||
${_dtds_data_files}
|
${_dtds_data_files}
|
||||||
${_diameter_data_files}
|
${_diameter_data_files}
|
||||||
${_radius_data_files}
|
${_radius_data_files}
|
||||||
|
${_protobuf_data_files}
|
||||||
${_profiles_data_files}
|
${_profiles_data_files}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
4
NEWS
4
NEWS
|
@ -86,8 +86,8 @@ Wireshark 3.5.0 Release Notes
|
||||||
New Protocol Support
|
New Protocol Support
|
||||||
|
|
||||||
Kerberos SPAKE, O-RAN fronthaul UC-plane (O-RAN), PDU Transport
|
Kerberos SPAKE, O-RAN fronthaul UC-plane (O-RAN), PDU Transport
|
||||||
Protocol, R09.x (R09), State Synchronization Protocol (SSyncP), and
|
Protocol, R09.x (R09), SparkplugB, State Synchronization Protocol (SSyncP),
|
||||||
UAVCAN\CAN
|
and UAVCAN\CAN.
|
||||||
|
|
||||||
Updated Protocol Support
|
Updated Protocol Support
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ They previously shipped with Npcap 1.20.
|
||||||
Kerberos SPAKE
|
Kerberos SPAKE
|
||||||
O-RAN fronthaul UC-plane (O-RAN)
|
O-RAN fronthaul UC-plane (O-RAN)
|
||||||
PDU Transport Protocol
|
PDU Transport Protocol
|
||||||
|
SparkplugB
|
||||||
State Synchronization Protocol (SSyncP)
|
State Synchronization Protocol (SSyncP)
|
||||||
UAVCAN\CAN
|
UAVCAN\CAN
|
||||||
R09.x (R09)
|
R09.x (R09)
|
||||||
|
|
|
@ -1773,6 +1773,7 @@ set(DISSECTOR_SRC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-someip.c
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-someip.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-someip-sd.c
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-someip-sd.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-soupbintcp.c
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-soupbintcp.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-sparkplug.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-spdy.c
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-spdy.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-spice.c
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-spice.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-spp.c
|
${CMAKE_CURRENT_SOURCE_DIR}/packet-spp.c
|
||||||
|
|
|
@ -752,7 +752,7 @@ static gboolean mqtt_user_decode_message(proto_tree *tree, proto_tree *mqtt_tree
|
||||||
message_decode_entry->payload_proto_name);
|
message_decode_entry->payload_proto_name);
|
||||||
proto_item_set_generated(ti);
|
proto_item_set_generated(ti);
|
||||||
|
|
||||||
call_dissector(message_decode_entry->payload_proto, msg_tvb, pinfo, tree);
|
call_dissector_with_data(message_decode_entry->payload_proto, msg_tvb, pinfo, tree, (void*)topic_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
/* packet-sparkplug.c
|
||||||
|
* Routines for Sparkplug dissection
|
||||||
|
* Copyright 2021 Graham Bloice <graham.bloice<at>trihedral.com>
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <epan/packet.h>
|
||||||
|
#include <epan/expert.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See
|
||||||
|
*
|
||||||
|
* https://cirrus-link.com/mqtt-sparkplug-tahu/
|
||||||
|
*
|
||||||
|
* and the specification is at
|
||||||
|
*
|
||||||
|
* https://www.eclipse.org/tahu/spec/Sparkplug%20Topic%20Namespace%20and%20State%20ManagementV2.2-with%20appendix%20B%20format%20-%20Eclipse.pdf
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
/* (Required to prevent [-Wmissing-prototypes] warnings */
|
||||||
|
void proto_reg_handoff_sparkplug(void);
|
||||||
|
|
||||||
|
/* Initialize the protocol field */
|
||||||
|
static int proto_sparkplugb = -1;
|
||||||
|
|
||||||
|
/* Initialize the subtree pointers */
|
||||||
|
static gint ett_sparkplugb = -1;
|
||||||
|
static gint ett_sparkplugb_namespace = -1;
|
||||||
|
|
||||||
|
/* The handle to the protobuf dissector */
|
||||||
|
dissector_handle_t protobuf_handle = NULL;
|
||||||
|
|
||||||
|
/* The hf items */
|
||||||
|
static int hf_sparkplugb_namespace = -1;
|
||||||
|
static int hf_sparkplugb_groupid = -1;
|
||||||
|
static int hf_sparkplugb_messagetype = -1;
|
||||||
|
static int hf_sparkplugb_edgenodeid = -1;
|
||||||
|
static int hf_sparkplugb_deviceid = -1;
|
||||||
|
|
||||||
|
/* The expert info items */
|
||||||
|
static expert_field ei_sparkplugb_missing_groupid = EI_INIT;
|
||||||
|
static expert_field ei_sparkplugb_missing_messagetype = EI_INIT;
|
||||||
|
static expert_field ei_sparkplugb_missing_edgenodeid = EI_INIT;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
dissect_sparkplugb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
||||||
|
{
|
||||||
|
proto_item *ti;
|
||||||
|
proto_tree *sparkplugb_tree, *namespace_tree;
|
||||||
|
gchar **topic_elements, **current_element;
|
||||||
|
char *topic = (char *)data;
|
||||||
|
|
||||||
|
/* Parse the topic into the elements */
|
||||||
|
topic_elements = g_strsplit(topic, "/", 5);
|
||||||
|
|
||||||
|
/* Heuristic check that the first element of the topic is the SparkplugB namespace */
|
||||||
|
if (!topic_elements || (strcmp("spBv1.0", topic_elements[0]) != 0)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make entries in Protocol column */
|
||||||
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SparkplugB");
|
||||||
|
|
||||||
|
/* Adjust the info column */
|
||||||
|
col_clear(pinfo->cinfo, COL_INFO);
|
||||||
|
col_set_str(pinfo->cinfo, COL_INFO, "SparkplugB");
|
||||||
|
|
||||||
|
/* create display subtree for the protocol */
|
||||||
|
ti = proto_tree_add_item(tree, proto_sparkplugb, tvb, 0, -1, ENC_NA);
|
||||||
|
sparkplugb_tree = proto_item_add_subtree(ti, ett_sparkplugb);
|
||||||
|
|
||||||
|
/* Add the elements parsed out from the topic string */
|
||||||
|
namespace_tree = proto_tree_add_subtree(sparkplugb_tree, tvb, 0, 0, ett_sparkplugb_namespace, &ti, "Topic Namespace");
|
||||||
|
proto_item_set_generated(ti);
|
||||||
|
|
||||||
|
current_element = topic_elements;
|
||||||
|
ti = proto_tree_add_string(namespace_tree, hf_sparkplugb_namespace, tvb, 0, 0, current_element[0]);
|
||||||
|
proto_item_set_generated(ti);
|
||||||
|
|
||||||
|
current_element += 1;
|
||||||
|
ti = proto_tree_add_string(namespace_tree, hf_sparkplugb_groupid, tvb, 0, 0, current_element[0]);
|
||||||
|
proto_item_set_generated(ti);
|
||||||
|
if (!current_element[0]) {
|
||||||
|
expert_add_info(pinfo, ti, &ei_sparkplugb_missing_groupid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the info colum text with the message type */
|
||||||
|
current_element += 1;
|
||||||
|
if (current_element[0]) {
|
||||||
|
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, current_element[0]);
|
||||||
|
col_set_fence(pinfo->cinfo, COL_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
ti = proto_tree_add_string(namespace_tree, hf_sparkplugb_messagetype, tvb, 0, 0, current_element[0]);
|
||||||
|
proto_item_set_generated(ti);
|
||||||
|
if (!current_element[0]) {
|
||||||
|
expert_add_info(pinfo, ti, &ei_sparkplugb_missing_messagetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_element += 1;
|
||||||
|
ti = proto_tree_add_string(namespace_tree, hf_sparkplugb_edgenodeid, tvb, 0, 0, current_element[0]);
|
||||||
|
proto_item_set_generated(ti);
|
||||||
|
if (!current_element[0]) {
|
||||||
|
expert_add_info(pinfo, ti, &ei_sparkplugb_missing_edgenodeid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device ID is optional */
|
||||||
|
current_element += 1;
|
||||||
|
ti = proto_tree_add_string(namespace_tree, hf_sparkplugb_deviceid, tvb, 0, 0, current_element[0]);
|
||||||
|
proto_item_set_generated(ti);
|
||||||
|
|
||||||
|
g_strfreev(topic_elements);
|
||||||
|
|
||||||
|
/* Now handoff the Payload message to the protobuf dissector */
|
||||||
|
call_dissector_with_data(protobuf_handle, tvb, pinfo, sparkplugb_tree, "message,com.cirruslink.sparkplug.protobuf.Payload");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proto_register_sparkplug(void)
|
||||||
|
{
|
||||||
|
expert_module_t* expert_sparkplugb;
|
||||||
|
|
||||||
|
static gint *ett[] = {
|
||||||
|
&ett_sparkplugb,
|
||||||
|
&ett_sparkplugb_namespace
|
||||||
|
};
|
||||||
|
|
||||||
|
static hf_register_info hf[] = {
|
||||||
|
{&hf_sparkplugb_namespace, {"Namespace", "sparkplugb.namespace", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
|
||||||
|
{&hf_sparkplugb_groupid, {"Group ID", "sparkplugb.groupid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
|
||||||
|
{&hf_sparkplugb_messagetype, {"Message Type", "sparkplugb.messagetype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
|
||||||
|
{&hf_sparkplugb_edgenodeid, {"Edge Node ID", "sparkplugb.edgenodeid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
|
||||||
|
{&hf_sparkplugb_deviceid, {"Device ID", "sparkplugb.deviceid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
|
||||||
|
};
|
||||||
|
|
||||||
|
static ei_register_info ei[] = {
|
||||||
|
{ &ei_sparkplugb_missing_groupid, { "sparkplugb.missing_groupid", PI_MALFORMED, PI_ERROR, "Missing Group ID", EXPFILL }},
|
||||||
|
{ &ei_sparkplugb_missing_messagetype, { "sparkplugb.missing_messagetype", PI_MALFORMED, PI_ERROR, "Missing Message Type", EXPFILL }},
|
||||||
|
{ &ei_sparkplugb_missing_edgenodeid, { "sparkplugb.missing_edgenodeid", PI_MALFORMED, PI_ERROR, "Missing Edge Node ID", EXPFILL }},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Register the protocol name and description, fields and trees */
|
||||||
|
proto_sparkplugb = proto_register_protocol("SparkplugB", "SparkplugB", "sparkplugb");
|
||||||
|
register_dissector("sparkplugb", dissect_sparkplugb, proto_sparkplugb);
|
||||||
|
|
||||||
|
proto_register_field_array(proto_sparkplugb, hf, array_length(hf));
|
||||||
|
proto_register_subtree_array(ett, array_length(ett));
|
||||||
|
|
||||||
|
expert_sparkplugb = expert_register_protocol(proto_sparkplugb);
|
||||||
|
expert_register_field_array(expert_sparkplugb, ei, array_length(ei));
|
||||||
|
}
|
||||||
|
|
||||||
|
void proto_reg_handoff_sparkplug(void)
|
||||||
|
{
|
||||||
|
protobuf_handle = find_dissector_add_dependency("protobuf", proto_sparkplugb);
|
||||||
|
|
||||||
|
/* register as heuristic dissector with MQTT */
|
||||||
|
heur_dissector_add("mqtt.topic", dissect_sparkplugb, "SparkplugB over MQTT",
|
||||||
|
"sparkplugb_mqtt", proto_sparkplugb, HEURISTIC_ENABLE);
|
||||||
|
}
|
|
@ -215,6 +215,7 @@ Delete "$INSTDIR\snmp\*.*"
|
||||||
Delete "$INSTDIR\snmp\mibs\*.*"
|
Delete "$INSTDIR\snmp\mibs\*.*"
|
||||||
Delete "$INSTDIR\styles\translations\*.*"
|
Delete "$INSTDIR\styles\translations\*.*"
|
||||||
Delete "$INSTDIR\styles\*.*"
|
Delete "$INSTDIR\styles\*.*"
|
||||||
|
Delete "$INSTDIR\protobuf\*.*"
|
||||||
Delete "$INSTDIR\tpncp\*.*"
|
Delete "$INSTDIR\tpncp\*.*"
|
||||||
Delete "$INSTDIR\translations\*.*"
|
Delete "$INSTDIR\translations\*.*"
|
||||||
Delete "$INSTDIR\ui\*.*"
|
Delete "$INSTDIR\ui\*.*"
|
||||||
|
@ -295,6 +296,7 @@ RMDir "$INSTDIR\snmp\mibs"
|
||||||
RMDir "$INSTDIR\snmp"
|
RMDir "$INSTDIR\snmp"
|
||||||
RMDir "$INSTDIR\radius"
|
RMDir "$INSTDIR\radius"
|
||||||
RMDir "$INSTDIR\dtds"
|
RMDir "$INSTDIR\dtds"
|
||||||
|
RMDir "$INSTDIR\protobuf"
|
||||||
RMDir "$INSTDIR\tpncp"
|
RMDir "$INSTDIR\tpncp"
|
||||||
RMDir "$INSTDIR\translations"
|
RMDir "$INSTDIR\translations"
|
||||||
RMDir "$INSTDIR\ui"
|
RMDir "$INSTDIR\ui"
|
||||||
|
|
|
@ -857,6 +857,12 @@ SetOutPath $INSTDIR
|
||||||
; Create the extcap directory
|
; Create the extcap directory
|
||||||
CreateDirectory $INSTDIR\extcap
|
CreateDirectory $INSTDIR\extcap
|
||||||
|
|
||||||
|
;
|
||||||
|
; install the protobuf .proto definitions in the protobuf subdirectory
|
||||||
|
;
|
||||||
|
SetOutPath $INSTDIR\protobuf
|
||||||
|
File "${STAGING_DIR}\protobuf\sparkplug_b.proto"
|
||||||
|
|
||||||
; Install the TPNCP DAT file in the "tpncp" subdirectory
|
; Install the TPNCP DAT file in the "tpncp" subdirectory
|
||||||
; of the installation directory.
|
; of the installation directory.
|
||||||
SetOutPath $INSTDIR\tpncp
|
SetOutPath $INSTDIR\tpncp
|
||||||
|
|
|
@ -221,6 +221,20 @@
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
|
<!-- protobuf TLV definitions -->
|
||||||
|
<Fragment>
|
||||||
|
<DirectoryRef Id="dirProtobuf">
|
||||||
|
<Component Id="cmpProtobuf_sparkplug_b_proto" Guid="*">
|
||||||
|
<File Id="filProtobuf_sparkplug_b_proto" KeyPath="yes" Source="$(var.Protobuf.Dir)\sparkplug_b.proto" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
</Fragment>
|
||||||
|
<Fragment>
|
||||||
|
<ComponentGroup Id="CG.Protobuf">
|
||||||
|
<ComponentRef Id="cmpProtobuf_sparkplug_b_proto" />
|
||||||
|
</ComponentGroup>
|
||||||
|
</Fragment>
|
||||||
|
|
||||||
<!-- TShark -->
|
<!-- TShark -->
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<DirectoryRef Id="INSTALLFOLDER">
|
<DirectoryRef Id="INSTALLFOLDER">
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
<Directory Id="dirTpncp" Name="tpncp"/>
|
<Directory Id="dirTpncp" Name="tpncp"/>
|
||||||
<Directory Id="dirTranslations" Name="translations"/>
|
<Directory Id="dirTranslations" Name="translations"/>
|
||||||
<Directory Id="dirWimaxasncp" Name="wimaxasncp"/>
|
<Directory Id="dirWimaxasncp" Name="wimaxasncp"/>
|
||||||
|
<Directory Id="dirProtobuf" Name="protobuf"/>
|
||||||
</Directory>
|
</Directory>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
<ComponentGroupRef Id="CG.Dtds" />
|
<ComponentGroupRef Id="CG.Dtds" />
|
||||||
<ComponentGroupRef Id="CG.Tpncp" />
|
<ComponentGroupRef Id="CG.Tpncp" />
|
||||||
<ComponentGroupRef Id="CG.Wimaxasncp" />
|
<ComponentGroupRef Id="CG.Wimaxasncp" />
|
||||||
|
<ComponentGroupRef Id="CG.Protobuf" />
|
||||||
<ComponentGroupRef Id="CG.RequiredDependencies" />
|
<ComponentGroupRef Id="CG.RequiredDependencies" />
|
||||||
|
|
||||||
</Feature>
|
</Feature>
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
<?define Dtds.Dir ="$(var.Staging.Dir)\dtds" ?>
|
<?define Dtds.Dir ="$(var.Staging.Dir)\dtds" ?>
|
||||||
<?define Tpncp.Dir ="$(var.Staging.Dir)\tpncp" ?>
|
<?define Tpncp.Dir ="$(var.Staging.Dir)\tpncp" ?>
|
||||||
<?define Wimaxasncp.Dir ="$(var.Staging.Dir)\wimaxasncp" ?>
|
<?define Wimaxasncp.Dir ="$(var.Staging.Dir)\wimaxasncp" ?>
|
||||||
|
<?define Protobuf.Dir ="$(var.Staging.Dir)\protobuf" ?>
|
||||||
<?define Help.Dir ="$(var.Staging.Dir)\help" ?>
|
<?define Help.Dir ="$(var.Staging.Dir)\help" ?>
|
||||||
<?define Epan.Lua.Dir ="..\..\epan\wslua" ?>
|
<?define Epan.Lua.Dir ="..\..\epan\wslua" ?>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
//
|
||||||
|
// To compile:
|
||||||
|
// cd client_libraries/java
|
||||||
|
// protoc --proto_path=../../ --java_out=src/main/java ../../sparkplug_b.proto
|
||||||
|
//
|
||||||
|
package com.cirruslink.sparkplug.protobuf;
|
||||||
|
|
||||||
|
option java_package = "com.cirruslink.sparkplug.protobuf";
|
||||||
|
option java_outer_classname = "SparkplugBProto";
|
||||||
|
|
||||||
|
message Payload {
|
||||||
|
/*
|
||||||
|
// Indexes of Data Types
|
||||||
|
|
||||||
|
// Unknown placeholder for future expansion.
|
||||||
|
Unknown = 0;
|
||||||
|
|
||||||
|
// Basic Types
|
||||||
|
Int8 = 1;
|
||||||
|
Int16 = 2;
|
||||||
|
Int32 = 3;
|
||||||
|
Int64 = 4;
|
||||||
|
UInt8 = 5;
|
||||||
|
UInt16 = 6;
|
||||||
|
UInt32 = 7;
|
||||||
|
UInt64 = 8;
|
||||||
|
Float = 9;
|
||||||
|
Double = 10;
|
||||||
|
Boolean = 11;
|
||||||
|
String = 12;
|
||||||
|
DateTime = 13;
|
||||||
|
Text = 14;
|
||||||
|
|
||||||
|
// Additional Metric Types
|
||||||
|
UUID = 15;
|
||||||
|
DataSet = 16;
|
||||||
|
Bytes = 17;
|
||||||
|
File = 18;
|
||||||
|
Template = 19;
|
||||||
|
|
||||||
|
// Additional PropertyValue Types
|
||||||
|
PropertySet = 20;
|
||||||
|
PropertySetList = 21;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
message Template {
|
||||||
|
|
||||||
|
message Parameter {
|
||||||
|
optional string name = 1;
|
||||||
|
optional uint32 type = 2;
|
||||||
|
|
||||||
|
oneof value {
|
||||||
|
uint32 int_value = 3;
|
||||||
|
uint64 long_value = 4;
|
||||||
|
float float_value = 5;
|
||||||
|
double double_value = 6;
|
||||||
|
bool boolean_value = 7;
|
||||||
|
string string_value = 8;
|
||||||
|
ParameterValueExtension extension_value = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ParameterValueExtension {
|
||||||
|
extensions 1 to max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional string version = 1; // The version of the Template to prevent mismatches
|
||||||
|
repeated Metric metrics = 2; // Each metric is the name of the metric and the datatype of the member but does not contain a value
|
||||||
|
repeated Parameter parameters = 3;
|
||||||
|
optional string template_ref = 4; // Reference to a template if this is extending a Template or an instance - must exist if an instance
|
||||||
|
optional bool is_definition = 5;
|
||||||
|
extensions 6 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DataSet {
|
||||||
|
|
||||||
|
message DataSetValue {
|
||||||
|
|
||||||
|
oneof value {
|
||||||
|
uint32 int_value = 1;
|
||||||
|
uint64 long_value = 2;
|
||||||
|
float float_value = 3;
|
||||||
|
double double_value = 4;
|
||||||
|
bool boolean_value = 5;
|
||||||
|
string string_value = 6;
|
||||||
|
DataSetValueExtension extension_value = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DataSetValueExtension {
|
||||||
|
extensions 1 to max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Row {
|
||||||
|
repeated DataSetValue elements = 1;
|
||||||
|
extensions 2 to max; // For third party extensions
|
||||||
|
}
|
||||||
|
|
||||||
|
optional uint64 num_of_columns = 1;
|
||||||
|
repeated string columns = 2;
|
||||||
|
repeated uint32 types = 3;
|
||||||
|
repeated Row rows = 4;
|
||||||
|
extensions 5 to max; // For third party extensions
|
||||||
|
}
|
||||||
|
|
||||||
|
message PropertyValue {
|
||||||
|
|
||||||
|
optional uint32 type = 1;
|
||||||
|
optional bool is_null = 2;
|
||||||
|
|
||||||
|
oneof value {
|
||||||
|
uint32 int_value = 3;
|
||||||
|
uint64 long_value = 4;
|
||||||
|
float float_value = 5;
|
||||||
|
double double_value = 6;
|
||||||
|
bool boolean_value = 7;
|
||||||
|
string string_value = 8;
|
||||||
|
PropertySet propertyset_value = 9;
|
||||||
|
PropertySetList propertysets_value = 10; // List of Property Values
|
||||||
|
PropertyValueExtension extension_value = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PropertyValueExtension {
|
||||||
|
extensions 1 to max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message PropertySet {
|
||||||
|
repeated string keys = 1; // Names of the properties
|
||||||
|
repeated PropertyValue values = 2;
|
||||||
|
extensions 3 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PropertySetList {
|
||||||
|
repeated PropertySet propertyset = 1;
|
||||||
|
extensions 2 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MetaData {
|
||||||
|
// Bytes specific metadata
|
||||||
|
optional bool is_multi_part = 1;
|
||||||
|
|
||||||
|
// General metadata
|
||||||
|
optional string content_type = 2; // Content/Media type
|
||||||
|
optional uint64 size = 3; // File size, String size, Multi-part size, etc
|
||||||
|
optional uint64 seq = 4; // Sequence number for multi-part messages
|
||||||
|
|
||||||
|
// File metadata
|
||||||
|
optional string file_name = 5; // File name
|
||||||
|
optional string file_type = 6; // File type (i.e. xml, json, txt, cpp, etc)
|
||||||
|
optional string md5 = 7; // md5 of data
|
||||||
|
|
||||||
|
// Catchalls and future expansion
|
||||||
|
optional string description = 8; // Could be anything such as json or xml of custom properties
|
||||||
|
extensions 9 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Metric {
|
||||||
|
|
||||||
|
optional string name = 1; // Metric name - should only be included on birth
|
||||||
|
optional uint64 alias = 2; // Metric alias - tied to name on birth and included in all later DATA messages
|
||||||
|
optional uint64 timestamp = 3; // Timestamp associated with data acquisition time
|
||||||
|
optional uint32 datatype = 4; // DataType of the metric/tag value
|
||||||
|
optional bool is_historical = 5; // If this is historical data and should not update real time tag
|
||||||
|
optional bool is_transient = 6; // Tells consuming clients such as MQTT Engine to not store this as a tag
|
||||||
|
optional bool is_null = 7; // If this is null - explicitly say so rather than using -1, false, etc for some datatypes.
|
||||||
|
optional MetaData metadata = 8; // Metadata for the payload
|
||||||
|
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; // Bytes, File
|
||||||
|
DataSet dataset_value = 17;
|
||||||
|
Template template_value = 18;
|
||||||
|
MetricValueExtension extension_value = 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MetricValueExtension {
|
||||||
|
extensions 1 to max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional uint64 timestamp = 1; // Timestamp at message sending time
|
||||||
|
repeated Metric metrics = 2; // Repeated forever - no limit in Google Protobufs
|
||||||
|
optional uint64 seq = 3; // Sequence number
|
||||||
|
optional string uuid = 4; // UUID to track message type in terms of schema definitions
|
||||||
|
optional bytes body = 5; // To optionally bypass the whole definition above
|
||||||
|
extensions 6 to max; // For third party extensions
|
||||||
|
}
|
Loading…
Reference in New Issue