Commit b0e3547b83e00533ba3a85262bda57ebd85b694a

Authored by Igor Kulikov
2 parents 7dd32619 247941bc

Merge branch 'master' of github.com:thingsboard/thingsboard

Showing 42 changed files with 820 additions and 352 deletions
... ... @@ -244,7 +244,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
244 244 rpc.setExpirationTime(request.getExpirationTime());
245 245 rpc.setRequest(JacksonUtil.valueToTree(request));
246 246 rpc.setStatus(status);
247   - rpc.setAdditionalInfo(JacksonUtil.valueToTree(request.getAdditionalInfo()));
  247 + rpc.setAdditionalInfo(JacksonUtil.toJsonNode(request.getAdditionalInfo()));
248 248 return systemContext.getTbRpcService().save(tenantId, rpc);
249 249 }
250 250
... ...
... ... @@ -177,7 +177,9 @@ public class TbAlarmDataSubCtx extends TbAbstractDataSubCtx<AlarmDataQuery> {
177 177 alarm.getLatest().computeIfAbsent(keyType, tmp -> new HashMap<>()).putAll(latestUpdate);
178 178 return alarm;
179 179 }).collect(Collectors.toList());
180   - wsService.sendWsMsg(sessionId, new AlarmDataUpdate(cmdId, null, update, maxEntitiesPerAlarmSubscription, data.getTotalElements()));
  180 + if (!update.isEmpty()) {
  181 + wsService.sendWsMsg(sessionId, new AlarmDataUpdate(cmdId, null, update, maxEntitiesPerAlarmSubscription, data.getTotalElements()));
  182 + }
181 183 } else {
182 184 log.trace("[{}][{}][{}][{}] Received stale subscription update: {}", sessionId, cmdId, subscriptionUpdate.getSubscriptionId(), keyType, subscriptionUpdate);
183 185 }
... ...
... ... @@ -52,7 +52,17 @@ public abstract class AbstractMqttAttributesRequestIntegrationTest extends Abstr
52 52
53 53 @Test
54 54 public void testRequestAttributesValuesFromTheServer() throws Exception {
55   - processTestRequestAttributesValuesFromTheServer();
  55 + processTestRequestAttributesValuesFromTheServer(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX);
  56 + }
  57 +
  58 + @Test
  59 + public void testRequestAttributesValuesFromTheServerOnShortTopic() throws Exception {
  60 + processTestRequestAttributesValuesFromTheServer(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX);
  61 + }
  62 +
  63 + @Test
  64 + public void testRequestAttributesValuesFromTheServerOnShortJsonTopic() throws Exception {
  65 + processTestRequestAttributesValuesFromTheServer(MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_JSON_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_JSON_TOPIC_PREFIX);
56 66 }
57 67
58 68 @Test
... ... @@ -60,18 +70,18 @@ public abstract class AbstractMqttAttributesRequestIntegrationTest extends Abstr
60 70 processTestGatewayRequestAttributesValuesFromTheServer();
61 71 }
62 72
63   - protected void processTestRequestAttributesValuesFromTheServer() throws Exception {
  73 + protected void processTestRequestAttributesValuesFromTheServer(String attrPubTopic, String attrSubTopic, String attrReqTopicPrefix) throws Exception {
64 74
65 75 MqttAsyncClient client = getMqttAsyncClient(accessToken);
66 76
67   - postAttributesAndSubscribeToTopic(savedDevice, client);
  77 + postAttributesAndSubscribeToTopic(savedDevice, client, attrPubTopic, attrSubTopic);
68 78
69 79 Thread.sleep(5000);
70 80
71 81 TestMqttCallback callback = getTestMqttCallback();
72 82 client.setCallback(callback);
73 83
74   - validateResponse(client, callback.getLatch(), callback);
  84 + validateResponse(client, callback.getLatch(), callback, attrReqTopicPrefix);
75 85 }
76 86
77 87 protected void processTestGatewayRequestAttributesValuesFromTheServer() throws Exception {
... ... @@ -103,10 +113,10 @@ public abstract class AbstractMqttAttributesRequestIntegrationTest extends Abstr
103 113 validateSharedResponseGateway(client, sharedAttributesCallback);
104 114 }
105 115
106   - protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client) throws Exception {
  116 + protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client, String attrPubTopic, String attrSubTopic) throws Exception {
107 117 doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
108   - client.publish(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, new MqttMessage(POST_ATTRIBUTES_PAYLOAD.getBytes())).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
109   - client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC, MqttQoS.AT_MOST_ONCE.value()).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
  118 + client.publish(attrPubTopic, new MqttMessage(POST_ATTRIBUTES_PAYLOAD.getBytes())).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
  119 + client.subscribe(attrSubTopic, MqttQoS.AT_MOST_ONCE.value()).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
110 120 }
111 121
112 122 protected void postGatewayDeviceClientAttributes(MqttAsyncClient client) throws Exception {
... ... @@ -114,12 +124,12 @@ public abstract class AbstractMqttAttributesRequestIntegrationTest extends Abstr
114 124 client.publish(MqttTopics.GATEWAY_ATTRIBUTES_TOPIC, new MqttMessage(postClientAttributes.getBytes())).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
115 125 }
116 126
117   - protected void validateResponse(MqttAsyncClient client, CountDownLatch latch, TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException {
  127 + protected void validateResponse(MqttAsyncClient client, CountDownLatch latch, TestMqttCallback callback, String attrReqTopicPrefix) throws MqttException, InterruptedException, InvalidProtocolBufferException {
118 128 String keys = "attribute1,attribute2,attribute3,attribute4,attribute5";
119 129 String payloadStr = "{\"clientKeys\":\"" + keys + "\", \"sharedKeys\":\"" + keys + "\"}";
120 130 MqttMessage mqttMessage = new MqttMessage();
121 131 mqttMessage.setPayload(payloadStr.getBytes());
122   - client.publish(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX + "1", mqttMessage).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
  132 + client.publish(attrReqTopicPrefix + "1", mqttMessage).waitForCompletion(TimeUnit.MINUTES.toMillis(1));
123 133 latch.await(1, TimeUnit.MINUTES);
124 134 assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS());
125 135 String expectedRequestPayload = "{\"client\":{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73,\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}},\"shared\":{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73,\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}}";
... ...
... ... @@ -20,6 +20,7 @@ import org.junit.After;
20 20 import org.junit.Before;
21 21 import org.junit.Test;
22 22 import org.thingsboard.server.common.data.TransportPayloadType;
  23 +import org.thingsboard.server.common.data.device.profile.MqttTopics;
23 24
24 25 @Slf4j
25 26 public abstract class AbstractMqttAttributesRequestJsonIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest {
... ... @@ -36,7 +37,17 @@ public abstract class AbstractMqttAttributesRequestJsonIntegrationTest extends A
36 37
37 38 @Test
38 39 public void testRequestAttributesValuesFromTheServer() throws Exception {
39   - processTestRequestAttributesValuesFromTheServer();
  40 + super.testRequestAttributesValuesFromTheServer();
  41 + }
  42 +
  43 + @Test
  44 + public void testRequestAttributesValuesFromTheServerOnShortTopic() throws Exception {
  45 + super.testRequestAttributesValuesFromTheServerOnShortTopic();
  46 + }
  47 +
  48 + @Test
  49 + public void testRequestAttributesValuesFromTheServerOnShortJsonTopic() throws Exception {
  50 + super.testRequestAttributesValuesFromTheServerOnShortJsonTopic();
40 51 }
41 52
42 53 @Test
... ...
... ... @@ -84,7 +84,21 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
84 84 public void testRequestAttributesValuesFromTheServer() throws Exception {
85 85 super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto",
86 86 TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED);
87   - processTestRequestAttributesValuesFromTheServer();
  87 + processTestRequestAttributesValuesFromTheServer(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX);
  88 + }
  89 +
  90 + @Test
  91 + public void testRequestAttributesValuesFromTheServerOnShortTopic() throws Exception {
  92 + super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto",
  93 + TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED);
  94 + processTestRequestAttributesValuesFromTheServer(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX);
  95 + }
  96 +
  97 + @Test
  98 + public void testRequestAttributesValuesFromTheServerOnShortProtoTopic() throws Exception {
  99 + super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto",
  100 + TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED);
  101 + processTestRequestAttributesValuesFromTheServer(MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_PROTO_TOPIC, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_PROTO_TOPIC_PREFIX);
88 102 }
89 103
90 104 @Test
... ... @@ -93,7 +107,10 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
93 107 processTestGatewayRequestAttributesValuesFromTheServer();
94 108 }
95 109
96   - protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client) throws Exception {
  110 + @Test
  111 + public void testRequestAttributesValuesFromTheServerOnShortJsonTopic() throws Exception { }
  112 +
  113 + protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client, String attrPubTopic, String attrSubTopic) throws Exception {
97 114 doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", AbstractMqttAttributesIntegrationTest.POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
98 115 DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
99 116 assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
... ... @@ -131,8 +148,8 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
131 148 .setField(postAttributesMsgDescriptor.findFieldByName("attribute5"), jsonObject)
132 149 .build();
133 150 byte[] payload = postAttributesMsg.toByteArray();
134   - client.publish(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, new MqttMessage(payload));
135   - client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC, MqttQoS.AT_MOST_ONCE.value());
  151 + client.publish(attrPubTopic, new MqttMessage(payload));
  152 + client.subscribe(attrSubTopic, MqttQoS.AT_MOST_ONCE.value());
136 153 }
137 154
138 155 protected void postGatewayDeviceClientAttributes(MqttAsyncClient client) throws Exception {
... ... @@ -149,7 +166,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
149 166 client.publish(MqttTopics.GATEWAY_ATTRIBUTES_TOPIC, new MqttMessage(bytes));
150 167 }
151 168
152   - protected void validateResponse(MqttAsyncClient client, CountDownLatch latch, AbstractMqttAttributesIntegrationTest.TestMqttCallback callback) throws MqttException, InterruptedException, InvalidProtocolBufferException {
  169 + protected void validateResponse(MqttAsyncClient client, CountDownLatch latch, TestMqttCallback callback, String attrReqTopic) throws MqttException, InterruptedException, InvalidProtocolBufferException {
153 170 String keys = "attribute1,attribute2,attribute3,attribute4,attribute5";
154 171 TransportApiProtos.AttributesRequest.Builder attributesRequestBuilder = TransportApiProtos.AttributesRequest.newBuilder();
155 172 attributesRequestBuilder.setClientKeys(keys);
... ... @@ -157,7 +174,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
157 174 TransportApiProtos.AttributesRequest attributesRequest = attributesRequestBuilder.build();
158 175 MqttMessage mqttMessage = new MqttMessage();
159 176 mqttMessage.setPayload(attributesRequest.toByteArray());
160   - client.publish(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX + "1", mqttMessage);
  177 + client.publish(attrReqTopic + "1", mqttMessage);
161 178 latch.await(3, TimeUnit.SECONDS);
162 179 assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS());
163 180 TransportProtos.GetAttributeResponseMsg expectedAttributesResponse = getExpectedAttributeResponseMsg();
... ...
... ... @@ -61,7 +61,17 @@ public abstract class AbstractMqttAttributesUpdatesIntegrationTest extends Abstr
61 61
62 62 @Test
63 63 public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
64   - processTestSubscribeToAttributesUpdates();
  64 + processTestSubscribeToAttributesUpdates(MqttTopics.DEVICE_ATTRIBUTES_TOPIC);
  65 + }
  66 +
  67 + @Test
  68 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortTopic() throws Exception {
  69 + processTestSubscribeToAttributesUpdates(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC);
  70 + }
  71 +
  72 + @Test
  73 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortJsonTopic() throws Exception {
  74 + processTestSubscribeToAttributesUpdates(MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC);
65 75 }
66 76
67 77 @Test
... ... @@ -69,14 +79,14 @@ public abstract class AbstractMqttAttributesUpdatesIntegrationTest extends Abstr
69 79 processGatewayTestSubscribeToAttributesUpdates();
70 80 }
71 81
72   - protected void processTestSubscribeToAttributesUpdates() throws Exception {
  82 + protected void processTestSubscribeToAttributesUpdates(String attrSubTopic) throws Exception {
73 83
74 84 MqttAsyncClient client = getMqttAsyncClient(accessToken);
75 85
76 86 TestMqttCallback onUpdateCallback = getTestMqttCallback();
77 87 client.setCallback(onUpdateCallback);
78 88
79   - client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, MqttQoS.AT_MOST_ONCE.value());
  89 + client.subscribe(attrSubTopic, MqttQoS.AT_MOST_ONCE.value());
80 90
81 91 Thread.sleep(1000);
82 92
... ...
... ... @@ -36,7 +36,17 @@ public abstract class AbstractMqttAttributesUpdatesJsonIntegrationTest extends A
36 36
37 37 @Test
38 38 public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
39   - processTestSubscribeToAttributesUpdates();
  39 + super.testSubscribeToAttributesUpdatesFromTheServer();
  40 + }
  41 +
  42 + @Test
  43 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortTopic() throws Exception {
  44 + super.testSubscribeToAttributesUpdatesFromTheServerOnShortTopic();
  45 + }
  46 +
  47 + @Test
  48 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortJsonTopic() throws Exception {
  49 + super.testSubscribeToAttributesUpdatesFromTheServerOnShortJsonTopic();
40 50 }
41 51
42 52 @Test
... ...
... ... @@ -21,6 +21,7 @@ import org.junit.After;
21 21 import org.junit.Before;
22 22 import org.junit.Test;
23 23 import org.thingsboard.server.common.data.TransportPayloadType;
  24 +import org.thingsboard.server.common.data.device.profile.MqttTopics;
24 25 import org.thingsboard.server.gen.transport.TransportApiProtos;
25 26 import org.thingsboard.server.gen.transport.TransportProtos;
26 27
... ... @@ -46,7 +47,20 @@ public abstract class AbstractMqttAttributesUpdatesProtoIntegrationTest extends
46 47
47 48 @Test
48 49 public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
49   - processTestSubscribeToAttributesUpdates();
  50 + super.testSubscribeToAttributesUpdatesFromTheServer();
  51 + }
  52 +
  53 + @Test
  54 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortTopic() throws Exception {
  55 + super.testSubscribeToAttributesUpdatesFromTheServerOnShortTopic();
  56 + }
  57 +
  58 + @Test
  59 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortJsonTopic() throws Exception {}
  60 +
  61 + @Test
  62 + public void testSubscribeToAttributesUpdatesFromTheServerOnShortProtoTopic() throws Exception {
  63 + processTestSubscribeToAttributesUpdates(MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC);
50 64 }
51 65
52 66 @Test
... ...
... ... @@ -21,6 +21,7 @@ import org.junit.After;
21 21 import org.junit.Assert;
22 22 import org.junit.Before;
23 23 import org.junit.Test;
  24 +import org.thingsboard.server.common.data.device.profile.MqttTopics;
