Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions specification/src/main/asciidoc/chapters/Sparkplug_6_Payloads.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ message Payload {

optional string name = 1; // Metric name - Required in BIRTH messages, optional in DATA messages if using aliases
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 - if omitted, the overall payload timestamp is assumed as the data acquisition time
optional uint64 timestamp = 3; // Metric value change time - the time this metric's value last changed - if omitted, the overall payload timestamp is assumed as the metric value change time
optional DataType datatype = 4; // DataType of the metric/tag value
optional int32 quality = 5; // Quality code of the metric/tag value
optional string quality_context = 6; // The optional quality context of the metric/tag value
Expand Down Expand Up @@ -494,6 +494,13 @@ nanoseconds since epoch (Jan 1, 1970).
*** [tck-testable tck-id-payloads-timestamp-in-UTC]#[yellow-background]*[tck-id-payloads-timestamp-in-UTC] This
timestamp MUST be in UTC.*#
*** This timestamp represents the time at which the message was published.
*** [tck-not-testable]#[yellow-background]*In an NBIRTH, NREBIRTH, DBIRTH, or DREBIRTH message, the
payload timestamp MUST represent the time at which the message was published, and the values of all
Metrics the message carries MUST be current as of that time.*#
**** Non-normative comment: a BIRTH message therefore carries two distinct times. The payload
timestamp is the point at which the reported values were current, and the timestamp of each Metric
is the time that metric's value last changed. A consuming application needs both to know what a
value is and how long it has held that value.
** _seq_
*** This is the sequence number which is an unsigned 64-bit integer.
**** [tck-testable tck-id-payloads-sequence-num-always-included]#[yellow-background]*[tck-id-payloads-sequence-num-always-included] A
Expand Down Expand Up @@ -661,12 +668,27 @@ DDATA, NCMD, and DCMD messages MUST only include an alias and the metric name MU
* *timestamp*
** This is the timestamp in the form of an unsigned 64-bit integer representing the number of
nanoseconds since epoch (Jan 1, 1970).
** [tck-not-testable]#[yellow-background]*In an NBIRTH, NREBIRTH, DBIRTH, DREBIRTH, NDATA, or DDATA
message, the timestamp of a Metric MUST represent the metric value change time, meaning the time at
which that metric's value last changed. It MUST NOT represent the time at which the value was read
from the underlying device, nor the time at which the message carrying it was published.*#
*** Non-normative comment: an Edge Node that knows when a metric's value last changed reports that
time, including in a BIRTH message. This is what allows a single BIRTH to convey both the current
values of an Edge Node's metrics and how long each of those values has been in effect.
** [tck-testable tck-id-payloads-name-birth-data-requirement]#[yellow-background]*[tck-id-payloads-name-birth-data-requirement] The
timestamp MAY be included with every metric in all NBIRTH, DBIRTH, NDATA, and DDATA messages.*#
*** If the timestamp is omitted from the Metric definition, the overall payload timestamp MUST be
assumed as the data acquisition time.
*** Non-normative comment: This timestamp represents the time at which the value of a metric was
acquired for message types of NBIRTH, NREBIRTH, NDATA, NBIRTH, DREBIRTH, and DDATA.
assumed as the metric value change time.
*** Non-normative comment: the distinction between a metric value change time that an Edge Node has
reported and one that a consuming application has substituted from the payload timestamp is carried
by whether the field is present, not by its value. A consuming application that needs to know
whether an Edge Node reports change times at all, for example in order to determine how long a value
has held, checks for the presence of the field rather than comparing it against the payload
timestamp.
*** Non-normative comment: for message types of NBIRTH, NREBIRTH, DBIRTH, DREBIRTH, NDATA, and DDATA
this timestamp represents the time at which the value of the metric last changed, which is not
necessarily the time at which it was read from the underlying device or the time at which the
message carrying it was published.
** [tck-testable tck-id-payloads-name-cmd-requirement]#[yellow-background]*[tck-id-payloads-name-cmd-requirement] The
timestamp MAY be included with metrics in NCMD and DCMD messages.*#
*** If the timestamp is omitted from the Metric definition, the overall payload timestamp MUST be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_NDATA_SEQ;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_NDATA_TIMESTAMP;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_TEMPLATE_DEFINITION_MEMBERS;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS_DEFAULT;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_TEMPLATE_DEFINITION_REF;
Expand Down Expand Up @@ -59,8 +57,6 @@
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_NDATA_SEQ;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_NDATA_TIMESTAMP;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_TEMPLATE_DEFINITION_MEMBERS;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_TEMPLATE_DEFINITION_NBIRTH;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS_DEFAULT;
import static org.eclipse.sparkplug.tck.test.common.Requirements.PAYLOADS_TEMPLATE_DEFINITION_REF;
Expand Down Expand Up @@ -139,11 +135,11 @@ public class SendDataTest extends TCKTest {
ID_TOPICS_DDATA_MQTT, ID_TOPICS_DDATA_SEQ_NUM, ID_TOPICS_DDATA_TIMESTAMP_1, ID_TOPICS_DDATA_PAYLOAD,
ID_PAYLOADS_NDATA_TIMESTAMP, ID_PAYLOADS_NDATA_SEQ, ID_PAYLOADS_NDATA_QOS, ID_PAYLOADS_NDATA_RETAIN,
ID_PAYLOADS_DDATA_TIMESTAMP, ID_PAYLOADS_DDATA_SEQ, ID_PAYLOADS_DDATA_QOS, ID_PAYLOADS_DDATA_RETAIN,
ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY, ID_PAYLOADS_TEMPLATE_DEFINITION_REF,
ID_PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS_DEFAULT, ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY,
ID_PAYLOADS_TEMPLATE_DEFINITION_REF,
ID_PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS_DEFAULT,
ID_PAYLOADS_TEMPLATE_INSTANCE_REF, ID_PAYLOADS_TEMPLATE_DEFINITION_MEMBERS,
ID_PAYLOADS_TEMPLATE_INSTANCE_MEMBERS_BIRTH, ID_PAYLOADS_TEMPLATE_INSTANCE_MEMBERS_DATA,
ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH, ID_PAYLOADS_TEMPLATE_INSTANCE_MEMBERS,
ID_PAYLOADS_TEMPLATE_INSTANCE_MEMBERS,
ID_PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS, ID_PAYLOADS_TEMPLATE_INSTANCE_PARAMETERS,
ID_TOPICS_NDATA_TOPIC, ID_TOPICS_DDATA_TOPIC, ID_PAYLOADS_METRIC_TIMESTAMP_IN_UTC);

Expand Down Expand Up @@ -529,9 +525,6 @@ private Boolean[] checkValidPayload(PayloadOrBuilder payload) {
return bValidPayload;
}

@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY)
@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_INSTANCE_REF)
Expand All @@ -544,9 +537,6 @@ private Boolean[] checkValidPayload(PayloadOrBuilder payload) {
@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_INSTANCE_MEMBERS_DATA)
@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH)
@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_DEFINITION_MEMBERS)
Expand All @@ -563,8 +553,11 @@ private void checkInstance(String sparkplugDescriptor, String instanceName, Payl
String msgtype) {
Payload.Template definition = null;
if (instance.hasIsDefinition() && instance.getIsDefinition()) {
setResultIfNotFail(testResults, !msgtype.equals(TOPIC_PATH_NBIRTH),
ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY, PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY);
// The assertions previously recorded here, payloads-template-definition-nbirth-only and
// payloads-template-definition-nbirth, were replaced in the specification by
// payloads-template-definition-nmeta-only and payloads-template-definition-nmeta, which
// require Template definitions in the NMETA rather than the NBIRTH. The v3 TCK has no NMETA
// concept, so these checks need rewriting; see the Sparkplug v4 TCK rewrite.
} else {
if (!instance.hasTemplateRef()) {
setResultIfNotFail(testResults, false, ID_PAYLOADS_TEMPLATE_INSTANCE_REF,
Expand All @@ -576,9 +569,6 @@ private void checkInstance(String sparkplugDescriptor, String instanceName, Payl
setResultIfNotFail(testResults, defFound, ID_PAYLOADS_TEMPLATE_INSTANCE_REF,
PAYLOADS_TEMPLATE_INSTANCE_REF);

setResultIfNotFail(testResults, defFound, ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH,
PAYLOADS_TEMPLATE_DEFINITION_NBIRTH);

if (defFound) {
definition = definitions.get(defname);
}
Expand Down Expand Up @@ -667,9 +657,6 @@ private void checkInstance(String sparkplugDescriptor, String instanceName, Payl
}
}

@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY)
@SpecAssertion(
section = Sections.PAYLOADS_C_TEMPLATE,
id = ID_PAYLOADS_TEMPLATE_DEFINITION_REF)
Expand All @@ -678,9 +665,6 @@ private void checkInstance(String sparkplugDescriptor, String instanceName, Payl
id = ID_PAYLOADS_TEMPLATE_DEFINITION_PARAMETERS_DEFAULT)
public void checkNBIRTH(String clientId, PublishPacket packet) {

setResultIfNotFail(testResults, true, ID_PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY,
PAYLOADS_TEMPLATE_DEFINITION_NBIRTH_ONLY);

final PayloadOrBuilder sparkplugPayload = Utils.getSparkplugPayload(packet);

// record definitions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_HOST_TOPIC_PHID_DEATH_RETAIN;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_HOST_TOPIC_PHID_DEATH_TOPIC;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_INTRO_SPARKPLUG_HOST_STATE;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_MESSAGE_FLOW_HID_SPARKPLUG_STATE_MESSAGE_DELIVERED;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_MESSAGE_FLOW_PHID_SPARKPLUG_CLEAN_SESSION_311;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_MESSAGE_FLOW_PHID_SPARKPLUG_CLEAN_SESSION_50;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_MESSAGE_FLOW_PHID_SPARKPLUG_STATE_PUBLISH;
Expand All @@ -71,7 +70,6 @@
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PAYLOADS_STATE_WILL_MESSAGE_RETAIN;
import static org.eclipse.sparkplug.tck.test.common.Requirements.ID_PRINCIPLES_BIRTH_CERTIFICATES_ORDER;
import static org.eclipse.sparkplug.tck.test.common.Requirements.INTRO_SPARKPLUG_HOST_STATE;
import static org.eclipse.sparkplug.tck.test.common.Requirements.MESSAGE_FLOW_HID_SPARKPLUG_STATE_MESSAGE_DELIVERED;
import static org.eclipse.sparkplug.tck.test.common.Requirements.MESSAGE_FLOW_PHID_SPARKPLUG_CLEAN_SESSION_311;
import static org.eclipse.sparkplug.tck.test.common.Requirements.MESSAGE_FLOW_PHID_SPARKPLUG_CLEAN_SESSION_50;
import static org.eclipse.sparkplug.tck.test.common.Requirements.MESSAGE_FLOW_PHID_SPARKPLUG_STATE_PUBLISH;
Expand Down Expand Up @@ -178,8 +176,7 @@ public class SessionEstablishmentTest extends TCKTest {
ID_PAYLOADS_STATE_BIRTH, ID_MESSAGE_FLOW_PHID_SPARKPLUG_STATE_PUBLISH_PAYLOAD_TIMESTAMP,
ID_MESSAGE_FLOW_PHID_SPARKPLUG_STATE_PUBLISH_PAYLOAD, ID_PAYLOADS_STATE_BIRTH_PAYLOAD,
ID_HOST_TOPIC_PHID_BIRTH_REQUIRED, ID_HOST_TOPIC_PHID_BIRTH_PAYLOAD_TIMESTAMP,
ID_HOST_TOPIC_PHID_DEATH_REQUIRED, ID_HOST_TOPIC_PHID_BIRTH_SUB_REQUIRED,
ID_MESSAGE_FLOW_HID_SPARKPLUG_STATE_MESSAGE_DELIVERED);
ID_HOST_TOPIC_PHID_DEATH_REQUIRED, ID_HOST_TOPIC_PHID_BIRTH_SUB_REQUIRED);

private @NotNull String hostApplicationId;

Expand Down Expand Up @@ -302,9 +299,6 @@ public void subscribe(final @NotNull String clientId, final @NotNull SubscribePa
@SpecAssertion(
section = Sections.TOPICS_BIRTH_MESSAGE_STATE,
id = ID_HOST_TOPIC_PHID_BIRTH_REQUIRED)
@SpecAssertion(
section = Sections.OPERATIONAL_BEHAVIOR_PRIMARY_HOST_APPLICATION_SESSION_ESTABLISHMENT,
id = ID_MESSAGE_FLOW_HID_SPARKPLUG_STATE_MESSAGE_DELIVERED)
public void publish(final @NotNull String clientId, final @NotNull PublishPacket packet) {

// ignore messages before connect
Expand All @@ -314,10 +308,10 @@ public void publish(final @NotNull String clientId, final @NotNull PublishPacket

if (hostClientId.equals(clientId)) {
if (state == HostState.PUBLISHED) {
final boolean overallPass = checkBirthMessage(packet);

testResults.put(ID_MESSAGE_FLOW_HID_SPARKPLUG_STATE_MESSAGE_DELIVERED,
setResult(overallPass, MESSAGE_FLOW_HID_SPARKPLUG_STATE_MESSAGE_DELIVERED));
// The assertion previously recorded here, message-flow-hid-sparkplug-state-message-delivered,
// was replaced in the specification by the operational-behavior-hid-state-* assertions.
// This check needs rewriting against those; see the Sparkplug v4 TCK rewrite.
checkBirthMessage(packet);
theTCK.endTest("resend good");
} else {
logger.info("Primary - {} test - PUBLISH - topic: {}, state: {} ", getName(), packet.getTopic(), state);
Expand Down
Loading