Skip to content

Commit 370c6d9

Browse files
authored
Merge pull request #528 from icraggs-sparkplug/develop
Allow nodes without a separate device #517
2 parents cb82610 + 117e9d3 commit 370c6d9

File tree

8 files changed

+178
-122
lines changed

8 files changed

+178
-122
lines changed

tck/src/main/java/org/eclipse/sparkplug/tck/test/edge/MultipleBrokerTest.java

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2021, 2023 Ian Craggs
2+
* Copyright (c) 2021, 2024 Ian Craggs
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License v2.0
@@ -84,11 +84,11 @@ public class MultipleBrokerTest extends TCKTest {
8484
ID_OPERATIONAL_BEHAVIOR_PRIMARY_APPLICATION_STATE_WITH_MULTIPLE_SERVERS_WALK,
8585
ID_OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT);
8686

87-
private @NotNull String deviceId;
88-
private @NotNull String groupId;
89-
private @NotNull String edgeNodeId;
90-
private @NotNull String hostApplicationId;
91-
private @NotNull String brokerURL;
87+
private @NotNull String deviceId = null;
88+
private @NotNull String groupId = null;
89+
private @NotNull String edgeNodeId = null;
90+
private @NotNull String hostApplicationId = null;
91+
private @NotNull String brokerURL = null;
9292

9393
private HostApplication broker2 = new HostApplication("tcp://localhost:1884");
9494