24 25 import org.thingsboard.server.service.security.AccessValidator;
25 26
26 27 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
... ... @@ -81,12 +82,32 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab
81 82
82 83 @Test
83 84 public void testServerMqttOneWayRpc() throws Exception {
84   - processOneWayRpcTest();
  85 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC);
  86 + }
  87 +
  88 + @Test
  89 + public void testServerMqttOneWayRpcOnShortTopic() throws Exception {
  90 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC);
  91 + }
  92 +
  93 + @Test
  94 + public void testServerMqttOneWayRpcOnShortJsonTopic() throws Exception {
  95 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC);
85 96 }
86 97
87 98 @Test
88 99 public void testServerMqttTwoWayRpc() throws Exception {
89   - processTwoWayRpcTest();
  100 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC);
  101 + }
  102 +
  103 + @Test
  104 + public void testServerMqttTwoWayRpcOnShortTopic() throws Exception {
  105 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC);
  106 + }
  107 +
  108 + @Test
  109 + public void testServerMqttTwoWayRpcOnShortJsonTopic() throws Exception {
  110 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC);
90 111 }
91 112
92 113 @Test
... ...
... ... @@ -60,14 +60,14 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
60 60 asyncContextTimeoutToUseRpcPlugin = 10000L;
61 61 }
62 62
63   - protected void processOneWayRpcTest() throws Exception {
  63 + protected void processOneWayRpcTest(String rpcSubTopic) throws Exception {
64 64 MqttAsyncClient client = getMqttAsyncClient(accessToken);
65 65
66 66 CountDownLatch latch = new CountDownLatch(1);
67 67 TestMqttCallback callback = new TestMqttCallback(client, latch);
68 68 client.setCallback(callback);
69 69
70   - client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, MqttQoS.AT_MOST_ONCE.value());
  70 + client.subscribe(rpcSubTopic, MqttQoS.AT_MOST_ONCE.value());
71 71
72 72 Thread.sleep(1000);
73 73
... ... @@ -86,9 +86,9 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
86 86 validateOneWayRpcGatewayResponse(deviceName, client, payloadBytes);
87 87 }
88 88
89   - protected void processTwoWayRpcTest() throws Exception {
  89 + protected void processTwoWayRpcTest(String rpcSubTopic) throws Exception {
90 90 MqttAsyncClient client = getMqttAsyncClient(accessToken);
91   - client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, 1);
  91 + client.subscribe(rpcSubTopic, 1);
92 92
93 93 CountDownLatch latch = new CountDownLatch(1);
94 94 TestMqttCallback callback = new TestMqttCallback(client, latch);
... ... @@ -199,7 +199,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
199 199
200 200 protected MqttMessage processMessageArrived(String requestTopic, MqttMessage mqttMessage) throws MqttException, InvalidProtocolBufferException {
201 201 MqttMessage message = new MqttMessage();
202   - if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC)) {
  202 + if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC) || requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC_V2)) {
203 203 message.setPayload(DEVICE_RESPONSE.getBytes(StandardCharset.UTF_8));
204 204 } else {
205 205 JsonNode requestMsgNode = JacksonUtil.toJsonNode(new String(mqttMessage.getPayload(), StandardCharset.UTF_8));
... ... @@ -232,7 +232,12 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
232 232 @Override
233 233 public void messageArrived(String requestTopic, MqttMessage mqttMessage) throws Exception {
234 234 log.info("Message Arrived: " + Arrays.toString(mqttMessage.getPayload()));
235   - String responseTopic = requestTopic.replace("request", "response");
  235 + String responseTopic;
  236 + if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC_V2)) {
  237 + responseTopic = requestTopic.replace("req", "res");
  238 + } else {
  239 + responseTopic = requestTopic.replace("request", "response");
  240 + }
236 241 qoS = mqttMessage.getQos();
237 242 client.publish(responseTopic, processMessageArrived(requestTopic, mqttMessage));
238 243 latch.countDown();
... ...
... ... @@ -21,6 +21,7 @@ import org.junit.After;
21 21 import org.junit.Before;
22 22 import org.junit.Test;
23 23 import org.thingsboard.server.common.data.TransportPayloadType;
  24 +import org.thingsboard.server.common.data.device.profile.MqttTopics;
24 25
25 26 @Slf4j
26 27 public abstract class AbstractMqttServerSideRpcJsonIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest {
... ... @@ -37,12 +38,32 @@ public abstract class AbstractMqttServerSideRpcJsonIntegrationTest extends Abstr
37 38
38 39 @Test
39 40 public void testServerMqttOneWayRpc() throws Exception {
40   - processOneWayRpcTest();
  41 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC);
  42 + }
  43 +
  44 + @Test
  45 + public void testServerMqttOneWayRpcOnShortTopic() throws Exception {
  46 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC);
  47 + }
  48 +
  49 + @Test
  50 + public void testServerMqttOneWayRpcOnShortJsonTopic() throws Exception {
  51 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC);
41 52 }
42 53
43 54 @Test
44 55 public void testServerMqttTwoWayRpc() throws Exception {
45   - processTwoWayRpcTest();
  56 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC);
  57 + }
  58 +
  59 + @Test
  60 + public void testServerMqttTwoWayRpcOnShortTopic() throws Exception {
  61 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC);
  62 + }
  63 +
  64 + @Test
  65 + public void testServerMqttTwoWayRpcOnShortJsonTopic() throws Exception {
  66 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC);
46 67 }
47 68
48 69 @Test
... ...
... ... @@ -78,12 +78,32 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
78 78
79 79 @Test
80 80 public void testServerMqttOneWayRpc() throws Exception {
81   - processOneWayRpcTest();
  81 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC);
  82 + }
  83 +
  84 + @Test
  85 + public void testServerMqttOneWayRpcOnShortTopic() throws Exception {
  86 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC);
  87 + }
  88 +
  89 + @Test
  90 + public void testServerMqttOneWayRpcOnShortProtoTopic() throws Exception {
  91 + processOneWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_PROTO_TOPIC);
82 92 }
83 93
84 94 @Test
85 95 public void testServerMqttTwoWayRpc() throws Exception {
86   - processTwoWayRpcTest();
  96 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC);
  97 + }
  98 +
  99 + @Test
  100 + public void testServerMqttTwoWayRpcOnShortTopic() throws Exception {
  101 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC);
  102 + }
  103 +
  104 + @Test
  105 + public void testServerMqttTwoWayRpcOnShortProtoTopic() throws Exception {
  106 + processTwoWayRpcTest(MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_PROTO_TOPIC);
87 107 }
88 108
89 109 @Test
... ... @@ -118,9 +138,9 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
118 138 return builder.build();
119 139 }
120 140
121   - protected void processTwoWayRpcTest() throws Exception {
  141 + protected void processTwoWayRpcTest(String rpcSubTopic) throws Exception {
122 142 MqttAsyncClient client = getMqttAsyncClient(accessToken);
123   - client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, 1);
  143 + client.subscribe(rpcSubTopic, 1);
124 144
125 145 CountDownLatch latch = new CountDownLatch(1);
126 146 TestMqttCallback callback = new TestMqttCallback(client, latch);
... ... @@ -139,7 +159,7 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
139 159
140 160 protected MqttMessage processMessageArrived(String requestTopic, MqttMessage mqttMessage) throws MqttException, InvalidProtocolBufferException {
141 161 MqttMessage message = new MqttMessage();
142   - if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC)) {
  162 + if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC) || requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC_V2)) {
143 163 ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration();
144 164 ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA);
145 165 DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA);
... ...
... ... @@ -61,6 +61,18 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt
61 61 }
62 62
63 63 @Test
  64 + public void testPushAttributesOnShortTopic() throws Exception {
  65 + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
  66 + processJsonPayloadAttributesTest(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC, expectedKeys, PAYLOAD_VALUES_STR.getBytes());
  67 + }
  68 +
  69 + @Test
  70 + public void testPushAttributesOnShortJsonTopic() throws Exception {
  71 + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
  72 + processJsonPayloadAttributesTest(MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC, expectedKeys, PAYLOAD_VALUES_STR.getBytes());
  73 + }
  74 +
  75 + @Test
64 76 public void testPushAttributesGateway() throws Exception {
65 77 List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
66 78 String deviceName1 = "Device A";
... ...
... ... @@ -20,6 +20,7 @@ import org.junit.After;
20 20 import org.junit.Before;
21 21 import org.junit.Test;
22 22 import org.thingsboard.server.common.data.TransportPayloadType;
  23 +import org.thingsboard.server.common.data.device.profile.MqttTopics;
23 24
24 25 import java.util.Arrays;
25 26 import java.util.List;
... ... @@ -46,11 +47,17 @@ public abstract class AbstractMqttAttributesJsonIntegrationTest extends Abstract
46 47 }
47 48
48 49 @Test
  50 + public void testPushAttributesOnShortTopic() throws Exception {
  51 + super.testPushAttributesOnShortTopic();
  52 + }
  53 +
  54 + @Test
  55 + public void testPushAttributesOnShortJsonTopic() throws Exception {
  56 + super.testPushAttributesOnShortJsonTopic();
  57 + }
  58 +
  59 + @Test
49 60 public void testPushAttributesGateway() throws Exception {
50   - List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
51   - String deviceName1 = "Device A";
52   - String deviceName2 = "Device B";
53   - String payload = getGatewayAttributesJsonPayload(deviceName1, deviceName2);
54   - processGatewayAttributesTest(expectedKeys, payload.getBytes(), deviceName1, deviceName2);
  61 + super.testPushAttributesGateway();
55 62 }
56 63 }
... ...
... ... @@ -25,6 +25,7 @@ import org.junit.Test;
25 25 import org.thingsboard.server.common.data.TransportPayloadType;
26 26 import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
27 27 import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
  28 +import org.thingsboard.server.common.data.device.profile.MqttTopics;
28 29 import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
29 30 import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
30 31 import org.thingsboard.server.gen.transport.TransportApiProtos;
... ... @@ -49,14 +50,14 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
49 50 @Test
50 51 public void testPushAttributes() throws Exception {
51 52 super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC);
52   - DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
53   - assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
54   - MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
55   - TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
56   - assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
57   - ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
58   - ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_ATTRIBUTES_PROTO_SCHEMA);
59   - DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA);
  53 + DynamicMessage postAttributesMsg = getDefaultDynamicMessage();
  54 + processAttributesTest(POST_DATA_ATTRIBUTES_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postAttributesMsg.toByteArray(), false);
  55 + }
  56 +
  57 + @Test
  58 + public void testPushAttributesWithExplicitPresenceProtoKeys() throws Exception {
  59 + super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC);
  60 + DynamicSchema attributesSchema = getDynamicSchema();
60 61
61 62 DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject");
62 63 Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
... ... @@ -67,7 +68,6 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
67 68 Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType();
68 69 assertNotNull(jsonObjectBuilderDescriptor);
69 70 DynamicMessage jsonObject = jsonObjectBuilder
70   - .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42)
71 71 .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1)
72 72 .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2)
73 73 .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3)
... ... @@ -78,18 +78,50 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
78 78 Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType();
79 79 assertNotNull(postAttributesMsgDescriptor);
80 80 DynamicMessage postAttributesMsg = postAttributesBuilder
81   - .setField(postAttributesMsgDescriptor.findFieldByName("key1"), "value1")
82   - .setField(postAttributesMsgDescriptor.findFieldByName("key2"), true)
83   - .setField(postAttributesMsgDescriptor.findFieldByName("key3"), 3.0)
84   - .setField(postAttributesMsgDescriptor.findFieldByName("key4"), 4)
  81 + .setField(postAttributesMsgDescriptor.findFieldByName("key1"), "")
  82 + .setField(postAttributesMsgDescriptor.findFieldByName("key2"), false)
  83 + .setField(postAttributesMsgDescriptor.findFieldByName("key3"), 0.0)
  84 + .setField(postAttributesMsgDescriptor.findFieldByName("key4"), 0)
85 85 .setField(postAttributesMsgDescriptor.findFieldByName("key5"), jsonObject)
86 86 .build();
87   - processAttributesTest(POST_DATA_ATTRIBUTES_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postAttributesMsg.toByteArray(), false);
  87 + processAttributesTest(POST_DATA_ATTRIBUTES_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postAttributesMsg.toByteArray(), true);
88 88 }
89 89
90 90 @Test
91   - public void testPushAttributesWithExplicitPresenceProtoKeys() throws Exception {
  91 + public void testPushAttributesOnShortTopic() throws Exception {
92 92 super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC);
  93 + DynamicMessage postAttributesMsg = getDefaultDynamicMessage();
  94 + processAttributesTest(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postAttributesMsg.toByteArray(), false);
  95 + }
  96 +
  97 + @Test
  98 + public void testPushAttributesOnShortJsonTopic() throws Exception {
  99 + super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC);
  100 + processJsonPayloadAttributesTest(MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), PAYLOAD_VALUES_STR.getBytes());
  101 + }
  102 +
  103 + @Test
  104 + public void testPushAttributesOnShortProtoTopic() throws Exception {
  105 + super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC);
  106 + DynamicMessage postAttributesMsg = getDefaultDynamicMessage();
  107 + processAttributesTest(MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postAttributesMsg.toByteArray(), false);
  108 + }
  109 +
  110 + @Test
  111 + public void testPushAttributesGateway() throws Exception {
  112 + super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, null);
  113 + TransportApiProtos.GatewayAttributesMsg.Builder gatewayAttributesMsgProtoBuilder = TransportApiProtos.GatewayAttributesMsg.newBuilder();
  114 + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
  115 + String deviceName1 = "Device A";
  116 + String deviceName2 = "Device B";
  117 + TransportApiProtos.AttributesMsg firstDeviceAttributesMsgProto = getDeviceAttributesMsgProto(deviceName1, expectedKeys);
  118 + TransportApiProtos.AttributesMsg secondDeviceAttributesMsgProto = getDeviceAttributesMsgProto(deviceName2, expectedKeys);
  119 + gatewayAttributesMsgProtoBuilder.addAllMsg(Arrays.asList(firstDeviceAttributesMsgProto, secondDeviceAttributesMsgProto));
  120 + TransportApiProtos.GatewayAttributesMsg gatewayAttributesMsg = gatewayAttributesMsgProtoBuilder.build();
  121 + processGatewayAttributesTest(expectedKeys, gatewayAttributesMsg.toByteArray(), deviceName1, deviceName2);
  122 + }
  123 +
  124 + private DynamicSchema getDynamicSchema() {
93 125 DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
94 126 assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
95 127 MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
... ... @@ -97,7 +129,11 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
97 129 assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
98 130 ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
99 131 ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_ATTRIBUTES_PROTO_SCHEMA);
100   - DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA);
  132 + return protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA);
  133 + }
  134 +
  135 + private DynamicMessage getDefaultDynamicMessage() {
  136 + DynamicSchema attributesSchema = getDynamicSchema();
101 137
102 138 DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject");
103 139 Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
... ... @@ -108,6 +144,7 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
108 144 Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType();
109 145 assertNotNull(jsonObjectBuilderDescriptor);
110 146 DynamicMessage jsonObject = jsonObjectBuilder
  147 + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42)
