Commit 321fb731a6537399a6e4572837967fe41cdaf58a
Committed by
GitHub
1 parent
51b0d505
Support of server-side RPC requests via protobuf for CoAP and MQTT
* rpc response schema added * rpc request proto * fixed device profile validation * fix error messages
Showing
32 changed files
with
568 additions
and
165 deletions
@@ -15,35 +15,11 @@ | @@ -15,35 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport; | 16 | package org.thingsboard.server.transport; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
19 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
20 | -import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ||
21 | -import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | ||
22 | -import org.eclipse.paho.client.mqttv3.MqttException; | ||
23 | -import org.eclipse.paho.client.mqttv3.MqttMessage; | ||
24 | -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; | ||
25 | -import org.junit.Assert; | ||
26 | -import org.springframework.util.StringUtils; | ||
27 | import org.thingsboard.server.common.data.Device; | 19 | import org.thingsboard.server.common.data.Device; |
28 | import org.thingsboard.server.common.data.DeviceProfile; | 20 | import org.thingsboard.server.common.data.DeviceProfile; |
29 | -import org.thingsboard.server.common.data.DeviceProfileProvisionType; | ||
30 | -import org.thingsboard.server.common.data.DeviceProfileType; | ||
31 | -import org.thingsboard.server.common.data.DeviceTransportType; | ||
32 | import org.thingsboard.server.common.data.Tenant; | 21 | import org.thingsboard.server.common.data.Tenant; |
33 | -import org.thingsboard.server.common.data.TransportPayloadType; | ||
34 | import org.thingsboard.server.common.data.User; | 22 | import org.thingsboard.server.common.data.User; |
35 | -import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration; | ||
36 | -import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration; | ||
37 | -import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; | ||
38 | -import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | ||
39 | -import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; | ||
40 | -import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; | ||
41 | -import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; | ||
42 | -import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
43 | -import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
44 | -import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
45 | -import org.thingsboard.server.common.data.security.Authority; | ||
46 | -import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
47 | import org.thingsboard.server.controller.AbstractControllerTest; | 23 | import org.thingsboard.server.controller.AbstractControllerTest; |
48 | import org.thingsboard.server.gen.transport.TransportProtos; | 24 | import org.thingsboard.server.gen.transport.TransportProtos; |
49 | 25 | ||
@@ -51,8 +27,6 @@ import java.util.ArrayList; | @@ -51,8 +27,6 @@ import java.util.ArrayList; | ||
51 | import java.util.List; | 27 | import java.util.List; |
52 | import java.util.concurrent.atomic.AtomicInteger; | 28 | import java.util.concurrent.atomic.AtomicInteger; |
53 | 29 | ||
54 | -import static org.junit.Assert.assertEquals; | ||
55 | -import static org.junit.Assert.assertNotNull; | ||
56 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 30 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
57 | 31 | ||
58 | @Slf4j | 32 | @Slf4j |
@@ -105,6 +79,22 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle | @@ -105,6 +79,22 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle | ||
105 | " }\n" + | 79 | " }\n" + |
106 | "}"; | 80 | "}"; |
107 | 81 | ||
82 | + protected static final String DEVICE_RPC_RESPONSE_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | ||
83 | + "package rpc;\n" + | ||
84 | + "\n" + | ||
85 | + "message RpcResponseMsg {\n" + | ||
86 | + " string payload = 1;\n" + | ||
87 | + "}"; | ||
88 | + | ||
89 | + protected static final String DEVICE_RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | ||
90 | + "package rpc;\n" + | ||
91 | + "\n" + | ||
92 | + "message RpcRequestMsg {\n" + | ||
93 | + " string method = 1;\n" + | ||
94 | + " int32 requestId = 2;\n" + | ||
95 | + " string params = 3;\n" + | ||
96 | + "}"; | ||
97 | + | ||
108 | protected Tenant savedTenant; | 98 | protected Tenant savedTenant; |
109 | protected User tenantAdmin; | 99 | protected User tenantAdmin; |
110 | 100 |
@@ -53,7 +53,7 @@ import static org.junit.Assert.assertNotNull; | @@ -53,7 +53,7 @@ import static org.junit.Assert.assertNotNull; | ||
53 | public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { | 53 | public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { |
54 | 54 | ||
55 | protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { | 55 | protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { |
56 | - this.processBeforeTest(deviceName, coapDeviceType, payloadType, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 56 | + this.processBeforeTest(deviceName, coapDeviceType, payloadType, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
57 | } | 57 | } |
58 | 58 | ||
59 | protected void processBeforeTest(String deviceName, | 59 | protected void processBeforeTest(String deviceName, |
@@ -61,8 +61,11 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | @@ -61,8 +61,11 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | ||
61 | TransportPayloadType payloadType, | 61 | TransportPayloadType payloadType, |
62 | String telemetryProtoSchema, | 62 | String telemetryProtoSchema, |
63 | String attributesProtoSchema, | 63 | String attributesProtoSchema, |
64 | - DeviceProfileProvisionType provisionType, | ||
65 | - String provisionKey, String provisionSecret | 64 | + String rpcResponseProtoSchema, |
65 | + String rpcRequestProtoSchema, | ||
66 | + String provisionKey, | ||
67 | + String provisionSecret, | ||
68 | + DeviceProfileProvisionType provisionType | ||
66 | ) throws Exception { | 69 | ) throws Exception { |
67 | loginSysAdmin(); | 70 | loginSysAdmin(); |
68 | 71 | ||
@@ -85,7 +88,7 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | @@ -85,7 +88,7 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | ||
85 | device.setType("default"); | 88 | device.setType("default"); |
86 | 89 | ||
87 | if (coapDeviceType != null) { | 90 | if (coapDeviceType != null) { |
88 | - DeviceProfile coapDeviceProfile = createCoapDeviceProfile(payloadType, coapDeviceType, attributesProtoSchema, provisionType, provisionKey, provisionSecret, telemetryProtoSchema); | 91 | + DeviceProfile coapDeviceProfile = createCoapDeviceProfile(payloadType, coapDeviceType, provisionSecret, provisionType, provisionKey, attributesProtoSchema, telemetryProtoSchema, rpcResponseProtoSchema, rpcRequestProtoSchema); |
89 | deviceProfile = doPost("/api/deviceProfile", coapDeviceProfile, DeviceProfile.class); | 92 | deviceProfile = doPost("/api/deviceProfile", coapDeviceProfile, DeviceProfile.class); |
90 | device.setType(deviceProfile.getName()); | 93 | device.setType(deviceProfile.getName()); |
91 | device.setDeviceProfileId(deviceProfile.getId()); | 94 | device.setDeviceProfileId(deviceProfile.getId()); |
@@ -103,8 +106,9 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | @@ -103,8 +106,9 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | ||
103 | } | 106 | } |
104 | 107 | ||
105 | protected DeviceProfile createCoapDeviceProfile(TransportPayloadType transportPayloadType, CoapDeviceType coapDeviceType, | 108 | protected DeviceProfile createCoapDeviceProfile(TransportPayloadType transportPayloadType, CoapDeviceType coapDeviceType, |
106 | - String attributesProtoSchema, DeviceProfileProvisionType provisionType, | ||
107 | - String provisionKey, String provisionSecret, String telemetryProtoSchema) { | 109 | + String provisionSecret, DeviceProfileProvisionType provisionType, |
110 | + String provisionKey, String attributesProtoSchema, | ||
111 | + String telemetryProtoSchema, String rpcResponseProtoSchema, String rpcRequestProtoSchema) { | ||
108 | DeviceProfile deviceProfile = new DeviceProfile(); | 112 | DeviceProfile deviceProfile = new DeviceProfile(); |
109 | deviceProfile.setName(transportPayloadType.name()); | 113 | deviceProfile.setName(transportPayloadType.name()); |
110 | deviceProfile.setType(DeviceProfileType.DEFAULT); | 114 | deviceProfile.setType(DeviceProfileType.DEFAULT); |
@@ -127,8 +131,16 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | @@ -127,8 +131,16 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg | ||
127 | if (StringUtils.isEmpty(attributesProtoSchema)) { | 131 | if (StringUtils.isEmpty(attributesProtoSchema)) { |
128 | attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; | 132 | attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; |
129 | } | 133 | } |
134 | + if (StringUtils.isEmpty(rpcResponseProtoSchema)) { | ||
135 | + rpcResponseProtoSchema = DEVICE_RPC_RESPONSE_PROTO_SCHEMA; | ||
136 | + } | ||
137 | + if (StringUtils.isEmpty(rpcRequestProtoSchema)) { | ||
138 | + rpcRequestProtoSchema = DEVICE_RPC_REQUEST_PROTO_SCHEMA; | ||
139 | + } | ||
130 | protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); | 140 | protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); |
131 | protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); | 141 | protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); |
142 | + protoTransportPayloadConfiguration.setDeviceRpcResponseProtoSchema(rpcResponseProtoSchema); | ||
143 | + protoTransportPayloadConfiguration.setDeviceRpcRequestProtoSchema(rpcRequestProtoSchema); | ||
132 | transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; | 144 | transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; |
133 | } else { | 145 | } else { |
134 | transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); | 146 | transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); |
@@ -79,7 +79,7 @@ public abstract class AbstractCoapAttributesRequestProtoIntegrationTest extends | @@ -79,7 +79,7 @@ public abstract class AbstractCoapAttributesRequestProtoIntegrationTest extends | ||
79 | @Test | 79 | @Test |
80 | public void testRequestAttributesValuesFromTheServer() throws Exception { | 80 | public void testRequestAttributesValuesFromTheServer() throws Exception { |
81 | super.processBeforeTest("Test Request attribute values from the server proto", CoapDeviceType.DEFAULT, | 81 | super.processBeforeTest("Test Request attribute values from the server proto", CoapDeviceType.DEFAULT, |
82 | - TransportPayloadType.PROTOBUF, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); | 82 | + TransportPayloadType.PROTOBUF, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
83 | processTestRequestAttributesValuesFromTheServer(); | 83 | processTestRequestAttributesValuesFromTheServer(); |
84 | } | 84 | } |
85 | 85 |
@@ -88,7 +88,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | @@ -88,7 +88,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | ||
88 | 88 | ||
89 | 89 | ||
90 | private void processTestProvisioningDisabledDevice() throws Exception { | 90 | private void processTestProvisioningDisabledDevice() throws Exception { |
91 | - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 91 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
92 | byte[] result = createCoapClientAndPublish().getPayload(); | 92 | byte[] result = createCoapClientAndPublish().getPayload(); |
93 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 93 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
94 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | 94 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
@@ -97,7 +97,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | @@ -97,7 +97,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | ||
97 | 97 | ||
98 | 98 | ||
99 | private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | 99 | private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
100 | - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 100 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
101 | byte[] result = createCoapClientAndPublish().getPayload(); | 101 | byte[] result = createCoapClientAndPublish().getPayload(); |
102 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 102 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
103 | 103 | ||
@@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | @@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | ||
113 | 113 | ||
114 | 114 | ||
115 | private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | 115 | private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
116 | - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 116 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
117 | String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; | 117 | String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; |
118 | byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); | 118 | byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); |
119 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 119 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -132,7 +132,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | @@ -132,7 +132,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | ||
132 | 132 | ||
133 | 133 | ||
134 | private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | 134 | private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
135 | - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 135 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
136 | String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; | 136 | String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; |
137 | byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); | 137 | byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); |
138 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 138 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -156,7 +156,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | @@ -156,7 +156,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | ||
156 | } | 156 | } |
157 | 157 | ||
158 | private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | 158 | private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
159 | - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | 159 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
160 | byte[] result = createCoapClientAndPublish().getPayload(); | 160 | byte[] result = createCoapClientAndPublish().getPayload(); |
161 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 161 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
162 | 162 | ||
@@ -167,7 +167,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | @@ -167,7 +167,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn | ||
167 | } | 167 | } |
168 | 168 | ||
169 | private void processTestProvisioningWithBadKeyDevice() throws Exception { | 169 | private void processTestProvisioningWithBadKeyDevice() throws Exception { |
170 | - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | 170 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
171 | byte[] result = createCoapClientAndPublish().getPayload(); | 171 | byte[] result = createCoapClientAndPublish().getPayload(); |
172 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 172 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
173 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | 173 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
@@ -92,14 +92,14 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | @@ -92,14 +92,14 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | ||
92 | 92 | ||
93 | 93 | ||
94 | private void processTestProvisioningDisabledDevice() throws Exception { | 94 | private void processTestProvisioningDisabledDevice() throws Exception { |
95 | - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 95 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
96 | ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | 96 | ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
97 | Assert.assertNotNull(result); | 97 | Assert.assertNotNull(result); |
98 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); | 98 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); |
99 | } | 99 | } |
100 | 100 | ||
101 | private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | 101 | private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
102 | - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 102 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
103 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | 103 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
104 | 104 | ||
105 | Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | 105 | Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
@@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | @@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | ||
113 | } | 113 | } |
114 | 114 | ||
115 | private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | 115 | private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
116 | - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 116 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
117 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); | 117 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); |
118 | 118 | ||
119 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload()); | 119 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload()); |
@@ -131,7 +131,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | @@ -131,7 +131,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | ||
131 | } | 131 | } |
132 | 132 | ||
133 | private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | 133 | private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
134 | - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 134 | + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
135 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); | 135 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); |
136 | 136 | ||
137 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload()); | 137 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload()); |
@@ -155,7 +155,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | @@ -155,7 +155,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | ||
155 | } | 155 | } |
156 | 156 | ||
157 | private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | 157 | private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
158 | - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | 158 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
159 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | 159 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
160 | 160 | ||
161 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); | 161 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); |
@@ -165,7 +165,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | @@ -165,7 +165,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI | ||
165 | } | 165 | } |
166 | 166 | ||
167 | private void processTestProvisioningWithBadKeyDevice() throws Exception { | 167 | private void processTestProvisioningWithBadKeyDevice() throws Exception { |
168 | - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | 168 | + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
169 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); | 169 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
170 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); | 170 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); |
171 | } | 171 | } |
@@ -124,7 +124,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC | @@ -124,7 +124,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC | ||
124 | return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId; | 124 | return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId; |
125 | } | 125 | } |
126 | 126 | ||
127 | - private class TestCoapCallback implements CoapHandler { | 127 | + protected class TestCoapCallback implements CoapHandler { |
128 | 128 | ||
129 | private final CoapClient client; | 129 | private final CoapClient client; |
130 | private final CountDownLatch latch; | 130 | private final CountDownLatch latch; |
@@ -136,7 +136,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC | @@ -136,7 +136,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC | ||
136 | 136 | ||
137 | private Integer observe; | 137 | private Integer observe; |
138 | 138 | ||
139 | - private TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) { | 139 | + TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) { |
140 | this.client = client; | 140 | this.client = client; |
141 | this.latch = latch; | 141 | this.latch = latch; |
142 | this.isOneWayRpc = isOneWayRpc; | 142 | this.isOneWayRpc = isOneWayRpc; |
@@ -144,7 +144,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC | @@ -144,7 +144,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC | ||
144 | 144 | ||
145 | @Override | 145 | @Override |
146 | public void onLoad(CoapResponse response) { | 146 | public void onLoad(CoapResponse response) { |
147 | - log.warn("coap response: {}, {}", response, response.getCode()); | 147 | + log.warn("coap response: {}, {}", response.getResponseText(), response.getCode()); |
148 | assertNotNull(response.getPayload()); | 148 | assertNotNull(response.getPayload()); |
149 | assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); | 149 | assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); |
150 | observe = response.getOptions().getObserve(); | 150 | observe = response.getOptions().getObserve(); |
@@ -36,12 +36,12 @@ public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends Abstr | @@ -36,12 +36,12 @@ public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends Abstr | ||
36 | } | 36 | } |
37 | 37 | ||
38 | @Test | 38 | @Test |
39 | - public void testServerMqttOneWayRpc() throws Exception { | 39 | + public void testServerCoapOneWayRpc() throws Exception { |
40 | processOneWayRpcTest(); | 40 | processOneWayRpcTest(); |
41 | } | 41 | } |
42 | 42 | ||
43 | @Test | 43 | @Test |
44 | - public void testServerMqttTwoWayRpc() throws Exception { | 44 | + public void testServerCoapTwoWayRpc() throws Exception { |
45 | processTwoWayRpcTest(); | 45 | processTwoWayRpcTest(); |
46 | } | 46 | } |
47 | 47 |
@@ -15,26 +15,62 @@ | @@ -15,26 +15,62 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.coap.rpc; | 16 | package org.thingsboard.server.transport.coap.rpc; |
17 | 17 | ||
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
19 | +import com.google.protobuf.Descriptors; | ||
20 | +import com.google.protobuf.DynamicMessage; | ||
21 | +import com.google.protobuf.InvalidProtocolBufferException; | ||
22 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
18 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
19 | import org.eclipse.californium.core.CoapClient; | 24 | import org.eclipse.californium.core.CoapClient; |
20 | import org.eclipse.californium.core.CoapHandler; | 25 | import org.eclipse.californium.core.CoapHandler; |
26 | +import org.eclipse.californium.core.CoapObserveRelation; | ||
21 | import org.eclipse.californium.core.CoapResponse; | 27 | import org.eclipse.californium.core.CoapResponse; |
28 | +import org.eclipse.californium.core.coap.CoAP; | ||
22 | import org.eclipse.californium.core.coap.MediaTypeRegistry; | 29 | import org.eclipse.californium.core.coap.MediaTypeRegistry; |
30 | +import org.eclipse.californium.core.coap.Request; | ||
23 | import org.junit.After; | 31 | import org.junit.After; |
24 | import org.junit.Before; | 32 | import org.junit.Before; |
25 | import org.junit.Test; | 33 | import org.junit.Test; |
26 | import org.thingsboard.server.common.data.CoapDeviceType; | 34 | import org.thingsboard.server.common.data.CoapDeviceType; |
35 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | ||
27 | import org.thingsboard.server.common.data.TransportPayloadType; | 36 | import org.thingsboard.server.common.data.TransportPayloadType; |
28 | -import org.thingsboard.server.gen.transport.TransportProtos; | 37 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; |
38 | +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; | ||
39 | +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; | ||
40 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | ||
41 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
42 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
43 | +import org.thingsboard.server.common.msg.session.FeatureType; | ||
29 | 44 | ||
45 | +import java.util.List; | ||
30 | import java.util.concurrent.CountDownLatch; | 46 | import java.util.concurrent.CountDownLatch; |
47 | +import java.util.concurrent.TimeUnit; | ||
48 | + | ||
49 | +import static org.junit.Assert.assertEquals; | ||
50 | +import static org.junit.Assert.assertNotNull; | ||
51 | +import static org.junit.Assert.assertTrue; | ||
52 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
31 | 53 | ||
32 | @Slf4j | 54 | @Slf4j |
33 | public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { | 55 | public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { |
34 | 56 | ||
57 | + private static final String RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | ||
58 | + "package rpc;\n" + | ||
59 | + "\n" + | ||
60 | + "message RpcRequestMsg {\n" + | ||
61 | + " string method = 1;\n" + | ||
62 | + " int32 requestId = 2;\n" + | ||
63 | + " Params params = 3;\n" + | ||
64 | + "\n" + | ||
65 | + " message Params {\n" + | ||
66 | + " string pin = 1;\n" + | ||
67 | + " int32 value = 2;\n" + | ||
68 | + " }\n" + | ||
69 | + "}"; | ||
70 | + | ||
35 | @Before | 71 | @Before |
36 | public void beforeTest() throws Exception { | 72 | public void beforeTest() throws Exception { |
37 | - processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); | 73 | + processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, RPC_REQUEST_PROTO_SCHEMA, null, null, DeviceProfileProvisionType.DISABLED); |
38 | } | 74 | } |
39 | 75 | ||
40 | @After | 76 | @After |
@@ -43,33 +79,91 @@ public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends Abst | @@ -43,33 +79,91 @@ public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends Abst | ||
43 | } | 79 | } |
44 | 80 | ||
45 | @Test | 81 | @Test |
46 | - public void testServerMqttOneWayRpc() throws Exception { | 82 | + public void testServerCoapOneWayRpc() throws Exception { |
47 | processOneWayRpcTest(); | 83 | processOneWayRpcTest(); |
48 | } | 84 | } |
49 | 85 | ||
50 | @Test | 86 | @Test |
51 | - public void testServerMqttTwoWayRpc() throws Exception { | 87 | + public void testServerCoapTwoWayRpc() throws Exception { |
52 | processTwoWayRpcTest(); | 88 | processTwoWayRpcTest(); |
53 | } | 89 | } |
54 | 90 | ||
91 | + protected void processTwoWayRpcTest() throws Exception { | ||
92 | + CoapClient client = getCoapClient(FeatureType.RPC); | ||
93 | + client.useCONs(); | ||
94 | + | ||
95 | + CountDownLatch latch = new CountDownLatch(1); | ||
96 | + TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, false); | ||
97 | + | ||
98 | + Request request = Request.newGet().setObserve(); | ||
99 | + request.setType(CoAP.Type.CON); | ||
100 | + CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); | ||
101 | + | ||
102 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; | ||
103 | + String deviceId = savedDevice.getId().getId().toString(); | ||
104 | + | ||
105 | + String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}"; | ||
106 | + | ||
107 | + String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | ||
108 | + latch.await(3, TimeUnit.SECONDS); | ||
109 | + | ||
110 | + assertEquals(expected, result); | ||
111 | + assertEquals(0, testCoapCallback.getObserve().intValue()); | ||
112 | + observeRelation.proactiveCancel(); | ||
113 | + assertTrue(observeRelation.isCanceled()); | ||
114 | + } | ||
115 | + | ||
55 | @Override | 116 | @Override |
56 | protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { | 117 | protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { |
57 | client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); | 118 | client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); |
58 | - TransportProtos.ToDeviceRpcResponseMsg toDeviceRpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
59 | - .setPayload(DEVICE_RESPONSE) | ||
60 | - .setRequestId(observe) | ||
61 | - .build(); | ||
62 | - client.post(new CoapHandler() { | ||
63 | - @Override | ||
64 | - public void onLoad(CoapResponse response) { | ||
65 | - log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); | ||
66 | - latch.countDown(); | ||
67 | - } | 119 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration(); |
120 | + ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA); | ||
121 | + DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA); | ||
68 | 122 | ||
69 | - @Override | ||
70 | - public void onError() { | ||
71 | - log.warn("Command Response Ack Error, No connect"); | 123 | + byte[] requestPayload = response.getPayload(); |
124 | + DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg"); | ||
125 | + Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType(); | ||
126 | + assertNotNull(rpcRequestMsgDescriptor); | ||
127 | + try { | ||
128 | + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload); | ||
129 | + List<Descriptors.FieldDescriptor> fields = rpcRequestMsgDescriptor.getFields(); | ||
130 | + for (Descriptors.FieldDescriptor fieldDescriptor: fields) { | ||
131 | + assertTrue(dynamicMessage.hasField(fieldDescriptor)); | ||
72 | } | 132 | } |
73 | - }, toDeviceRpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON); | 133 | + ProtoFileElement rpcResponseProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA); |
134 | + DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcResponseProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA); | ||
135 | + DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg"); | ||
136 | + Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType(); | ||
137 | + assertNotNull(rpcResponseMsgDescriptor); | ||
138 | + DynamicMessage rpcResponseMsg = rpcResponseBuilder | ||
139 | + .setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE) | ||
140 | + .build(); | ||
141 | + client.post(new CoapHandler() { | ||
142 | + @Override | ||
143 | + public void onLoad(CoapResponse response) { | ||
144 | + log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); | ||
145 | + latch.countDown(); | ||
146 | + } | ||
147 | + | ||
148 | + @Override | ||
149 | + public void onError() { | ||
150 | + log.warn("Command Response Ack Error, No connect"); | ||
151 | + } | ||
152 | + }, rpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON); | ||
153 | + } catch (InvalidProtocolBufferException e) { | ||
154 | + log.warn("Command Response Ack Error, Invalid response received: ", e); | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + private ProtoTransportPayloadConfiguration getProtoTransportPayloadConfiguration() { | ||
159 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | ||
160 | + assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); | ||
161 | + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | ||
162 | + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); | ||
163 | + assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); | ||
164 | + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; | ||
165 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); | ||
166 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | ||
167 | + return (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
74 | } | 168 | } |
75 | } | 169 | } |
@@ -114,7 +114,7 @@ public abstract class AbstractCoapTimeseriesProtoIntegrationTest extends Abstrac | @@ -114,7 +114,7 @@ public abstract class AbstractCoapTimeseriesProtoIntegrationTest extends Abstrac | ||
114 | " }\n" + | 114 | " }\n" + |
115 | " }\n" + | 115 | " }\n" + |
116 | "}"; | 116 | "}"; |
117 | - super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); | 117 | + super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, schemaStr, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
118 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | 118 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
119 | assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); | 119 | assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); |
120 | CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | 120 | CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; |
@@ -62,7 +62,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | @@ -62,7 +62,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | ||
62 | protected DeviceProfile deviceProfile; | 62 | protected DeviceProfile deviceProfile; |
63 | 63 | ||
64 | protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { | 64 | protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { |
65 | - this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 65 | + this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
66 | } | 66 | } |
67 | 67 | ||
68 | protected void processBeforeTest(String deviceName, | 68 | protected void processBeforeTest(String deviceName, |
@@ -72,9 +72,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | @@ -72,9 +72,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | ||
72 | String attributesTopic, | 72 | String attributesTopic, |
73 | String telemetryProtoSchema, | 73 | String telemetryProtoSchema, |
74 | String attributesProtoSchema, | 74 | String attributesProtoSchema, |
75 | - DeviceProfileProvisionType provisionType, | ||
76 | - String provisionKey, String provisionSecret | ||
77 | - ) throws Exception { | 75 | + String rpcResponseProtoSchema, |
76 | + String rpcRequestProtoSchema, | ||
77 | + String provisionKey, | ||
78 | + String provisionSecret, | ||
79 | + DeviceProfileProvisionType provisionType | ||
80 | + ) throws Exception { | ||
78 | loginSysAdmin(); | 81 | loginSysAdmin(); |
79 | 82 | ||
80 | Tenant tenant = new Tenant(); | 83 | Tenant tenant = new Tenant(); |
@@ -103,7 +106,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | @@ -103,7 +106,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | ||
103 | gateway.setAdditionalInfo(additionalInfo); | 106 | gateway.setAdditionalInfo(additionalInfo); |
104 | 107 | ||
105 | if (payloadType != null) { | 108 | if (payloadType != null) { |
106 | - DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, provisionType, provisionKey, provisionSecret); | 109 | + DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, rpcResponseProtoSchema, rpcRequestProtoSchema, provisionKey, provisionSecret, provisionType); |
107 | deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); | 110 | deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); |
108 | device.setType(deviceProfile.getName()); | 111 | device.setType(deviceProfile.getName()); |
109 | device.setDeviceProfileId(deviceProfile.getId()); | 112 | device.setDeviceProfileId(deviceProfile.getId()); |
@@ -157,8 +160,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | @@ -157,8 +160,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | ||
157 | protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, | 160 | protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, |
158 | String telemetryTopic, String attributesTopic, | 161 | String telemetryTopic, String attributesTopic, |
159 | String telemetryProtoSchema, String attributesProtoSchema, | 162 | String telemetryProtoSchema, String attributesProtoSchema, |
160 | - DeviceProfileProvisionType provisionType, | ||
161 | - String provisionKey, String provisionSecret) { | 163 | + String rpcResponseProtoSchema, String rpcRequestProtoSchema, |
164 | + String provisionKey, String provisionSecret, | ||
165 | + DeviceProfileProvisionType provisionType) { | ||
162 | DeviceProfile deviceProfile = new DeviceProfile(); | 166 | DeviceProfile deviceProfile = new DeviceProfile(); |
163 | deviceProfile.setName(transportPayloadType.name()); | 167 | deviceProfile.setName(transportPayloadType.name()); |
164 | deviceProfile.setType(DeviceProfileType.DEFAULT); | 168 | deviceProfile.setType(DeviceProfileType.DEFAULT); |
@@ -186,8 +190,16 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | @@ -186,8 +190,16 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg | ||
186 | if (StringUtils.isEmpty(attributesProtoSchema)) { | 190 | if (StringUtils.isEmpty(attributesProtoSchema)) { |
187 | attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; | 191 | attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; |
188 | } | 192 | } |
193 | + if (StringUtils.isEmpty(rpcResponseProtoSchema)) { | ||
194 | + rpcResponseProtoSchema = DEVICE_RPC_RESPONSE_PROTO_SCHEMA; | ||
195 | + } | ||
196 | + if (StringUtils.isEmpty(rpcRequestProtoSchema)) { | ||
197 | + rpcRequestProtoSchema = DEVICE_RPC_REQUEST_PROTO_SCHEMA; | ||
198 | + } | ||
189 | protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); | 199 | protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); |
190 | protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); | 200 | protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); |
201 | + protoTransportPayloadConfiguration.setDeviceRpcResponseProtoSchema(rpcResponseProtoSchema); | ||
202 | + protoTransportPayloadConfiguration.setDeviceRpcRequestProtoSchema(rpcRequestProtoSchema); | ||
191 | transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; | 203 | transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; |
192 | } | 204 | } |
193 | mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); | 205 | mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); |
@@ -83,7 +83,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends | @@ -83,7 +83,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends | ||
83 | @Test | 83 | @Test |
84 | public void testRequestAttributesValuesFromTheServer() throws Exception { | 84 | public void testRequestAttributesValuesFromTheServer() throws Exception { |
85 | super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", | 85 | super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", |
86 | - TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); | 86 | + TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
87 | processTestRequestAttributesValuesFromTheServer(); | 87 | processTestRequestAttributesValuesFromTheServer(); |
88 | } | 88 | } |
89 | 89 |
@@ -94,7 +94,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -94,7 +94,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
94 | 94 | ||
95 | 95 | ||
96 | protected void processTestProvisioningDisabledDevice() throws Exception { | 96 | protected void processTestProvisioningDisabledDevice() throws Exception { |
97 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 97 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
98 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 98 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
99 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 99 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
100 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | 100 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
@@ -103,7 +103,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -103,7 +103,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
103 | 103 | ||
104 | 104 | ||
105 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | 105 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
106 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 106 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
107 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 107 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
108 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 108 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
109 | 109 | ||
@@ -119,7 +119,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -119,7 +119,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
119 | 119 | ||
120 | 120 | ||
121 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | 121 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
122 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 122 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
123 | String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; | 123 | String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; |
124 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); | 124 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); |
125 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 125 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -138,7 +138,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -138,7 +138,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
138 | 138 | ||
139 | 139 | ||
140 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | 140 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
141 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 141 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
142 | String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; | 142 | String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; |
143 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); | 143 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); |
144 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 144 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -163,7 +163,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -163,7 +163,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
163 | 163 | ||
164 | 164 | ||
165 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { | 165 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { |
166 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 166 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
167 | String requestCredentials = ",\"credentialsType\": \"MQTT_BASIC\",\"clientId\": \"test_clientId\",\"username\": \"test_username\",\"password\": \"test_password\""; | 167 | String requestCredentials = ",\"credentialsType\": \"MQTT_BASIC\",\"clientId\": \"test_clientId\",\"username\": \"test_username\",\"password\": \"test_password\""; |
168 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); | 168 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); |
169 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 169 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -188,7 +188,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -188,7 +188,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
188 | } | 188 | } |
189 | 189 | ||
190 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | 190 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
191 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | 191 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
192 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 192 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
193 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 193 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
194 | 194 | ||
@@ -199,7 +199,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -199,7 +199,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
199 | } | 199 | } |
200 | 200 | ||
201 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { | 201 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { |
202 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | 202 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
203 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 203 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
204 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 204 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
205 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | 205 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
@@ -101,14 +101,14 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -101,14 +101,14 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
101 | 101 | ||
102 | 102 | ||
103 | protected void processTestProvisioningDisabledDevice() throws Exception { | 103 | protected void processTestProvisioningDisabledDevice() throws Exception { |
104 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 104 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
105 | ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 105 | ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
106 | Assert.assertNotNull(result); | 106 | Assert.assertNotNull(result); |
107 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); | 107 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); |
108 | } | 108 | } |
109 | 109 | ||
110 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | 110 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
111 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 111 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
112 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 112 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
113 | 113 | ||
114 | Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | 114 | Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
@@ -122,7 +122,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -122,7 +122,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
122 | } | 122 | } |
123 | 123 | ||
124 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | 124 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
125 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null,null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 125 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null,null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
126 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); | 126 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); |
127 | 127 | ||
128 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayloadBytes()); | 128 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayloadBytes()); |
@@ -140,7 +140,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -140,7 +140,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
140 | } | 140 | } |
141 | 141 | ||
142 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | 142 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
143 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 143 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
144 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); | 144 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); |
145 | 145 | ||
146 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayloadBytes()); | 146 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayloadBytes()); |
@@ -164,7 +164,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -164,7 +164,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
164 | } | 164 | } |
165 | 165 | ||
166 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { | 166 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { |
167 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 167 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES); |
168 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateBasicMqttCredRequestMsg( | 168 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateBasicMqttCredRequestMsg( |
169 | ValidateBasicMqttCredRequestMsg.newBuilder() | 169 | ValidateBasicMqttCredRequestMsg.newBuilder() |
170 | .setClientId("test_clientId") | 170 | .setClientId("test_clientId") |
@@ -195,7 +195,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -195,7 +195,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
195 | } | 195 | } |
196 | 196 | ||
197 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | 197 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
198 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | 198 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
199 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 199 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
200 | 200 | ||
201 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); | 201 | DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); |
@@ -205,7 +205,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -205,7 +205,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
205 | } | 205 | } |
206 | 206 | ||
207 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { | 207 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { |
208 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | 208 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES); |
209 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 209 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
210 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); | 210 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); |
211 | } | 211 | } |
@@ -180,7 +180,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM | @@ -180,7 +180,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM | ||
180 | return message; | 180 | return message; |
181 | } | 181 | } |
182 | 182 | ||
183 | - private class TestMqttCallback implements MqttCallback { | 183 | + protected class TestMqttCallback implements MqttCallback { |
184 | 184 | ||
185 | private final MqttAsyncClient client; | 185 | private final MqttAsyncClient client; |
186 | private final CountDownLatch latch; | 186 | private final CountDownLatch latch; |
@@ -15,25 +15,60 @@ | @@ -15,25 +15,60 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.mqtt.rpc; | 16 | package org.thingsboard.server.transport.mqtt.rpc; |
17 | 17 | ||
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
19 | +import com.google.protobuf.Descriptors; | ||
20 | +import com.google.protobuf.DynamicMessage; | ||
18 | import com.google.protobuf.InvalidProtocolBufferException; | 21 | import com.google.protobuf.InvalidProtocolBufferException; |
22 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
19 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
24 | +import org.eclipse.californium.core.CoapHandler; | ||
25 | +import org.eclipse.californium.core.CoapResponse; | ||
26 | +import org.eclipse.californium.core.coap.MediaTypeRegistry; | ||
20 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 27 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
21 | import org.eclipse.paho.client.mqttv3.MqttException; | 28 | import org.eclipse.paho.client.mqttv3.MqttException; |
22 | import org.eclipse.paho.client.mqttv3.MqttMessage; | 29 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
30 | +import org.jetbrains.annotations.NotNull; | ||
23 | import org.junit.After; | 31 | import org.junit.After; |
32 | +import org.junit.Assert; | ||
24 | import org.junit.Before; | 33 | import org.junit.Before; |
25 | import org.junit.Test; | 34 | import org.junit.Test; |
35 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | ||
26 | import org.thingsboard.server.common.data.TransportPayloadType; | 36 | import org.thingsboard.server.common.data.TransportPayloadType; |
37 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | ||
38 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
27 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 39 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
40 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
41 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
28 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 42 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
29 | -import org.thingsboard.server.gen.transport.TransportProtos; | 43 | + |
44 | +import java.util.List; | ||
45 | +import java.util.concurrent.CountDownLatch; | ||
46 | +import java.util.concurrent.TimeUnit; | ||
47 | + | ||
48 | +import static org.junit.Assert.assertNotNull; | ||
49 | +import static org.junit.Assert.assertTrue; | ||
50 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
30 | 51 | ||
31 | @Slf4j | 52 | @Slf4j |
32 | public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest { | 53 | public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest { |
33 | 54 | ||
55 | + private static final String RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | ||
56 | + "package rpc;\n" + | ||
57 | + "\n" + | ||
58 | + "message RpcRequestMsg {\n" + | ||
59 | + " string method = 1;\n" + | ||
60 | + " int32 requestId = 2;\n" + | ||
61 | + " Params params = 3;\n" + | ||
62 | + "\n" + | ||
63 | + " message Params {\n" + | ||
64 | + " string pin = 1;\n" + | ||
65 | + " int32 value = 2;\n" + | ||
66 | + " }\n" + | ||
67 | + "}"; | ||
68 | + | ||
34 | @Before | 69 | @Before |
35 | public void beforeTest() throws Exception { | 70 | public void beforeTest() throws Exception { |
36 | - processBeforeTest("RPC test device", "RPC test gateway", TransportPayloadType.PROTOBUF, null, null); | 71 | + processBeforeTest("RPC test device", "RPC test gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, RPC_REQUEST_PROTO_SCHEMA, null, null, DeviceProfileProvisionType.DISABLED); |
37 | } | 72 | } |
38 | 73 | ||
39 | @After | 74 | @After |
@@ -83,14 +118,55 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst | @@ -83,14 +118,55 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst | ||
83 | return builder.build(); | 118 | return builder.build(); |
84 | } | 119 | } |
85 | 120 | ||
121 | + protected void processTwoWayRpcTest() throws Exception { | ||
122 | + MqttAsyncClient client = getMqttAsyncClient(accessToken); | ||
123 | + client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, 1); | ||
124 | + | ||
125 | + CountDownLatch latch = new CountDownLatch(1); | ||
126 | + TestMqttCallback callback = new TestMqttCallback(client, latch); | ||
127 | + client.setCallback(callback); | ||
128 | + | ||
129 | + Thread.sleep(1000); | ||
130 | + | ||
131 | + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; | ||
132 | + String deviceId = savedDevice.getId().getId().toString(); | ||
133 | + | ||
134 | + String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); | ||
135 | + String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}"; | ||
136 | + latch.await(3, TimeUnit.SECONDS); | ||
137 | + Assert.assertEquals(expected, result); | ||
138 | + } | ||
139 | + | ||
86 | protected MqttMessage processMessageArrived(String requestTopic, MqttMessage mqttMessage) throws MqttException, InvalidProtocolBufferException { | 140 | protected MqttMessage processMessageArrived(String requestTopic, MqttMessage mqttMessage) throws MqttException, InvalidProtocolBufferException { |
87 | MqttMessage message = new MqttMessage(); | 141 | MqttMessage message = new MqttMessage(); |
88 | if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC)) { | 142 | if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC)) { |
89 | - TransportProtos.ToDeviceRpcResponseMsg toDeviceRpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
90 | - .setPayload(DEVICE_RESPONSE) | ||
91 | - .setRequestId(0) | 143 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration(); |
144 | + ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA); | ||
145 | + DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA); | ||
146 | + | ||
147 | + byte[] requestPayload = mqttMessage.getPayload(); | ||
148 | + DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg"); | ||
149 | + Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType(); | ||
150 | + assertNotNull(rpcRequestMsgDescriptor); | ||
151 | + try { | ||
152 | + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload); | ||
153 | + List<Descriptors.FieldDescriptor> fields = rpcRequestMsgDescriptor.getFields(); | ||
154 | + for (Descriptors.FieldDescriptor fieldDescriptor: fields) { | ||
155 | + assertTrue(dynamicMessage.hasField(fieldDescriptor)); | ||
156 | + } | ||
157 | + ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA); | ||
158 | + DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA); | ||
159 | + | ||
160 | + DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg"); | ||
161 | + Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType(); | ||
162 | + assertNotNull(rpcResponseMsgDescriptor); | ||
163 | + DynamicMessage rpcResponseMsg = rpcResponseBuilder | ||
164 | + .setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE) | ||
92 | .build(); | 165 | .build(); |
93 | - message.setPayload(toDeviceRpcResponseMsg.toByteArray()); | 166 | + message.setPayload(rpcResponseMsg.toByteArray()); |
167 | + } catch (InvalidProtocolBufferException e) { | ||
168 | + log.warn("Command Response Ack Error, Invalid response received: ", e); | ||
169 | + } | ||
94 | } else { | 170 | } else { |
95 | TransportApiProtos.GatewayDeviceRpcRequestMsg msg = TransportApiProtos.GatewayDeviceRpcRequestMsg.parseFrom(mqttMessage.getPayload()); | 171 | TransportApiProtos.GatewayDeviceRpcRequestMsg msg = TransportApiProtos.GatewayDeviceRpcRequestMsg.parseFrom(mqttMessage.getPayload()); |
96 | String deviceName = msg.getDeviceName(); | 172 | String deviceName = msg.getDeviceName(); |
@@ -105,6 +181,14 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst | @@ -105,6 +181,14 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst | ||
105 | return message; | 181 | return message; |
106 | } | 182 | } |
107 | 183 | ||
184 | + private ProtoTransportPayloadConfiguration getProtoTransportPayloadConfiguration() { | ||
185 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | ||
186 | + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); | ||
187 | + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | ||
188 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); | ||
189 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | ||
190 | + return (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
191 | + } | ||
108 | 192 | ||
109 | 193 | ||
110 | } | 194 | } |
@@ -119,7 +119,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | @@ -119,7 +119,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | ||
119 | " }\n" + | 119 | " }\n" + |
120 | " }\n" + | 120 | " }\n" + |
121 | "}"; | 121 | "}"; |
122 | - super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); | 122 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, schemaStr, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
123 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 123 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
124 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | 124 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
125 | assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); | 125 | assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); |
@@ -172,7 +172,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | @@ -172,7 +172,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | ||
172 | 172 | ||
173 | @Test | 173 | @Test |
174 | public void testPushMqttTelemetryGateway() throws Exception { | 174 | public void testPushMqttTelemetryGateway() throws Exception { |
175 | - super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 175 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
176 | TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder(); | 176 | TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder(); |
177 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 177 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
178 | String deviceName1 = "Device A"; | 178 | String deviceName1 = "Device A"; |
@@ -186,7 +186,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | @@ -186,7 +186,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | ||
186 | 186 | ||
187 | @Test | 187 | @Test |
188 | public void testGatewayConnect() throws Exception { | 188 | public void testGatewayConnect() throws Exception { |
189 | - super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 189 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED); |
190 | String deviceName = "Device A"; | 190 | String deviceName = "Device A"; |
191 | TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName); | 191 | TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName); |
192 | MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); | 192 | MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.device.profile; | 16 | package org.thingsboard.server.common.data.device.profile; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | import com.github.os72.protobuf.dynamic.DynamicSchema; | 18 | import com.github.os72.protobuf.dynamic.DynamicSchema; |
20 | import com.github.os72.protobuf.dynamic.EnumDefinition; | 19 | import com.github.os72.protobuf.dynamic.EnumDefinition; |
21 | import com.github.os72.protobuf.dynamic.MessageDefinition; | 20 | import com.github.os72.protobuf.dynamic.MessageDefinition; |
@@ -46,9 +45,13 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC | @@ -46,9 +45,13 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC | ||
46 | public static final Location LOCATION = new Location("", "", -1, -1); | 45 | public static final Location LOCATION = new Location("", "", -1, -1); |
47 | public static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; | 46 | public static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; |
48 | public static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; | 47 | public static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; |
48 | + public static final String RPC_RESPONSE_PROTO_SCHEMA = "rpc response proto schema"; | ||
49 | + public static final String RPC_REQUEST_PROTO_SCHEMA = "rpc request proto schema"; | ||
49 | 50 | ||
50 | private String deviceTelemetryProtoSchema; | 51 | private String deviceTelemetryProtoSchema; |
51 | private String deviceAttributesProtoSchema; | 52 | private String deviceAttributesProtoSchema; |
53 | + private String deviceRpcRequestProtoSchema; | ||
54 | + private String deviceRpcResponseProtoSchema; | ||
52 | 55 | ||
53 | @Override | 56 | @Override |
54 | public TransportPayloadType getTransportPayloadType() { | 57 | public TransportPayloadType getTransportPayloadType() { |
@@ -63,13 +66,45 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC | @@ -63,13 +66,45 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC | ||
63 | return getDescriptor(deviceAttributesProtoSchema, ATTRIBUTES_PROTO_SCHEMA); | 66 | return getDescriptor(deviceAttributesProtoSchema, ATTRIBUTES_PROTO_SCHEMA); |
64 | } | 67 | } |
65 | 68 | ||
69 | + public Descriptors.Descriptor getRpcResponseDynamicMessageDescriptor(String deviceRpcResponseProtoSchema) { | ||
70 | + return getDescriptor(deviceRpcResponseProtoSchema, RPC_RESPONSE_PROTO_SCHEMA); | ||
71 | + } | ||
72 | + | ||
73 | + public DynamicMessage.Builder getRpcRequestDynamicMessageBuilder(String deviceRpcRequestProtoSchema) { | ||
74 | + return getDynamicMessageBuilder(deviceRpcRequestProtoSchema, RPC_REQUEST_PROTO_SCHEMA); | ||
75 | + } | ||
76 | + | ||
77 | + public String getDeviceRpcResponseProtoSchema() { | ||
78 | + if (!isEmptyStr(deviceRpcResponseProtoSchema)) { | ||
79 | + return deviceRpcResponseProtoSchema; | ||
80 | + } else { | ||
81 | + return "syntax =\"proto3\";\n" + | ||
82 | + "package rpc;\n" + | ||
83 | + "\n" + | ||
84 | + "message RpcResponseMsg {\n" + | ||
85 | + " string payload = 1;\n" + | ||
86 | + "}"; | ||
87 | + } | ||
88 | + } | ||
89 | + | ||
90 | + public String getDeviceRpcRequestProtoSchema() { | ||
91 | + if (!isEmptyStr(deviceRpcRequestProtoSchema)) { | ||
92 | + return deviceRpcRequestProtoSchema; | ||
93 | + } else { | ||
94 | + return "syntax =\"proto3\";\n" + | ||
95 | + "package rpc;\n" + | ||
96 | + "\n" + | ||
97 | + "message RpcRequestMsg {\n" + | ||
98 | + " string method = 1;\n" + | ||
99 | + " int32 requestId = 2;\n" + | ||
100 | + " string params = 3;\n" + | ||
101 | + "}"; | ||
102 | + } | ||
103 | + } | ||
104 | + | ||
66 | private Descriptors.Descriptor getDescriptor(String protoSchema, String schemaName) { | 105 | private Descriptors.Descriptor getDescriptor(String protoSchema, String schemaName) { |
67 | try { | 106 | try { |
68 | - ProtoFileElement protoFileElement = getTransportProtoSchema(protoSchema); | ||
69 | - DynamicSchema dynamicSchema = getDynamicSchema(protoFileElement, schemaName); | ||
70 | - String lastMsgName = getMessageTypes(protoFileElement.getTypes()).stream() | ||
71 | - .map(MessageElement::getName).reduce((previous, last) -> last).get(); | ||
72 | - DynamicMessage.Builder builder = dynamicSchema.newMessageBuilder(lastMsgName); | 107 | + DynamicMessage.Builder builder = getDynamicMessageBuilder(protoSchema, schemaName); |
73 | return builder.getDescriptorForType(); | 108 | return builder.getDescriptorForType(); |
74 | } catch (Exception e) { | 109 | } catch (Exception e) { |
75 | log.warn("Failed to get Message Descriptor due to {}", e.getMessage()); | 110 | log.warn("Failed to get Message Descriptor due to {}", e.getMessage()); |
@@ -77,6 +112,14 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC | @@ -77,6 +112,14 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC | ||
77 | } | 112 | } |
78 | } | 113 | } |
79 | 114 | ||
115 | + public DynamicMessage.Builder getDynamicMessageBuilder(String protoSchema, String schemaName) { | ||
116 | + ProtoFileElement protoFileElement = getTransportProtoSchema(protoSchema); | ||
117 | + DynamicSchema dynamicSchema = getDynamicSchema(protoFileElement, schemaName); | ||
118 | + String lastMsgName = getMessageTypes(protoFileElement.getTypes()).stream() | ||
119 | + .map(MessageElement::getName).reduce((previous, last) -> last).get(); | ||
120 | + return dynamicSchema.newMessageBuilder(lastMsgName); | ||
121 | + } | ||
122 | + | ||
80 | public DynamicSchema getDynamicSchema(ProtoFileElement protoFileElement, String schemaName) { | 123 | public DynamicSchema getDynamicSchema(ProtoFileElement protoFileElement, String schemaName) { |
81 | DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder(); | 124 | DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder(); |
82 | schemaBuilder.setName(schemaName); | 125 | schemaBuilder.setName(schemaName); |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
@@ -17,6 +17,7 @@ package org.thingsboard.server.transport.coap; | @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.coap; | ||
17 | 17 | ||
18 | import com.google.gson.JsonParseException; | 18 | import com.google.gson.JsonParseException; |
19 | import com.google.protobuf.Descriptors; | 19 | import com.google.protobuf.Descriptors; |
20 | +import com.google.protobuf.DynamicMessage; | ||
20 | import lombok.Data; | 21 | import lombok.Data; |
21 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
22 | import org.eclipse.californium.core.coap.CoAP; | 23 | import org.eclipse.californium.core.coap.CoAP; |
@@ -261,7 +262,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -261,7 +262,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
261 | TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); | 262 | TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); |
262 | if (currentAttrSession == null) { | 263 | if (currentAttrSession == null) { |
263 | attributeSubscriptions.add(sessionId); | 264 | attributeSubscriptions.add(sessionId); |
264 | - registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, getTokenFromRequest(request)); | 265 | + registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, |
266 | + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder(), getTokenFromRequest(request)); | ||
265 | transportService.process(sessionInfo, | 267 | transportService.process(sessionInfo, |
266 | TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), new CoapNoOpCallback(exchange)); | 268 | TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), new CoapNoOpCallback(exchange)); |
267 | } | 269 | } |
@@ -281,7 +283,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -281,7 +283,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
281 | TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); | 283 | TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); |
282 | if (currentRpcSession == null) { | 284 | if (currentRpcSession == null) { |
283 | rpcSubscriptions.add(sessionId); | 285 | rpcSubscriptions.add(sessionId); |
284 | - registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, getTokenFromRequest(request)); | 286 | + registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, |
287 | + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder(), getTokenFromRequest(request)); | ||
285 | transportService.process(sessionInfo, | 288 | transportService.process(sessionInfo, |
286 | TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), | 289 | TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), |
287 | new CoapNoOpCallback(exchange)); | 290 | new CoapNoOpCallback(exchange)); |
@@ -303,17 +306,19 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -303,17 +306,19 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
303 | break; | 306 | break; |
304 | case TO_DEVICE_RPC_RESPONSE: | 307 | case TO_DEVICE_RPC_RESPONSE: |
305 | transportService.process(sessionInfo, | 308 | transportService.process(sessionInfo, |
306 | - coapTransportAdaptor.convertToDeviceRpcResponse(sessionId, request), | 309 | + coapTransportAdaptor.convertToDeviceRpcResponse(sessionId, request, transportConfigurationContainer.getRpcResponseMsgDescriptor()), |
307 | new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); | 310 | new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); |
308 | break; | 311 | break; |
309 | case TO_SERVER_RPC_REQUEST: | 312 | case TO_SERVER_RPC_REQUEST: |
310 | - transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor), timeout); | 313 | + transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor, |
314 | + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder()), timeout); | ||
311 | transportService.process(sessionInfo, | 315 | transportService.process(sessionInfo, |
312 | coapTransportAdaptor.convertToServerRpcRequest(sessionId, request), | 316 | coapTransportAdaptor.convertToServerRpcRequest(sessionId, request), |
313 | new CoapNoOpCallback(exchange)); | 317 | new CoapNoOpCallback(exchange)); |
314 | break; | 318 | break; |
315 | case GET_ATTRIBUTES_REQUEST: | 319 | case GET_ATTRIBUTES_REQUEST: |
316 | - transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor), timeout); | 320 | + transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor, |
321 | + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder()), timeout); | ||
317 | transportService.process(sessionInfo, | 322 | transportService.process(sessionInfo, |
318 | coapTransportAdaptor.convertToGetAttributes(sessionId, request), | 323 | coapTransportAdaptor.convertToGetAttributes(sessionId, request), |
319 | new CoapNoOpCallback(exchange)); | 324 | new CoapNoOpCallback(exchange)); |
@@ -330,14 +335,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -330,14 +335,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
330 | return tokenToSessionIdMap.remove(token); | 335 | return tokenToSessionIdMap.remove(token); |
331 | } | 336 | } |
332 | 337 | ||
333 | - private void registerAsyncCoapSession(CoapExchange exchange, TransportProtos.SessionInfoProto sessionInfo, CoapTransportAdaptor coapTransportAdaptor, String token) { | 338 | + private void registerAsyncCoapSession(CoapExchange exchange, TransportProtos.SessionInfoProto sessionInfo, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder, String token) { |
334 | tokenToSessionIdMap.putIfAbsent(token, sessionInfo); | 339 | tokenToSessionIdMap.putIfAbsent(token, sessionInfo); |
335 | - transportService.registerAsyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor)); | 340 | + transportService.registerAsyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder)); |
336 | transportService.process(sessionInfo, getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); | 341 | transportService.process(sessionInfo, getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); |
337 | } | 342 | } |
338 | 343 | ||
339 | - private CoapSessionListener getCoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor) { | ||
340 | - return new CoapSessionListener(exchange, coapTransportAdaptor); | 344 | + private CoapSessionListener getCoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) { |
345 | + return new CoapSessionListener(exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder); | ||
341 | } | 346 | } |
342 | 347 | ||
343 | private String getTokenFromRequest(Request request) { | 348 | private String getTokenFromRequest(Request request) { |
@@ -423,10 +428,12 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -423,10 +428,12 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
423 | 428 | ||
424 | private final CoapExchange exchange; | 429 | private final CoapExchange exchange; |
425 | private final CoapTransportAdaptor coapTransportAdaptor; | 430 | private final CoapTransportAdaptor coapTransportAdaptor; |
431 | + private final DynamicMessage.Builder rpcRequestDynamicMessageBuilder; | ||
426 | 432 | ||
427 | - CoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor) { | 433 | + CoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) { |
428 | this.exchange = exchange; | 434 | this.exchange = exchange; |
429 | this.coapTransportAdaptor = coapTransportAdaptor; | 435 | this.coapTransportAdaptor = coapTransportAdaptor; |
436 | + this.rpcRequestDynamicMessageBuilder = rpcRequestDynamicMessageBuilder; | ||
430 | } | 437 | } |
431 | 438 | ||
432 | @Override | 439 | @Override |
@@ -457,7 +464,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -457,7 +464,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
457 | @Override | 464 | @Override |
458 | public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg msg) { | 465 | public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg msg) { |
459 | try { | 466 | try { |
460 | - exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg)); | 467 | + exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg, rpcRequestDynamicMessageBuilder)); |
461 | } catch (AdaptorException e) { | 468 | } catch (AdaptorException e) { |
462 | log.trace("Failed to reply due to error", e); | 469 | log.trace("Failed to reply due to error", e); |
463 | exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); | 470 | exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); |
@@ -545,9 +552,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -545,9 +552,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
545 | (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | 552 | (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
546 | String deviceTelemetryProtoSchema = protoTransportPayloadConfiguration.getDeviceTelemetryProtoSchema(); | 553 | String deviceTelemetryProtoSchema = protoTransportPayloadConfiguration.getDeviceTelemetryProtoSchema(); |
547 | String deviceAttributesProtoSchema = protoTransportPayloadConfiguration.getDeviceAttributesProtoSchema(); | 554 | String deviceAttributesProtoSchema = protoTransportPayloadConfiguration.getDeviceAttributesProtoSchema(); |
555 | + String deviceRpcRequestProtoSchema = protoTransportPayloadConfiguration.getDeviceRpcRequestProtoSchema(); | ||
556 | + String deviceRpcResponseProtoSchema = protoTransportPayloadConfiguration.getDeviceRpcResponseProtoSchema(); | ||
548 | return new TransportConfigurationContainer(false, | 557 | return new TransportConfigurationContainer(false, |
549 | protoTransportPayloadConfiguration.getTelemetryDynamicMessageDescriptor(deviceTelemetryProtoSchema), | 558 | protoTransportPayloadConfiguration.getTelemetryDynamicMessageDescriptor(deviceTelemetryProtoSchema), |
550 | - protoTransportPayloadConfiguration.getAttributesDynamicMessageDescriptor(deviceAttributesProtoSchema)); | 559 | + protoTransportPayloadConfiguration.getAttributesDynamicMessageDescriptor(deviceAttributesProtoSchema), |
560 | + protoTransportPayloadConfiguration.getRpcResponseDynamicMessageDescriptor(deviceRpcResponseProtoSchema), | ||
561 | + protoTransportPayloadConfiguration.getRpcRequestDynamicMessageBuilder(deviceRpcRequestProtoSchema) | ||
562 | + ); | ||
551 | } | 563 | } |
552 | } else { | 564 | } else { |
553 | throw new AdaptorException("Invalid CoapDeviceTypeConfiguration type: " + coapDeviceTypeConfiguration.getClass().getSimpleName() + "!"); | 565 | throw new AdaptorException("Invalid CoapDeviceTypeConfiguration type: " + coapDeviceTypeConfiguration.getClass().getSimpleName() + "!"); |
@@ -567,11 +579,15 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -567,11 +579,15 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
567 | private boolean jsonPayload; | 579 | private boolean jsonPayload; |
568 | private Descriptors.Descriptor telemetryMsgDescriptor; | 580 | private Descriptors.Descriptor telemetryMsgDescriptor; |
569 | private Descriptors.Descriptor attributesMsgDescriptor; | 581 | private Descriptors.Descriptor attributesMsgDescriptor; |
582 | + private Descriptors.Descriptor rpcResponseMsgDescriptor; | ||
583 | + private DynamicMessage.Builder rpcRequestDynamicMessageBuilder; | ||
570 | 584 | ||
571 | - public TransportConfigurationContainer(boolean jsonPayload, Descriptors.Descriptor telemetryMsgDescriptor, Descriptors.Descriptor attributesMsgDescriptor) { | 585 | + public TransportConfigurationContainer(boolean jsonPayload, Descriptors.Descriptor telemetryMsgDescriptor, Descriptors.Descriptor attributesMsgDescriptor, Descriptors.Descriptor rpcResponseMsgDescriptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) { |
572 | this.jsonPayload = jsonPayload; | 586 | this.jsonPayload = jsonPayload; |
573 | this.telemetryMsgDescriptor = telemetryMsgDescriptor; | 587 | this.telemetryMsgDescriptor = telemetryMsgDescriptor; |
574 | this.attributesMsgDescriptor = attributesMsgDescriptor; | 588 | this.attributesMsgDescriptor = attributesMsgDescriptor; |
589 | + this.rpcResponseMsgDescriptor = rpcResponseMsgDescriptor; | ||
590 | + this.rpcRequestDynamicMessageBuilder = rpcRequestDynamicMessageBuilder; | ||
575 | } | 591 | } |
576 | 592 | ||
577 | public TransportConfigurationContainer(boolean jsonPayload) { | 593 | public TransportConfigurationContainer(boolean jsonPayload) { |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.transport.coap.adaptors; | 16 | package org.thingsboard.server.transport.coap.adaptors; |
17 | 17 | ||
18 | import com.google.protobuf.Descriptors; | 18 | import com.google.protobuf.Descriptors; |
19 | +import com.google.protobuf.DynamicMessage; | ||
19 | import org.eclipse.californium.core.coap.Request; | 20 | import org.eclipse.californium.core.coap.Request; |
20 | import org.eclipse.californium.core.coap.Response; | 21 | import org.eclipse.californium.core.coap.Response; |
21 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 22 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
@@ -32,7 +33,7 @@ public interface CoapTransportAdaptor { | @@ -32,7 +33,7 @@ public interface CoapTransportAdaptor { | ||
32 | 33 | ||
33 | TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException; | 34 | TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException; |
34 | 35 | ||
35 | - TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException; | 36 | + TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound, Descriptors.Descriptor rpcResponseMsgDescriptor) throws AdaptorException; |
36 | 37 | ||
37 | TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(UUID sessionId, Request inbound) throws AdaptorException; | 38 | TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(UUID sessionId, Request inbound) throws AdaptorException; |
38 | 39 | ||
@@ -42,7 +43,7 @@ public interface CoapTransportAdaptor { | @@ -42,7 +43,7 @@ public interface CoapTransportAdaptor { | ||
42 | 43 | ||
43 | Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; | 44 | Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; |
44 | 45 | ||
45 | - Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException; | 46 | + Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException; |
46 | 47 | ||
47 | Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException; | 48 | Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException; |
48 | 49 |
@@ -20,6 +20,7 @@ import com.google.gson.JsonObject; | @@ -20,6 +20,7 @@ import com.google.gson.JsonObject; | ||
20 | import com.google.gson.JsonParser; | 20 | import com.google.gson.JsonParser; |
21 | import com.google.gson.JsonSyntaxException; | 21 | import com.google.gson.JsonSyntaxException; |
22 | import com.google.protobuf.Descriptors; | 22 | import com.google.protobuf.Descriptors; |
23 | +import com.google.protobuf.DynamicMessage; | ||
23 | import lombok.extern.slf4j.Slf4j; | 24 | import lombok.extern.slf4j.Slf4j; |
24 | import org.eclipse.californium.core.coap.CoAP; | 25 | import org.eclipse.californium.core.coap.CoAP; |
25 | import org.eclipse.californium.core.coap.Request; | 26 | import org.eclipse.californium.core.coap.Request; |
@@ -64,7 +65,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | @@ -64,7 +65,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | ||
64 | } | 65 | } |
65 | 66 | ||
66 | @Override | 67 | @Override |
67 | - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException { | 68 | + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound, Descriptors.Descriptor rpcResponseMsgDescriptor) throws AdaptorException { |
68 | Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); | 69 | Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); |
69 | String payload = validatePayload(sessionId, inbound, false); | 70 | String payload = validatePayload(sessionId, inbound, false); |
70 | JsonObject response = new JsonParser().parse(payload).getAsJsonObject(); | 71 | JsonObject response = new JsonParser().parse(payload).getAsJsonObject(); |
@@ -95,7 +96,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | @@ -95,7 +96,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | ||
95 | } | 96 | } |
96 | 97 | ||
97 | @Override | 98 | @Override |
98 | - public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException { | 99 | + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException { |
99 | return getObserveNotification(isConfirmable, JsonConverter.toJson(msg, true)); | 100 | return getObserveNotification(isConfirmable, JsonConverter.toJson(msg, true)); |
100 | } | 101 | } |
101 | 102 |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.coap.adaptors; | 16 | package org.thingsboard.server.transport.coap.adaptors; |
17 | 17 | ||
18 | +import com.google.gson.JsonElement; | ||
18 | import com.google.gson.JsonParser; | 19 | import com.google.gson.JsonParser; |
19 | import com.google.protobuf.Descriptors; | 20 | import com.google.protobuf.Descriptors; |
20 | import com.google.protobuf.DynamicMessage; | 21 | import com.google.protobuf.DynamicMessage; |
@@ -63,16 +64,16 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor { | @@ -63,16 +64,16 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor { | ||
63 | } | 64 | } |
64 | 65 | ||
65 | @Override | 66 | @Override |
66 | - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException { | 67 | + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound, Descriptors.Descriptor rpcResponseMsgDescriptor) throws AdaptorException { |
67 | Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); | 68 | Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); |
68 | if (requestId.isEmpty()) { | 69 | if (requestId.isEmpty()) { |
69 | throw new AdaptorException("Request id is missing!"); | 70 | throw new AdaptorException("Request id is missing!"); |
70 | } else { | 71 | } else { |
71 | try { | 72 | try { |
72 | - String payload = TransportProtos.ToDeviceRpcResponseMsg.parseFrom(inbound.getPayload()).getPayload(); | ||
73 | - return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId.get()) | ||
74 | - .setPayload(payload).build(); | ||
75 | - } catch (InvalidProtocolBufferException e) { | 73 | + JsonElement response = new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), rpcResponseMsgDescriptor)); |
74 | + return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId.orElseThrow(() -> new AdaptorException("Request id is missing!"))) | ||
75 | + .setPayload(response.toString()).build(); | ||
76 | + } catch (Exception e) { | ||
76 | throw new AdaptorException(e); | 77 | throw new AdaptorException(e); |
77 | } | 78 | } |
78 | } | 79 | } |
@@ -112,8 +113,8 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor { | @@ -112,8 +113,8 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor { | ||
112 | } | 113 | } |
113 | 114 | ||
114 | @Override | 115 | @Override |
115 | - public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException { | ||
116 | - return getObserveNotification(isConfirmable, msg.toByteArray()); | 116 | + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException { |
117 | + return getObserveNotification(isConfirmable, ProtoConverter.convertToRpcRequest(rpcRequest, rpcRequestDynamicMessageBuilder)); | ||
117 | } | 118 | } |
118 | 119 | ||
119 | @Override | 120 | @Override |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.mqtt.adaptors; | 16 | package org.thingsboard.server.transport.mqtt.adaptors; |
17 | 17 | ||
18 | +import com.google.gson.JsonElement; | ||
18 | import com.google.gson.JsonParser; | 19 | import com.google.gson.JsonParser; |
19 | import com.google.protobuf.Descriptors; | 20 | import com.google.protobuf.Descriptors; |
20 | import com.google.protobuf.DynamicMessage; | 21 | import com.google.protobuf.DynamicMessage; |
@@ -64,9 +65,9 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -64,9 +65,9 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
64 | public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { | 65 | public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { |
65 | DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx; | 66 | DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx; |
66 | byte[] bytes = toBytes(inbound.payload()); | 67 | byte[] bytes = toBytes(inbound.payload()); |
67 | - Descriptors.Descriptor attributesDynamicMessage = getDescriptor(deviceSessionCtx.getAttributesDynamicMessageDescriptor()); | 68 | + Descriptors.Descriptor attributesDynamicMessageDescriptor = getDescriptor(deviceSessionCtx.getAttributesDynamicMessageDescriptor()); |
68 | try { | 69 | try { |
69 | - return JsonConverter.convertToAttributesProto(new JsonParser().parse(dynamicMsgToJson(bytes, attributesDynamicMessage))); | 70 | + return JsonConverter.convertToAttributesProto(new JsonParser().parse(dynamicMsgToJson(bytes, attributesDynamicMessageDescriptor))); |
70 | } catch (Exception e) { | 71 | } catch (Exception e) { |
71 | throw new AdaptorException(e); | 72 | throw new AdaptorException(e); |
72 | } | 73 | } |
@@ -86,8 +87,8 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -86,8 +87,8 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
86 | public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { | 87 | public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { |
87 | byte[] bytes = toBytes(inbound.payload()); | 88 | byte[] bytes = toBytes(inbound.payload()); |
88 | String topicName = inbound.variableHeader().topicName(); | 89 | String topicName = inbound.variableHeader().topicName(); |
89 | - int requestId = getRequestId(topicName, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX); | ||
90 | try { | 90 | try { |
91 | + int requestId = getRequestId(topicName, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX); | ||
91 | return ProtoConverter.convertToGetAttributeRequestMessage(bytes, requestId); | 92 | return ProtoConverter.convertToGetAttributeRequestMessage(bytes, requestId); |
92 | } catch (InvalidProtocolBufferException e) { | 93 | } catch (InvalidProtocolBufferException e) { |
93 | log.warn("Failed to decode get attributes request", e); | 94 | log.warn("Failed to decode get attributes request", e); |
@@ -97,10 +98,15 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -97,10 +98,15 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
97 | 98 | ||
98 | @Override | 99 | @Override |
99 | public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException { | 100 | public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException { |
101 | + DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx; | ||
102 | + String topicName = mqttMsg.variableHeader().topicName(); | ||
100 | byte[] bytes = toBytes(mqttMsg.payload()); | 103 | byte[] bytes = toBytes(mqttMsg.payload()); |
104 | + Descriptors.Descriptor rpcResponseDynamicMessageDescriptor = getDescriptor(deviceSessionCtx.getRpcResponseDynamicMessageDescriptor()); | ||
101 | try { | 105 | try { |
102 | - return TransportProtos.ToDeviceRpcResponseMsg.parseFrom(bytes); | ||
103 | - } catch (RuntimeException | InvalidProtocolBufferException e) { | 106 | + int requestId = getRequestId(topicName, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC); |
107 | + JsonElement response = new JsonParser().parse(dynamicMsgToJson(bytes, rpcResponseDynamicMessageDescriptor)); | ||
108 | + return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(response.toString()).build(); | ||
109 | + } catch (Exception e) { | ||
104 | log.warn("Failed to decode Rpc response", e); | 110 | log.warn("Failed to decode Rpc response", e); |
105 | throw new AdaptorException(e); | 111 | throw new AdaptorException(e); |
106 | } | 112 | } |
@@ -145,8 +151,10 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -145,8 +151,10 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
145 | 151 | ||
146 | 152 | ||
147 | @Override | 153 | @Override |
148 | - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { | ||
149 | - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), ProtoConverter.convertToRpcRequest(rpcRequest))); | 154 | + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException { |
155 | + DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx; | ||
156 | + DynamicMessage.Builder rpcRequestDynamicMessageBuilder = deviceSessionCtx.getRpcRequestDynamicMessageBuilder(); | ||
157 | + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), ProtoConverter.convertToRpcRequest(rpcRequest, rpcRequestDynamicMessageBuilder))); | ||
150 | } | 158 | } |
151 | 159 | ||
152 | @Override | 160 | @Override |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.transport.mqtt.session; | 16 | package org.thingsboard.server.transport.mqtt.session; |
17 | 17 | ||
18 | import com.google.protobuf.Descriptors; | 18 | import com.google.protobuf.Descriptors; |
19 | +import com.google.protobuf.DynamicMessage; | ||
19 | import io.netty.channel.ChannelHandlerContext; | 20 | import io.netty.channel.ChannelHandlerContext; |
20 | import lombok.Getter; | 21 | import lombok.Getter; |
21 | import lombok.Setter; | 22 | import lombok.Setter; |
@@ -60,6 +61,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -60,6 +61,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
60 | private volatile TransportPayloadType payloadType = TransportPayloadType.JSON; | 61 | private volatile TransportPayloadType payloadType = TransportPayloadType.JSON; |
61 | private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor; | 62 | private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor; |
62 | private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor; | 63 | private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor; |
64 | + private volatile Descriptors.Descriptor rpcResponseDynamicMessageDescriptor; | ||
65 | + private volatile DynamicMessage.Builder rpcRequestDynamicMessageBuilder; | ||
63 | 66 | ||
64 | @Getter | 67 | @Getter |
65 | @Setter | 68 | @Setter |
@@ -102,6 +105,14 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -102,6 +105,14 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
102 | return attributesDynamicMessageDescriptor; | 105 | return attributesDynamicMessageDescriptor; |
103 | } | 106 | } |
104 | 107 | ||
108 | + public Descriptors.Descriptor getRpcResponseDynamicMessageDescriptor() { | ||
109 | + return rpcResponseDynamicMessageDescriptor; | ||
110 | + } | ||
111 | + | ||
112 | + public DynamicMessage.Builder getRpcRequestDynamicMessageBuilder() { | ||
113 | + return rpcRequestDynamicMessageBuilder; | ||
114 | + } | ||
115 | + | ||
105 | @Override | 116 | @Override |
106 | public void setDeviceProfile(DeviceProfile deviceProfile) { | 117 | public void setDeviceProfile(DeviceProfile deviceProfile) { |
107 | super.setDeviceProfile(deviceProfile); | 118 | super.setDeviceProfile(deviceProfile); |
@@ -136,5 +147,7 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -136,5 +147,7 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
136 | ProtoTransportPayloadConfiguration protoTransportPayloadConfig = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | 147 | ProtoTransportPayloadConfiguration protoTransportPayloadConfig = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
137 | telemetryDynamicMessageDescriptor = protoTransportPayloadConfig.getTelemetryDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceTelemetryProtoSchema()); | 148 | telemetryDynamicMessageDescriptor = protoTransportPayloadConfig.getTelemetryDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceTelemetryProtoSchema()); |
138 | attributesDynamicMessageDescriptor = protoTransportPayloadConfig.getAttributesDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceAttributesProtoSchema()); | 149 | attributesDynamicMessageDescriptor = protoTransportPayloadConfig.getAttributesDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceAttributesProtoSchema()); |
150 | + rpcResponseDynamicMessageDescriptor = protoTransportPayloadConfig.getRpcResponseDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceRpcResponseProtoSchema()); | ||
151 | + rpcRequestDynamicMessageBuilder = protoTransportPayloadConfig.getRpcRequestDynamicMessageBuilder(protoTransportPayloadConfig.getDeviceRpcRequestProtoSchema()); | ||
139 | } | 152 | } |
140 | } | 153 | } |
@@ -15,10 +15,13 @@ | @@ -15,10 +15,13 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.transport.adaptor; | 16 | package org.thingsboard.server.common.transport.adaptor; |
17 | 17 | ||
18 | +import com.google.gson.Gson; | ||
18 | import com.google.gson.JsonElement; | 19 | import com.google.gson.JsonElement; |
20 | +import com.google.gson.JsonObject; | ||
19 | import com.google.gson.JsonParser; | 21 | import com.google.gson.JsonParser; |
20 | -import com.google.gson.JsonPrimitive; | 22 | +import com.google.protobuf.DynamicMessage; |
21 | import com.google.protobuf.InvalidProtocolBufferException; | 23 | import com.google.protobuf.InvalidProtocolBufferException; |
24 | +import com.google.protobuf.util.JsonFormat; | ||
22 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
23 | import org.springframework.util.CollectionUtils; | 26 | import org.springframework.util.CollectionUtils; |
24 | import org.springframework.util.StringUtils; | 27 | import org.springframework.util.StringUtils; |
@@ -34,6 +37,7 @@ import java.util.List; | @@ -34,6 +37,7 @@ import java.util.List; | ||
34 | @Slf4j | 37 | @Slf4j |
35 | public class ProtoConverter { | 38 | public class ProtoConverter { |
36 | 39 | ||
40 | + public static final Gson GSON = new Gson(); | ||
37 | public static final JsonParser JSON_PARSER = new JsonParser(); | 41 | public static final JsonParser JSON_PARSER = new JsonParser(); |
38 | 42 | ||
39 | public static TransportProtos.PostTelemetryMsg convertToTelemetryProto(byte[] payload) throws InvalidProtocolBufferException, IllegalArgumentException { | 43 | public static TransportProtos.PostTelemetryMsg convertToTelemetryProto(byte[] payload) throws InvalidProtocolBufferException, IllegalArgumentException { |
@@ -170,26 +174,20 @@ public class ProtoConverter { | @@ -170,26 +174,20 @@ public class ProtoConverter { | ||
170 | return kvList; | 174 | return kvList; |
171 | } | 175 | } |
172 | 176 | ||
173 | - public static byte[] convertToRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg) { | ||
174 | - TransportProtos.ToDeviceRpcRequestMsg.Builder toDeviceRpcRequestMsgBuilder = toDeviceRpcRequestMsg.newBuilderForType(); | ||
175 | - toDeviceRpcRequestMsgBuilder.mergeFrom(toDeviceRpcRequestMsg); | ||
176 | - toDeviceRpcRequestMsgBuilder.setParams(parseParams(toDeviceRpcRequestMsg)); | ||
177 | - TransportProtos.ToDeviceRpcRequestMsg result = toDeviceRpcRequestMsgBuilder.build(); | ||
178 | - return result.toByteArray(); | ||
179 | - } | ||
180 | - | ||
181 | - private static String parseParams(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg) { | 177 | + public static byte[] convertToRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException { |
178 | + rpcRequestDynamicMessageBuilder.clear(); | ||
179 | + JsonObject rpcRequestJson = new JsonObject(); | ||
180 | + rpcRequestJson.addProperty("method", toDeviceRpcRequestMsg.getMethodName()); | ||
181 | + rpcRequestJson.addProperty("requestId", toDeviceRpcRequestMsg.getRequestId()); | ||
182 | String params = toDeviceRpcRequestMsg.getParams(); | 182 | String params = toDeviceRpcRequestMsg.getParams(); |
183 | - JsonElement jsonElementParams = JSON_PARSER.parse(params); | ||
184 | - if (!jsonElementParams.isJsonPrimitive()) { | ||
185 | - return params; | ||
186 | - } else { | ||
187 | - JsonPrimitive primitiveParams = jsonElementParams.getAsJsonPrimitive(); | ||
188 | - if (jsonElementParams.getAsJsonPrimitive().isString()) { | ||
189 | - return primitiveParams.getAsString(); | ||
190 | - } else { | ||
191 | - return params; | ||
192 | - } | 183 | + try { |
184 | + JsonElement paramsElement = JSON_PARSER.parse(params); | ||
185 | + rpcRequestJson.add("params", paramsElement); | ||
186 | + JsonFormat.parser().ignoringUnknownFields().merge(GSON.toJson(rpcRequestJson), rpcRequestDynamicMessageBuilder); | ||
187 | + DynamicMessage dynamicRpcRequest = rpcRequestDynamicMessageBuilder.build(); | ||
188 | + return dynamicRpcRequest.toByteArray(); | ||
189 | + } catch (Exception e) { | ||
190 | + throw new AdaptorException("Failed to convert ToDeviceRpcRequestMsg to Dynamic Rpc request message due to: ", e); | ||
193 | } | 191 | } |
194 | } | 192 | } |
195 | } | 193 | } |
@@ -15,6 +15,8 @@ | @@ -15,6 +15,8 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.device; | 16 | package org.thingsboard.server.dao.device; |
17 | 17 | ||
18 | +import com.google.protobuf.Descriptors; | ||
19 | +import com.google.protobuf.DynamicMessage; | ||
18 | import com.squareup.wire.Syntax; | 20 | import com.squareup.wire.Syntax; |
19 | import com.squareup.wire.schema.Field; | 21 | import com.squareup.wire.schema.Field; |
20 | import com.squareup.wire.schema.Location; | 22 | import com.squareup.wire.schema.Location; |
@@ -87,6 +89,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -87,6 +89,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
87 | private static final Location LOCATION = new Location("", "", -1, -1); | 89 | private static final Location LOCATION = new Location("", "", -1, -1); |
88 | private static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; | 90 | private static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; |
89 | private static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; | 91 | private static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; |
92 | + private static final String RPC_REQUEST_PROTO_SCHEMA = "rpc request proto schema"; | ||
93 | + private static final String RPC_RESPONSE_PROTO_SCHEMA = "rpc response proto schema"; | ||
90 | 94 | ||
91 | private static String invalidSchemaProvidedMessage(String schemaName) { | 95 | private static String invalidSchemaProvidedMessage(String schemaName) { |
92 | return "[Transport Configuration] invalid " + schemaName + " provided!"; | 96 | return "[Transport Configuration] invalid " + schemaName + " provided!"; |
@@ -357,9 +361,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -357,9 +361,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
357 | if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { | 361 | if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { |
358 | MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | 362 | MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; |
359 | if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { | 363 | if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { |
360 | - ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration = | 364 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = |
361 | (ProtoTransportPayloadConfiguration) mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); | 365 | (ProtoTransportPayloadConfiguration) mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); |
362 | - validateProtoSchemas(protoTransportPayloadTypeConfiguration); | 366 | + validateProtoSchemas(protoTransportPayloadConfiguration); |
367 | + validateRpcRequestDynamicMessageFields(protoTransportPayloadConfiguration); | ||
363 | } | 368 | } |
364 | } else if (transportConfiguration instanceof CoapDeviceProfileTransportConfiguration) { | 369 | } else if (transportConfiguration instanceof CoapDeviceProfileTransportConfiguration) { |
365 | CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; | 370 | CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; |
@@ -370,6 +375,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -370,6 +375,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
370 | if (transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration) { | 375 | if (transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration) { |
371 | ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | 376 | ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
372 | validateProtoSchemas(protoTransportPayloadConfiguration); | 377 | validateProtoSchemas(protoTransportPayloadConfiguration); |
378 | + validateRpcRequestDynamicMessageFields(protoTransportPayloadConfiguration); | ||
373 | } | 379 | } |
374 | } | 380 | } |
375 | } | 381 | } |
@@ -417,6 +423,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -417,6 +423,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
417 | try { | 423 | try { |
418 | validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA); | 424 | validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA); |
419 | validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA); | 425 | validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA); |
426 | + validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceRpcRequestProtoSchema(), RPC_REQUEST_PROTO_SCHEMA); | ||
427 | + validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceRpcResponseProtoSchema(), RPC_RESPONSE_PROTO_SCHEMA); | ||
420 | } catch (Exception exception) { | 428 | } catch (Exception exception) { |
421 | throw new DataValidationException(exception.getMessage()); | 429 | throw new DataValidationException(exception.getMessage()); |
422 | } | 430 | } |
@@ -539,6 +547,48 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -539,6 +547,48 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
539 | 547 | ||
540 | }; | 548 | }; |
541 | 549 | ||
550 | + private void validateRpcRequestDynamicMessageFields(ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration) { | ||
551 | + DynamicMessage.Builder rpcRequestDynamicMessageBuilder = protoTransportPayloadTypeConfiguration.getRpcRequestDynamicMessageBuilder(protoTransportPayloadTypeConfiguration.getDeviceRpcRequestProtoSchema()); | ||
552 | + Descriptors.Descriptor rpcRequestDynamicMessageDescriptor = rpcRequestDynamicMessageBuilder.getDescriptorForType(); | ||
553 | + if (rpcRequestDynamicMessageDescriptor == null) { | ||
554 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Failed to get rpcRequestDynamicMessageDescriptor!"); | ||
555 | + } else { | ||
556 | + if (CollectionUtils.isEmpty(rpcRequestDynamicMessageDescriptor.getFields()) || rpcRequestDynamicMessageDescriptor.getFields().size() != 3) { | ||
557 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " " + rpcRequestDynamicMessageDescriptor.getName() + " message should always contains 3 fields: method, requestId and params!"); | ||
558 | + } | ||
559 | + Descriptors.FieldDescriptor methodFieldDescriptor = rpcRequestDynamicMessageDescriptor.findFieldByName("method"); | ||
560 | + if (methodFieldDescriptor == null) { | ||
561 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Failed to get field descriptor for field: method!"); | ||
562 | + } else { | ||
563 | + if (!Descriptors.FieldDescriptor.Type.STRING.equals(methodFieldDescriptor.getType())) { | ||
564 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Field 'method' has invalid data type. Only string type is supported!"); | ||
565 | + } | ||
566 | + if (methodFieldDescriptor.isRepeated()) { | ||
567 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Field 'method' has invalid label!"); | ||
568 | + } | ||
569 | + } | ||
570 | + Descriptors.FieldDescriptor requestIdFieldDescriptor = rpcRequestDynamicMessageDescriptor.findFieldByName("requestId"); | ||
571 | + if (requestIdFieldDescriptor == null) { | ||
572 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Failed to get field descriptor for field: requestId!"); | ||
573 | + } else { | ||
574 | + if (!Descriptors.FieldDescriptor.Type.INT32.equals(requestIdFieldDescriptor.getType())) { | ||
575 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Field 'requestId' has invalid data type. Only int32 type is supported!"); | ||
576 | + } | ||
577 | + if (requestIdFieldDescriptor.isRepeated()) { | ||
578 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Field 'requestId' has invalid label!"); | ||
579 | + } | ||
580 | + } | ||
581 | + Descriptors.FieldDescriptor paramsFieldDescriptor = rpcRequestDynamicMessageDescriptor.findFieldByName("params"); | ||
582 | + if (paramsFieldDescriptor == null) { | ||
583 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + " Failed to get field descriptor for field: params!"); | ||
584 | + } else { | ||
585 | + if (paramsFieldDescriptor.isRepeated()) { | ||
586 | + throw new DataValidationException(invalidSchemaProvidedMessage(RPC_REQUEST_PROTO_SCHEMA) + "Field 'params' has invalid label!"); | ||
587 | + } | ||
588 | + } | ||
589 | + } | ||
590 | + } | ||
591 | + | ||
542 | private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover = | 592 | private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover = |
543 | new PaginatedRemover<TenantId, DeviceProfile>() { | 593 | new PaginatedRemover<TenantId, DeviceProfile>() { |
544 | 594 |
@@ -61,6 +61,21 @@ | @@ -61,6 +61,21 @@ | ||
61 | {{ 'device-profile.attributes-proto-schema-required' | translate}} | 61 | {{ 'device-profile.attributes-proto-schema-required' | translate}} |
62 | </mat-error> | 62 | </mat-error> |
63 | </mat-form-field> | 63 | </mat-form-field> |
64 | + <mat-form-field style="padding-bottom: 20px" fxFlex> | ||
65 | + <mat-label translate>device-profile.rpc-request-proto-schema</mat-label> | ||
66 | + <textarea matInput required formControlName="deviceRpcRequestProtoSchema" rows="5"></textarea> | ||
67 | + <mat-error *ngIf="coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.deviceRpcRequestProtoSchema').hasError('required')"> | ||
68 | + {{ 'device-profile.rpc-request-proto-schema-required' | translate}} | ||
69 | + </mat-error> | ||
70 | + <mat-hint class="tb-hint" translate>device-profile.rpc-request-proto-schema-hint</mat-hint> | ||
71 | + </mat-form-field> | ||
72 | + <mat-form-field fxFlex> | ||
73 | + <mat-label translate>device-profile.rpc-response-proto-schema</mat-label> | ||
74 | + <textarea matInput required formControlName="deviceRpcResponseProtoSchema" rows="5"></textarea> | ||
75 | + <mat-error *ngIf="coapDeviceProfileTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.deviceRpcResponseProtoSchema').hasError('required')"> | ||
76 | + {{ 'device-profile.rpc-response-proto-schema-required' | translate}} | ||
77 | + </mat-error> | ||
78 | + </mat-form-field> | ||
64 | </div> | 79 | </div> |
65 | </div> | 80 | </div> |
66 | </fieldset> | 81 | </fieldset> |
@@ -24,6 +24,8 @@ import { | @@ -24,6 +24,8 @@ import { | ||
24 | coapDeviceTypeTranslationMap, | 24 | coapDeviceTypeTranslationMap, |
25 | CoapTransportDeviceType, | 25 | CoapTransportDeviceType, |
26 | defaultAttributesSchema, | 26 | defaultAttributesSchema, |
27 | + defaultRpcRequestSchema, | ||
28 | + defaultRpcResponseSchema, | ||
27 | defaultTelemetrySchema, | 29 | defaultTelemetrySchema, |
28 | DeviceProfileTransportConfiguration, | 30 | DeviceProfileTransportConfiguration, |
29 | DeviceTransportType, | 31 | DeviceTransportType, |
@@ -59,7 +61,9 @@ export class CoapDeviceProfileTransportConfigurationComponent implements Control | @@ -59,7 +61,9 @@ export class CoapDeviceProfileTransportConfigurationComponent implements Control | ||
59 | private transportPayloadTypeConfiguration = this.fb.group({ | 61 | private transportPayloadTypeConfiguration = this.fb.group({ |
60 | transportPayloadType: [TransportPayloadType.JSON, Validators.required], | 62 | transportPayloadType: [TransportPayloadType.JSON, Validators.required], |
61 | deviceTelemetryProtoSchema: [defaultTelemetrySchema, Validators.required], | 63 | deviceTelemetryProtoSchema: [defaultTelemetrySchema, Validators.required], |
62 | - deviceAttributesProtoSchema: [defaultAttributesSchema, Validators.required] | 64 | + deviceAttributesProtoSchema: [defaultAttributesSchema, Validators.required], |
65 | + deviceRpcRequestProtoSchema: [defaultRpcRequestSchema, Validators.required], | ||
66 | + deviceRpcResponseProtoSchema: [defaultRpcResponseSchema, Validators.required] | ||
63 | }); | 67 | }); |
64 | 68 | ||
65 | get required(): boolean { | 69 | get required(): boolean { |
@@ -88,6 +88,21 @@ | @@ -88,6 +88,21 @@ | ||
88 | {{ 'device-profile.attributes-proto-schema-required' | translate}} | 88 | {{ 'device-profile.attributes-proto-schema-required' | translate}} |
89 | </mat-error> | 89 | </mat-error> |
90 | </mat-form-field> | 90 | </mat-form-field> |
91 | + <mat-form-field style="padding-bottom: 20px" fxFlex> | ||
92 | + <mat-label translate>device-profile.rpc-request-proto-schema</mat-label> | ||
93 | + <textarea matInput required formControlName="deviceRpcRequestProtoSchema" rows="5"></textarea> | ||
94 | + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceRpcRequestProtoSchema').hasError('required')"> | ||
95 | + {{ 'device-profile.rpc-request-proto-schema-required' | translate}} | ||
96 | + </mat-error> | ||
97 | + <mat-hint class="tb-hint" translate>device-profile.rpc-request-proto-schema-hint</mat-hint> | ||
98 | + </mat-form-field> | ||
99 | + <mat-form-field fxFlex> | ||
100 | + <mat-label translate>device-profile.rpc-response-proto-schema</mat-label> | ||
101 | + <textarea matInput required formControlName="deviceRpcResponseProtoSchema" rows="5"></textarea> | ||
102 | + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceRpcResponseProtoSchema').hasError('required')"> | ||
103 | + {{ 'device-profile.rpc-response-proto-schema-required' | translate}} | ||
104 | + </mat-error> | ||
105 | + </mat-form-field> | ||
91 | </div> | 106 | </div> |
92 | </div> | 107 | </div> |
93 | </fieldset> | 108 | </fieldset> |
@@ -29,6 +29,8 @@ import { AppState } from '@app/core/core.state'; | @@ -29,6 +29,8 @@ import { AppState } from '@app/core/core.state'; | ||
29 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; | 29 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
30 | import { | 30 | import { |
31 | defaultAttributesSchema, | 31 | defaultAttributesSchema, |
32 | + defaultRpcRequestSchema, | ||
33 | + defaultRpcResponseSchema, | ||
32 | defaultTelemetrySchema, | 34 | defaultTelemetrySchema, |
33 | DeviceProfileTransportConfiguration, | 35 | DeviceProfileTransportConfiguration, |
34 | DeviceTransportType, | 36 | DeviceTransportType, |
@@ -90,7 +92,9 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | @@ -90,7 +92,9 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | ||
90 | transportPayloadTypeConfiguration: this.fb.group({ | 92 | transportPayloadTypeConfiguration: this.fb.group({ |
91 | transportPayloadType: [TransportPayloadType.JSON, Validators.required], | 93 | transportPayloadType: [TransportPayloadType.JSON, Validators.required], |
92 | deviceTelemetryProtoSchema: [defaultTelemetrySchema, Validators.required], | 94 | deviceTelemetryProtoSchema: [defaultTelemetrySchema, Validators.required], |
93 | - deviceAttributesProtoSchema: [defaultAttributesSchema, Validators.required] | 95 | + deviceAttributesProtoSchema: [defaultAttributesSchema, Validators.required], |
96 | + deviceRpcRequestProtoSchema: [defaultRpcRequestSchema, Validators.required], | ||
97 | + deviceRpcResponseProtoSchema: [defaultRpcResponseSchema, Validators.required] | ||
94 | }) | 98 | }) |
95 | }, {validator: this.uniqueDeviceTopicValidator} | 99 | }, {validator: this.uniqueDeviceTopicValidator} |
96 | ); | 100 | ); |
@@ -139,15 +143,21 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | @@ -139,15 +143,21 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | ||
139 | if (forceUpdated) { | 143 | if (forceUpdated) { |
140 | transportPayloadTypeForm.patchValue({ | 144 | transportPayloadTypeForm.patchValue({ |
141 | deviceTelemetryProtoSchema: defaultTelemetrySchema, | 145 | deviceTelemetryProtoSchema: defaultTelemetrySchema, |
142 | - deviceAttributesProtoSchema: defaultAttributesSchema | 146 | + deviceAttributesProtoSchema: defaultAttributesSchema, |
147 | + deviceRpcRequestProtoSchema: defaultRpcRequestSchema, | ||
148 | + deviceRpcResponseProtoSchema: defaultRpcResponseSchema | ||
143 | }, {emitEvent: false}); | 149 | }, {emitEvent: false}); |
144 | } | 150 | } |
145 | if (type === TransportPayloadType.PROTOBUF && !this.disabled) { | 151 | if (type === TransportPayloadType.PROTOBUF && !this.disabled) { |
146 | transportPayloadTypeForm.get('deviceTelemetryProtoSchema').enable({emitEvent: false}); | 152 | transportPayloadTypeForm.get('deviceTelemetryProtoSchema').enable({emitEvent: false}); |
147 | transportPayloadTypeForm.get('deviceAttributesProtoSchema').enable({emitEvent: false}); | 153 | transportPayloadTypeForm.get('deviceAttributesProtoSchema').enable({emitEvent: false}); |
154 | + transportPayloadTypeForm.get('deviceRpcRequestProtoSchema').enable({emitEvent: false}); | ||
155 | + transportPayloadTypeForm.get('deviceRpcResponseProtoSchema').enable({emitEvent: false}); | ||
148 | } else { | 156 | } else { |
149 | transportPayloadTypeForm.get('deviceTelemetryProtoSchema').disable({emitEvent: false}); | 157 | transportPayloadTypeForm.get('deviceTelemetryProtoSchema').disable({emitEvent: false}); |
150 | transportPayloadTypeForm.get('deviceAttributesProtoSchema').disable({emitEvent: false}); | 158 | transportPayloadTypeForm.get('deviceAttributesProtoSchema').disable({emitEvent: false}); |
159 | + transportPayloadTypeForm.get('deviceRpcRequestProtoSchema').enable({emitEvent: false}); | ||
160 | + transportPayloadTypeForm.get('deviceRpcResponseProtoSchema').disable({emitEvent: false}); | ||
151 | } | 161 | } |
152 | } | 162 | } |
153 | 163 |
@@ -140,6 +140,24 @@ export const defaultAttributesSchema = | @@ -140,6 +140,24 @@ export const defaultAttributesSchema = | ||
140 | ' string serialNumber = 2;\n' + | 140 | ' string serialNumber = 2;\n' + |
141 | '}'; | 141 | '}'; |
142 | 142 | ||
143 | +export const defaultRpcRequestSchema = | ||
144 | + 'syntax ="proto3";\n' + | ||
145 | + 'package rpc;\n' + | ||
146 | + '\n' + | ||
147 | + 'message RpcRequestMsg {\n' + | ||
148 | + ' string method = 1;\n' + | ||
149 | + ' int32 requestId = 2;\n' + | ||
150 | + ' string params = 3;\n' + | ||
151 | + '}'; | ||
152 | + | ||
153 | +export const defaultRpcResponseSchema = | ||
154 | + 'syntax ="proto3";\n' + | ||
155 | + 'package rpc;\n' + | ||
156 | + '\n' + | ||
157 | + 'message RpcResponseMsg {\n' + | ||
158 | + ' string payload = 1;\n' + | ||
159 | + '}'; | ||
160 | + | ||
143 | export const coapDeviceTypeTranslationMap = new Map<CoapTransportDeviceType, string>( | 161 | export const coapDeviceTypeTranslationMap = new Map<CoapTransportDeviceType, string>( |
144 | [ | 162 | [ |
145 | [CoapTransportDeviceType.DEFAULT, 'device-profile.coap-device-type-default'], | 163 | [CoapTransportDeviceType.DEFAULT, 'device-profile.coap-device-type-default'], |
@@ -170,6 +188,13 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy | @@ -170,6 +188,13 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy | ||
170 | hasProfileConfiguration: true, | 188 | hasProfileConfiguration: true, |
171 | hasDeviceConfiguration: false, | 189 | hasDeviceConfiguration: false, |
172 | } | 190 | } |
191 | + ], | ||
192 | + [ | ||
193 | + DeviceTransportType.COAP, | ||
194 | + { | ||
195 | + hasProfileConfiguration: true, | ||
196 | + hasDeviceConfiguration: false, | ||
197 | + } | ||
173 | ] | 198 | ] |
174 | ] | 199 | ] |
175 | ); | 200 | ); |
@@ -270,8 +295,10 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT | @@ -270,8 +295,10 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT | ||
270 | break; | 295 | break; |
271 | case DeviceTransportType.COAP: | 296 | case DeviceTransportType.COAP: |
272 | const coapTransportConfiguration: CoapDeviceProfileTransportConfiguration = { | 297 | const coapTransportConfiguration: CoapDeviceProfileTransportConfiguration = { |
273 | - coapDeviceTypeConfiguration: {coapDeviceType: CoapTransportDeviceType.DEFAULT, | ||
274 | - transportPayloadTypeConfiguration: {transportPayloadType: TransportPayloadType.JSON}} | 298 | + coapDeviceTypeConfiguration: { |
299 | + coapDeviceType: CoapTransportDeviceType.DEFAULT, | ||
300 | + transportPayloadTypeConfiguration: {transportPayloadType: TransportPayloadType.JSON} | ||
301 | + } | ||
275 | }; | 302 | }; |
276 | transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP}; | 303 | transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP}; |
277 | break; | 304 | break; |
@@ -1063,8 +1063,13 @@ | @@ -1063,8 +1063,13 @@ | ||
1063 | "telemetry-proto-schema-required": "Telemetry proto schema is required.", | 1063 | "telemetry-proto-schema-required": "Telemetry proto schema is required.", |
1064 | "attributes-proto-schema": "Attributes proto schema", | 1064 | "attributes-proto-schema": "Attributes proto schema", |
1065 | "attributes-proto-schema-required": "Attributes proto schema is required.", | 1065 | "attributes-proto-schema-required": "Attributes proto schema is required.", |
1066 | + "rpc-response-proto-schema": "RPC response proto schema", | ||
1067 | + "rpc-response-proto-schema-required": "RPC response proto schema is required.", | ||
1066 | "rpc-response-topic-filter": "RPC response topic filter", | 1068 | "rpc-response-topic-filter": "RPC response topic filter", |
1067 | "rpc-response-topic-filter-required": "RPC response topic filter is required.", | 1069 | "rpc-response-topic-filter-required": "RPC response topic filter is required.", |
1070 | + "rpc-request-proto-schema": "RPC request proto schema", | ||
1071 | + "rpc-request-proto-schema-required": "RPC request proto schema is required.", | ||
1072 | + "rpc-request-proto-schema-hint": "RPC request message should have always fields: string method = 1; int32 requestId = 2; and params = 3 of any data type.", | ||
1068 | "not-valid-pattern-topic-filter": "Not valid pattern topic filter", | 1073 | "not-valid-pattern-topic-filter": "Not valid pattern topic filter", |
1069 | "not-valid-single-character": "Invalid use of a single-level wildcard character", | 1074 | "not-valid-single-character": "Invalid use of a single-level wildcard character", |
1070 | "not-valid-multi-character": "Invalid use of a multi-level wildcard character", | 1075 | "not-valid-multi-character": "Invalid use of a multi-level wildcard character", |