@@ -111,16 +111,20 @@ public MultipleBrokerTest(TCK aTCK, Utilities utilities, String[] parms, Results
111111
// a portion of the bdSeq numbers
112112
utilities.getMonitor().setIgnoreBdSeqNumCheck(true);
113113

114-
if (parms.length < 5) {
114+
if (parms.length < 4) {
115115
log("Not enough parameters: " + Arrays.toString(parms));
116-
log("Parameters to edge multiple broker test must be: hostApplicationId, groupId edgeNodeId deviceId brokerURL");
116+
log("Parameters to edge multiple broker test must be: hostApplicationId, groupId edgeNodeId {deviceId} brokerURL");
117117
throw new IllegalArgumentException();
118118
}
119119
hostApplicationId = parms[0];
120120
groupId = parms[1];
121121
edgeNodeId = parms[2];
122-
deviceId = parms[3];
123-
brokerURL = parms[4];
122+
if (parms.length == 4) {
123+
brokerURL = parms[3];
124+
} else {
125+
deviceId = parms[3];
126+
brokerURL = parms[4];
127+
}
124128
logger.info("Parameters are HostApplicationId: {}, GroupId: {}, EdgeNodeId: {}, DeviceId: {} BrokerURL: {}",
125129
hostApplicationId, groupId, edgeNodeId, deviceId, brokerURL);
126130

@@ -358,10 +362,31 @@ public void publish(String clientId, PublishPacket packet) {
358362
Utils.setResultIfNotFail(testResults, true, ID_OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT,
359363
OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT);
360364

365+
if (deviceId == null) {
366+
// we've received NBIRTH, and not expecting DBIRTH, so set the second host online
367+
executorService.schedule(new Runnable() {
368+
@Override
369+
public void run() {
370+
setHost2Online();
371+
}
372+
}, 1, TimeUnit.SECONDS);
373+
}
374+
361375
} else if (state == TestStatus.EXPECT_DEATHS_AND_BIRTHS && births_on == 1) {
362376
Utils.setResultIfNotFail(testResults, true, ID_OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT,
363377
OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT);
364378

379+
if (deviceId == null) { // there's not going to be a DBIRTH
380+
// the edge node has reconnected to server 1 so that's the end of the test
381+
state = TestStatus.ENDING;
382+
executorService.schedule(new Runnable() {
383+
@Override
384+
public void run() {
385+
theTCK.endTest();
386+
}
387+
}, 1, TimeUnit.SECONDS);
388+
}
389+
365390
} else {
366391
// any other state is wrong
367392
logger.error("{} error received NBIRTH in state {}", getName(), state.toString());
@@ -373,7 +398,7 @@ public void publish(String clientId, PublishPacket packet) {
373398
Utils.setResult(testResults, false, ID_OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT,
374399
OPERATIONAL_BEHAVIOR_EDGE_NODE_BIRTH_SEQUENCE_WAIT);
375400
}
376-
} else if (topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_DBIRTH + "/"
401+
} else if (deviceId != null && topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_DBIRTH + "/"
377402
+ edgeNodeId + "/" + deviceId)) {
378403
// found the device DBIRTH
379404
dbirthReceived = true;
@@ -428,7 +453,7 @@ public void run() {
428453
ID_OPERATIONAL_BEHAVIOR_PRIMARY_APPLICATION_STATE_WITH_MULTIPLE_SERVERS_WALK,
429454
OPERATIONAL_BEHAVIOR_PRIMARY_APPLICATION_STATE_WITH_MULTIPLE_SERVERS_WALK);
430455
}
431-
} else if (topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_DDEATH + "/"
456+
} else if (deviceId != null && topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_DDEATH + "/"
432457
+ edgeNodeId + "/" + deviceId)) {
433458

434459
if (state == TestStatus.ENDING) {
@@ -460,13 +485,13 @@ private void checkBirths() {
460485
if (topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_NBIRTH + "/"
461486
+ edgeNodeId)) {
462487
nbirth_found = true;
463-
} else if (topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_DBIRTH
488+
} else if (deviceId != null && topic.equals(Constants.TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + Constants.TOPIC_PATH_DBIRTH
464489
+ "/" + edgeNodeId + "/" + deviceId)) {
465490
dbirth_found = true;
466491
}
467492
msg = broker2.getNextMessage();
468493
}
469-
Utils.setResultIfNotFail(testResults, nbirth_found && dbirth_found,
494+
Utils.setResultIfNotFail(testResults, nbirth_found && (deviceId == null || dbirth_found),
470495
ID_OPERATIONAL_BEHAVIOR_PRIMARY_APPLICATION_STATE_WITH_MULTIPLE_SERVERS_WALK,
471496
OPERATIONAL_BEHAVIOR_PRIMARY_APPLICATION_STATE_WITH_MULTIPLE_SERVERS_WALK);
472497
}

tck/src/main/java/org/eclipse/sparkplug/tck/test/edge/PrimaryHostTest.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,32 @@ public class PrimaryHostTest extends TCKTest {
9999
private final @NotNull TCK theTCK;
100100
private final ManagedExtensionExecutorService executorService = Services.extensionExecutorService();
101101

102-
private @NotNull String deviceId;
103-
private @NotNull String groupId;
104-
private @NotNull String edgeNodeId;
105-
private @NotNull String hostApplicationId;
102+
private @NotNull String deviceId = null;
103+
private @NotNull String groupId = null;
104+
private @NotNull String edgeNodeId = null;
105+
private @NotNull String hostApplicationId = null;
106106
private @NotNull long seqUnassigned = -1;
107107
private @NotNull long birthSeq = -1; // record the nbirth seq to check for matching ndeath
108108
private Utilities utilities = null;
109109

110110
private TestStatus state = TestStatus.NONE;
111111

112112
public PrimaryHostTest(TCK aTCK, Utilities utilities, String[] parms, Results.Config config) {
113-
logger.info("Edge Node payload validation test. Parameters: {} ", Arrays.asList(parms));
113+
logger.info("Edge Node Primary Host test. Parameters: {} ", Arrays.asList(parms));
114114
theTCK = aTCK;
115115
this.utilities = utilities;
116116

117-
if (parms.length < 4) {
117+
if (parms.length < 3) {
118118
log("Not enough parameters: " + Arrays.toString(parms));
119-
log("Parameters to edge primary host test must be: hostId groupId edgeNodeId deviceId");
119+
log("Parameters to edge primary host test must be: hostId groupId edgeNodeId {deviceId}");
120120
throw new IllegalArgumentException();
121121
}
122122
hostApplicationId = parms[0];
123123
groupId = parms[1];
124124
edgeNodeId = parms[2];
125-
deviceId = parms[3];
125+
if (parms.length == 4) {
126+
deviceId = parms[3];
127+
}
126128
logger.info("Parameters are HostId: {}, GroupId: {}, EdgeNodeId: {}, DeviceId: {}", hostApplicationId, groupId,
127129
edgeNodeId, deviceId);
128130

tck/src/main/java/org/eclipse/sparkplug/tck/test/edge/ReceiveCommandTest.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2021, 2023 Ian Craggs
2+
* Copyright (c) 2021, 2024 Ian Craggs
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License v2.0
@@ -105,13 +105,13 @@ public class ReceiveCommandTest extends TCKTest {
105105
ID_OPERATIONAL_BEHAVIOR_DATA_COMMANDS_REBIRTH_ACTION_2,
106106
ID_OPERATIONAL_BEHAVIOR_DATA_COMMANDS_REBIRTH_ACTION_3, ID_PAYLOADS_NDEATH_WILL_MESSAGE);
107107

108-
private @NotNull TestStatus state;
109-
private @NotNull String deviceId;
110-
private @NotNull String groupId;
111-
private @NotNull String edgeNodeId;
112-
private @NotNull String hostApplicationId;
108+
private @NotNull TestStatus state = null;
109+
private @NotNull String deviceId = null;
110+
private @NotNull String groupId = null;
111+
private @NotNull String edgeNodeId = null;
112+
private @NotNull String hostApplicationId = null;
113113
private @NotNull long deathBdSeq = -1;
114-
private String edgeNodeClientId;
114+
private String edgeNodeClientId = null;
115115
private boolean bNBirth = false, bDBirth = false;
116116
private PublishService publishService = Services.publishService();
117117
private final ManagedExtensionExecutorService executorService = Services.extensionExecutorService();
@@ -124,17 +124,19 @@ public ReceiveCommandTest(TCK aTCK, Utilities utilities, String[] params, Result
124124
theTCK = aTCK;
125125
this.utilities = utilities;
126126

127-
if (params.length < 4) {
127+
if (params.length < 3) {
128128
log("Not enough parameters: " + Arrays.toString(params));
129-
log("Parameters to edge receive command test must be: hostApplicationId groupId edgeNodeId deviceId");
129+
log("Parameters to edge receive command test must be: hostApplicationId groupId edgeNodeId {deviceId}");
130130
throw new IllegalArgumentException();
131131
}
132132
state = TestStatus.NONE;
133133
deathBdSeq = -1;
134134
hostApplicationId = params[0];
135135
groupId = params[1];
136136
edgeNodeId = params[2];
137-
deviceId = params[3];
137+
if (params.length == 4) {
138+
deviceId = params[3];
139+
}
138140
logger.info("Host application id: {}, Group id: {}, Edge node id: {}, Device id: {}", hostApplicationId,
139141
groupId, edgeNodeId, deviceId);
140142

@@ -314,8 +316,13 @@ public void publish(final String clientId, final PublishPacket packet) {
314316

315317
if (state == TestStatus.EXPECT_NODE_BIRTH
316318
&& topic.equals(TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + TOPIC_PATH_NBIRTH + "/" + edgeNodeId)) {
317-
log("Edge " + edgeNodeId + " is now online");
318-
state = TestStatus.EXPECT_DEVICE_BIRTH;
319+
if (deviceId == null) {
320+
log("Edge " + edgeNodeId + " is now online, sending rebirth");
321+
sendRebirth(true);
322+
} else {
323+
log("Edge " + edgeNodeId + " is now online");
324+
state = TestStatus.EXPECT_DEVICE_BIRTH;
325+
}
319326
} else if (state == TestStatus.EXPECT_DEVICE_BIRTH && topic.equals(
320327
TOPIC_ROOT_SP_BV_1_0 + "/" + groupId + "/" + TOPIC_PATH_DBIRTH + "/" + edgeNodeId + "/" + deviceId)) {
321328
log("Device " + deviceId + " is now online, sending rebirth");
@@ -343,7 +350,7 @@ public void publish(final String clientId, final PublishPacket packet) {
343350
deathBdSeq, birthSeq);
344351
}
345352
}
346-
} else if (levels.length == 5 && levels[2].equals(TOPIC_PATH_DBIRTH)) {
353+
} else if (levels.length == 5 && levels[2].equals(TOPIC_PATH_DBIRTH) && levels[4].equals(deviceId)) {
347354
log("Device birth received for device: " + levels[4]);
348355
bDBirth = true;
349356

@@ -363,7 +370,7 @@ public void publish(final String clientId, final PublishPacket packet) {
363370
setResult(false, OPERATIONAL_BEHAVIOR_DATA_COMMANDS_REBIRTH_ACTION_1));
364371
}
365372

366-
if (bNBirth && bDBirth && state == TestStatus.SENDING_NODE_REBIRTH) {
373+
if (bNBirth && (deviceId == null || bDBirth) && state == TestStatus.SENDING_NODE_REBIRTH) {
367374
logger.debug(
368375
"Check Req: {} After an Edge Node stops sending DATA messages, it MUST send a complete BIRTH sequence including the NBIRTH and DBIRTH(s) if applicable.",
369376
ID_OPERATIONAL_BEHAVIOR_DATA_COMMANDS_REBIRTH_ACTION_2);

tck/src/main/java/org/eclipse/sparkplug/tck/test/edge/SendComplexDataTest.java

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ public class SendComplexDataTest extends TCKTest {
164164
private final @NotNull TCK theTCK;
165165
private @NotNull Utilities utilities = null;
166166

167-
private @NotNull String deviceId;
168-
private @NotNull String groupId;
169-
private @NotNull String edgeNodeId;
170-
private @NotNull String hostApplicationId;
167+
private @NotNull String deviceId = null;
168+
private @NotNull String groupId = null;
169+
private @NotNull String edgeNodeId = null;
170+
private @NotNull String hostApplicationId = null;
171171
private @NotNull long seqUnassigned = -1;
172172

173173
// Host Application variables
@@ -179,15 +179,17 @@ public SendComplexDataTest(TCK aTCK, Utilities utilities, String[] parms, Result
179179
theTCK = aTCK;
180180
this.utilities = utilities;
181181

182-
if (parms.length < 4) {
182+
if (parms.length < 3) {
183183
log("Not enough parameters: " + Arrays.toString(parms));
184-
log(getName() + " Parameters must be: hostId groupId edgeNodeId deviceId");
184+
log(getName() + " Parameters must be: hostId groupId edgeNodeId {deviceId}");
185185
throw new IllegalArgumentException();
186186
}
187187
hostApplicationId = parms[0];
188188
groupId = parms[1];
189189
edgeNodeId = parms[2];
190-
deviceId = parms[3];
190+
if (parms.length == 4) {
191+
deviceId = parms[3];
192+
}
191193
logger.info("Parameters are HostId: {}, GroupId: {}, EdgeNodeId: {}, DeviceId: {}", hostApplicationId, groupId,
192194
edgeNodeId, deviceId);
193195

@@ -271,10 +273,26 @@ public void publish(final @NotNull String clientId, final @NotNull PublishPacket
271273
logger.error("Skip Edge payload validation - no sparkplug payload.");
272274
return;
273275
}
274-
boolean isDataTopic =
275-
isSparkplugTopic && (topic.contains(TOPIC_PATH_DDATA) || topic.contains(TOPIC_PATH_NDATA));
276-
boolean isCommandTopic =
277-
isSparkplugTopic && (topic.contains(TOPIC_PATH_NCMD) || topic.contains(TOPIC_PATH_DCMD));
276+
277+
String cmd = "";
278+
String[] levels = topic.split("/");
279+
if (levels.length >= 3) {
280+
cmd = levels[2];
281+
logger.info("Looking for {}", cmd);
282+
} else {
283+
return;
284+
}
285+
if (!levels[1].equals(groupId) || !levels[3].equals(edgeNodeId)) {
286+
logger.error("GroupId {} or edgeNodeId {} not matched.", groupId, edgeNodeId);
287+
return;
288+
}
289+
// ignore device messages if we don't have a deviceId
290+
boolean isDataTopic = (deviceId != null && cmd.equals(TOPIC_PATH_DDATA)) || cmd.equals(TOPIC_PATH_NDATA);
291+
boolean isCommandTopic = (deviceId != null && cmd.equals(TOPIC_PATH_DCMD)) || cmd.equals(TOPIC_PATH_NCMD);
292+
if (deviceId != null && levels.length >= 5 && !levels[4].equals(deviceId)) {
293+
logger.error("deviceId not matched.");
294+
return;
295+
}
278296

279297
checkPropertiesValidType(packet, topic);
280298
checkSequenceNumberIncluded(packet, topic);
@@ -300,31 +318,27 @@ public void publish(final @NotNull String clientId, final @NotNull PublishPacket
300318
}
301319

302320
private void checkDataTopicPayload(final @NotNull String clientId, final @NotNull PublishPacket packet,
303-
final @NotNull String topic) {
304-
if (clientId.contentEquals(deviceId) || topic.contains(groupId) && topic.contains(edgeNodeId)) {
305-
final PayloadOrBuilder sparkplugPayload = Utils.getSparkplugPayload(packet);
306-
if (sparkplugPayload != null) {
307-
checkPayloadsNameRequirement(sparkplugPayload);
308-
checkAliasInData(sparkplugPayload, topic);
309-
checkMetricsDataTypeNotRec(sparkplugPayload, topic);
310-
checkPayloadsNameInDataRequirement(sparkplugPayload);
311-
} else {
312-
logger.error("Skip Edge payload validation - no sparkplug payload.");
313-
}
321+
final @NotNull String topic) {
322+
final PayloadOrBuilder sparkplugPayload = Utils.getSparkplugPayload(packet);
323+
if (sparkplugPayload != null) {
324+
checkPayloadsNameRequirement(sparkplugPayload);
325+
checkAliasInData(sparkplugPayload, topic);
326+
checkMetricsDataTypeNotRec(sparkplugPayload, topic);
327+
checkPayloadsNameInDataRequirement(sparkplugPayload);
328+
} else {
329+
logger.error("Skip Edge payload validation - no sparkplug payload.");
314330
}
315331
}
316332

317333
private void checkCommandTopicPayload(final @NotNull String clientId, final @NotNull PublishPacket packet,
318-
final @NotNull String topic) {
319-
if (clientId.contentEquals(deviceId) || topic.contains(groupId) && topic.contains(edgeNodeId)) {
320-
final PayloadOrBuilder sparkplugPayload = Utils.getSparkplugPayload(packet);
321-
if (sparkplugPayload != null) {
322-
checkAliasInData(sparkplugPayload, topic);
323-
checkMetricsDataTypeNotRec(sparkplugPayload, topic);
324-
checkPayloadsNameRequirement(sparkplugPayload);
325-
} else {
326-
logger.error("Skip Edge payload validation - no sparkplug payload.");
327-
}
334+
final @NotNull String topic) {
335+
final PayloadOrBuilder sparkplugPayload = Utils.getSparkplugPayload(packet);
336+
if (sparkplugPayload != null) {
337+
checkAliasInData(sparkplugPayload, topic);
338+
checkMetricsDataTypeNotRec(sparkplugPayload, topic);
339+
checkPayloadsNameRequirement(sparkplugPayload);
340+
} else {
341+
logger.error("Skip Edge payload validation - no sparkplug payload.");
328342
}
329343
}
330344

@@ -381,6 +395,7 @@ public void checkDatatypeValidType(final @NotNull PublishPacket packet) {
381395
if(!Utils.hasValidDatatype(m)){
382396
isValid_DataType = false;
383397
isValid_DataTypeValue = false;
398+
logger.error("Metric error {}", m);
384399
break;
385400
}
386401
}

tck/src/main/java/org/eclipse/sparkplug/tck/test/edge/SendDataTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,17 @@ public SendDataTest(TCK aTCK, Utilities utilities, String[] params, Results.Conf
172172
this.utilities = utilities;
173173
this.config = config;
174174

175-
if (params.length < 3) {
175+
if (params.length < 2) {
176176
log("Not enough parameters: " + Arrays.toString(params));
177-
log("Parameters to send data test must be: groupId edgeNodeId deviceId");
177+
log("Parameters to send data test must be: hostApplicationId groupId edgeNodeId {deviceId}");
178178
throw new IllegalArgumentException();
179179
}
180180
hostApplicationId = params[0];
181181
groupId = params[1];
182182
edgeNodeId = params[2];
183-
deviceId = params[3];
183+
if (params.length == 4) {
184+
deviceId = params[3];
185+
}
184186
logger.info("Parameters are Host application ID: {}, GroupId: {}, EdgeNodeId: {}, DeviceId: {}",
185187
hostApplicationId, groupId, edgeNodeId, deviceId);
186188

@@ -285,7 +287,7 @@ public void publish(String clientId, PublishPacket packet) {
285287
checkDDATA(clientId, packet);
286288
}
287289

288-
if (isEdgeNodeChecked && isDeviceChecked) {
290+
if (isEdgeNodeChecked && (deviceId == null || isDeviceChecked)) {
289291
theTCK.endTest();
290292
}
291293
}

0 commit comments

Comments
 (0)