111 148 .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1)
112 149 .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2)
113 150 .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3)
... ... @@ -117,25 +154,13 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
117 154 DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes");
118 155 Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType();
119 156 assertNotNull(postAttributesMsgDescriptor);
120   - DynamicMessage postAttributesMsg = postAttributesBuilder
121   - .setField(postAttributesMsgDescriptor.findFieldByName("key1"), "")
  157 + return postAttributesBuilder
  158 + .setField(postAttributesMsgDescriptor.findFieldByName("key1"), "value1")
  159 + .setField(postAttributesMsgDescriptor.findFieldByName("key2"), true)
  160 + .setField(postAttributesMsgDescriptor.findFieldByName("key3"), 3.0)
  161 + .setField(postAttributesMsgDescriptor.findFieldByName("key4"), 4)
122 162 .setField(postAttributesMsgDescriptor.findFieldByName("key5"), jsonObject)
123 163 .build();
124   - processAttributesTest(POST_DATA_ATTRIBUTES_TOPIC, Arrays.asList("key1", "key5"), postAttributesMsg.toByteArray(), true);
125   - }
126   -
127   - @Test
128   - public void testPushAttributesGateway() throws Exception {
129   - super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, null);
130   - TransportApiProtos.GatewayAttributesMsg.Builder gatewayAttributesMsgProtoBuilder = TransportApiProtos.GatewayAttributesMsg.newBuilder();
131   - List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
132   - String deviceName1 = "Device A";
133   - String deviceName2 = "Device B";
134   - TransportApiProtos.AttributesMsg firstDeviceAttributesMsgProto = getDeviceAttributesMsgProto(deviceName1, expectedKeys);
135   - TransportApiProtos.AttributesMsg secondDeviceAttributesMsgProto = getDeviceAttributesMsgProto(deviceName2, expectedKeys);
136   - gatewayAttributesMsgProtoBuilder.addAllMsg(Arrays.asList(firstDeviceAttributesMsgProto, secondDeviceAttributesMsgProto));
137   - TransportApiProtos.GatewayAttributesMsg gatewayAttributesMsg = gatewayAttributesMsgProtoBuilder.build();
138   - processGatewayAttributesTest(expectedKeys, gatewayAttributesMsg.toByteArray(), deviceName1, deviceName2);
139 164 }
140 165
141 166 private TransportApiProtos.AttributesMsg getDeviceAttributesMsgProto(String deviceName, List<String> expectedKeys) {
... ...
... ... @@ -74,6 +74,18 @@ public abstract class AbstractMqttTimeseriesIntegrationTest extends AbstractMqtt
74 74 }
75 75
76 76 @Test
  77 + public void testPushTelemetryOnShortTopic() throws Exception {
  78 + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
  79 + processJsonPayloadTelemetryTest(MqttTopics.DEVICE_TELEMETRY_SHORT_TOPIC, expectedKeys, PAYLOAD_VALUES_STR.getBytes(), false);
  80 + }
  81 +
  82 + @Test
  83 + public void testPushTelemetryOnShortJsonTopic() throws Exception {
  84 + List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
  85 + processJsonPayloadTelemetryTest(MqttTopics.DEVICE_TELEMETRY_SHORT_JSON_TOPIC, expectedKeys, PAYLOAD_VALUES_STR.getBytes(), false);
  86 + }
  87 +
  88 + @Test
77 89 public void testPushTelemetryGateway() throws Exception {
78 90 List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
79 91 String deviceName1 = "Device A";
... ...
... ... @@ -58,24 +58,22 @@ public abstract class AbstractMqttTimeseriesJsonIntegrationTest extends Abstract
58 58 }
59 59
60 60 @Test
  61 + public void testPushTelemetryOnShortTopic() throws Exception {
  62 + super.testPushTelemetryOnShortTopic();
  63 + }
  64 +
  65 + @Test
  66 + public void testPushTelemetryWithTsOnShortJsonTopic() throws Exception {
  67 + super.testPushTelemetryOnShortJsonTopic();
  68 + }
  69 +
  70 + @Test
61 71 public void testPushTelemetryGateway() throws Exception {
62   - List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
63   - String deviceName1 = "Device A";
64   - String deviceName2 = "Device B";
65   - String payload = getGatewayTelemetryJsonPayload(deviceName1, deviceName2, "10000", "20000");
66   - processGatewayTelemetryTest(MqttTopics.GATEWAY_TELEMETRY_TOPIC, expectedKeys, payload.getBytes(), deviceName1, deviceName2);
  72 + super.testPushTelemetryGateway();
67 73 }
68 74
69 75 @Test
70 76 public void testGatewayConnect() throws Exception {
71   - String payload = "{\"device\":\"Device A\", \"type\": \"" + TransportPayloadType.JSON.name() + "\"}";
72   - MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken);
73   - publishMqttMsg(client, payload.getBytes(), MqttTopics.GATEWAY_CONNECT_TOPIC);
74   -
75   - String deviceName = "Device A";
76   - Device device = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class),
77   - 20,
78   - 100);
79   - assertNotNull(device);
  77 + super.testGatewayConnect();
80 78 }
81 79 }
... ...
... ... @@ -21,6 +21,7 @@ import com.google.protobuf.DynamicMessage;
21 21 import com.squareup.wire.schema.internal.parser.ProtoFileElement;
22 22 import lombok.extern.slf4j.Slf4j;
23 23 import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
  24 +import org.jetbrains.annotations.NotNull;
24 25 import org.junit.After;
25 26 import org.junit.Ignore;
26 27 import org.junit.Test;
... ... @@ -55,41 +56,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
55 56 @Test
56 57 public void testPushTelemetry() throws Exception {
57 58 super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null);
58   - DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
59   - assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
60   - MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
61   - TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
62   - assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
63   - ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
64   - ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_TELEMETRY_PROTO_SCHEMA);
65   - DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema");
66   -
67   - DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject");
68   - Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
69   - assertNotNull(nestedJsonObjectBuilderDescriptor);
70   - DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build();
71   -
72   - DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject");
73   - Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType();
74   - assertNotNull(jsonObjectBuilderDescriptor);
75   - DynamicMessage jsonObject = jsonObjectBuilder
76   - .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42)
77   - .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1)
78   - .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2)
79   - .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3)
80   - .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject)
81   - .build();
82   -
83   - DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry");
84   - Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType();
85   - assertNotNull(postTelemetryMsgDescriptor);
86   - DynamicMessage postTelemetryMsg = postTelemetryBuilder
87   - .setField(postTelemetryMsgDescriptor.findFieldByName("key1"), "value1")
88   - .setField(postTelemetryMsgDescriptor.findFieldByName("key2"), true)
89   - .setField(postTelemetryMsgDescriptor.findFieldByName("key3"), 3.0)
90   - .setField(postTelemetryMsgDescriptor.findFieldByName("key4"), 4)
91   - .setField(postTelemetryMsgDescriptor.findFieldByName("key5"), jsonObject)
92   - .build();
  59 + DynamicMessage postTelemetryMsg = getDefaultDynamicMessage();
93 60 processTelemetryTest(POST_DATA_TELEMETRY_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postTelemetryMsg.toByteArray(), false, false);
94 61 }
95 62
... ... @@ -121,14 +88,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
121 88 " }\n" +
122 89 "}";
123 90 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);
124   - DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
125   - assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
126   - MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
127   - TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
128   - assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
129   - ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
130   - ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(schemaStr);
131   - DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema");
  91 + DynamicSchema telemetrySchema = getDynamicSchema(schemaStr);
132 92
133 93 DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject");
134 94 Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
... ... @@ -173,14 +133,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
173 133 @Test
174 134 public void testPushTelemetryWithExplicitPresenceProtoKeys() throws Exception {
175 135 super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null);
176   - DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
177   - assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
178   - MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
179   - TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
180   - assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
181   - ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
182   - ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_TELEMETRY_PROTO_SCHEMA);
183   - DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema");
  136 + DynamicSchema telemetrySchema = getDynamicSchema(DEVICE_TELEMETRY_PROTO_SCHEMA);
184 137
185 138 DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject");
186 139 Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
... ... @@ -237,14 +190,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
237 190 " }\n" +
238 191 "}";
239 192 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);
240   - DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
241   - assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
242   - MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
243   - TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
244   - assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
245   - ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
246   - ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(schemaStr);
247   - DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema");
  193 + DynamicSchema telemetrySchema = getDynamicSchema(schemaStr);
248 194
249 195 DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject");
250 196 Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
... ... @@ -282,6 +228,26 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
282 228 }
283 229
284 230 @Test
  231 + public void testPushTelemetryOnShortTopic() throws Exception {
  232 + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null);
  233 + DynamicMessage postTelemetryMsg = getDefaultDynamicMessage();
  234 + processTelemetryTest(MqttTopics.DEVICE_TELEMETRY_SHORT_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postTelemetryMsg.toByteArray(), false, false);
  235 + }
  236 +
  237 + @Test
  238 + public void testPushTelemetryOnShortJsonTopic() throws Exception {
  239 + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null);
  240 + processJsonPayloadTelemetryTest(MqttTopics.DEVICE_TELEMETRY_SHORT_JSON_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), PAYLOAD_VALUES_STR.getBytes(), false);
  241 + }
  242 +
  243 + @Test
  244 + public void testPushTelemetryOnShortProtoTopic() throws Exception {
  245 + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null);
  246 + DynamicMessage postTelemetryMsg = getDefaultDynamicMessage();
  247 + processTelemetryTest(MqttTopics.DEVICE_TELEMETRY_SHORT_PROTO_TOPIC, Arrays.asList("key1", "key2", "key3", "key4", "key5"), postTelemetryMsg.toByteArray(), false, false);
  248 + }
  249 +
  250 + @Test
285 251 public void testPushTelemetryGateway() throws Exception {
286 252 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);
287 253 TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder();
... ... @@ -310,6 +276,48 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
310 276 assertNotNull(device);
311 277 }
312 278
  279 + private DynamicSchema getDynamicSchema(String deviceTelemetryProtoSchema) {
  280 + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
  281 + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
  282 + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
  283 + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
  284 + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
  285 + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
  286 + ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(deviceTelemetryProtoSchema);
  287 + return protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema");
  288 + }
  289 +
  290 + private DynamicMessage getDefaultDynamicMessage() {
  291 + DynamicSchema telemetrySchema = getDynamicSchema(DEVICE_TELEMETRY_PROTO_SCHEMA);
  292 +
  293 + DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject");
  294 + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
  295 + assertNotNull(nestedJsonObjectBuilderDescriptor);
  296 + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build();
  297 +
  298 + DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject");
  299 + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType();
  300 + assertNotNull(jsonObjectBuilderDescriptor);
  301 + DynamicMessage jsonObject = jsonObjectBuilder
  302 + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42)
  303 + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1)
  304 + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2)
  305 + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3)
  306 + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject)
  307 + .build();
  308 +
  309 + DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry");
  310 + Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType();
  311 + assertNotNull(postTelemetryMsgDescriptor);
  312 + return postTelemetryBuilder
  313 + .setField(postTelemetryMsgDescriptor.findFieldByName("key1"), "value1")
  314 + .setField(postTelemetryMsgDescriptor.findFieldByName("key2"), true)
  315 + .setField(postTelemetryMsgDescriptor.findFieldByName("key3"), 3.0)
  316 + .setField(postTelemetryMsgDescriptor.findFieldByName("key4"), 4)
  317 + .setField(postTelemetryMsgDescriptor.findFieldByName("key5"), jsonObject)
  318 + .build();
  319 + }
  320 +
