diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java index 69d40f5409..1a2f4f1d02 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadCon import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.msg.session.FeatureType; import org.thingsboard.server.transport.AbstractTransportIntegrationTest; import org.thingsboard.server.utils.PortFinder; @@ -176,4 +177,14 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg device.setType(type); return doPost("/api/device", device, Device.class); } + + protected CoapTestClient createClientForFeatureWithConfirmableParameter(FeatureType featureType, boolean confirmable) { + CoapTestClient coapTestClient = new CoapTestClient(accessToken, featureType); + if (confirmable) { + coapTestClient.useCONs(); + } else { + coapTestClient.useNONs(); + } + return coapTestClient; + } } diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/client/AbstractCoapClientPiggybackedIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/client/AbstractCoapClientPiggybackedIntegrationTest.java new file mode 100644 index 0000000000..32b7e9dc80 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/coap/client/AbstractCoapClientPiggybackedIntegrationTest.java @@ -0,0 +1,52 @@ +/** + * Copyright © 2016-2026 The Thingsboard Authors + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.transport.coap.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.californium.core.CoapResponse;
+import org.eclipse.californium.core.coap.CoAP;
+import org.junit.After;
+import org.junit.Before;
+import org.thingsboard.server.common.msg.session.FeatureType;
+import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
+import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@Slf4j
+public abstract class AbstractCoapClientPiggybackedIntegrationTest extends AbstractCoapIntegrationTest {
+
+ @Before
+ public void beforeTest() throws Exception {
+ CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()
+ .deviceName("CoAP Message Flow Piggyback Device")
+ .build();
+ processBeforeTest(configProperties);
+ }
+
+ @After
+ public void afterTest() throws Exception {
+ processAfterTest();
+ }
+
+ protected void testCase(boolean confirmable, CoAP.Type expectedResponseType) throws Exception {
+ client = createClientForFeatureWithConfirmableParameter(FeatureType.ATTRIBUTES, confirmable);
+ CoapResponse response = client.postMethod(PAYLOAD_VALUES_STR);
+ assertNotNull(response);
+ assertEquals(expectedResponseType, response.advanced().getType());
+ }
+}
diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java
index 12b2b677d4..a128710078 100644
--- a/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java
+++ b/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -100,7 +100,7 @@ public class CoapClientIntegrationTest extends AbstractCoapIntegrationTest {
client = createClientForFeatureWithConfirmableParameter(FeatureType.ATTRIBUTES, confirmable);
CoapResponse coapResponse = client.postMethod(PAYLOAD_VALUES_STR.getBytes());
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
- assertEquals("CoAP response type is wrong!", client.getType(), coapResponse.advanced().getType());
+ assertValidResponseType(client.getType(), coapResponse.advanced().getType());
DeviceId deviceId = savedDevice.getId();
List
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.transport.coap.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.californium.core.coap.CoAP;
+import org.junit.Test;
+import org.springframework.test.context.TestPropertySource;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+@Slf4j
+@DaoSqlTest
+@TestPropertySource(properties = {
+ "transport.coap.piggyback_timeout=0"
+})
+public class CoapClientNoPiggybackIntegrationTest extends AbstractCoapClientPiggybackedIntegrationTest {
+ @Test
+ public void testConfirmable() throws Exception {
+ // response should be sent via seperate CON transaction (not piggybacked)
+ testCase(true, CoAP.Type.CON);
+ }
+
+ @Test
+ public void testNonConfirmable() throws Exception {
+ testCase(false, CoAP.Type.NON);
+ }
+}
diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientPiggybackedIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientPiggybackedIntegrationTest.java
new file mode 100644
index 0000000000..68f28ce4db
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientPiggybackedIntegrationTest.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright © 2016-2026 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.transport.coap.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.californium.core.coap.CoAP;
+import org.junit.Test;
+import org.springframework.test.context.TestPropertySource;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+@Slf4j
+@DaoSqlTest
+@TestPropertySource(properties = {
+ "transport.coap.piggyback_timeout=2000"
+})
+public class CoapClientPiggybackedIntegrationTest extends AbstractCoapClientPiggybackedIntegrationTest {
+ @Test
+ public void testConfirmable() throws Exception {
+ // response should be included in the ACK packet (piggybacked)
+ testCase(true, CoAP.Type.ACK);
+ }
+
+ @Test
+ public void testNonConfirmable() throws Exception {
+ testCase(false, CoAP.Type.NON);
+ }
+}
diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/AbstractSyncSessionCallback.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/AbstractSyncSessionCallback.java
index bf23ea6766..6fa56dbd47 100644
--- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/AbstractSyncSessionCallback.java
+++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/AbstractSyncSessionCallback.java
@@ -87,7 +87,6 @@ public abstract class AbstractSyncSessionCallback implements SessionMsgListener
protected void respond(Response response) {
response.getOptions().setContentFormat(TbCoapContentFormatUtil.getContentFormat(exchange.getRequestOptions().getContentFormat(), state.getContentFormat()));
- response.setConfirmable(exchange.advanced().getRequest().isConfirmable());
exchange.respond(response);
}
diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java
index c3f70ce0d7..2502f40bfc 100644
--- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java
+++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java
@@ -36,7 +36,6 @@ public class CoapResponseCallback implements TransportServiceCallback