313 321 private TransportApiProtos.ConnectMsg getConnectProto(String deviceName) {
314 322 TransportApiProtos.ConnectMsg.Builder builder = TransportApiProtos.ConnectMsg.newBuilder();
315 323 builder.setDeviceName(deviceName);
... ...
... ... @@ -34,20 +34,25 @@ public class MqttTopics {
34 34 private static final String SOFTWARE = "/sw";
35 35 private static final String CHUNK = "/chunk/";
36 36 private static final String ERROR = "/error";
37   -
  37 + private static final String TELEMETRY_SHORT = "/t";
  38 + private static final String ATTRIBUTES_SHORT = "/a";
  39 + private static final String RPC_SHORT = "/r";
  40 + private static final String REQUEST_SHORT = "/req";
  41 + private static final String RESPONSE_SHORT = "/res";
  42 + private static final String JSON_SHORT = "j";
  43 + private static final String PROTO_SHORT = "p";
38 44 private static final String ATTRIBUTES_RESPONSE = ATTRIBUTES + RESPONSE;
39 45 private static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST;
40   -
  46 + private static final String ATTRIBUTES_RESPONSE_SHORT = ATTRIBUTES_SHORT + RESPONSE_SHORT + "/";
  47 + private static final String ATTRIBUTES_REQUEST_SHORT = ATTRIBUTES_SHORT + REQUEST_SHORT + "/";
41 48 private static final String DEVICE_RPC_RESPONSE = RPC + RESPONSE + "/";
42 49 private static final String DEVICE_RPC_REQUEST = RPC + REQUEST + "/";
43   -
  50 + private static final String DEVICE_RPC_RESPONSE_SHORT = RPC_SHORT + RESPONSE_SHORT + "/";
  51 + private static final String DEVICE_RPC_REQUEST_SHORT = RPC_SHORT + REQUEST_SHORT + "/";
44 52 private static final String DEVICE_ATTRIBUTES_RESPONSE = ATTRIBUTES_RESPONSE + "/";
45 53 private static final String DEVICE_ATTRIBUTES_REQUEST = ATTRIBUTES_REQUEST + "/";
46   -
47   - // V1_JSON topics
48   -
  54 + // v1 topics
49 55 public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me";
50   -
51 56 public static final String DEVICE_RPC_RESPONSE_TOPIC = BASE_DEVICE_API_TOPIC + DEVICE_RPC_RESPONSE;
52 57 public static final String DEVICE_RPC_RESPONSE_SUB_TOPIC = DEVICE_RPC_RESPONSE_TOPIC + SUB_TOPIC;
53 58 public static final String DEVICE_RPC_REQUESTS_TOPIC = BASE_DEVICE_API_TOPIC + DEVICE_RPC_REQUEST;
... ... @@ -60,9 +65,7 @@ public class MqttTopics {
60 65 public static final String DEVICE_ATTRIBUTES_TOPIC = BASE_DEVICE_API_TOPIC + ATTRIBUTES;
61 66 public static final String DEVICE_PROVISION_REQUEST_TOPIC = PROVISION + REQUEST;
62 67 public static final String DEVICE_PROVISION_RESPONSE_TOPIC = PROVISION + RESPONSE;
63   -
64   - // V1_JSON gateway topics
65   -
  68 + // v1 gateway topics
66 69 public static final String BASE_GATEWAY_API_TOPIC = "v1/gateway";
67 70 public static final String GATEWAY_CONNECT_TOPIC = BASE_GATEWAY_API_TOPIC + CONNECT;
68 71 public static final String GATEWAY_DISCONNECT_TOPIC = BASE_GATEWAY_API_TOPIC + DISCONNECT;
... ... @@ -72,22 +75,44 @@ public class MqttTopics {
72 75 public static final String GATEWAY_RPC_TOPIC = BASE_GATEWAY_API_TOPIC + RPC;
73 76 public static final String GATEWAY_ATTRIBUTES_REQUEST_TOPIC = BASE_GATEWAY_API_TOPIC + ATTRIBUTES_REQUEST;
74 77 public static final String GATEWAY_ATTRIBUTES_RESPONSE_TOPIC = BASE_GATEWAY_API_TOPIC + ATTRIBUTES_RESPONSE;
75   -
76 78 // v2 topics
77 79 public static final String BASE_DEVICE_API_TOPIC_V2 = "v2";
78   -
79 80 public static final String REQUEST_ID_PATTERN = "(?<requestId>\\d+)";
80 81 public static final String CHUNK_PATTERN = "(?<chunk>\\d+)";
81   -
82 82 public static final String DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + REQUEST + "/" + REQUEST_ID_PATTERN + CHUNK + CHUNK_PATTERN;
83 83 public static final String DEVICE_FIRMWARE_RESPONSES_TOPIC = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + RESPONSE + "/" + SUB_TOPIC + CHUNK + SUB_TOPIC;
84 84 public static final String DEVICE_FIRMWARE_ERROR_TOPIC = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + ERROR;
85   -
86 85 public static final String DEVICE_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT = BASE_DEVICE_API_TOPIC_V2 + "/%s" + RESPONSE + "/%s" + CHUNK + "%d";
87   -
88 86 public static final String DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + REQUEST + "/" + REQUEST_ID_PATTERN + CHUNK + CHUNK_PATTERN;
89 87 public static final String DEVICE_SOFTWARE_RESPONSES_TOPIC = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + RESPONSE + "/" + SUB_TOPIC + CHUNK + SUB_TOPIC;
90 88 public static final String DEVICE_SOFTWARE_ERROR_TOPIC = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + ERROR;
  89 + public static final String DEVICE_ATTRIBUTES_SHORT_TOPIC = BASE_DEVICE_API_TOPIC_V2 + ATTRIBUTES_SHORT;
  90 + public static final String DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC = BASE_DEVICE_API_TOPIC_V2 + ATTRIBUTES_SHORT + "/" + JSON_SHORT;
  91 + public static final String DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC = BASE_DEVICE_API_TOPIC_V2 + ATTRIBUTES_SHORT + "/" + PROTO_SHORT;
  92 + public static final String DEVICE_TELEMETRY_SHORT_TOPIC = BASE_DEVICE_API_TOPIC_V2 + TELEMETRY_SHORT;
  93 + public static final String DEVICE_TELEMETRY_SHORT_JSON_TOPIC = BASE_DEVICE_API_TOPIC_V2 + TELEMETRY_SHORT + "/" + JSON_SHORT;
  94 + public static final String DEVICE_TELEMETRY_SHORT_PROTO_TOPIC = BASE_DEVICE_API_TOPIC_V2 + TELEMETRY_SHORT + "/" + PROTO_SHORT;
  95 + public static final String DEVICE_RPC_RESPONSE_SHORT_TOPIC = BASE_DEVICE_API_TOPIC_V2 + DEVICE_RPC_RESPONSE_SHORT;
  96 + public static final String DEVICE_RPC_RESPONSE_SHORT_JSON_TOPIC = BASE_DEVICE_API_TOPIC_V2 + DEVICE_RPC_RESPONSE_SHORT + JSON_SHORT + "/";
  97 + public static final String DEVICE_RPC_RESPONSE_SHORT_PROTO_TOPIC = BASE_DEVICE_API_TOPIC_V2 + DEVICE_RPC_RESPONSE_SHORT + PROTO_SHORT + "/";
  98 + public static final String DEVICE_RPC_RESPONSE_SUB_SHORT_TOPIC = DEVICE_RPC_RESPONSE_SHORT_TOPIC + SUB_TOPIC;
  99 + public static final String DEVICE_RPC_RESPONSE_SUB_SHORT_JSON_TOPIC = DEVICE_RPC_RESPONSE_SHORT_TOPIC + JSON_SHORT + "/" + SUB_TOPIC;
  100 + public static final String DEVICE_RPC_RESPONSE_SUB_SHORT_PROTO_TOPIC = DEVICE_RPC_RESPONSE_SHORT_TOPIC + PROTO_SHORT + "/" + SUB_TOPIC;
  101 + public static final String DEVICE_RPC_REQUESTS_SHORT_TOPIC = BASE_DEVICE_API_TOPIC_V2 + DEVICE_RPC_REQUEST_SHORT;
  102 + public static final String DEVICE_RPC_REQUESTS_SHORT_JSON_TOPIC = BASE_DEVICE_API_TOPIC_V2 + DEVICE_RPC_REQUEST_SHORT + JSON_SHORT + "/";
  103 + public static final String DEVICE_RPC_REQUESTS_SHORT_PROTO_TOPIC = BASE_DEVICE_API_TOPIC_V2 + DEVICE_RPC_REQUEST_SHORT + PROTO_SHORT + "/";
  104 + public static final String DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC = DEVICE_RPC_REQUESTS_SHORT_TOPIC + SUB_TOPIC;
  105 + public static final String DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC = DEVICE_RPC_REQUESTS_SHORT_TOPIC + JSON_SHORT + "/" + SUB_TOPIC;
  106 + public static final String DEVICE_RPC_REQUESTS_SUB_SHORT_PROTO_TOPIC = DEVICE_RPC_REQUESTS_SHORT_TOPIC + PROTO_SHORT + "/" + SUB_TOPIC;
  107 + public static final String DEVICE_ATTRIBUTES_RESPONSE_SHORT_TOPIC_PREFIX = BASE_DEVICE_API_TOPIC_V2 + ATTRIBUTES_RESPONSE_SHORT;
  108 + public static final String DEVICE_ATTRIBUTES_RESPONSES_SHORT_TOPIC = DEVICE_ATTRIBUTES_RESPONSE_SHORT_TOPIC_PREFIX + SUB_TOPIC;
  109 + public static final String DEVICE_ATTRIBUTES_RESPONSE_SHORT_JSON_TOPIC_PREFIX = DEVICE_ATTRIBUTES_RESPONSE_SHORT_TOPIC_PREFIX + JSON_SHORT + "/";
  110 + public static final String DEVICE_ATTRIBUTES_RESPONSES_SHORT_JSON_TOPIC = DEVICE_ATTRIBUTES_RESPONSE_SHORT_JSON_TOPIC_PREFIX + SUB_TOPIC;
  111 + public static final String DEVICE_ATTRIBUTES_RESPONSE_SHORT_PROTO_TOPIC_PREFIX = DEVICE_ATTRIBUTES_RESPONSE_SHORT_TOPIC_PREFIX + PROTO_SHORT + "/";
  112 + public static final String DEVICE_ATTRIBUTES_RESPONSES_SHORT_PROTO_TOPIC = DEVICE_ATTRIBUTES_RESPONSE_SHORT_PROTO_TOPIC_PREFIX + SUB_TOPIC;
  113 + public static final String DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX = BASE_DEVICE_API_TOPIC_V2 + ATTRIBUTES_REQUEST_SHORT;
  114 + public static final String DEVICE_ATTRIBUTES_REQUEST_SHORT_JSON_TOPIC_PREFIX = DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX + JSON_SHORT + "/";
  115 + public static final String DEVICE_ATTRIBUTES_REQUEST_SHORT_PROTO_TOPIC_PREFIX = DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX + PROTO_SHORT + "/";
91 116
92 117 private MqttTopics() {
93 118 }
... ...
... ... @@ -20,7 +20,6 @@ import com.google.gson.JsonParser;
20 20 import com.google.protobuf.Descriptors;
21 21 import com.google.protobuf.DynamicMessage;
22 22 import com.google.protobuf.InvalidProtocolBufferException;
23   -import com.google.protobuf.util.JsonFormat;
24 23 import lombok.extern.slf4j.Slf4j;
25 24 import org.eclipse.californium.core.coap.CoAP;
26 25 import org.eclipse.californium.core.coap.MediaTypeRegistry;
... ... @@ -32,6 +31,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
32 31 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
33 32 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
34 33 import org.thingsboard.server.common.transport.adaptor.ProtoConverter;
  34 +import org.thingsboard.server.gen.transport.TransportApiProtos;
35 35 import org.thingsboard.server.gen.transport.TransportProtos;
36 36 import org.thingsboard.server.transport.coap.CoapTransportResource;
37 37
... ... @@ -44,8 +44,9 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor {
44 44
45 45 @Override
46 46 public TransportProtos.PostTelemetryMsg convertToPostTelemetry(UUID sessionId, Request inbound, Descriptors.Descriptor telemetryMsgDescriptor) throws AdaptorException {
  47 + ProtoConverter.validateDescriptor(telemetryMsgDescriptor);
47 48 try {
48   - return JsonConverter.convertToTelemetryProto(new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), telemetryMsgDescriptor)));
  49 + return JsonConverter.convertToTelemetryProto(new JsonParser().parse(ProtoConverter.dynamicMsgToJson(inbound.getPayload(), telemetryMsgDescriptor)));
49 50 } catch (Exception e) {
50 51 throw new AdaptorException(e);
51 52 }
... ... @@ -53,8 +54,9 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor {
53 54
54 55 @Override
55 56 public TransportProtos.PostAttributeMsg convertToPostAttributes(UUID sessionId, Request inbound, Descriptors.Descriptor attributesMsgDescriptor) throws AdaptorException {
  57 + ProtoConverter.validateDescriptor(attributesMsgDescriptor);
56 58 try {
57   - return JsonConverter.convertToAttributesProto(new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), attributesMsgDescriptor)));
  59 + return JsonConverter.convertToAttributesProto(new JsonParser().parse(ProtoConverter.dynamicMsgToJson(inbound.getPayload(), attributesMsgDescriptor)));
58 60 } catch (Exception e) {
59 61 throw new AdaptorException(e);
60 62 }
... ... @@ -71,8 +73,9 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor {
71 73 if (requestId.isEmpty()) {
72 74 throw new AdaptorException("Request id is missing!");
73 75 } else {
  76 + ProtoConverter.validateDescriptor(rpcResponseMsgDescriptor);
74 77 try {
75   - JsonElement response = new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), rpcResponseMsgDescriptor));
  78 + JsonElement response = new JsonParser().parse(ProtoConverter.dynamicMsgToJson(inbound.getPayload(), rpcResponseMsgDescriptor));
76 79 return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId.orElseThrow(() -> new AdaptorException("Request id is missing!")))
77 80 .setPayload(response.toString()).build();
78 81 } catch (Exception e) {
... ... @@ -158,11 +161,6 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor {
158 161 return response;
159 162 }
160 163
161   - private String dynamicMsgToJson(byte[] bytes, Descriptors.Descriptor descriptor) throws InvalidProtocolBufferException {
162   - DynamicMessage dynamicMessage = DynamicMessage.parseFrom(descriptor, bytes);
163   - return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage);
164   - }
165   -
166 164 @Override
167 165 public int getContentFormat() {
168 166 return MediaTypeRegistry.APPLICATION_OCTET_STREAM;
... ...
... ... @@ -15,24 +15,16 @@
15 15 */
16 16 package org.thingsboard.server.transport.lwm2m.config;
17 17
18   -import com.google.common.io.Resources;
19 18 import lombok.Getter;
20 19 import lombok.Setter;
21 20 import lombok.extern.slf4j.Slf4j;
22   -import org.eclipse.leshan.server.model.LwM2mModelProvider;
23   -import org.jetbrains.annotations.NotNull;
24 21 import org.springframework.beans.factory.annotation.Value;
25 22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
26 23 import org.springframework.stereotype.Component;
27 24 import org.thingsboard.server.common.data.ResourceUtils;
28 25
29 26 import javax.annotation.PostConstruct;
30   -import java.io.File;
31   -import java.io.FileInputStream;
32   -import java.io.FileNotFoundException;
33 27 import java.io.InputStream;
34   -import java.net.URI;
35   -import java.net.URISyntaxException;
36 28 import java.security.KeyStore;
37 29
38 30 @Slf4j
... ... @@ -41,10 +33,6 @@ import java.security.KeyStore;
41 33 public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
42 34
43 35 @Getter
44   - @Setter
45   - private LwM2mModelProvider modelProvider;
46   -
47   - @Getter
48 36 @Value("${transport.lwm2m.timeout:}")
49 37 private Long timeout;
50 38
... ... @@ -147,6 +135,4 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
147 135 }
148 136 }
149 137
150   -
151   -
152 138 }
... ...
... ... @@ -62,14 +62,13 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
62 62
63 63 private final LwM2mTransportContext context;
64 64 private final LwM2MTransportServerConfig config;
65   - private final LwM2mTransportServerHelper helper;
66 65 private final OtaPackageDataCache otaPackageDataCache;
67 66 private final DefaultLwM2MUplinkMsgHandler handler;
68 67 private final CaliforniumRegistrationStore registrationStore;
69 68 private final TbSecurityStore securityStore;
70   - private final LwM2mClientContext lwM2mClientContext;
71 69 private final TbLwM2MDtlsCertificateVerifier certificateVerifier;
72 70 private final TbLwM2MAuthorizer authorizer;
  71 + private final LwM2mVersionedModelProvider modelProvider;
73 72
74 73 private LeshanServer server;
75 74
... ... @@ -118,8 +117,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
118 117 builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort(), config));
119 118
120 119 /* Define model provider (Create Models )*/
121   - LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context);
122   - config.setModelProvider(modelProvider);
123 120 builder.setObjectModelProvider(modelProvider);
124 121
125 122 /* Set securityStore with new registrationStore */
... ...
... ... @@ -97,15 +97,15 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
97 97 }
98 98
99 99 @Override
100   - public void onResourceUpdate(@NotNull Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
101   - if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) {
  100 + public void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {
  101 + if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.getResourceType())) {
102 102 this.handler.onResourceUpdate(resourceUpdateMsgOpt);
103 103 }
104 104 }
105 105
106 106 @Override
107   - public void onResourceDelete(@NotNull Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
108   - if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) {
  107 + public void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceDeleteMsgOpt) {
  108 + if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.getResourceType())) {
109 109 this.handler.onResourceDelete(resourceDeleteMsgOpt);
110 110 }
111 111 }
... ...
... ... @@ -15,7 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.transport.lwm2m.server;
17 17
18   -import lombok.RequiredArgsConstructor;
19 18 import lombok.extern.slf4j.Slf4j;
20 19 import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
21 20 import org.eclipse.leshan.core.model.LwM2mModel;
... ... @@ -23,8 +22,11 @@ import org.eclipse.leshan.core.model.ObjectModel;
23 22 import org.eclipse.leshan.core.model.ResourceModel;
24 23 import org.eclipse.leshan.server.model.LwM2mModelProvider;
25 24 import org.eclipse.leshan.server.registration.Registration;
  25 +import org.springframework.context.annotation.Lazy;
  26 +import org.springframework.stereotype.Service;
26 27 import org.thingsboard.server.common.data.TbResource;
27 28 import org.thingsboard.server.common.data.id.TenantId;
  29 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
28 30 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
29 31
30 32 import java.util.ArrayList;
... ... @@ -32,47 +34,58 @@ import java.util.Base64;
32 34 import java.util.Collection;
33 35 import java.util.Map;
34 36 import java.util.Optional;
  37 +import java.util.concurrent.ConcurrentHashMap;
  38 +import java.util.concurrent.ConcurrentMap;
  39 +import java.util.concurrent.locks.Lock;
  40 +import java.util.concurrent.locks.ReentrantLock;
35 41
36 42 import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL;
37 43 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
38 44
39 45 @Slf4j
40   -@RequiredArgsConstructor
  46 +@Service
  47 +@TbLwM2mTransportComponent
41 48 public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
42 49
43   - /**
44   - * int objectId
45   - * String version ("1.01")
46   - * Key = objectId + "##" + version
47   - * Value = TenantId
48   - */
49 50 private final LwM2mClientContext lwM2mClientContext;
50 51 private final LwM2mTransportServerHelper helper;
51 52 private final LwM2mTransportContext context;
  53 + private final ConcurrentMap<TenantId, ConcurrentMap<String, ObjectModel>> models;
  54 +
  55 + public LwM2mVersionedModelProvider(@Lazy LwM2mClientContext lwM2mClientContext, LwM2mTransportServerHelper helper, LwM2mTransportContext context) {
  56 + this.lwM2mClientContext = lwM2mClientContext;
  57 + this.helper = helper;
  58 + this.context = context;
  59 + this.models = new ConcurrentHashMap<>();
  60 + }
52 61
53 62 private String getKeyIdVer(Integer objectId, String version) {
54 63 return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null;
55 64 }
56 65
57   - /**
58   - * Update repository if need
59   - *
60   - * @param registration
61   - * @return
62   - */
63 66 @Override
64 67 public LwM2mModel getObjectModel(Registration registration) {
65 68 return new DynamicModel(registration);
66 69 }
67 70
68   - private class DynamicModel implements LwM2mModel {
  71 + public void evict(TenantId tenantId, String key) {
  72 + if (tenantId.isNullUid()) {
  73 + models.values().forEach(m -> m.remove(key));
  74 + } else {
  75 + models.get(tenantId).remove(key);
  76 + }
  77 + }
69 78
  79 + private class DynamicModel implements LwM2mModel {
70 80 private final Registration registration;
71 81 private final TenantId tenantId;
  82 + private final Lock modelsLock;
72 83
73 84 public DynamicModel(Registration registration) {
74 85 this.registration = registration;
75 86 this.tenantId = lwM2mClientContext.getClientByEndpoint(registration.getEndpoint()).getTenantId();
  87 + this.modelsLock = new ReentrantLock();
  88 + models.computeIfAbsent(tenantId, t -> new ConcurrentHashMap<>());
76 89 }
77 90
78 91 @Override
... ... @@ -114,6 +127,25 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
114 127
115 128 private ObjectModel getObjectModelDynamic(Integer objectId, String version) {
116 129 String key = getKeyIdVer(objectId, version);
  130 + ObjectModel objectModel = models.get(tenantId).get(key);
  131 +
  132 + if (objectModel == null) {
  133 + modelsLock.lock();
  134 + try {
  135 + objectModel = models.get(tenantId).get(key);
  136 + if (objectModel == null) {
  137 + objectModel = getObjectModel(key);
  138 + models.get(tenantId).put(key, objectModel);
  139 + }
  140 + } finally {
  141 + modelsLock.unlock();
  142 + }
  143 + }
  144 +
  145 + return objectModel;
  146 + }
  147 +
  148 + private ObjectModel getObjectModel(String key) {
117 149 Optional<TbResource> tbResource = context.getTransportResourceCache().get(this.tenantId, LWM2M_MODEL, key);
118 150 return tbResource.map(resource -> helper.parseFromXmlToObjectModel(
119 151 Base64.getDecoder().decode(resource.getData()),
... ...
... ... @@ -21,13 +21,11 @@ import lombok.Setter;
21 21 import lombok.extern.slf4j.Slf4j;
22 22 import org.eclipse.leshan.core.model.ObjectModel;
23 23 import org.eclipse.leshan.core.model.ResourceModel;
24   -import org.eclipse.leshan.core.node.LwM2mMultipleResource;
25 24 import org.eclipse.leshan.core.node.LwM2mPath;
26 25 import org.eclipse.leshan.core.node.LwM2mResource;
27 26 import org.eclipse.leshan.core.node.LwM2mSingleResource;
28 27 import org.eclipse.leshan.core.node.codec.LwM2mValueConverter;
29 28 import org.eclipse.leshan.core.request.ContentFormat;
30   -import org.eclipse.leshan.core.util.Hex;
31 29 import org.eclipse.leshan.server.model.LwM2mModelProvider;
32 30 import org.eclipse.leshan.server.registration.Registration;
33 31 import org.thingsboard.server.common.data.Device;
... ... @@ -44,7 +42,6 @@ import java.io.IOException;
44 42 import java.io.ObjectInputStream;
45 43 import java.io.Serializable;
46 44 import java.util.Collection;
47   -import java.util.HashMap;
48 45 import java.util.Map;
49 46 import java.util.Optional;
50 47 import java.util.Set;
... ... @@ -58,7 +55,6 @@ import java.util.concurrent.locks.Lock;
58 55 import java.util.concurrent.locks.ReentrantLock;
59 56 import java.util.stream.Collectors;
60 57
61   -import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
62 58 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
63 59 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_OBJECT_VERSION_DEFAULT;
64 60 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId;
... ... @@ -281,8 +277,6 @@ public class LwM2mClient implements Serializable {
281 277 .getObjectModel(pathIds.getObjectId()) : null;
282 278 }
283 279
284   -
285   -
286 280 public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
287 281 LwM2mValueConverter converter) {
288 282 LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRezIdVer));
... ... @@ -378,7 +372,7 @@ public class LwM2mClient implements Serializable {
378 372 this.lock = new ReentrantLock();
379 373 }
380 374
381   - public long updateLastUplinkTime(){
  375 + public long updateLastUplinkTime() {
382 376 this.lastUplinkTime = System.currentTimeMillis();
383 377 this.firstEdrxDownlink = true;
384 378 return lastUplinkTime;
... ...
... ... @@ -40,6 +40,7 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion;
40 40 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
41 41 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
42 42 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  43 +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
43 44 import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
44 45 import org.thingsboard.server.transport.lwm2m.server.session.LwM2MSessionManager;
45 46 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientStore;
... ... @@ -74,6 +75,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
74 75 private final TbLwM2MClientStore clientStore;
75 76 private final LwM2MSessionManager sessionManager;
76 77 private final TransportDeviceProfileCache deviceProfileCache;
  78 + private final LwM2mVersionedModelProvider modelProvider;
77 79
78 80 @Autowired
79 81 @Lazy
... ... @@ -543,8 +545,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
543 545 }
544 546
545 547 private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {
546   - ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.config
547   - .getModelProvider());
  548 + ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, modelProvider);
548 549 Integer objectId = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)).getObjectId();
549 550 String objectVer = validateObjectVerFromKey(pathIdVer);
550 551 return resourceModel != null && (isWritableNotOptional ?
... ...
... ... @@ -60,6 +60,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
60 60 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
61 61 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
62 62 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
  63 +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
63 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
64 65 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
65 66 import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService;
... ... @@ -99,6 +100,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
99 100 private final LwM2MTransportServerConfig config;
100 101 private final LwM2MTelemetryLogService logService;
101 102 private final LwM2mClientContext clientContext;
  103 + private final LwM2mVersionedModelProvider modelProvider;
102 104
103 105 @PostConstruct
104 106 public void init() {
... ... @@ -124,7 +126,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
124 126 @Override
125 127 public void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
126 128 validateVersionedId(client, request);
127   - ReadRequest downlink = new ReadRequest(getRequestContentFormat(client, request, this.config.getModelProvider()), request.getObjectId());
  129 + ReadRequest downlink = new ReadRequest(getRequestContentFormat(client, request, modelProvider), request.getObjectId());
128 130 sendSimpleRequest(client, downlink, request.getTimeout(), callback);
129 131 }
130 132
... ... @@ -145,7 +147,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
145 147 Set<Observation> observations = context.getServer().getObservationService().getObservations(client.getRegistration());
146 148 if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) {
147 149 ObserveRequest downlink;
148   - ContentFormat contentFormat = getRequestContentFormat(client, request, this.config.getModelProvider());
  150 + ContentFormat contentFormat = getRequestContentFormat(client, request, modelProvider);
149 151 if (resultIds.isResource()) {
150 152 downlink = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
151 153 } else if (resultIds.isObjectInstance()) {
... ... @@ -174,7 +176,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
174 176
175 177 @Override
176 178 public void sendExecuteRequest(LwM2mClient client, TbLwM2MExecuteRequest request, DownlinkRequestCallback<ExecuteRequest, ExecuteResponse> callback) {
177   - ResourceModel resourceModelExecute = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider());
  179 + ResourceModel resourceModelExecute = client.getResourceModel(request.getVersionedId(), modelProvider);
178 180 if (resourceModelExecute != null) {
179 181 ExecuteRequest downlink;
180 182 if (request.getParams() != null && !resourceModelExecute.multiple) {
... ... @@ -231,7 +233,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
231 233
232 234 @Override
233 235 public void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback<WriteRequest, WriteResponse> callback) {
234   - ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider());
  236 + ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
235 237 if (resourceModelWrite != null) {
236 238 ContentFormat contentFormat = convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
237 239 try {
... ... @@ -267,8 +269,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
267 269 * send request: path = '/3/0' node == wM2mObjectInstance
268 270 * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
269 271 **/
270   - Collection<LwM2mResource> resources = client.getNewResourceForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter);
271   - ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider());
  272 + Collection<LwM2mResource> resources = client.getNewResourceForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
  273 + ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
272 274 ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
273 275 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
274 276 resultIds.getObjectInstanceId(), resources);
... ... @@ -279,7 +281,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
279 281 * int rscId = resultIds.getObjectInstanceId();
280 282 * contentFormat – Format of the payload (TLV or JSON).
281 283 */
282   - Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter);
  284 + Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
283 285 if (resources.size() > 0) {
284 286 ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : ContentFormat.DEFAULT;
285 287 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources);
... ...
... ... @@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
46 46 import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
47 47 import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;
48 48 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
  49 +import org.thingsboard.server.common.data.id.TenantId;
49 50 import org.thingsboard.server.common.data.ota.OtaPackageUtil;
50 51 import org.thingsboard.server.common.transport.TransportService;
51 52 import org.thingsboard.server.common.transport.TransportServiceCallback;
... ... @@ -57,6 +58,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mOtaConvert;
57 58 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
58 59 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
59 60 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  61 +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
60 62 import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService;
61 63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState;
62 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateException;
... ... @@ -139,8 +141,8 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
139 141 private final LwM2mTransportServerHelper helper;
140 142 private final TbLwM2MDtlsSessionStore sessionStore;
141 143 private final LwM2mClientContext clientContext;
142   - private final LwM2MRpcRequestHandler rpcHandler;
143 144 private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler;
  145 + private final LwM2mVersionedModelProvider modelProvider;
144 146
145 147 public DefaultLwM2MUplinkMsgHandler(TransportService transportService,
146 148 LwM2MTransportServerConfig config,
... ... @@ -150,9 +152,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
150 152 LwM2MSessionManager sessionManager,
151 153 @Lazy LwM2MOtaUpdateService otaService,
152 154 @Lazy LwM2MAttributesService attributesService,
153   - @Lazy LwM2MRpcRequestHandler rpcHandler,
154 155 @Lazy LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler,
155   - LwM2mTransportContext context, TbLwM2MDtlsSessionStore sessionStore) {
  156 + LwM2mTransportContext context,
  157 + TbLwM2MDtlsSessionStore sessionStore,
  158 + LwM2mVersionedModelProvider modelProvider) {
156 159 this.transportService = transportService;
157 160 this.sessionManager = sessionManager;
158 161 this.attributesService = attributesService;
... ... @@ -161,10 +164,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
161 164 this.helper = helper;
162 165 this.clientContext = clientContext;
163 166 this.logService = logService;
164   - this.rpcHandler = rpcHandler;
165 167 this.defaultLwM2MDownlinkMsgHandler = defaultLwM2MDownlinkMsgHandler;
166 168 this.context = context;
167 169 this.sessionStore = sessionStore;
  170 + this.modelProvider = modelProvider;
168 171 }
169 172
170 173 @PostConstruct
... ... @@ -309,7 +312,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
309 312 public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response) {
310 313 if (response.getContent() != null) {
311 314 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
312   - ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider());
  315 + ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, modelProvider);
313 316 if (objectModelVersion != null) {
314 317 if (response.getContent() instanceof LwM2mObject) {
315 318 LwM2mObject lwM2mObject = (LwM2mObject) response.getContent();
... ... @@ -388,15 +391,19 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
388 391 }
389 392
390 393 @Override
391   - public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
392   - String idVer = resourceUpdateMsgOpt.get().getResourceKey();
393   - clientContext.getLwM2mClients().forEach(e -> e.updateResourceModel(idVer, this.config.getModelProvider()));
  394 + public void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {
  395 + String idVer = resourceUpdateMsgOpt.getResourceKey();
  396 + TenantId tenantId = new TenantId(new UUID(resourceUpdateMsgOpt.getTenantIdMSB(), resourceUpdateMsgOpt.getTenantIdLSB()));
  397 + modelProvider.evict(tenantId, idVer);
  398 + clientContext.getLwM2mClients().forEach(e -> e.updateResourceModel(idVer, modelProvider));
394 399 }
395 400
396 401 @Override
397   - public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
398   - String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey();
399   - clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider()));
  402 + public void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceDeleteMsgOpt) {
  403 + String pathIdVer = resourceDeleteMsgOpt.getResourceKey();
  404 + TenantId tenantId = new TenantId(new UUID(resourceDeleteMsgOpt.getTenantIdMSB(), resourceDeleteMsgOpt.getTenantIdLSB()));
  405 + modelProvider.evict(tenantId, pathIdVer);
  406 + clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, modelProvider));
400 407 }
401 408
402 409 /**
... ... @@ -544,7 +551,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
544 551 */
545 552 private void updateResourcesValue(LwM2mClient lwM2MClient, LwM2mResource lwM2mResource, String path) {
546 553 Registration registration = lwM2MClient.getRegistration();
547   - if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config.getModelProvider())) {
  554 + if (lwM2MClient.saveResourceValue(path, lwM2mResource, modelProvider)) {
548 555 if (path.equals(convertObjectIdToVersionedId(FW_NAME_ID, registration))) {
549 556 otaService.onCurrentFirmwareNameUpdate(lwM2MClient, (String) lwM2mResource.getValue());
550 557 } else if (path.equals(convertObjectIdToVersionedId(FW_3_VER_ID, registration))) {
... ...
... ... @@ -48,9 +48,9 @@ public interface LwM2mUplinkMsgHandler {
48 48
49 49 void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt);
50 50
51   - void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt);
  51 + void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt);
52 52
53   - void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt);
  53 + void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceDeleteMsgOpt);
54 54
55 55 void onAwakeDev(Registration registration);
56 56
... ...
... ... @@ -101,8 +101,6 @@ import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK;
101 101 import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE;
102 102 import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
103 103 import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE;
104   -import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN;
105   -import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN;
106 104
107 105 /**
108 106 * @author Andrew Shvayka
... ... @@ -110,8 +108,8 @@ import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVIC
110 108 @Slf4j
111 109 public class MqttTransportHandler extends ChannelInboundHandlerAdapter implements GenericFutureListener<Future<? super Void>>, SessionMsgListener {
112 110
113   - private static final Pattern FW_REQUEST_PATTERN = Pattern.compile(DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN);
114   - private static final Pattern SW_REQUEST_PATTERN = Pattern.compile(DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN);
  111 + private static final Pattern FW_REQUEST_PATTERN = Pattern.compile(MqttTopics.DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN);
  112 + private static final Pattern SW_REQUEST_PATTERN = Pattern.compile(MqttTopics.DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN);
115 113
116 114
117 115 private static final String PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE";
... ... @@ -133,6 +131,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
133 131 private final ConcurrentHashMap<String, Integer> chunkSizes;
134 132 private final ConcurrentMap<Integer, TransportProtos.ToDeviceRpcRequestMsg> rpcAwaitingAck;
135 133
  134 + private TopicType attrSubTopicType;
  135 + private TopicType rpcSubTopicType;
  136 + private TopicType attrReqTopicType;
  137 + private TopicType toServerRpcSubTopicType;
  138 +
136 139 MqttTransportHandler(MqttTransportContext context, SslHandler sslHandler) {
137 140 this.sessionId = UUID.randomUUID();
138 141 this.context = context;
... ... @@ -355,14 +358,16 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
355 358 TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, mqttMsg);
356 359 transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg));
357 360 } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) {
358   - TransportProtos.GetAttributeRequestMsg getAttributeMsg = payloadAdaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg);
  361 + TransportProtos.GetAttributeRequestMsg getAttributeMsg = payloadAdaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX);
359 362 transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
  363 + attrReqTopicType = TopicType.V1;
360 364 } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC)) {
361   - TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg);
  365 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC);
362 366 transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
363 367 } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)) {
364   - TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg);
  368 + TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC);
365 369 transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
  370 + toServerRpcSubTopicType = TopicType.V1;
366 371 } else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) {
367 372 TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg);
368 373 transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg));
... ... @@ -370,6 +375,57 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
370 375 getOtaPackageCallback(ctx, mqttMsg, msgId, fwMatcher, OtaPackageType.FIRMWARE);
371 376 } else if ((fwMatcher = SW_REQUEST_PATTERN.matcher(topicName)).find()) {
372 377 getOtaPackageCallback(ctx, mqttMsg, msgId, fwMatcher, OtaPackageType.SOFTWARE);
  378 + } else if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_SHORT_TOPIC)) {
  379 + TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, mqttMsg);
  380 + transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg));
  381 + } else if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_SHORT_JSON_TOPIC)) {
  382 + TransportProtos.PostTelemetryMsg postTelemetryMsg = context.getJsonMqttAdaptor().convertToPostTelemetry(deviceSessionCtx, mqttMsg);
  383 + transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg));
  384 + } else if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_SHORT_PROTO_TOPIC)) {
  385 + TransportProtos.PostTelemetryMsg postTelemetryMsg = context.getProtoMqttAdaptor().convertToPostTelemetry(deviceSessionCtx, mqttMsg);
  386 + transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg));
  387 + } else if (topicName.equals(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC)) {
  388 + TransportProtos.PostAttributeMsg postAttributeMsg = payloadAdaptor.convertToPostAttributes(deviceSessionCtx, mqttMsg);
  389 + transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg));
  390 + } else if (topicName.equals(MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC)) {
  391 + TransportProtos.PostAttributeMsg postAttributeMsg = context.getJsonMqttAdaptor().convertToPostAttributes(deviceSessionCtx, mqttMsg);
  392 + transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg));
  393 + } else if (topicName.equals(MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC)) {
  394 + TransportProtos.PostAttributeMsg postAttributeMsg = context.getProtoMqttAdaptor().convertToPostAttributes(deviceSessionCtx, mqttMsg);
  395 + transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg));
  396 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_SHORT_JSON_TOPIC)) {
  397 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = context.getJsonMqttAdaptor().convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_SHORT_JSON_TOPIC);
  398 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
  399 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_SHORT_PROTO_TOPIC)) {
  400 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = context.getProtoMqttAdaptor().convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_SHORT_PROTO_TOPIC);
  401 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
  402 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_SHORT_TOPIC)) {
  403 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_SHORT_TOPIC);
  404 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
  405 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_SHORT_JSON_TOPIC)) {
  406 + TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = context.getJsonMqttAdaptor().convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_SHORT_JSON_TOPIC);
  407 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
  408 + toServerRpcSubTopicType = TopicType.V2_JSON;
  409 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_SHORT_PROTO_TOPIC)) {
  410 + TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = context.getProtoMqttAdaptor().convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_SHORT_PROTO_TOPIC);
  411 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
  412 + toServerRpcSubTopicType = TopicType.V2_PROTO;
  413 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_SHORT_TOPIC)) {
  414 + TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_SHORT_TOPIC);
  415 + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
  416 + toServerRpcSubTopicType = TopicType.V2;
  417 + } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_JSON_TOPIC_PREFIX)) {
  418 + TransportProtos.GetAttributeRequestMsg getAttributeMsg = context.getJsonMqttAdaptor().convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_JSON_TOPIC_PREFIX);
  419 + transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
  420 + attrReqTopicType = TopicType.V2_JSON;
  421 + } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_PROTO_TOPIC_PREFIX)) {
  422 + TransportProtos.GetAttributeRequestMsg getAttributeMsg = context.getProtoMqttAdaptor().convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_PROTO_TOPIC_PREFIX);
  423 + transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
  424 + attrReqTopicType = TopicType.V2_PROTO;
  425 + } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX)) {
  426 + TransportProtos.GetAttributeRequestMsg getAttributeMsg = payloadAdaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX);
  427 + transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
  428 + attrReqTopicType = TopicType.V2;
373 429 } else {
374 430 transportService.reportActivity(deviceSessionCtx.getSessionInfo());
375 431 ack(ctx, msgId);
... ... @@ -541,19 +597,53 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
541 597 try {
542 598 switch (topic) {
543 599 case MqttTopics.DEVICE_ATTRIBUTES_TOPIC: {
544   - transportService.process(deviceSessionCtx.getSessionInfo(), TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
545   - registerSubQoS(topic, grantedQoSList, reqQoS);
  600 + processAttributesSubscribe(grantedQoSList, topic, reqQoS, TopicType.V1);
  601 + activityReported = true;
  602 + break;
  603 + }
  604 + case MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC: {
  605 + processAttributesSubscribe(grantedQoSList, topic, reqQoS, TopicType.V2);
  606 + activityReported = true;
  607 + break;
  608 + }
  609 + case MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC: {
  610 + processAttributesSubscribe(grantedQoSList, topic, reqQoS, TopicType.V2_JSON);
  611 + activityReported = true;
  612 + break;
  613 + }
  614 + case MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC: {
  615 + processAttributesSubscribe(grantedQoSList, topic, reqQoS, TopicType.V2_PROTO);
546 616 activityReported = true;
547 617 break;
548 618 }
549 619 case MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC: {
550   - transportService.process(deviceSessionCtx.getSessionInfo(), TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null);
551   - registerSubQoS(topic, grantedQoSList, reqQoS);
  620 + processRpcSubscribe(grantedQoSList, topic, reqQoS, TopicType.V1);
  621 + activityReported = true;
  622 + break;
  623 + }
  624 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC: {
  625 + processRpcSubscribe(grantedQoSList, topic, reqQoS, TopicType.V2);
  626 + activityReported = true;
  627 + break;
  628 + }
  629 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC: {
  630 + processRpcSubscribe(grantedQoSList, topic, reqQoS, TopicType.V2_JSON);
  631 + activityReported = true;
  632 + break;
  633 + }
  634 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_PROTO_TOPIC: {
  635 + processRpcSubscribe(grantedQoSList, topic, reqQoS, TopicType.V2_PROTO);
552 636 activityReported = true;
553 637 break;
554 638 }
555 639 case MqttTopics.DEVICE_RPC_RESPONSE_SUB_TOPIC:
  640 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_SHORT_TOPIC:
  641 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_SHORT_JSON_TOPIC:
  642 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_SHORT_PROTO_TOPIC:
556 643 case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC:
  644 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_TOPIC:
  645 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_JSON_TOPIC:
  646 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_PROTO_TOPIC:
557 647 case MqttTopics.GATEWAY_ATTRIBUTES_TOPIC:
558 648 case MqttTopics.GATEWAY_RPC_TOPIC:
559 649 case MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC:
... ... @@ -580,6 +670,18 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
580 670 ctx.writeAndFlush(createSubAckMessage(mqttMsg.variableHeader().messageId(), grantedQoSList));
581 671 }
582 672
  673 + private void processRpcSubscribe(List<Integer> grantedQoSList, String topic, MqttQoS reqQoS, TopicType topicType) {
  674 + transportService.process(deviceSessionCtx.getSessionInfo(), TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null);
  675 + rpcSubTopicType = topicType;
  676 + registerSubQoS(topic, grantedQoSList, reqQoS);
  677 + }
  678 +
  679 + private void processAttributesSubscribe(List<Integer> grantedQoSList, String topic, MqttQoS reqQoS, TopicType topicType) {
  680 + transportService.process(deviceSessionCtx.getSessionInfo(), TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
  681 + attrSubTopicType = topicType;
  682 + registerSubQoS(topic, grantedQoSList, reqQoS);
  683 + }
  684 +
583 685 private void registerSubQoS(String topic, List<Integer> grantedQoSList, MqttQoS reqQoS) {
584 686 grantedQoSList.add(getMinSupportedQos(reqQoS));
585 687 mqttQoSMap.put(new MqttTopicMatcher(topic), getMinSupportedQos(reqQoS));
... ... @@ -595,18 +697,43 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
595 697 mqttQoSMap.remove(new MqttTopicMatcher(topicName));
596 698 try {
597 699 switch (topicName) {
598   - case MqttTopics.DEVICE_ATTRIBUTES_TOPIC: {
  700 + case MqttTopics.DEVICE_ATTRIBUTES_TOPIC:
  701 + case MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC:
  702 + case MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC:
  703 + case MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC: {
599 704 transportService.process(deviceSessionCtx.getSessionInfo(),
600 705 TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setUnsubscribe(true).build(), null);
601 706 activityReported = true;
602 707 break;
603 708 }
604   - case MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC: {
  709 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC:
  710 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_TOPIC:
  711 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_JSON_TOPIC:
  712 + case MqttTopics.DEVICE_RPC_REQUESTS_SUB_SHORT_PROTO_TOPIC: {
605 713 transportService.process(deviceSessionCtx.getSessionInfo(),
606 714 TransportProtos.SubscribeToRPCMsg.newBuilder().setUnsubscribe(true).build(), null);
607 715 activityReported = true;
608 716 break;
609 717 }
  718 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_TOPIC:
  719 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_SHORT_TOPIC:
  720 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_SHORT_JSON_TOPIC:
  721 + case MqttTopics.DEVICE_RPC_RESPONSE_SUB_SHORT_PROTO_TOPIC:
  722 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC:
  723 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_TOPIC:
  724 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_JSON_TOPIC:
  725 + case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_SHORT_PROTO_TOPIC:
  726 + case MqttTopics.GATEWAY_ATTRIBUTES_TOPIC:
  727 + case MqttTopics.GATEWAY_RPC_TOPIC:
  728 + case MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC:
  729 + case MqttTopics.DEVICE_PROVISION_RESPONSE_TOPIC:
  730 + case MqttTopics.DEVICE_FIRMWARE_RESPONSES_TOPIC:
  731 + case MqttTopics.DEVICE_FIRMWARE_ERROR_TOPIC:
  732 + case MqttTopics.DEVICE_SOFTWARE_RESPONSES_TOPIC:
  733 + case MqttTopics.DEVICE_SOFTWARE_ERROR_TOPIC: {
  734 + activityReported = true;
  735 + break;
  736 + }
610 737 }
611 738 } catch (Exception e) {
612 739 log.warn("[{}] Failed to process unsubscription [{}] to [{}]", sessionId, mqttMsg.variableHeader().messageId(), topicName);
... ... @@ -837,8 +964,29 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
837 964
838 965 @Override
839 966 public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg response) {
  967 + log.trace("[{}] Received get attributes response", sessionId);
  968 + String topicBase;
  969 + MqttTransportAdaptor adaptor;
  970 + switch (attrReqTopicType) {
  971 + case V2:
  972 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  973 + topicBase = MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_SHORT_TOPIC_PREFIX;
  974 + break;
  975 + case V2_JSON:
  976 + adaptor = context.getJsonMqttAdaptor();
  977 + topicBase = MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_SHORT_JSON_TOPIC_PREFIX;
  978 + break;
  979 + case V2_PROTO:
  980 + adaptor = context.getProtoMqttAdaptor();
  981 + topicBase = MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_SHORT_PROTO_TOPIC_PREFIX;
  982 + break;
  983 + default:
  984 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  985 + topicBase = MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_TOPIC_PREFIX;
  986 + break;
  987 + }
840 988 try {
841   - deviceSessionCtx.getPayloadAdaptor().convertToPublish(deviceSessionCtx, response).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
  989 + adaptor.convertToPublish(deviceSessionCtx, response, topicBase).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
842 990 } catch (Exception e) {
843 991 log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e);
844 992 }
... ... @@ -847,8 +995,29 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
847 995 @Override
848 996 public void onAttributeUpdate(UUID sessionId, TransportProtos.AttributeUpdateNotificationMsg notification) {
849 997 log.trace("[{}] Received attributes update notification to device", sessionId);
  998 + log.info("[{}] : attrSubTopicType: {}", notification.toString(), attrSubTopicType);
  999 + String topic;
  1000 + MqttTransportAdaptor adaptor;
  1001 + switch (attrSubTopicType) {
  1002 + case V2:
  1003 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  1004 + topic = MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC;
  1005 + break;
  1006 + case V2_JSON:
  1007 + adaptor = context.getJsonMqttAdaptor();
  1008 + topic = MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC;
  1009 + break;
  1010 + case V2_PROTO:
  1011 + adaptor = context.getProtoMqttAdaptor();
  1012 + topic = MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC;
  1013 + break;
  1014 + default:
  1015 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  1016 + topic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
  1017 + break;
  1018 + }
850 1019 try {
851   - deviceSessionCtx.getPayloadAdaptor().convertToPublish(deviceSessionCtx, notification).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
  1020 + adaptor.convertToPublish(deviceSessionCtx, notification, topic).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
852 1021 } catch (Exception e) {
853 1022 log.trace("[{}] Failed to convert device attributes update to MQTT msg", sessionId, e);
854 1023 }
... ... @@ -862,9 +1031,29 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
862 1031
863 1032 @Override
864 1033 public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) {
865   - log.trace("[{}] Received RPC command to device", sessionId);
  1034 + log.info("[{}] Received RPC command to device", sessionId);
  1035 + String baseTopic;
  1036 + MqttTransportAdaptor adaptor;
  1037 + switch (rpcSubTopicType) {
  1038 + case V2:
  1039 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  1040 + baseTopic = MqttTopics.DEVICE_RPC_REQUESTS_SHORT_TOPIC;
  1041 + break;
  1042 + case V2_JSON:
  1043 + adaptor = context.getJsonMqttAdaptor();
  1044 + baseTopic = MqttTopics.DEVICE_RPC_REQUESTS_SHORT_JSON_TOPIC;
  1045 + break;
  1046 + case V2_PROTO:
  1047 + adaptor = context.getProtoMqttAdaptor();
  1048 + baseTopic = MqttTopics.DEVICE_RPC_REQUESTS_SHORT_PROTO_TOPIC;
  1049 + break;
  1050 + default:
  1051 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  1052 + baseTopic = MqttTopics.DEVICE_RPC_REQUESTS_TOPIC;
  1053 + break;
  1054 + }
866 1055 try {
867   - deviceSessionCtx.getPayloadAdaptor().convertToPublish(deviceSessionCtx, rpcRequest).ifPresent(payload -> {
  1056 + adaptor.convertToPublish(deviceSessionCtx, rpcRequest, baseTopic).ifPresent(payload -> {
868 1057 int msgId = ((MqttPublishMessage) payload).variableHeader().packetId();
869 1058 if (isAckExpected(payload)) {
870 1059 rpcAwaitingAck.put(msgId, rpcRequest);
... ... @@ -898,9 +1087,29 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
898 1087
899 1088 @Override
900 1089 public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg rpcResponse) {
901   - log.trace("[{}] Received RPC command to server", sessionId);
  1090 + log.trace("[{}] Received RPC response from server", sessionId);
  1091 + String baseTopic;
  1092 + MqttTransportAdaptor adaptor;
  1093 + switch (toServerRpcSubTopicType) {
  1094 + case V2:
  1095 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  1096 + baseTopic = MqttTopics.DEVICE_RPC_RESPONSE_SHORT_TOPIC;
  1097 + break;
  1098 + case V2_JSON:
  1099 + adaptor = context.getJsonMqttAdaptor();
  1100 + baseTopic = MqttTopics.DEVICE_RPC_RESPONSE_SHORT_JSON_TOPIC;
  1101 + break;
  1102 + case V2_PROTO:
  1103 + adaptor = context.getProtoMqttAdaptor();
  1104 + baseTopic = MqttTopics.DEVICE_RPC_RESPONSE_SHORT_PROTO_TOPIC;
  1105 + break;
  1106 + default:
  1107 + adaptor = deviceSessionCtx.getPayloadAdaptor();
  1108 + baseTopic = MqttTopics.DEVICE_RPC_RESPONSE_TOPIC;
  1109 + break;
  1110 + }
902 1111 try {
903   - deviceSessionCtx.getPayloadAdaptor().convertToPublish(deviceSessionCtx, rpcResponse).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
  1112 + adaptor.convertToPublish(deviceSessionCtx, rpcResponse, baseTopic).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
904 1113 } catch (Exception e) {
905 1114 log.trace("[{}] Failed to convert device RPC command to MQTT msg", sessionId, e);
906 1115 }
... ... @@ -923,4 +1132,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
923 1132 public void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {
924 1133 deviceSessionCtx.onDeviceUpdate(sessionInfo, device, deviceProfileOpt);
925 1134 }
  1135 +
  1136 + private enum TopicType {
  1137 + V1, V2, V2_JSON, V2_PROTO
  1138 + }
  1139 +
926 1140 }
... ...
... ... @@ -64,6 +64,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
64 64 try {
65 65 return JsonConverter.convertToTelemetryProto(new JsonParser().parse(payload));
66 66 } catch (IllegalStateException | JsonSyntaxException ex) {
  67 + log.warn("Failed to decode post telemetry request", ex);
67 68 throw new AdaptorException(ex);
68 69 }
69 70 }
... ... @@ -74,6 +75,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
74 75 try {
75 76 return JsonConverter.convertToAttributesProto(new JsonParser().parse(payload));
76 77 } catch (IllegalStateException | JsonSyntaxException ex) {
  78 + log.warn("Failed to decode post attributes request", ex);
77 79 throw new AdaptorException(ex);
78 80 }
79 81 }
... ... @@ -84,6 +86,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
84 86 try {
85 87 return JsonConverter.convertToClaimDeviceProto(ctx.getDeviceId(), payload);
86 88 } catch (IllegalStateException | JsonSyntaxException ex) {
  89 + log.warn("Failed to decode claim device request", ex);
87 90 throw new AdaptorException(ex);
88 91 }
89 92 }
... ... @@ -99,33 +102,33 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
99 102 }
100 103
101 104 @Override
102   - public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
103   - return processGetAttributeRequestMsg(inbound, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX);
  105 + public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException {
  106 + return processGetAttributeRequestMsg(inbound, topicBase);
104 107 }
105 108
106 109 @Override
107   - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
108   - return processToDeviceRpcResponseMsg(inbound, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC);
  110 + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException {
  111 + return processToDeviceRpcResponseMsg(inbound, topicBase);
109 112 }
110 113
111 114 @Override
112   - public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
113   - return processToServerRpcRequestMsg(ctx, inbound, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC);
  115 + public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException {
  116 + return processToServerRpcRequestMsg(ctx, inbound, topicBase);
114 117 }
115 118
116 119 @Override
117   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
118   - return processConvertFromAttributeResponseMsg(ctx, responseMsg, MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_TOPIC_PREFIX);
  120 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException {
  121 + return processConvertFromAttributeResponseMsg(ctx, responseMsg, topicBase);
119 122 }
120 123
121 124 @Override
122 125 public Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
123   - return processConvertFromGatewayAttributeResponseMsg(ctx, deviceName, responseMsg, MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC);
  126 + return processConvertFromGatewayAttributeResponseMsg(ctx, deviceName, responseMsg);
124 127 }
125 128
126 129 @Override
127   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) {
128   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_ATTRIBUTES_TOPIC, JsonConverter.toJson(notificationMsg)));
  130 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg, String topic) {
  131 + return Optional.of(createMqttPublishMsg(ctx, topic, JsonConverter.toJson(notificationMsg)));
129 132 }
130 133
131 134 @Override
... ... @@ -135,8 +138,8 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
135 138 }
136 139
137 140 @Override
138   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) {
139   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), JsonConverter.toJson(rpcRequest, false)));
  141 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, String topicBase) {
  142 + return Optional.of(createMqttPublishMsg(ctx, topicBase + rpcRequest.getRequestId(), JsonConverter.toJson(rpcRequest, false)));
140 143 }
141 144
142 145 @Override
... ... @@ -145,8 +148,8 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
145 148 }
146 149
147 150 @Override
148   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse) {
149   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(), JsonConverter.toJson(rpcResponse)));
  151 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse, String topicBase) {
  152 + return Optional.of(createMqttPublishMsg(ctx, topicBase + rpcResponse.getRequestId(), JsonConverter.toJson(rpcResponse)));
150 153 }
151 154
152 155 @Override
... ... @@ -169,11 +172,11 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
169 172 }
170 173 }
171 174
172   - protected TransportProtos.GetAttributeRequestMsg processGetAttributeRequestMsg(MqttPublishMessage inbound, String topic) throws AdaptorException {
  175 + private TransportProtos.GetAttributeRequestMsg processGetAttributeRequestMsg(MqttPublishMessage inbound, String topicBase) throws AdaptorException {
173 176 String topicName = inbound.variableHeader().topicName();
174 177 try {
175 178 TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder();
176   - result.setRequestId(getRequestId(topicName, topic));
  179 + result.setRequestId(getRequestId(topicName, topicBase));
177 180 String payload = inbound.payload().toString(UTF8);
178 181 JsonElement requestBody = new JsonParser().parse(payload);
179 182 Set<String> clientKeys = toStringSet(requestBody, "clientKeys");
... ... @@ -191,49 +194,50 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
191 194 }
192 195 }
193 196
194   - protected TransportProtos.ToDeviceRpcResponseMsg processToDeviceRpcResponseMsg(MqttPublishMessage inbound, String topic) throws AdaptorException {
  197 + private TransportProtos.ToDeviceRpcResponseMsg processToDeviceRpcResponseMsg(MqttPublishMessage inbound, String topicBase) throws AdaptorException {
195 198 String topicName = inbound.variableHeader().topicName();
196 199 try {
197   - int requestId = getRequestId(topicName, topic);
  200 + int requestId = getRequestId(topicName, topicBase);
198 201 String payload = inbound.payload().toString(UTF8);
199 202 return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(payload).build();
200 203 } catch (RuntimeException e) {
201   - log.warn("Failed to decode Rpc response", e);
  204 + log.warn("Failed to decode rpc response", e);
202 205 throw new AdaptorException(e);
203 206 }
204 207 }
205 208
206   - protected TransportProtos.ToServerRpcRequestMsg processToServerRpcRequestMsg(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topic) throws AdaptorException {
  209 + private TransportProtos.ToServerRpcRequestMsg processToServerRpcRequestMsg(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException {
207 210 String topicName = inbound.variableHeader().topicName();
208 211 String payload = validatePayload(ctx.getSessionId(), inbound.payload(), false);
209 212 try {
210   - int requestId = getRequestId(topicName, topic);
  213 + int requestId = getRequestId(topicName, topicBase);
211 214 return JsonConverter.convertToServerRpcRequest(new JsonParser().parse(payload), requestId);
212 215 } catch (IllegalStateException | JsonSyntaxException ex) {
  216 + log.warn("Failed to decode to server rpc request", ex);
213 217 throw new AdaptorException(ex);
214 218 }
215 219 }
216 220
217   - protected Optional<MqttMessage> processConvertFromAttributeResponseMsg(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topic) throws AdaptorException {
  221 + private Optional<MqttMessage> processConvertFromAttributeResponseMsg(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException {
218 222 if (!StringUtils.isEmpty(responseMsg.getError())) {
219 223 throw new AdaptorException(responseMsg.getError());
220 224 } else {
221 225 int requestId = responseMsg.getRequestId();
222 226 if (requestId >= 0) {
223 227 return Optional.of(createMqttPublishMsg(ctx,
224   - topic + requestId,
  228 + topicBase + requestId,
225 229 JsonConverter.toJson(responseMsg)));
226 230 }
227 231 return Optional.empty();
228 232 }
229 233 }
230 234
231   - protected Optional<MqttMessage> processConvertFromGatewayAttributeResponseMsg(MqttDeviceAwareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg, String topic) throws AdaptorException {
  235 + private Optional<MqttMessage> processConvertFromGatewayAttributeResponseMsg(MqttDeviceAwareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
232 236 if (!StringUtils.isEmpty(responseMsg.getError())) {
233 237 throw new AdaptorException(responseMsg.getError());
234 238 } else {
235 239 JsonObject result = JsonConverter.getJsonObjectForGateway(deviceName, responseMsg);
236   - return Optional.of(createMqttPublishMsg(ctx, topic, result));
  240 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC, result));
237 241 }
238 242 }
239 243
... ...
... ... @@ -52,27 +52,27 @@ public interface MqttTransportAdaptor {
52 52
53 53 PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
54 54
55   - GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
  55 + GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException;
56 56
57   - ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
  57 + ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException;
58 58
59   - ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
  59 + ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException;
60 60
61 61 ClaimDeviceMsg convertToClaimDevice(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
62 62
63   - Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, GetAttributeResponseMsg responseMsg) throws AdaptorException;
  63 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException;
64 64
65 65 Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, GetAttributeResponseMsg responseMsg) throws AdaptorException;
66 66
67   - Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
  67 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, AttributeUpdateNotificationMsg notificationMsg, String topic) throws AdaptorException;
68 68
69 69 Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
70 70
71   - Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException;
  71 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToDeviceRpcRequestMsg rpcRequest, String topicBase) throws AdaptorException;
72 72
73 73 Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException;
74 74
75   - Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToServerRpcResponseMsg rpcResponse) throws AdaptorException;
  75 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToServerRpcResponseMsg rpcResponse, String topicBase) throws AdaptorException;
76 76
77 77 ProvisionDeviceRequestMsg convertToProvisionRequestMsg(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
78 78
... ...
... ... @@ -20,7 +20,6 @@ import com.google.gson.JsonParser;
20 20 import com.google.protobuf.Descriptors;
21 21 import com.google.protobuf.DynamicMessage;
22 22 import com.google.protobuf.InvalidProtocolBufferException;
23   -import com.google.protobuf.util.JsonFormat;
24 23 import io.netty.buffer.ByteBuf;
25 24 import io.netty.handler.codec.mqtt.MqttMessage;
26 25 import io.netty.handler.codec.mqtt.MqttPublishMessage;
... ... @@ -49,10 +48,11 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
49 48 public TransportProtos.PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
50 49 DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx;
51 50 byte[] bytes = toBytes(inbound.payload());
52   - Descriptors.Descriptor telemetryDynamicMsgDescriptor = getDescriptor(deviceSessionCtx.getTelemetryDynamicMsgDescriptor());
  51 + Descriptors.Descriptor telemetryDynamicMsgDescriptor = ProtoConverter.validateDescriptor(deviceSessionCtx.getTelemetryDynamicMsgDescriptor());
53 52 try {
54   - return JsonConverter.convertToTelemetryProto(new JsonParser().parse(dynamicMsgToJson(bytes, telemetryDynamicMsgDescriptor)));
  53 + return JsonConverter.convertToTelemetryProto(new JsonParser().parse(ProtoConverter.dynamicMsgToJson(bytes, telemetryDynamicMsgDescriptor)));
55 54 } catch (Exception e) {
  55 + log.warn("Failed to decode post telemetry request", e);
56 56 throw new AdaptorException(e);
57 57 }
58 58 }
... ... @@ -61,10 +61,11 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
61 61 public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
62 62 DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx;
63 63 byte[] bytes = toBytes(inbound.payload());
64   - Descriptors.Descriptor attributesDynamicMessageDescriptor = getDescriptor(deviceSessionCtx.getAttributesDynamicMessageDescriptor());
  64 + Descriptors.Descriptor attributesDynamicMessageDescriptor = ProtoConverter.validateDescriptor(deviceSessionCtx.getAttributesDynamicMessageDescriptor());
65 65 try {
66   - return JsonConverter.convertToAttributesProto(new JsonParser().parse(dynamicMsgToJson(bytes, attributesDynamicMessageDescriptor)));
  66 + return JsonConverter.convertToAttributesProto(new JsonParser().parse(ProtoConverter.dynamicMsgToJson(bytes, attributesDynamicMessageDescriptor)));
67 67 } catch (Exception e) {
  68 + log.warn("Failed to decode post attributes request", e);
68 69 throw new AdaptorException(e);
69 70 }
70 71 }
... ... @@ -75,16 +76,17 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
75 76 try {
76 77 return ProtoConverter.convertToClaimDeviceProto(ctx.getDeviceId(), bytes);
77 78 } catch (InvalidProtocolBufferException e) {
  79 + log.warn("Failed to decode claim device request", e);
78 80 throw new AdaptorException(e);
79 81 }
80 82 }
81 83
82 84 @Override
83   - public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
  85 + public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException {
84 86 byte[] bytes = toBytes(inbound.payload());
85 87 String topicName = inbound.variableHeader().topicName();
86 88 try {
87   - int requestId = getRequestId(topicName, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX);
  89 + int requestId = getRequestId(topicName, topicBase);
88 90 return ProtoConverter.convertToGetAttributeRequestMessage(bytes, requestId);
89 91 } catch (InvalidProtocolBufferException e) {
90 92 log.warn("Failed to decode get attributes request", e);
... ... @@ -93,29 +95,30 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
93 95 }
94 96
95 97 @Override
96   - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException {
  98 + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException {
97 99 DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx;
98 100 String topicName = mqttMsg.variableHeader().topicName();
99 101 byte[] bytes = toBytes(mqttMsg.payload());
100   - Descriptors.Descriptor rpcResponseDynamicMessageDescriptor = getDescriptor(deviceSessionCtx.getRpcResponseDynamicMessageDescriptor());
  102 + Descriptors.Descriptor rpcResponseDynamicMessageDescriptor = ProtoConverter.validateDescriptor(deviceSessionCtx.getRpcResponseDynamicMessageDescriptor());
101 103 try {
102   - int requestId = getRequestId(topicName, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC);
103   - JsonElement response = new JsonParser().parse(dynamicMsgToJson(bytes, rpcResponseDynamicMessageDescriptor));
  104 + int requestId = getRequestId(topicName, topicBase);
  105 + JsonElement response = new JsonParser().parse(ProtoConverter.dynamicMsgToJson(bytes, rpcResponseDynamicMessageDescriptor));
104 106 return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(response.toString()).build();
105 107 } catch (Exception e) {
106   - log.warn("Failed to decode Rpc response", e);
  108 + log.warn("Failed to decode rpc response", e);
107 109 throw new AdaptorException(e);
108 110 }
109 111 }
110 112
111 113 @Override
112   - public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException {
  114 + public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException {
113 115 byte[] bytes = toBytes(mqttMsg.payload());
114 116 String topicName = mqttMsg.variableHeader().topicName();
115 117 try {
116   - int requestId = getRequestId(topicName, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC);
  118 + int requestId = getRequestId(topicName, topicBase);
117 119 return ProtoConverter.convertToServerRpcRequest(bytes, requestId);
118 120 } catch (InvalidProtocolBufferException e) {
  121 + log.warn("Failed to decode to server rpc request", e);
119 122 throw new AdaptorException(e);
120 123 }
121 124 }
... ... @@ -126,40 +129,43 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
126 129 try {
127 130 return ProtoConverter.convertToProvisionRequestMsg(bytes);
128 131 } catch (InvalidProtocolBufferException ex) {
  132 + log.warn("Failed to decode provision request", ex);
129 133 throw new AdaptorException(ex);
130 134 }
131 135 }
132 136
133 137 @Override
134   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
  138 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException {
135 139 if (!StringUtils.isEmpty(responseMsg.getError())) {
136 140 throw new AdaptorException(responseMsg.getError());
137 141 } else {
138 142 int requestId = responseMsg.getRequestId();
139 143 if (requestId >= 0) {
140   - return Optional.of(createMqttPublishMsg(ctx,
141   - MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_TOPIC_PREFIX + requestId,
142   - responseMsg.toByteArray()));
  144 + return Optional.of(createMqttPublishMsg(ctx, topicBase + requestId, responseMsg.toByteArray()));
143 145 }
144 146 return Optional.empty();
145 147 }
146 148 }
147 149
148 150 @Override
149   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException {
  151 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, String topicBase) throws AdaptorException {
150 152 DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx;
151 153 DynamicMessage.Builder rpcRequestDynamicMessageBuilder = deviceSessionCtx.getRpcRequestDynamicMessageBuilder();
152   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), ProtoConverter.convertToRpcRequest(rpcRequest, rpcRequestDynamicMessageBuilder)));
  154 + if (rpcRequestDynamicMessageBuilder == null) {
  155 + throw new AdaptorException("Failed to get rpcRequestDynamicMessageBuilder!");
  156 + } else {
  157 + return Optional.of(createMqttPublishMsg(ctx, topicBase + rpcRequest.getRequestId(), ProtoConverter.convertToRpcRequest(rpcRequest, rpcRequestDynamicMessageBuilder)));
  158 + }
153 159 }
154 160
155 161 @Override
156   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse) {
157   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(), rpcResponse.toByteArray()));
  162 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse, String topicBase) {
  163 + return Optional.of(createMqttPublishMsg(ctx, topicBase + rpcResponse.getRequestId(), rpcResponse.toByteArray()));
158 164 }
159 165
160 166 @Override
161   - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) {
162   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_ATTRIBUTES_TOPIC, notificationMsg.toByteArray()));
  167 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg, String topic) {
  168 + return Optional.of(createMqttPublishMsg(ctx, topic, notificationMsg.toByteArray()));
163 169 }
164 170
165 171 @Override
... ... @@ -213,17 +219,4 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
213 219 private int getRequestId(String topicName, String topic) {
214 220 return Integer.parseInt(topicName.substring(topic.length()));
215 221 }
216   -
217   - private Descriptors.Descriptor getDescriptor(Descriptors.Descriptor descriptor) throws AdaptorException {
218   - if (descriptor == null) {
219   - throw new AdaptorException("Failed to get dynamic message descriptor!");
220   - }
221   - return descriptor;
222   - }
223   -
224   - private String dynamicMsgToJson(byte[] bytes, Descriptors.Descriptor descriptor) throws InvalidProtocolBufferException {
225   - DynamicMessage dynamicMessage = DynamicMessage.parseFrom(descriptor, bytes);
226   - return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage);
227   - }
228   -
229 222 }
... ...
... ... @@ -56,7 +56,7 @@ public interface SessionMsgListener {
56 56
57 57 default void onDeviceDeleted(DeviceId deviceId) {}
58 58
59   - default void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {}
  59 + default void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {}
60 60
61   - default void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceUpdateMsgOpt) {}
  61 + default void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceUpdateMsgOpt) {}
62 62 }
... ...
... ... @@ -19,6 +19,7 @@ import com.google.gson.Gson;
19 19 import com.google.gson.JsonElement;
20 20 import com.google.gson.JsonObject;
21 21 import com.google.gson.JsonParser;
  22 +import com.google.protobuf.Descriptors;
22 23 import com.google.protobuf.DynamicMessage;
23 24 import com.google.protobuf.InvalidProtocolBufferException;
24 25 import com.google.protobuf.util.JsonFormat;
... ... @@ -190,4 +191,17 @@ public class ProtoConverter {
190 191 throw new AdaptorException("Failed to convert ToDeviceRpcRequestMsg to Dynamic Rpc request message due to: ", e);
191 192 }
192 193 }
  194 +
  195 + public static Descriptors.Descriptor validateDescriptor(Descriptors.Descriptor descriptor) throws AdaptorException {
  196 + if (descriptor == null) {
  197 + throw new AdaptorException("Failed to get dynamic message descriptor!");
  198 + }
  199 + return descriptor;
  200 + }
  201 +
  202 + public static String dynamicMsgToJson(byte[] bytes, Descriptors.Descriptor descriptor) throws InvalidProtocolBufferException {
  203 + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(descriptor, bytes);
  204 + return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage);
  205 + }
  206 +
193 207 }
... ...
... ... @@ -908,7 +908,7 @@ public class DefaultTransportService implements TransportService {
908 908 transportResourceCache.update(tenantId, resourceType, resourceId);
909 909 sessions.forEach((id, mdRez) -> {
910 910 log.warn("ResourceUpdate - [{}] [{}]", id, mdRez);
911   - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(Optional.ofNullable(msg)));
  911 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(msg));
912 912 });
913 913
914 914 } else if (toSessionMsg.hasResourceDeleteMsg()) {
... ... @@ -919,7 +919,7 @@ public class DefaultTransportService implements TransportService {
919 919 transportResourceCache.evict(tenantId, resourceType, resourceId);
920 920 sessions.forEach((id, mdRez) -> {
921 921 log.warn("ResourceDelete - [{}] [{}]", id, mdRez);
922   - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(Optional.ofNullable(msg)));
  922 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(msg));
923 923 });
924 924 } else {
925 925 //TODO: should we notify the device actor about missed session?
... ...
... ... @@ -95,15 +95,8 @@ public class TbSendRPCRequestNode implements TbNode {
95 95 tmp = msg.getMetaData().getValue(DataConstants.RETRIES);
96 96 Integer retries = !StringUtils.isEmpty(tmp) ? Integer.parseInt(tmp) : null;
97 97
98   - String params;
99   - JsonElement paramsEl = json.get("params");
100   - if (paramsEl.isJsonPrimitive()) {
101   - params = paramsEl.getAsString();
102   - } else {
103   - params = gson.toJson(paramsEl);
104   - }
105   -
106   - String additionalInfo = gson.toJson(json.get(DataConstants.ADDITIONAL_INFO));
  98 + String params = parseJsonData(json.get("params"));
  99 + String additionalInfo = parseJsonData(json.get(DataConstants.ADDITIONAL_INFO));
107 100
108 101 RuleEngineDeviceRpcRequest request = RuleEngineDeviceRpcRequest.builder()
109 102 .oneway(oneway)
... ... @@ -144,4 +137,8 @@ public class TbSendRPCRequestNode implements TbNode {
144 137 return gson.toJson(json);
145 138 }
146 139
  140 + private String parseJsonData(JsonElement paramsEl) {
  141 + return paramsEl.isJsonPrimitive() ? paramsEl.getAsString() : gson.toJson(paramsEl);
  142 + }
  143 +
147 144 }
... ...
... ... @@ -96,7 +96,7 @@ keytool -genkeypair -v \
96 96 -keypass $CLIENT_KEY_PASSWORD \
97 97 -storepass $CLIENT_KEYSTORE_PASSWORD \
98 98 -keyalg $CLIENT_KEY_ALG \
99   - -keysize $CLIENT_KEY_SIZE\
  99 + -groupname $CLIENT_KEY_GROUP_NAME \
100 100 -validity 9999 \
101 101 -dname "CN=$DOMAIN_SUFFIX, OU=$ORGANIZATIONAL_UNIT, O=$ORGANIZATION, L=$CITY, ST=$STATE_OR_PROVINCE, C=$TWO_LETTER_COUNTRY_CODE"
102 102
... ...
... ... @@ -16,8 +16,8 @@
16 16
17 17 DOMAIN_SUFFIX="$(hostname)"
18 18 SUBJECT_ALTERNATIVE_NAMES="ip:127.0.0.1"
19   -ORGANIZATIONAL_UNIT=Thingsboard
20   -ORGANIZATION=Thingsboard
  19 +ORGANIZATIONAL_UNIT=ThingsBoard
  20 +ORGANIZATION=ThingsBoard
21 21 CITY="San Francisco"
22 22 STATE_OR_PROVINCE=CA
23 23 TWO_LETTER_COUNTRY_CODE=US
... ... @@ -27,8 +27,8 @@ SERVER_KEY_PASSWORD=password
27 27
28 28 SERVER_KEY_ALIAS="serveralias"
29 29 SERVER_FILE_PREFIX="server"
30   -SERVER_KEY_ALG="RSA"
31   -SERVER_KEY_SIZE="2048"
  30 +SERVER_KEY_ALG="EC"
  31 +SERVER_KEY_GROUP_NAME="secp256r1"
32 32 SERVER_KEYSTORE_DIR="/etc/thingsboard/conf"
33 33
34 34 CLIENT_KEYSTORE_PASSWORD=password
... ... @@ -36,5 +36,5 @@ CLIENT_KEY_PASSWORD=password
36 36
37 37 CLIENT_KEY_ALIAS="clientalias"
38 38 CLIENT_FILE_PREFIX="client"
39   -CLIENT_KEY_ALG="RSA"
40   -CLIENT_KEY_SIZE="2048"
  39 +CLIENT_KEY_ALG="EC"
  40 +CLIENT_KEY_GROUP_NAME="secp256r1"
... ...
... ... @@ -105,7 +105,7 @@ keytool -genkeypair -v \
105 105 -keypass $SERVER_KEY_PASSWORD \
106 106 -storepass $SERVER_KEYSTORE_PASSWORD \
107 107 -keyalg $SERVER_KEY_ALG \
108   - -keysize $SERVER_KEY_SIZE \
  108 + -groupname $SERVER_KEY_GROUP_NAME \
109 109 -validity 9999 \
110 110 $EXT
111 111
... ...
... ... @@ -15,6 +15,6 @@
15 15 limitations under the License.
16 16
17 17 -->
18   -<button mat-icon-button type="button" (click)="togglePassword($event)" [attr.aria-pressed]="showPassword" *ngIf="!hideToggle">
  18 +<button mat-icon-button type="button" tabindex="-1" (click)="togglePassword($event)" [attr.aria-pressed]="showPassword" *ngIf="!hideToggle">
19 19 <mat-icon>{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>
20 20 </button>
... ...
... ... @@ -124,8 +124,9 @@ export class ValueInputComponent implements OnInit, ControlValueAccessor {
124 124 onValueTypeChanged() {
125 125 if (this.valueType === ValueType.BOOLEAN) {
126 126 this.modelValue = false;
127   - } if (this.valueType === ValueType.JSON) {
  127 + } else if (this.valueType === ValueType.JSON) {
128 128 this.modelValue = {};
  129 + this.inputForm.form.get('value').patchValue({});
129 130 } else {
130 131 this.modelValue = null;
131 132 }
... ...