Commit 6b55f3308455dfb7d69a6f60f0310693d6be6778
Committed by
GitHub
Merge pull request #3740 from thingsboard/feature/device-profile-telemetry-proto-schema
Support of Custom Protobuf payloads
Showing
50 changed files
with
1324 additions
and
225 deletions
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | -import com.datastax.oss.driver.api.core.uuid.Uuids; | ||
19 | import com.fasterxml.jackson.core.type.TypeReference; | 18 | import com.fasterxml.jackson.core.type.TypeReference; |
20 | import com.fasterxml.jackson.databind.JsonNode; | 19 | import com.fasterxml.jackson.databind.JsonNode; |
21 | import com.fasterxml.jackson.databind.ObjectMapper; | 20 | import com.fasterxml.jackson.databind.ObjectMapper; |
@@ -33,12 +32,7 @@ import org.junit.Rule; | @@ -33,12 +32,7 @@ import org.junit.Rule; | ||
33 | import org.junit.rules.TestRule; | 32 | import org.junit.rules.TestRule; |
34 | import org.junit.rules.TestWatcher; | 33 | import org.junit.rules.TestWatcher; |
35 | import org.junit.runner.Description; | 34 | import org.junit.runner.Description; |
36 | -import org.junit.runner.RunWith; | ||
37 | import org.springframework.beans.factory.annotation.Autowired; | 35 | import org.springframework.beans.factory.annotation.Autowired; |
38 | -import org.springframework.boot.test.context.SpringBootContextLoader; | ||
39 | -import org.springframework.boot.test.context.SpringBootTest; | ||
40 | -import org.springframework.context.annotation.ComponentScan; | ||
41 | -import org.springframework.context.annotation.Configuration; | ||
42 | import org.springframework.http.HttpHeaders; | 36 | import org.springframework.http.HttpHeaders; |
43 | import org.springframework.http.MediaType; | 37 | import org.springframework.http.MediaType; |
44 | import org.springframework.http.converter.HttpMessageConverter; | 38 | import org.springframework.http.converter.HttpMessageConverter; |
@@ -46,10 +40,6 @@ import org.springframework.http.converter.StringHttpMessageConverter; | @@ -46,10 +40,6 @@ import org.springframework.http.converter.StringHttpMessageConverter; | ||
46 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | 40 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; |
47 | import org.springframework.mock.http.MockHttpInputMessage; | 41 | import org.springframework.mock.http.MockHttpInputMessage; |
48 | import org.springframework.mock.http.MockHttpOutputMessage; | 42 | import org.springframework.mock.http.MockHttpOutputMessage; |
49 | -import org.springframework.test.annotation.DirtiesContext; | ||
50 | -import org.springframework.test.context.ActiveProfiles; | ||
51 | -import org.springframework.test.context.ContextConfiguration; | ||
52 | -import org.springframework.test.context.junit4.SpringRunner; | ||
53 | import org.springframework.test.web.servlet.MockMvc; | 43 | import org.springframework.test.web.servlet.MockMvc; |
54 | import org.springframework.test.web.servlet.MvcResult; | 44 | import org.springframework.test.web.servlet.MvcResult; |
55 | import org.springframework.test.web.servlet.ResultActions; | 45 | import org.springframework.test.web.servlet.ResultActions; |
@@ -58,7 +48,6 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilde | @@ -58,7 +48,6 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilde | ||
58 | import org.springframework.util.LinkedMultiValueMap; | 48 | import org.springframework.util.LinkedMultiValueMap; |
59 | import org.springframework.util.MultiValueMap; | 49 | import org.springframework.util.MultiValueMap; |
60 | import org.springframework.web.context.WebApplicationContext; | 50 | import org.springframework.web.context.WebApplicationContext; |
61 | -import org.thingsboard.server.common.data.BaseData; | ||
62 | import org.thingsboard.server.common.data.Customer; | 51 | import org.thingsboard.server.common.data.Customer; |
63 | import org.thingsboard.server.common.data.DeviceProfile; | 52 | import org.thingsboard.server.common.data.DeviceProfile; |
64 | import org.thingsboard.server.common.data.DeviceProfileType; | 53 | import org.thingsboard.server.common.data.DeviceProfileType; |
@@ -68,11 +57,13 @@ import org.thingsboard.server.common.data.User; | @@ -68,11 +57,13 @@ import org.thingsboard.server.common.data.User; | ||
68 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; | 57 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; |
69 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; | 58 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; |
70 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | 59 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
71 | -import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials; | 60 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
61 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
62 | +import org.thingsboard.server.common.data.device.profile.MqttTopics; | ||
63 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
64 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
72 | import org.thingsboard.server.common.data.id.HasId; | 65 | import org.thingsboard.server.common.data.id.HasId; |
73 | -import org.thingsboard.server.common.data.id.RuleChainId; | ||
74 | import org.thingsboard.server.common.data.id.TenantId; | 66 | import org.thingsboard.server.common.data.id.TenantId; |
75 | -import org.thingsboard.server.common.data.id.UUIDBased; | ||
76 | import org.thingsboard.server.common.data.page.PageLink; | 67 | import org.thingsboard.server.common.data.page.PageLink; |
77 | import org.thingsboard.server.common.data.page.TimePageLink; | 68 | import org.thingsboard.server.common.data.page.TimePageLink; |
78 | import org.thingsboard.server.common.data.security.Authority; | 69 | import org.thingsboard.server.common.data.security.Authority; |
@@ -330,7 +321,7 @@ public abstract class AbstractWebTest { | @@ -330,7 +321,7 @@ public abstract class AbstractWebTest { | ||
330 | } | 321 | } |
331 | } | 322 | } |
332 | 323 | ||
333 | - protected DeviceProfile createDeviceProfile(String name) { | 324 | + protected DeviceProfile createDeviceProfile(String name, DeviceProfileTransportConfiguration deviceProfileTransportConfiguration) { |
334 | DeviceProfile deviceProfile = new DeviceProfile(); | 325 | DeviceProfile deviceProfile = new DeviceProfile(); |
335 | deviceProfile.setName(name); | 326 | deviceProfile.setName(name); |
336 | deviceProfile.setType(DeviceProfileType.DEFAULT); | 327 | deviceProfile.setType(DeviceProfileType.DEFAULT); |
@@ -338,15 +329,34 @@ public abstract class AbstractWebTest { | @@ -338,15 +329,34 @@ public abstract class AbstractWebTest { | ||
338 | deviceProfile.setDescription(name + " Test"); | 329 | deviceProfile.setDescription(name + " Test"); |
339 | DeviceProfileData deviceProfileData = new DeviceProfileData(); | 330 | DeviceProfileData deviceProfileData = new DeviceProfileData(); |
340 | DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); | 331 | DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); |
341 | - DefaultDeviceProfileTransportConfiguration transportConfiguration = new DefaultDeviceProfileTransportConfiguration(); | ||
342 | deviceProfileData.setConfiguration(configuration); | 332 | deviceProfileData.setConfiguration(configuration); |
343 | - deviceProfileData.setTransportConfiguration(transportConfiguration); | 333 | + if (deviceProfileTransportConfiguration != null) { |
334 | + deviceProfileData.setTransportConfiguration(deviceProfileTransportConfiguration); | ||
335 | + } else { | ||
336 | + deviceProfileData.setTransportConfiguration(new DefaultDeviceProfileTransportConfiguration()); | ||
337 | + } | ||
344 | deviceProfile.setProfileData(deviceProfileData); | 338 | deviceProfile.setProfileData(deviceProfileData); |
345 | deviceProfile.setDefault(false); | 339 | deviceProfile.setDefault(false); |
346 | deviceProfile.setDefaultRuleChainId(null); | 340 | deviceProfile.setDefaultRuleChainId(null); |
347 | return deviceProfile; | 341 | return deviceProfile; |
348 | } | 342 | } |
349 | 343 | ||
344 | + protected MqttDeviceProfileTransportConfiguration createMqttDeviceProfileTransportConfiguration(TransportPayloadTypeConfiguration transportPayloadTypeConfiguration) { | ||
345 | + MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration(); | ||
346 | + mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(MqttTopics.DEVICE_TELEMETRY_TOPIC); | ||
347 | + mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(MqttTopics.DEVICE_ATTRIBUTES_TOPIC); | ||
348 | + mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); | ||
349 | + return mqttDeviceProfileTransportConfiguration; | ||
350 | + } | ||
351 | + | ||
352 | + protected ProtoTransportPayloadConfiguration createProtoTransportPayloadConfiguration(String deviceAttributesProtoSchema, String deviceTelemetryProtoSchema) { | ||
353 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = new ProtoTransportPayloadConfiguration(); | ||
354 | + protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(deviceAttributesProtoSchema); | ||
355 | + protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(deviceTelemetryProtoSchema); | ||
356 | + return protoTransportPayloadConfiguration; | ||
357 | + } | ||
358 | + | ||
359 | + | ||
350 | protected ResultActions doGet(String urlTemplate, Object... urlVariables) throws Exception { | 360 | protected ResultActions doGet(String urlTemplate, Object... urlVariables) throws Exception { |
351 | MockHttpServletRequestBuilder getRequest = get(urlTemplate, urlVariables); | 361 | MockHttpServletRequestBuilder getRequest = get(urlTemplate, urlVariables); |
352 | setJwtToken(getRequest); | 362 | setJwtToken(getRequest); |
@@ -16,6 +16,12 @@ | @@ -16,6 +16,12 @@ | ||
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | import com.fasterxml.jackson.core.type.TypeReference; | 18 | import com.fasterxml.jackson.core.type.TypeReference; |
19 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
20 | +import com.google.protobuf.Descriptors; | ||
21 | +import com.google.protobuf.DynamicMessage; | ||
22 | +import com.google.protobuf.InvalidProtocolBufferException; | ||
23 | +import com.google.protobuf.util.JsonFormat; | ||
24 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
19 | import org.junit.After; | 25 | import org.junit.After; |
20 | import org.junit.Assert; | 26 | import org.junit.Assert; |
21 | import org.junit.Before; | 27 | import org.junit.Before; |
@@ -28,7 +34,10 @@ import org.thingsboard.server.common.data.DeviceProfileType; | @@ -28,7 +34,10 @@ import org.thingsboard.server.common.data.DeviceProfileType; | ||
28 | import org.thingsboard.server.common.data.DeviceTransportType; | 34 | import org.thingsboard.server.common.data.DeviceTransportType; |
29 | import org.thingsboard.server.common.data.Tenant; | 35 | import org.thingsboard.server.common.data.Tenant; |
30 | import org.thingsboard.server.common.data.User; | 36 | import org.thingsboard.server.common.data.User; |
31 | -import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials; | 37 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
38 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
39 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
40 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
32 | import org.thingsboard.server.common.data.page.PageData; | 41 | import org.thingsboard.server.common.data.page.PageData; |
33 | import org.thingsboard.server.common.data.page.PageLink; | 42 | import org.thingsboard.server.common.data.page.PageLink; |
34 | import org.thingsboard.server.common.data.security.Authority; | 43 | import org.thingsboard.server.common.data.security.Authority; |
@@ -36,9 +45,13 @@ import org.thingsboard.server.common.data.security.Authority; | @@ -36,9 +45,13 @@ import org.thingsboard.server.common.data.security.Authority; | ||
36 | import java.util.ArrayList; | 45 | import java.util.ArrayList; |
37 | import java.util.Collections; | 46 | import java.util.Collections; |
38 | import java.util.List; | 47 | import java.util.List; |
48 | +import java.util.Set; | ||
39 | import java.util.stream.Collectors; | 49 | import java.util.stream.Collectors; |
40 | 50 | ||
41 | import static org.hamcrest.Matchers.containsString; | 51 | import static org.hamcrest.Matchers.containsString; |
52 | +import static org.junit.Assert.assertEquals; | ||
53 | +import static org.junit.Assert.assertNotNull; | ||
54 | +import static org.junit.Assert.assertTrue; | ||
42 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 55 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
43 | 56 | ||
44 | public abstract class BaseDeviceProfileControllerTest extends AbstractControllerTest { | 57 | public abstract class BaseDeviceProfileControllerTest extends AbstractControllerTest { |
@@ -78,7 +91,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -78,7 +91,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
78 | 91 | ||
79 | @Test | 92 | @Test |
80 | public void testSaveDeviceProfile() throws Exception { | 93 | public void testSaveDeviceProfile() throws Exception { |
81 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 94 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
82 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 95 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
83 | Assert.assertNotNull(savedDeviceProfile); | 96 | Assert.assertNotNull(savedDeviceProfile); |
84 | Assert.assertNotNull(savedDeviceProfile.getId()); | 97 | Assert.assertNotNull(savedDeviceProfile.getId()); |
@@ -96,7 +109,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -96,7 +109,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
96 | 109 | ||
97 | @Test | 110 | @Test |
98 | public void testFindDeviceProfileById() throws Exception { | 111 | public void testFindDeviceProfileById() throws Exception { |
99 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 112 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
100 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 113 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
101 | DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/"+savedDeviceProfile.getId().getId().toString(), DeviceProfile.class); | 114 | DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/"+savedDeviceProfile.getId().getId().toString(), DeviceProfile.class); |
102 | Assert.assertNotNull(foundDeviceProfile); | 115 | Assert.assertNotNull(foundDeviceProfile); |
@@ -105,7 +118,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -105,7 +118,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
105 | 118 | ||
106 | @Test | 119 | @Test |
107 | public void testFindDeviceProfileInfoById() throws Exception { | 120 | public void testFindDeviceProfileInfoById() throws Exception { |
108 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 121 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
109 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 122 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
110 | DeviceProfileInfo foundDeviceProfileInfo = doGet("/api/deviceProfileInfo/"+savedDeviceProfile.getId().getId().toString(), DeviceProfileInfo.class); | 123 | DeviceProfileInfo foundDeviceProfileInfo = doGet("/api/deviceProfileInfo/"+savedDeviceProfile.getId().getId().toString(), DeviceProfileInfo.class); |
111 | Assert.assertNotNull(foundDeviceProfileInfo); | 124 | Assert.assertNotNull(foundDeviceProfileInfo); |
@@ -127,7 +140,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -127,7 +140,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
127 | 140 | ||
128 | @Test | 141 | @Test |
129 | public void testSetDefaultDeviceProfile() throws Exception { | 142 | public void testSetDefaultDeviceProfile() throws Exception { |
130 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile 1"); | 143 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile 1", null); |
131 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 144 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
132 | DeviceProfile defaultDeviceProfile = doPost("/api/deviceProfile/"+savedDeviceProfile.getId().getId().toString()+"/default", null, DeviceProfile.class); | 145 | DeviceProfile defaultDeviceProfile = doPost("/api/deviceProfile/"+savedDeviceProfile.getId().getId().toString()+"/default", null, DeviceProfile.class); |
133 | Assert.assertNotNull(defaultDeviceProfile); | 146 | Assert.assertNotNull(defaultDeviceProfile); |
@@ -147,19 +160,19 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -147,19 +160,19 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
147 | 160 | ||
148 | @Test | 161 | @Test |
149 | public void testSaveDeviceProfileWithSameName() throws Exception { | 162 | public void testSaveDeviceProfileWithSameName() throws Exception { |
150 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 163 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
151 | doPost("/api/deviceProfile", deviceProfile).andExpect(status().isOk()); | 164 | doPost("/api/deviceProfile", deviceProfile).andExpect(status().isOk()); |
152 | - DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile"); | 165 | + DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile", null); |
153 | doPost("/api/deviceProfile", deviceProfile2).andExpect(status().isBadRequest()) | 166 | doPost("/api/deviceProfile", deviceProfile2).andExpect(status().isBadRequest()) |
154 | .andExpect(statusReason(containsString("Device profile with such name already exists"))); | 167 | .andExpect(statusReason(containsString("Device profile with such name already exists"))); |
155 | } | 168 | } |
156 | 169 | ||
157 | @Test | 170 | @Test |
158 | public void testSaveDeviceProfileWithSameProvisionDeviceKey() throws Exception { | 171 | public void testSaveDeviceProfileWithSameProvisionDeviceKey() throws Exception { |
159 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 172 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
160 | deviceProfile.setProvisionDeviceKey("testProvisionDeviceKey"); | 173 | deviceProfile.setProvisionDeviceKey("testProvisionDeviceKey"); |
161 | doPost("/api/deviceProfile", deviceProfile).andExpect(status().isOk()); | 174 | doPost("/api/deviceProfile", deviceProfile).andExpect(status().isOk()); |
162 | - DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile 2"); | 175 | + DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile 2", null); |
163 | deviceProfile2.setProvisionDeviceKey("testProvisionDeviceKey"); | 176 | deviceProfile2.setProvisionDeviceKey("testProvisionDeviceKey"); |
164 | doPost("/api/deviceProfile", deviceProfile2).andExpect(status().isBadRequest()) | 177 | doPost("/api/deviceProfile", deviceProfile2).andExpect(status().isBadRequest()) |
165 | .andExpect(statusReason(containsString("Device profile with such provision device key already exists"))); | 178 | .andExpect(statusReason(containsString("Device profile with such provision device key already exists"))); |
@@ -168,7 +181,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -168,7 +181,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
168 | @Ignore | 181 | @Ignore |
169 | @Test | 182 | @Test |
170 | public void testChangeDeviceProfileTypeWithExistingDevices() throws Exception { | 183 | public void testChangeDeviceProfileTypeWithExistingDevices() throws Exception { |
171 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 184 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
172 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 185 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
173 | Device device = new Device(); | 186 | Device device = new Device(); |
174 | device.setName("Test device"); | 187 | device.setName("Test device"); |
@@ -183,7 +196,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -183,7 +196,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
183 | 196 | ||
184 | @Test | 197 | @Test |
185 | public void testChangeDeviceProfileTransportTypeWithExistingDevices() throws Exception { | 198 | public void testChangeDeviceProfileTransportTypeWithExistingDevices() throws Exception { |
186 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 199 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
187 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 200 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
188 | Device device = new Device(); | 201 | Device device = new Device(); |
189 | device.setName("Test device"); | 202 | device.setName("Test device"); |
@@ -197,7 +210,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -197,7 +210,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
197 | 210 | ||
198 | @Test | 211 | @Test |
199 | public void testDeleteDeviceProfileWithExistingDevice() throws Exception { | 212 | public void testDeleteDeviceProfileWithExistingDevice() throws Exception { |
200 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 213 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
201 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 214 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
202 | 215 | ||
203 | Device device = new Device(); | 216 | Device device = new Device(); |
@@ -214,7 +227,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -214,7 +227,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
214 | 227 | ||
215 | @Test | 228 | @Test |
216 | public void testDeleteDeviceProfile() throws Exception { | 229 | public void testDeleteDeviceProfile() throws Exception { |
217 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"); | 230 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); |
218 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | 231 | DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); |
219 | 232 | ||
220 | doDelete("/api/deviceProfile/" + savedDeviceProfile.getId().getId().toString()) | 233 | doDelete("/api/deviceProfile/" + savedDeviceProfile.getId().getId().toString()) |
@@ -235,7 +248,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -235,7 +248,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
235 | deviceProfiles.addAll(pageData.getData()); | 248 | deviceProfiles.addAll(pageData.getData()); |
236 | 249 | ||
237 | for (int i=0;i<28;i++) { | 250 | for (int i=0;i<28;i++) { |
238 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i); | 251 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i, null); |
239 | deviceProfiles.add(doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class)); | 252 | deviceProfiles.add(doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class)); |
240 | } | 253 | } |
241 | 254 | ||
@@ -280,7 +293,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -280,7 +293,7 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
280 | deviceProfiles.addAll(deviceProfilePageData.getData()); | 293 | deviceProfiles.addAll(deviceProfilePageData.getData()); |
281 | 294 | ||
282 | for (int i=0;i<28;i++) { | 295 | for (int i=0;i<28;i++) { |
283 | - DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i); | 296 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i, null); |
284 | deviceProfiles.add(doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class)); | 297 | deviceProfiles.add(doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class)); |
285 | } | 298 | } |
286 | 299 | ||
@@ -318,4 +331,341 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -318,4 +331,341 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
318 | Assert.assertEquals(1, pageData.getTotalElements()); | 331 | Assert.assertEquals(1, pageData.getTotalElements()); |
319 | } | 332 | } |
320 | 333 | ||
334 | + @Test | ||
335 | + public void testSaveProtoDeviceProfileWithInvalidProtoFile() throws Exception { | ||
336 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
337 | + "\n" + | ||
338 | + "package schemavalidation;\n" + | ||
339 | + "\n" + | ||
340 | + "message SchemaValidationTest {\n" + | ||
341 | + " required int32 parameter = 1;\n" + | ||
342 | + "}", "[Transport Configuration] failed to parse attributes proto schema due to: Syntax error in :6:4: 'required' label forbidden in proto3 field declarations"); | ||
343 | + } | ||
344 | + | ||
345 | + @Test | ||
346 | + public void testSaveProtoDeviceProfileWithInvalidProtoSyntax() throws Exception { | ||
347 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto2\";\n" + | ||
348 | + "\n" + | ||
349 | + "package schemavalidation;\n" + | ||
350 | + "\n" + | ||
351 | + "message SchemaValidationTest {\n" + | ||
352 | + " required int32 parameter = 1;\n" + | ||
353 | + "}", "[Transport Configuration] invalid schema syntax: proto2 for attributes proto schema provided! Only proto3 allowed!"); | ||
354 | + } | ||
355 | + | ||
356 | + @Test | ||
357 | + public void testSaveProtoDeviceProfileOptionsNotSupported() throws Exception { | ||
358 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
359 | + "\n" + | ||
360 | + "option java_package = \"com.test.schemavalidation\";\n" + | ||
361 | + "option java_multiple_files = true;\n" + | ||
362 | + "\n" + | ||
363 | + "package schemavalidation;\n" + | ||
364 | + "\n" + | ||
365 | + "message SchemaValidationTest {\n" + | ||
366 | + " int32 parameter = 1;\n" + | ||
367 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Schema options don't support!"); | ||
368 | + } | ||
369 | + | ||
370 | + @Test | ||
371 | + public void testSaveProtoDeviceProfilePublicImportsNotSupported() throws Exception { | ||
372 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
373 | + "\n" + | ||
374 | + "import public \"oldschema.proto\";\n" + | ||
375 | + "\n" + | ||
376 | + "package schemavalidation;\n" + | ||
377 | + "\n" + | ||
378 | + "message SchemaValidationTest {\n" + | ||
379 | + " int32 parameter = 1;\n" + | ||
380 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Schema public imports don't support!"); | ||
381 | + } | ||
382 | + | ||
383 | + @Test | ||
384 | + public void testSaveProtoDeviceProfileImportsNotSupported() throws Exception { | ||
385 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
386 | + "\n" + | ||
387 | + "import \"oldschema.proto\";\n" + | ||
388 | + "\n" + | ||
389 | + "package schemavalidation;\n" + | ||
390 | + "\n" + | ||
391 | + "message SchemaValidationTest {\n" + | ||
392 | + " int32 parameter = 1;\n" + | ||
393 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Schema imports don't support!"); | ||
394 | + } | ||
395 | + | ||
396 | + @Test | ||
397 | + public void testSaveProtoDeviceProfileExtendDeclarationsNotSupported() throws Exception { | ||
398 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
399 | + "\n" + | ||
400 | + "package schemavalidation;\n" + | ||
401 | + "\n" + | ||
402 | + "extend google.protobuf.MethodOptions {\n" + | ||
403 | + " MyMessage my_method_option = 50007;\n" + | ||
404 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Schema extend declarations don't support!"); | ||
405 | + } | ||
406 | + | ||
407 | + @Test | ||
408 | + public void testSaveProtoDeviceProfileEnumOptionsNotSupported() throws Exception { | ||
409 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
410 | + "\n" + | ||
411 | + "package schemavalidation;\n" + | ||
412 | + "\n" + | ||
413 | + "enum testEnum {\n" + | ||
414 | + " option allow_alias = true;\n" + | ||
415 | + " DEFAULT = 0;\n" + | ||
416 | + " STARTED = 1;\n" + | ||
417 | + " RUNNING = 2;\n" + | ||
418 | + "}\n" + | ||
419 | + "\n" + | ||
420 | + "message testMessage {\n" + | ||
421 | + " int32 parameter = 1;\n" + | ||
422 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Enum definitions options are not supported!"); | ||
423 | + } | ||
424 | + | ||
425 | + @Test | ||
426 | + public void testSaveProtoDeviceProfileNoOneMessageTypeExists() throws Exception { | ||
427 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
428 | + "\n" + | ||
429 | + "package schemavalidation;\n" + | ||
430 | + "\n" + | ||
431 | + "enum testEnum {\n" + | ||
432 | + " DEFAULT = 0;\n" + | ||
433 | + " STARTED = 1;\n" + | ||
434 | + " RUNNING = 2;\n" + | ||
435 | + "}", "[Transport Configuration] invalid attributes proto schema provided! At least one Message definition should exists!"); | ||
436 | + } | ||
437 | + | ||
438 | + @Test | ||
439 | + public void testSaveProtoDeviceProfileMessageTypeOptionsNotSupported() throws Exception { | ||
440 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
441 | + "\n" + | ||
442 | + "package schemavalidation;\n" + | ||
443 | + "\n" + | ||
444 | + "message testMessage {\n" + | ||
445 | + " option allow_alias = true;\n" + | ||
446 | + " int32 parameter = 1;\n" + | ||
447 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Message definition options don't support!"); | ||
448 | + } | ||
449 | + | ||
450 | + @Test | ||
451 | + public void testSaveProtoDeviceProfileMessageTypeExtensionsNotSupported() throws Exception { | ||
452 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
453 | + "\n" + | ||
454 | + "package schemavalidation;\n" + | ||
455 | + "\n" + | ||
456 | + "message TestMessage {\n" + | ||
457 | + " extensions 100 to 199;\n" + | ||
458 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Message definition extensions don't support!"); | ||
459 | + } | ||
460 | + | ||
461 | + @Test | ||
462 | + public void testSaveProtoDeviceProfileMessageTypeReservedElementsNotSupported() throws Exception { | ||
463 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
464 | + "\n" + | ||
465 | + "package schemavalidation;\n" + | ||
466 | + "\n" + | ||
467 | + "message Foo {\n" + | ||
468 | + " reserved 2, 15, 9 to 11;\n" + | ||
469 | + " reserved \"foo\", \"bar\";\n" + | ||
470 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Message definition reserved elements don't support!"); | ||
471 | + } | ||
472 | + | ||
473 | + @Test | ||
474 | + public void testSaveProtoDeviceProfileMessageTypeGroupsElementsNotSupported() throws Exception { | ||
475 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
476 | + "\n" + | ||
477 | + "package schemavalidation;\n" + | ||
478 | + "\n" + | ||
479 | + "message TestMessage {\n" + | ||
480 | + " repeated group Result = 1 {\n" + | ||
481 | + " string url = 2;\n" + | ||
482 | + " string title = 3;\n" + | ||
483 | + " repeated string snippets = 4;\n" + | ||
484 | + " }\n" + | ||
485 | + "}", "[Transport Configuration] invalid attributes proto schema provided! Message definition groups don't support!"); | ||
486 | + } | ||
487 | + | ||
488 | + @Test | ||
489 | + public void testSaveProtoDeviceProfileOneOfsGroupsElementsNotSupported() throws Exception { | ||
490 | + testSaveDeviceProfileWithInvalidProtoSchema("syntax = \"proto3\";\n" + | ||
491 | + "\n" + | ||
492 | + "package schemavalidation;\n" + | ||
493 | + "\n" + | ||
494 | + "message SampleMessage {\n" + | ||
495 | + " oneof test_oneof {\n" + | ||
496 | + " string name = 1;\n" + | ||
497 | + " group Result = 2 {\n" + | ||
498 | + " \tstring url = 3;\n" + | ||
499 | + " \tstring title = 4;\n" + | ||
500 | + " \trepeated string snippets = 5;\n" + | ||
501 | + " }\n" + | ||
502 | + " }" + | ||
503 | + "}", "[Transport Configuration] invalid attributes proto schema provided! OneOf definition groups don't support!"); | ||
504 | + } | ||
505 | + | ||
506 | + @Test | ||
507 | + public void testSaveProtoDeviceProfileWithMessageNestedTypes() throws Exception { | ||
508 | + String schema = "syntax = \"proto3\";\n" + | ||
509 | + "\n" + | ||
510 | + "package testnested;\n" + | ||
511 | + "\n" + | ||
512 | + "message Outer {\n" + | ||
513 | + " message MiddleAA {\n" + | ||
514 | + " message Inner {\n" + | ||
515 | + " int64 ival = 1;\n" + | ||
516 | + " bool booly = 2;\n" + | ||
517 | + " }\n" + | ||
518 | + " Inner inner = 1;\n" + | ||
519 | + " }\n" + | ||
520 | + " message MiddleBB {\n" + | ||
521 | + " message Inner {\n" + | ||
522 | + " int32 ival = 1;\n" + | ||
523 | + " bool booly = 2;\n" + | ||
524 | + " }\n" + | ||
525 | + " Inner inner = 1;\n" + | ||
526 | + " }\n" + | ||
527 | + " MiddleAA middleAA = 1;\n" + | ||
528 | + " MiddleBB middleBB = 2;\n" + | ||
529 | + "}"; | ||
530 | + DynamicSchema dynamicSchema = getDynamicSchema(schema); | ||
531 | + assertNotNull(dynamicSchema); | ||
532 | + Set<String> messageTypes = dynamicSchema.getMessageTypes(); | ||
533 | + assertEquals(5, messageTypes.size()); | ||
534 | + assertTrue(messageTypes.contains("testnested.Outer")); | ||
535 | + assertTrue(messageTypes.contains("testnested.Outer.MiddleAA")); | ||
536 | + assertTrue(messageTypes.contains("testnested.Outer.MiddleAA.Inner")); | ||
537 | + assertTrue(messageTypes.contains("testnested.Outer.MiddleBB")); | ||
538 | + assertTrue(messageTypes.contains("testnested.Outer.MiddleBB.Inner")); | ||
539 | + | ||
540 | + DynamicMessage.Builder middleAAInnerMsgBuilder = dynamicSchema.newMessageBuilder("testnested.Outer.MiddleAA.Inner"); | ||
541 | + Descriptors.Descriptor middleAAInnerMsgDescriptor = middleAAInnerMsgBuilder.getDescriptorForType(); | ||
542 | + DynamicMessage middleAAInnerMsg = middleAAInnerMsgBuilder | ||
543 | + .setField(middleAAInnerMsgDescriptor.findFieldByName("ival"), 1L) | ||
544 | + .setField(middleAAInnerMsgDescriptor.findFieldByName("booly"), true) | ||
545 | + .build(); | ||
546 | + | ||
547 | + DynamicMessage.Builder middleAAMsgBuilder = dynamicSchema.newMessageBuilder("testnested.Outer.MiddleAA"); | ||
548 | + Descriptors.Descriptor middleAAMsgDescriptor = middleAAMsgBuilder.getDescriptorForType(); | ||
549 | + DynamicMessage middleAAMsg = middleAAMsgBuilder | ||
550 | + .setField(middleAAMsgDescriptor.findFieldByName("inner"), middleAAInnerMsg) | ||
551 | + .build(); | ||
552 | + | ||
553 | + DynamicMessage.Builder middleBBInnerMsgBuilder = dynamicSchema.newMessageBuilder("testnested.Outer.MiddleAA.Inner"); | ||
554 | + Descriptors.Descriptor middleBBInnerMsgDescriptor = middleBBInnerMsgBuilder.getDescriptorForType(); | ||
555 | + DynamicMessage middleBBInnerMsg = middleBBInnerMsgBuilder | ||
556 | + .setField(middleBBInnerMsgDescriptor.findFieldByName("ival"), 0L) | ||
557 | + .setField(middleBBInnerMsgDescriptor.findFieldByName("booly"), false) | ||
558 | + .build(); | ||
559 | + | ||
560 | + DynamicMessage.Builder middleBBMsgBuilder = dynamicSchema.newMessageBuilder("testnested.Outer.MiddleBB"); | ||
561 | + Descriptors.Descriptor middleBBMsgDescriptor = middleBBMsgBuilder.getDescriptorForType(); | ||
562 | + DynamicMessage middleBBMsg = middleBBMsgBuilder | ||
563 | + .setField(middleBBMsgDescriptor.findFieldByName("inner"), middleBBInnerMsg) | ||
564 | + .build(); | ||
565 | + | ||
566 | + | ||
567 | + DynamicMessage.Builder outerMsgBuilder = dynamicSchema.newMessageBuilder("testnested.Outer"); | ||
568 | + Descriptors.Descriptor outerMsgBuilderDescriptor = outerMsgBuilder.getDescriptorForType(); | ||
569 | + DynamicMessage outerMsg = outerMsgBuilder | ||
570 | + .setField(outerMsgBuilderDescriptor.findFieldByName("middleAA"), middleAAMsg) | ||
571 | + .setField(outerMsgBuilderDescriptor.findFieldByName("middleBB"), middleBBMsg) | ||
572 | + .build(); | ||
573 | + | ||
574 | + assertEquals("{\n" + | ||
575 | + " \"middleAA\": {\n" + | ||
576 | + " \"inner\": {\n" + | ||
577 | + " \"ival\": \"1\",\n" + | ||
578 | + " \"booly\": true\n" + | ||
579 | + " }\n" + | ||
580 | + " },\n" + | ||
581 | + " \"middleBB\": {\n" + | ||
582 | + " \"inner\": {\n" + | ||
583 | + " \"ival\": 0,\n" + | ||
584 | + " \"booly\": false\n" + | ||
585 | + " }\n" + | ||
586 | + " }\n" + | ||
587 | + "}", dynamicMsgToJson(outerMsgBuilderDescriptor, outerMsg.toByteArray())); | ||
588 | + } | ||
589 | + | ||
590 | + @Test | ||
591 | + public void testSaveProtoDeviceProfileWithMessageOneOfs() throws Exception { | ||
592 | + String schema = "syntax = \"proto3\";\n" + | ||
593 | + "\n" + | ||
594 | + "package testoneofs;\n" + | ||
595 | + "\n" + | ||
596 | + "message SubMessage {\n" + | ||
597 | + " repeated string name = 1;\n" + | ||
598 | + "}\n" + | ||
599 | + "\n" + | ||
600 | + "message SampleMessage {\n" + | ||
601 | + " oneof testOneOf {\n" + | ||
602 | + " string name = 4;\n" + | ||
603 | + " SubMessage subMessage = 9;\n" + | ||
604 | + " }\n" + | ||
605 | + "}"; | ||
606 | + DynamicSchema dynamicSchema = getDynamicSchema(schema); | ||
607 | + assertNotNull(dynamicSchema); | ||
608 | + Set<String> messageTypes = dynamicSchema.getMessageTypes(); | ||
609 | + assertEquals(2, messageTypes.size()); | ||
610 | + assertTrue(messageTypes.contains("testoneofs.SubMessage")); | ||
611 | + assertTrue(messageTypes.contains("testoneofs.SampleMessage")); | ||
612 | + | ||
613 | + DynamicMessage.Builder sampleMsgBuilder = dynamicSchema.newMessageBuilder("testoneofs.SampleMessage"); | ||
614 | + Descriptors.Descriptor sampleMsgDescriptor = sampleMsgBuilder.getDescriptorForType(); | ||
615 | + assertNotNull(sampleMsgDescriptor); | ||
616 | + | ||
617 | + List<Descriptors.FieldDescriptor> fields = sampleMsgDescriptor.getFields(); | ||
618 | + assertEquals(2, fields.size()); | ||
619 | + DynamicMessage sampleMsg = sampleMsgBuilder | ||
620 | + .setField(sampleMsgDescriptor.findFieldByName("name"), "Bob") | ||
621 | + .build(); | ||
622 | + assertEquals("{\n" + " \"name\": \"Bob\"\n" + "}", dynamicMsgToJson(sampleMsgDescriptor, sampleMsg.toByteArray())); | ||
623 | + | ||
624 | + DynamicMessage.Builder subMsgBuilder = dynamicSchema.newMessageBuilder("testoneofs.SubMessage"); | ||
625 | + Descriptors.Descriptor subMsgDescriptor = subMsgBuilder.getDescriptorForType(); | ||
626 | + DynamicMessage subMsg = subMsgBuilder | ||
627 | + .addRepeatedField(subMsgDescriptor.findFieldByName("name"), "Alice") | ||
628 | + .addRepeatedField(subMsgDescriptor.findFieldByName("name"), "John") | ||
629 | + .build(); | ||
630 | + | ||
631 | + DynamicMessage sampleMsgWithOneOfSubMessage = sampleMsgBuilder.setField(sampleMsgDescriptor.findFieldByName("subMessage"), subMsg).build(); | ||
632 | + assertEquals("{\n" + " \"subMessage\": {\n" + " \"name\": [\"Alice\", \"John\"]\n" + " }\n" + "}", | ||
633 | + dynamicMsgToJson(sampleMsgDescriptor, sampleMsgWithOneOfSubMessage.toByteArray())); | ||
634 | + } | ||
635 | + | ||
636 | + private DeviceProfile testSaveDeviceProfileWithProtoPayloadType(String schema) throws Exception { | ||
637 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = this.createProtoTransportPayloadConfiguration(schema, schema); | ||
638 | + MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = this.createMqttDeviceProfileTransportConfiguration(protoTransportPayloadConfiguration); | ||
639 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", mqttDeviceProfileTransportConfiguration); | ||
640 | + DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | ||
641 | + DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/"+savedDeviceProfile.getId().getId().toString(), DeviceProfile.class); | ||
642 | + Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfile.getName()); | ||
643 | + return savedDeviceProfile; | ||
644 | + } | ||
645 | + | ||
646 | + private void testSaveDeviceProfileWithInvalidProtoSchema(String schema, String errorMsg) throws Exception { | ||
647 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = this.createProtoTransportPayloadConfiguration(schema, schema); | ||
648 | + MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = this.createMqttDeviceProfileTransportConfiguration(protoTransportPayloadConfiguration); | ||
649 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", mqttDeviceProfileTransportConfiguration); | ||
650 | + doPost("/api/deviceProfile", deviceProfile).andExpect(status().isBadRequest()) | ||
651 | + .andExpect(statusReason(containsString(errorMsg))); | ||
652 | + } | ||
653 | + | ||
654 | + private DynamicSchema getDynamicSchema(String schema) throws Exception { | ||
655 | + DeviceProfile deviceProfile = testSaveDeviceProfileWithProtoPayloadType(schema); | ||
656 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | ||
657 | + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); | ||
658 | + MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | ||
659 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttDeviceProfileTransportConfiguration.getTransportPayloadTypeConfiguration(); | ||
660 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | ||
661 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
662 | + ProtoFileElement protoFile = protoTransportPayloadConfiguration.getTransportProtoSchema(schema); | ||
663 | + return protoTransportPayloadConfiguration.getDynamicSchema(protoFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); | ||
664 | + } | ||
665 | + | ||
666 | + private String dynamicMsgToJson(Descriptors.Descriptor descriptor, byte[] payload) throws InvalidProtocolBufferException { | ||
667 | + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(descriptor, payload); | ||
668 | + return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage); | ||
669 | + } | ||
670 | + | ||
321 | } | 671 | } |
@@ -38,7 +38,10 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileCon | @@ -38,7 +38,10 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileCon | ||
38 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | 38 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
39 | import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; | 39 | import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; |
40 | import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; | 40 | import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; |
41 | +import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; | ||
41 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | 42 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; |
43 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
44 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
42 | import org.thingsboard.server.common.data.security.Authority; | 45 | import org.thingsboard.server.common.data.security.Authority; |
43 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 46 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
44 | import org.thingsboard.server.controller.AbstractControllerTest; | 47 | import org.thingsboard.server.controller.AbstractControllerTest; |
@@ -47,7 +50,6 @@ import org.thingsboard.server.gen.transport.TransportProtos; | @@ -47,7 +50,6 @@ import org.thingsboard.server.gen.transport.TransportProtos; | ||
47 | import java.util.ArrayList; | 50 | import java.util.ArrayList; |
48 | import java.util.List; | 51 | import java.util.List; |
49 | import java.util.concurrent.atomic.AtomicInteger; | 52 | import java.util.concurrent.atomic.AtomicInteger; |
50 | -import java.util.function.Supplier; | ||
51 | 53 | ||
52 | import static org.junit.Assert.assertEquals; | 54 | import static org.junit.Assert.assertEquals; |
53 | import static org.junit.Assert.assertNotNull; | 55 | import static org.junit.Assert.assertNotNull; |
@@ -60,6 +62,48 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -60,6 +62,48 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
60 | 62 | ||
61 | private static final AtomicInteger atomicInteger = new AtomicInteger(2); | 63 | private static final AtomicInteger atomicInteger = new AtomicInteger(2); |
62 | 64 | ||
65 | + public static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | ||
66 | + "\n" + | ||
67 | + "package test;\n" + | ||
68 | + "\n" + | ||
69 | + "message PostTelemetry {\n" + | ||
70 | + " string key1 = 1;\n" + | ||
71 | + " bool key2 = 2;\n" + | ||
72 | + " double key3 = 3;\n" + | ||
73 | + " int32 key4 = 4;\n" + | ||
74 | + " JsonObject key5 = 5;\n" + | ||
75 | + "\n" + | ||
76 | + " message JsonObject {\n" + | ||
77 | + " int32 someNumber = 6;\n" + | ||
78 | + " repeated int32 someArray = 7;\n" + | ||
79 | + " NestedJsonObject someNestedObject = 8;\n" + | ||
80 | + " message NestedJsonObject {\n" + | ||
81 | + " string key = 9;\n" + | ||
82 | + " }\n" + | ||
83 | + " }\n" + | ||
84 | + "}"; | ||
85 | + | ||
86 | + public static final String DEVICE_ATTRIBUTES_PROTO_SCHEMA = "syntax =\"proto3\";\n" + | ||
87 | + "\n" + | ||
88 | + "package test;\n" + | ||
89 | + "\n" + | ||
90 | + "message PostAttributes {\n" + | ||
91 | + " string key1 = 1;\n" + | ||
92 | + " bool key2 = 2;\n" + | ||
93 | + " double key3 = 3;\n" + | ||
94 | + " int32 key4 = 4;\n" + | ||
95 | + " JsonObject key5 = 5;\n" + | ||
96 | + "\n" + | ||
97 | + " message JsonObject {\n" + | ||
98 | + " int32 someNumber = 6;\n" + | ||
99 | + " repeated int32 someArray = 7;\n" + | ||
100 | + " NestedJsonObject someNestedObject = 8;\n" + | ||
101 | + " message NestedJsonObject {\n" + | ||
102 | + " string key = 9;\n" + | ||
103 | + " }\n" + | ||
104 | + " }\n" + | ||
105 | + "}"; | ||
106 | + | ||
63 | protected Tenant savedTenant; | 107 | protected Tenant savedTenant; |
64 | protected User tenantAdmin; | 108 | protected User tenantAdmin; |
65 | 109 | ||
@@ -69,8 +113,10 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -69,8 +113,10 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
69 | protected Device savedGateway; | 113 | protected Device savedGateway; |
70 | protected String gatewayAccessToken; | 114 | protected String gatewayAccessToken; |
71 | 115 | ||
116 | + protected DeviceProfile deviceProfile; | ||
117 | + | ||
72 | protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { | 118 | protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { |
73 | - this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, DeviceProfileProvisionType.DISABLED, null, null); | 119 | + this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, DeviceProfileProvisionType.DISABLED, null, null); |
74 | } | 120 | } |
75 | 121 | ||
76 | protected void processBeforeTest(String deviceName, | 122 | protected void processBeforeTest(String deviceName, |
@@ -78,6 +124,8 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -78,6 +124,8 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
78 | TransportPayloadType payloadType, | 124 | TransportPayloadType payloadType, |
79 | String telemetryTopic, | 125 | String telemetryTopic, |
80 | String attributesTopic, | 126 | String attributesTopic, |
127 | + String telemetryProtoSchema, | ||
128 | + String attributesProtoSchema, | ||
81 | DeviceProfileProvisionType provisionType, | 129 | DeviceProfileProvisionType provisionType, |
82 | String provisionKey, String provisionSecret | 130 | String provisionKey, String provisionSecret |
83 | ) throws Exception { | 131 | ) throws Exception { |
@@ -109,12 +157,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -109,12 +157,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
109 | gateway.setAdditionalInfo(additionalInfo); | 157 | gateway.setAdditionalInfo(additionalInfo); |
110 | 158 | ||
111 | if (payloadType != null) { | 159 | if (payloadType != null) { |
112 | - DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, provisionType, provisionKey, provisionSecret); | ||
113 | - DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); | ||
114 | - device.setType(savedDeviceProfile.getName()); | ||
115 | - device.setDeviceProfileId(savedDeviceProfile.getId()); | ||
116 | - gateway.setType(savedDeviceProfile.getName()); | ||
117 | - gateway.setDeviceProfileId(savedDeviceProfile.getId()); | 160 | + DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, provisionType, provisionKey, provisionSecret); |
161 | + deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); | ||
162 | + device.setType(deviceProfile.getName()); | ||
163 | + device.setDeviceProfileId(deviceProfile.getId()); | ||
164 | + gateway.setType(deviceProfile.getName()); | ||
165 | + gateway.setDeviceProfileId(deviceProfile.getId()); | ||
118 | } | 166 | } |
119 | 167 | ||
120 | savedDevice = doPost("/api/device", device, Device.class); | 168 | savedDevice = doPost("/api/device", device, Device.class); |
@@ -201,9 +249,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -201,9 +249,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
201 | 249 | ||
202 | protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, | 250 | protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, |
203 | String telemetryTopic, String attributesTopic, | 251 | String telemetryTopic, String attributesTopic, |
252 | + String telemetryProtoSchema, String attributesProtoSchema, | ||
204 | DeviceProfileProvisionType provisionType, | 253 | DeviceProfileProvisionType provisionType, |
205 | - String provisionKey, String provisionSecret | ||
206 | - ) { | 254 | + String provisionKey, String provisionSecret) { |
207 | DeviceProfile deviceProfile = new DeviceProfile(); | 255 | DeviceProfile deviceProfile = new DeviceProfile(); |
208 | deviceProfile.setName(transportPayloadType.name()); | 256 | deviceProfile.setName(transportPayloadType.name()); |
209 | deviceProfile.setType(DeviceProfileType.DEFAULT); | 257 | deviceProfile.setType(DeviceProfileType.DEFAULT); |
@@ -213,15 +261,30 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -213,15 +261,30 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
213 | deviceProfile.setDescription(transportPayloadType.name() + " Test"); | 261 | deviceProfile.setDescription(transportPayloadType.name() + " Test"); |
214 | DeviceProfileData deviceProfileData = new DeviceProfileData(); | 262 | DeviceProfileData deviceProfileData = new DeviceProfileData(); |
215 | DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); | 263 | DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); |
216 | - MqttDeviceProfileTransportConfiguration transportConfiguration = new MqttDeviceProfileTransportConfiguration(); | ||
217 | - transportConfiguration.setTransportPayloadType(transportPayloadType); | 264 | + MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration(); |
218 | if (!StringUtils.isEmpty(telemetryTopic)) { | 265 | if (!StringUtils.isEmpty(telemetryTopic)) { |
219 | - transportConfiguration.setDeviceTelemetryTopic(telemetryTopic); | 266 | + mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(telemetryTopic); |
220 | } | 267 | } |
221 | if (!StringUtils.isEmpty(attributesTopic)) { | 268 | if (!StringUtils.isEmpty(attributesTopic)) { |
222 | - transportConfiguration.setDeviceAttributesTopic(attributesTopic); | 269 | + mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(attributesTopic); |
223 | } | 270 | } |
224 | - deviceProfileData.setTransportConfiguration(transportConfiguration); | 271 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; |
272 | + if (TransportPayloadType.JSON.equals(transportPayloadType)) { | ||
273 | + transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); | ||
274 | + } else { | ||
275 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = new ProtoTransportPayloadConfiguration(); | ||
276 | + if (StringUtils.isEmpty(telemetryProtoSchema)) { | ||
277 | + telemetryProtoSchema = DEVICE_TELEMETRY_PROTO_SCHEMA; | ||
278 | + } | ||
279 | + if (StringUtils.isEmpty(attributesProtoSchema)) { | ||
280 | + attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; | ||
281 | + } | ||
282 | + protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); | ||
283 | + protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); | ||
284 | + transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; | ||
285 | + } | ||
286 | + mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); | ||
287 | + deviceProfileData.setTransportConfiguration(mqttDeviceProfileTransportConfiguration); | ||
225 | DeviceProfileProvisionConfiguration provisionConfiguration; | 288 | DeviceProfileProvisionConfiguration provisionConfiguration; |
226 | switch (provisionType) { | 289 | switch (provisionType) { |
227 | case ALLOW_CREATE_NEW_DEVICES: | 290 | case ALLOW_CREATE_NEW_DEVICES: |
@@ -233,6 +296,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | @@ -233,6 +296,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest | ||
233 | case DISABLED: | 296 | case DISABLED: |
234 | default: | 297 | default: |
235 | provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(provisionSecret); | 298 | provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(provisionSecret); |
299 | + break; | ||
236 | } | 300 | } |
237 | deviceProfileData.setProvisionConfiguration(provisionConfiguration); | 301 | deviceProfileData.setProvisionConfiguration(provisionConfiguration); |
238 | deviceProfileData.setConfiguration(configuration); | 302 | deviceProfileData.setConfiguration(configuration); |
@@ -56,7 +56,6 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt | @@ -56,7 +56,6 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt | ||
56 | return tsKvProtoList; | 56 | return tsKvProtoList; |
57 | } | 57 | } |
58 | 58 | ||
59 | - | ||
60 | protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) { | 59 | protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) { |
61 | TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder(); | 60 | TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder(); |
62 | TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType); | 61 | TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType); |
@@ -18,9 +18,7 @@ package org.thingsboard.server.mqtt.attributes.request; | @@ -18,9 +18,7 @@ package org.thingsboard.server.mqtt.attributes.request; | ||
18 | import com.google.protobuf.InvalidProtocolBufferException; | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | import io.netty.handler.codec.mqtt.MqttQoS; | 19 | import io.netty.handler.codec.mqtt.MqttQoS; |
20 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
21 | -import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; | ||
22 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 21 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
23 | -import org.eclipse.paho.client.mqttv3.MqttCallback; | ||
24 | import org.eclipse.paho.client.mqttv3.MqttException; | 22 | import org.eclipse.paho.client.mqttv3.MqttException; |
25 | import org.eclipse.paho.client.mqttv3.MqttMessage; | 23 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
26 | import org.junit.After; | 24 | import org.junit.After; |
@@ -36,9 +34,7 @@ import java.util.concurrent.CountDownLatch; | @@ -36,9 +34,7 @@ import java.util.concurrent.CountDownLatch; | ||
36 | import java.util.concurrent.TimeUnit; | 34 | import java.util.concurrent.TimeUnit; |
37 | 35 | ||
38 | import static org.junit.Assert.assertEquals; | 36 | import static org.junit.Assert.assertEquals; |
39 | -import static org.junit.Assert.assertFalse; | ||
40 | import static org.junit.Assert.assertNotNull; | 37 | import static org.junit.Assert.assertNotNull; |
41 | -import static org.junit.Assert.assertTrue; | ||
42 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 38 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
43 | 39 | ||
44 | @Slf4j | 40 | @Slf4j |
@@ -18,14 +18,9 @@ package org.thingsboard.server.mqtt.attributes.request; | @@ -18,14 +18,9 @@ package org.thingsboard.server.mqtt.attributes.request; | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.junit.After; | 19 | import org.junit.After; |
20 | import org.junit.Before; | 20 | import org.junit.Before; |
21 | -import org.junit.Ignore; | ||
22 | import org.junit.Test; | 21 | import org.junit.Test; |
23 | import org.thingsboard.server.common.data.TransportPayloadType; | 22 | import org.thingsboard.server.common.data.TransportPayloadType; |
24 | 23 | ||
25 | -import static org.junit.Assert.assertEquals; | ||
26 | -import static org.junit.Assert.assertNotNull; | ||
27 | -import static org.junit.Assert.assertTrue; | ||
28 | - | ||
29 | @Slf4j | 24 | @Slf4j |
30 | public abstract class AbstractMqttAttributesRequestJsonIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { | 25 | public abstract class AbstractMqttAttributesRequestJsonIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { |
31 | 26 |
@@ -15,18 +15,26 @@ | @@ -15,18 +15,26 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.mqtt.attributes.request; | 16 | package org.thingsboard.server.mqtt.attributes.request; |
17 | 17 | ||
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
19 | +import com.google.protobuf.Descriptors; | ||
20 | +import com.google.protobuf.DynamicMessage; | ||
18 | import com.google.protobuf.InvalidProtocolBufferException; | 21 | import com.google.protobuf.InvalidProtocolBufferException; |
22 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
19 | import io.netty.handler.codec.mqtt.MqttQoS; | 23 | import io.netty.handler.codec.mqtt.MqttQoS; |
20 | import lombok.extern.slf4j.Slf4j; | 24 | import lombok.extern.slf4j.Slf4j; |
21 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 25 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
22 | import org.eclipse.paho.client.mqttv3.MqttException; | 26 | import org.eclipse.paho.client.mqttv3.MqttException; |
23 | import org.eclipse.paho.client.mqttv3.MqttMessage; | 27 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
24 | import org.junit.After; | 28 | import org.junit.After; |
25 | -import org.junit.Before; | ||
26 | import org.junit.Test; | 29 | import org.junit.Test; |
27 | import org.thingsboard.server.common.data.Device; | 30 | import org.thingsboard.server.common.data.Device; |
31 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | ||
28 | import org.thingsboard.server.common.data.TransportPayloadType; | 32 | import org.thingsboard.server.common.data.TransportPayloadType; |
33 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | ||
34 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
35 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
29 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 36 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
37 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
30 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 38 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
31 | import org.thingsboard.server.gen.transport.TransportProtos; | 39 | import org.thingsboard.server.gen.transport.TransportProtos; |
32 | 40 | ||
@@ -38,16 +46,33 @@ import java.util.concurrent.TimeUnit; | @@ -38,16 +46,33 @@ import java.util.concurrent.TimeUnit; | ||
38 | import java.util.stream.Collectors; | 46 | import java.util.stream.Collectors; |
39 | 47 | ||
40 | import static org.junit.Assert.assertEquals; | 48 | import static org.junit.Assert.assertEquals; |
49 | +import static org.junit.Assert.assertNotNull; | ||
41 | import static org.junit.Assert.assertTrue; | 50 | import static org.junit.Assert.assertTrue; |
42 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 51 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
43 | 52 | ||
44 | @Slf4j | 53 | @Slf4j |
45 | public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { | 54 | public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { |
46 | 55 | ||
47 | - @Before | ||
48 | - public void beforeTest() throws Exception { | ||
49 | - processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", TransportPayloadType.PROTOBUF, null, null); | ||
50 | - } | 56 | + public static final String ATTRIBUTES_SCHEMA_STR = "syntax =\"proto3\";\n" + |
57 | + "\n" + | ||
58 | + "package test;\n" + | ||
59 | + "\n" + | ||
60 | + "message PostAttributes {\n" + | ||
61 | + " string attribute1 = 1;\n" + | ||
62 | + " bool attribute2 = 2;\n" + | ||
63 | + " double attribute3 = 3;\n" + | ||
64 | + " int32 attribute4 = 4;\n" + | ||
65 | + " JsonObject attribute5 = 5;\n" + | ||
66 | + "\n" + | ||
67 | + " message JsonObject {\n" + | ||
68 | + " int32 someNumber = 6;\n" + | ||
69 | + " repeated int32 someArray = 7;\n" + | ||
70 | + " NestedJsonObject someNestedObject = 8;\n" + | ||
71 | + " message NestedJsonObject {\n" + | ||
72 | + " string key = 9;\n" + | ||
73 | + " }\n" + | ||
74 | + " }\n" + | ||
75 | + "}"; | ||
51 | 76 | ||
52 | @After | 77 | @After |
53 | public void afterTest() throws Exception { | 78 | public void afterTest() throws Exception { |
@@ -56,21 +81,55 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends | @@ -56,21 +81,55 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends | ||
56 | 81 | ||
57 | @Test | 82 | @Test |
58 | public void testRequestAttributesValuesFromTheServer() throws Exception { | 83 | public void testRequestAttributesValuesFromTheServer() throws Exception { |
84 | + super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", | ||
85 | + TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); | ||
59 | processTestRequestAttributesValuesFromTheServer(); | 86 | processTestRequestAttributesValuesFromTheServer(); |
60 | } | 87 | } |
61 | 88 | ||
62 | - | ||
63 | @Test | 89 | @Test |
64 | public void testRequestAttributesValuesFromTheServerGateway() throws Exception { | 90 | public void testRequestAttributesValuesFromTheServerGateway() throws Exception { |
91 | + super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", TransportPayloadType.PROTOBUF, null, null); | ||
65 | processTestGatewayRequestAttributesValuesFromTheServer(); | 92 | processTestGatewayRequestAttributesValuesFromTheServer(); |
66 | } | 93 | } |
67 | 94 | ||
68 | protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client) throws Exception { | 95 | protected void postAttributesAndSubscribeToTopic(Device savedDevice, MqttAsyncClient client) throws Exception { |
69 | doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); | 96 | doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); |
70 | - String keys = "attribute1,attribute2,attribute3,attribute4,attribute5"; | ||
71 | - List<String> expectedKeys = Arrays.asList(keys.split(",")); | ||
72 | - TransportProtos.PostAttributeMsg postAttributeMsg = getPostAttributeMsg(expectedKeys); | ||
73 | - byte[] payload = postAttributeMsg.toByteArray(); | 97 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
98 | + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); | ||
99 | + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | ||
100 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); | ||
101 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | ||
102 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
103 | + ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(ATTRIBUTES_SCHEMA_STR); | ||
104 | + DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); | ||
105 | + | ||
106 | + DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject"); | ||
107 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | ||
108 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | ||
109 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | ||
110 | + | ||
111 | + DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject"); | ||
112 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | ||
113 | + assertNotNull(jsonObjectBuilderDescriptor); | ||
114 | + DynamicMessage jsonObject = jsonObjectBuilder | ||
115 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | ||
116 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | ||
117 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | ||
118 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | ||
119 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | ||
120 | + .build(); | ||
121 | + | ||
122 | + DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes"); | ||
123 | + Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType(); | ||
124 | + assertNotNull(postAttributesMsgDescriptor); | ||
125 | + DynamicMessage postAttributesMsg = postAttributesBuilder | ||
126 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute1"), "value1") | ||
127 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute2"), true) | ||
128 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute3"), 42.0) | ||
129 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute4"), 73) | ||
130 | + .setField(postAttributesMsgDescriptor.findFieldByName("attribute5"), jsonObject) | ||
131 | + .build(); | ||
132 | + byte[] payload = postAttributesMsg.toByteArray(); | ||
74 | client.publish(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, new MqttMessage(payload)); | 133 | client.publish(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, new MqttMessage(payload)); |
75 | client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC, MqttQoS.AT_MOST_ONCE.value()); | 134 | client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC, MqttQoS.AT_MOST_ONCE.value()); |
76 | } | 135 | } |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.attributes.request.sql; | 16 | package org.thingsboard.server.mqtt.attributes.request.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestJsonIntegrationTest; | 19 | import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestJsonIntegrationTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.attributes.request.sql; | 16 | package org.thingsboard.server.mqtt.attributes.request.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestJsonIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestProtoIntegrationTest; | 19 | import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestProtoIntegrationTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -18,11 +18,7 @@ package org.thingsboard.server.mqtt.attributes.updates; | @@ -18,11 +18,7 @@ package org.thingsboard.server.mqtt.attributes.updates; | ||
18 | import com.google.protobuf.InvalidProtocolBufferException; | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | import io.netty.handler.codec.mqtt.MqttQoS; | 19 | import io.netty.handler.codec.mqtt.MqttQoS; |
20 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
21 | -import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; | ||
22 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 21 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
23 | -import org.eclipse.paho.client.mqttv3.MqttCallback; | ||
24 | -import org.eclipse.paho.client.mqttv3.MqttException; | ||
25 | -import org.eclipse.paho.client.mqttv3.MqttMessage; | ||
26 | import org.junit.After; | 22 | import org.junit.After; |
27 | import org.junit.Before; | 23 | import org.junit.Before; |
28 | import org.junit.Test; | 24 | import org.junit.Test; |
@@ -33,12 +29,10 @@ import org.thingsboard.server.dao.util.mapping.JacksonUtil; | @@ -33,12 +29,10 @@ import org.thingsboard.server.dao.util.mapping.JacksonUtil; | ||
33 | import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest; | 29 | import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest; |
34 | 30 | ||
35 | import java.nio.charset.StandardCharsets; | 31 | import java.nio.charset.StandardCharsets; |
36 | -import java.util.concurrent.CountDownLatch; | ||
37 | import java.util.concurrent.TimeUnit; | 32 | import java.util.concurrent.TimeUnit; |
38 | 33 | ||
39 | import static org.junit.Assert.assertEquals; | 34 | import static org.junit.Assert.assertEquals; |
40 | import static org.junit.Assert.assertNotNull; | 35 | import static org.junit.Assert.assertNotNull; |
41 | -import static org.junit.Assert.assertTrue; | ||
42 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 36 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
43 | 37 | ||
44 | @Slf4j | 38 | @Slf4j |
@@ -21,11 +21,6 @@ import org.junit.Before; | @@ -21,11 +21,6 @@ import org.junit.Before; | ||
21 | import org.junit.Test; | 21 | import org.junit.Test; |
22 | import org.thingsboard.server.common.data.TransportPayloadType; | 22 | import org.thingsboard.server.common.data.TransportPayloadType; |
23 | 23 | ||
24 | -import static org.junit.Assert.assertEquals; | ||
25 | -import static org.junit.Assert.assertFalse; | ||
26 | -import static org.junit.Assert.assertNotNull; | ||
27 | -import static org.junit.Assert.assertTrue; | ||
28 | - | ||
29 | @Slf4j | 24 | @Slf4j |
30 | public abstract class AbstractMqttAttributesUpdatesJsonIntegrationTest extends AbstractMqttAttributesUpdatesIntegrationTest { | 25 | public abstract class AbstractMqttAttributesUpdatesJsonIntegrationTest extends AbstractMqttAttributesUpdatesIntegrationTest { |
31 | 26 |
@@ -21,11 +21,9 @@ import org.junit.After; | @@ -21,11 +21,9 @@ import org.junit.After; | ||
21 | import org.junit.Before; | 21 | import org.junit.Before; |
22 | import org.junit.Test; | 22 | import org.junit.Test; |
23 | import org.thingsboard.server.common.data.TransportPayloadType; | 23 | import org.thingsboard.server.common.data.TransportPayloadType; |
24 | -import org.thingsboard.server.common.data.device.profile.MqttTopics; | ||
25 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 24 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
26 | import org.thingsboard.server.gen.transport.TransportProtos; | 25 | import org.thingsboard.server.gen.transport.TransportProtos; |
27 | 26 | ||
28 | -import java.nio.charset.StandardCharsets; | ||
29 | import java.util.List; | 27 | import java.util.List; |
30 | import java.util.stream.Collectors; | 28 | import java.util.stream.Collectors; |
31 | 29 |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.attributes.updates.sql; | 16 | package org.thingsboard.server.mqtt.attributes.updates.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesJsonIntegrationTest; | 19 | import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesJsonIntegrationTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.attributes.updates.sql; | 16 | package org.thingsboard.server.mqtt.attributes.updates.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesJsonIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesProtoIntegrationTest; | 19 | import org.thingsboard.server.mqtt.attributes.updates.AbstractMqttAttributesUpdatesProtoIntegrationTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -20,7 +20,6 @@ import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | @@ -20,7 +20,6 @@ import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ||
20 | import org.eclipse.paho.client.mqttv3.MqttMessage; | 20 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
21 | import org.junit.After; | 21 | import org.junit.After; |
22 | import org.junit.Before; | 22 | import org.junit.Before; |
23 | -import org.junit.Ignore; | ||
24 | import org.junit.Test; | 23 | import org.junit.Test; |
25 | import org.thingsboard.server.common.data.ClaimRequest; | 24 | import org.thingsboard.server.common.data.ClaimRequest; |
26 | import org.thingsboard.server.common.data.Customer; | 25 | import org.thingsboard.server.common.data.Customer; |
@@ -18,7 +18,6 @@ package org.thingsboard.server.mqtt.claim; | @@ -18,7 +18,6 @@ package org.thingsboard.server.mqtt.claim; | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.junit.After; | 19 | import org.junit.After; |
20 | import org.junit.Before; | 20 | import org.junit.Before; |
21 | -import org.junit.Ignore; | ||
22 | import org.junit.Test; | 21 | import org.junit.Test; |
23 | import org.thingsboard.server.common.data.TransportPayloadType; | 22 | import org.thingsboard.server.common.data.TransportPayloadType; |
24 | 23 |
@@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; | @@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; | ||
19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
20 | import org.junit.After; | 20 | import org.junit.After; |
21 | import org.junit.Before; | 21 | import org.junit.Before; |
22 | -import org.junit.Ignore; | ||
23 | import org.junit.Test; | 22 | import org.junit.Test; |
24 | import org.thingsboard.server.common.data.TransportPayloadType; | 23 | import org.thingsboard.server.common.data.TransportPayloadType; |
25 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 24 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.claim.sql; | 16 | package org.thingsboard.server.mqtt.claim.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.claim.AbstractMqttClaimDeviceTest; | ||
20 | import org.thingsboard.server.mqtt.claim.AbstractMqttClaimJsonDeviceTest; | 19 | import org.thingsboard.server.mqtt.claim.AbstractMqttClaimJsonDeviceTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.claim.sql; | 16 | package org.thingsboard.server.mqtt.claim.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.claim.AbstractMqttClaimJsonDeviceTest; | ||
20 | import org.thingsboard.server.mqtt.claim.AbstractMqttClaimProtoDeviceTest; | 19 | import org.thingsboard.server.mqtt.claim.AbstractMqttClaimProtoDeviceTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -94,7 +94,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -94,7 +94,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
94 | 94 | ||
95 | 95 | ||
96 | protected void processTestProvisioningDisabledDevice() throws Exception { | 96 | protected void processTestProvisioningDisabledDevice() throws Exception { |
97 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 97 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); |
98 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 98 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
99 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 99 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
100 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | 100 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
@@ -103,7 +103,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -103,7 +103,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
103 | 103 | ||
104 | 104 | ||
105 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | 105 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
106 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 106 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
107 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 107 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
108 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 108 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
109 | 109 | ||
@@ -121,7 +121,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -121,7 +121,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
121 | 121 | ||
122 | 122 | ||
123 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | 123 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
124 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 124 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
125 | String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; | 125 | String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; |
126 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); | 126 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); |
127 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 127 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -142,7 +142,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -142,7 +142,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
142 | 142 | ||
143 | 143 | ||
144 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | 144 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
145 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 145 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
146 | String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; | 146 | String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; |
147 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); | 147 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); |
148 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 148 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -169,7 +169,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -169,7 +169,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
169 | 169 | ||
170 | 170 | ||
171 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { | 171 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { |
172 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 172 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
173 | String requestCredentials = ",\"credentialsType\": \"MQTT_BASIC\",\"clientId\": \"test_clientId\",\"username\": \"test_username\",\"password\": \"test_password\""; | 173 | String requestCredentials = ",\"credentialsType\": \"MQTT_BASIC\",\"clientId\": \"test_clientId\",\"username\": \"test_username\",\"password\": \"test_password\""; |
174 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); | 174 | byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); |
175 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 175 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
@@ -197,7 +197,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -197,7 +197,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
197 | } | 197 | } |
198 | 198 | ||
199 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | 199 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
200 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | 200 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); |
201 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 201 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
202 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 202 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
203 | Assert.assertEquals(savedDevice.getId().toString(), response.get("deviceId").getAsString()); | 203 | Assert.assertEquals(savedDevice.getId().toString(), response.get("deviceId").getAsString()); |
@@ -210,7 +210,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | @@ -210,7 +210,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn | ||
210 | } | 210 | } |
211 | 211 | ||
212 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { | 212 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { |
213 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | 213 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); |
214 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); | 214 | byte[] result = createMqttClientAndPublish().getPayloadBytes(); |
215 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); | 215 | JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
216 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); | 216 | Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
@@ -102,14 +102,14 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -102,14 +102,14 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
102 | 102 | ||
103 | 103 | ||
104 | protected void processTestProvisioningDisabledDevice() throws Exception { | 104 | protected void processTestProvisioningDisabledDevice() throws Exception { |
105 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.DISABLED, null, null); | 105 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); |
106 | ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 106 | ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
107 | Assert.assertNotNull(result); | 107 | Assert.assertNotNull(result); |
108 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getProvisionResponseStatus().toString()); | 108 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getProvisionResponseStatus().toString()); |
109 | } | 109 | } |
110 | 110 | ||
111 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { | 111 | protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
112 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 112 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
113 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 113 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
114 | 114 | ||
115 | Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); | 115 | Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
@@ -125,7 +125,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -125,7 +125,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
125 | } | 125 | } |
126 | 126 | ||
127 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { | 127 | protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
128 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 128 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null,null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
129 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); | 129 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); |
130 | 130 | ||
131 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayloadBytes()); | 131 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayloadBytes()); |
@@ -145,7 +145,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -145,7 +145,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
145 | } | 145 | } |
146 | 146 | ||
147 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { | 147 | protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
148 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 148 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
149 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); | 149 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); |
150 | 150 | ||
151 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayloadBytes()); | 151 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayloadBytes()); |
@@ -171,7 +171,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -171,7 +171,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
171 | } | 171 | } |
172 | 172 | ||
173 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { | 173 | protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { |
174 | - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); | 174 | + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
175 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateBasicMqttCredRequestMsg( | 175 | CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateBasicMqttCredRequestMsg( |
176 | ValidateBasicMqttCredRequestMsg.newBuilder() | 176 | ValidateBasicMqttCredRequestMsg.newBuilder() |
177 | .setClientId("test_clientId") | 177 | .setClientId("test_clientId") |
@@ -205,7 +205,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -205,7 +205,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
205 | } | 205 | } |
206 | 206 | ||
207 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { | 207 | protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
208 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); | 208 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); |
209 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 209 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
210 | Assert.assertEquals(savedDevice.getId().getId(), new UUID(response.getDeviceCredentials().getDeviceIdMSB(), response.getDeviceCredentials().getDeviceIdLSB())); | 210 | Assert.assertEquals(savedDevice.getId().getId(), new UUID(response.getDeviceCredentials().getDeviceIdMSB(), response.getDeviceCredentials().getDeviceIdLSB())); |
211 | 211 | ||
@@ -217,7 +217,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | @@ -217,7 +217,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI | ||
217 | } | 217 | } |
218 | 218 | ||
219 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { | 219 | protected void processTestProvisioningWithBadKeyDevice() throws Exception { |
220 | - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); | 220 | + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); |
221 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); | 221 | ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); |
222 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getProvisionResponseStatus().toString()); | 222 | Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getProvisionResponseStatus().toString()); |
223 | } | 223 | } |
@@ -15,49 +15,14 @@ | @@ -15,49 +15,14 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.mqtt.rpc; | 16 | package org.thingsboard.server.mqtt.rpc; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.databind.JsonNode; | ||
19 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | -import com.google.protobuf.InvalidProtocolBufferException; | ||
21 | -import com.nimbusds.jose.util.StandardCharset; | ||
22 | import com.datastax.oss.driver.api.core.uuid.Uuids; | 18 | import com.datastax.oss.driver.api.core.uuid.Uuids; |
23 | -import io.netty.handler.codec.mqtt.MqttQoS; | ||
24 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
25 | -import org.apache.commons.lang3.StringUtils; | ||
26 | -import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; | ||
27 | -import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ||
28 | -import org.eclipse.paho.client.mqttv3.MqttCallback; | ||
29 | -import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | ||
30 | -import org.eclipse.paho.client.mqttv3.MqttException; | ||
31 | -import org.eclipse.paho.client.mqttv3.MqttMessage; | ||
32 | import org.junit.After; | 20 | import org.junit.After; |
33 | import org.junit.Assert; | 21 | import org.junit.Assert; |
34 | import org.junit.Before; | 22 | import org.junit.Before; |
35 | -import org.junit.Ignore; | ||
36 | import org.junit.Test; | 23 | import org.junit.Test; |
37 | -import org.thingsboard.server.common.data.Device; | ||
38 | -import org.thingsboard.server.common.data.DeviceProfile; | ||
39 | -import org.thingsboard.server.common.data.DeviceProfileType; | ||
40 | -import org.thingsboard.server.common.data.DeviceTransportType; | ||
41 | -import org.thingsboard.server.common.data.Tenant; | ||
42 | -import org.thingsboard.server.common.data.TransportPayloadType; | ||
43 | -import org.thingsboard.server.common.data.User; | ||
44 | -import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; | ||
45 | -import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | ||
46 | -import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
47 | -import org.thingsboard.server.common.data.device.profile.MqttTopics; | ||
48 | -import org.thingsboard.server.common.data.security.Authority; | ||
49 | -import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
50 | -import org.thingsboard.server.controller.AbstractControllerTest; | ||
51 | -import org.thingsboard.server.dao.util.mapping.JacksonUtil; | ||
52 | import org.thingsboard.server.service.security.AccessValidator; | 24 | import org.thingsboard.server.service.security.AccessValidator; |
53 | 25 | ||
54 | -import java.util.Arrays; | ||
55 | -import java.util.concurrent.CountDownLatch; | ||
56 | -import java.util.concurrent.TimeUnit; | ||
57 | -import java.util.concurrent.atomic.AtomicInteger; | ||
58 | - | ||
59 | -import static org.junit.Assert.assertEquals; | ||
60 | -import static org.junit.Assert.assertNotNull; | ||
61 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
62 | 27 | ||
63 | /** | 28 | /** |
@@ -15,9 +15,7 @@ | @@ -15,9 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.mqtt.rpc; | 16 | package org.thingsboard.server.mqtt.rpc; |
17 | 17 | ||
18 | -import com.datastax.oss.driver.api.core.uuid.Uuids; | ||
19 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
20 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
21 | import com.google.protobuf.InvalidProtocolBufferException; | 19 | import com.google.protobuf.InvalidProtocolBufferException; |
22 | import com.nimbusds.jose.util.StandardCharset; | 20 | import com.nimbusds.jose.util.StandardCharset; |
23 | import io.netty.handler.codec.mqtt.MqttQoS; | 21 | import io.netty.handler.codec.mqtt.MqttQoS; |
@@ -26,35 +24,18 @@ import org.apache.commons.lang3.StringUtils; | @@ -26,35 +24,18 @@ import org.apache.commons.lang3.StringUtils; | ||
26 | import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; | 24 | import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; |
27 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 25 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
28 | import org.eclipse.paho.client.mqttv3.MqttCallback; | 26 | import org.eclipse.paho.client.mqttv3.MqttCallback; |
29 | -import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | ||
30 | import org.eclipse.paho.client.mqttv3.MqttException; | 27 | import org.eclipse.paho.client.mqttv3.MqttException; |
31 | import org.eclipse.paho.client.mqttv3.MqttMessage; | 28 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
32 | -import org.junit.After; | ||
33 | import org.junit.Assert; | 29 | import org.junit.Assert; |
34 | -import org.junit.Before; | ||
35 | -import org.junit.Test; | ||
36 | import org.thingsboard.server.common.data.Device; | 30 | import org.thingsboard.server.common.data.Device; |
37 | -import org.thingsboard.server.common.data.DeviceProfile; | ||
38 | -import org.thingsboard.server.common.data.DeviceProfileType; | ||
39 | -import org.thingsboard.server.common.data.DeviceTransportType; | ||
40 | -import org.thingsboard.server.common.data.Tenant; | ||
41 | import org.thingsboard.server.common.data.TransportPayloadType; | 31 | import org.thingsboard.server.common.data.TransportPayloadType; |
42 | -import org.thingsboard.server.common.data.User; | ||
43 | -import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; | ||
44 | -import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | ||
45 | -import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
46 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
47 | -import org.thingsboard.server.common.data.security.Authority; | ||
48 | -import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
49 | -import org.thingsboard.server.controller.AbstractControllerTest; | ||
50 | import org.thingsboard.server.dao.util.mapping.JacksonUtil; | 33 | import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
51 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | 34 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; |
52 | -import org.thingsboard.server.service.security.AccessValidator; | ||
53 | 35 | ||
54 | import java.util.Arrays; | 36 | import java.util.Arrays; |
55 | import java.util.concurrent.CountDownLatch; | 37 | import java.util.concurrent.CountDownLatch; |
56 | import java.util.concurrent.TimeUnit; | 38 | import java.util.concurrent.TimeUnit; |
57 | -import java.util.concurrent.atomic.AtomicInteger; | ||
58 | 39 | ||
59 | import static org.junit.Assert.assertEquals; | 40 | import static org.junit.Assert.assertEquals; |
60 | import static org.junit.Assert.assertNotNull; | 41 | import static org.junit.Assert.assertNotNull; |
@@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; | @@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; | ||
19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
20 | import org.junit.After; | 20 | import org.junit.After; |
21 | import org.junit.Before; | 21 | import org.junit.Before; |
22 | -import org.junit.Ignore; | ||
23 | import org.junit.Test; | 22 | import org.junit.Test; |
24 | import org.thingsboard.server.common.data.TransportPayloadType; | 23 | import org.thingsboard.server.common.data.TransportPayloadType; |
25 | 24 |
@@ -22,16 +22,12 @@ import org.eclipse.paho.client.mqttv3.MqttException; | @@ -22,16 +22,12 @@ import org.eclipse.paho.client.mqttv3.MqttException; | ||
22 | import org.eclipse.paho.client.mqttv3.MqttMessage; | 22 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
23 | import org.junit.After; | 23 | import org.junit.After; |
24 | import org.junit.Before; | 24 | import org.junit.Before; |
25 | -import org.junit.Ignore; | ||
26 | import org.junit.Test; | 25 | import org.junit.Test; |
27 | import org.thingsboard.server.common.data.TransportPayloadType; | 26 | import org.thingsboard.server.common.data.TransportPayloadType; |
28 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 27 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
29 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 28 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
30 | import org.thingsboard.server.gen.transport.TransportProtos; | 29 | import org.thingsboard.server.gen.transport.TransportProtos; |
31 | 30 | ||
32 | -import static org.junit.Assert.assertEquals; | ||
33 | -import static org.junit.Assert.assertNotNull; | ||
34 | - | ||
35 | @Slf4j | 31 | @Slf4j |
36 | public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest { | 32 | public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest { |
37 | 33 |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.mqtt.telemetry.attributes; | 16 | package org.thingsboard.server.mqtt.telemetry.attributes; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.core.JsonProcessingException; | ||
18 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 20 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
20 | import org.junit.After; | 21 | import org.junit.After; |
@@ -142,7 +143,7 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt | @@ -142,7 +143,7 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt | ||
142 | 143 | ||
143 | } | 144 | } |
144 | 145 | ||
145 | - protected void assertAttributesValues(List<Map<String, Object>> deviceValues, Set<String> expectedKeySet) { | 146 | + protected void assertAttributesValues(List<Map<String, Object>> deviceValues, Set<String> expectedKeySet) throws JsonProcessingException { |
146 | for (Map<String, Object> map : deviceValues) { | 147 | for (Map<String, Object> map : deviceValues) { |
147 | String key = (String) map.get("key"); | 148 | String key = (String) map.get("key"); |
148 | Object value = map.get("value"); | 149 | Object value = map.get("value"); |
@@ -15,18 +15,24 @@ | @@ -15,18 +15,24 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.mqtt.telemetry.attributes; | 16 | package org.thingsboard.server.mqtt.telemetry.attributes; |
17 | 17 | ||
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
19 | +import com.google.protobuf.Descriptors; | ||
20 | +import com.google.protobuf.DynamicMessage; | ||
21 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
18 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
19 | import org.junit.After; | 23 | import org.junit.After; |
20 | -import org.junit.Before; | ||
21 | import org.junit.Test; | 24 | import org.junit.Test; |
22 | import org.thingsboard.server.common.data.TransportPayloadType; | 25 | import org.thingsboard.server.common.data.TransportPayloadType; |
26 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | ||
27 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
28 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
29 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
23 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 30 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
24 | import org.thingsboard.server.gen.transport.TransportProtos; | 31 | import org.thingsboard.server.gen.transport.TransportProtos; |
25 | 32 | ||
26 | import java.util.Arrays; | 33 | import java.util.Arrays; |
27 | import java.util.List; | 34 | import java.util.List; |
28 | 35 | ||
29 | -import static org.junit.Assert.assertEquals; | ||
30 | import static org.junit.Assert.assertNotNull; | 36 | import static org.junit.Assert.assertNotNull; |
31 | import static org.junit.Assert.assertTrue; | 37 | import static org.junit.Assert.assertTrue; |
32 | 38 | ||
@@ -35,11 +41,6 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac | @@ -35,11 +41,6 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac | ||
35 | 41 | ||
36 | private static final String POST_DATA_ATTRIBUTES_TOPIC = "proto/attributes"; | 42 | private static final String POST_DATA_ATTRIBUTES_TOPIC = "proto/attributes"; |
37 | 43 | ||
38 | - @Before | ||
39 | - public void beforeTest() throws Exception { | ||
40 | - processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC); | ||
41 | - } | ||
42 | - | ||
43 | @After | 44 | @After |
44 | public void afterTest() throws Exception { | 45 | public void afterTest() throws Exception { |
45 | processAfterTest(); | 46 | processAfterTest(); |
@@ -47,13 +48,49 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac | @@ -47,13 +48,49 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac | ||
47 | 48 | ||
48 | @Test | 49 | @Test |
49 | public void testPushMqttAttributes() throws Exception { | 50 | public void testPushMqttAttributes() throws Exception { |
51 | + super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, POST_DATA_ATTRIBUTES_TOPIC); | ||
50 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 52 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
51 | - TransportProtos.PostAttributeMsg msg = getPostAttributeMsg(expectedKeys); | ||
52 | - processAttributesTest(POST_DATA_ATTRIBUTES_TOPIC, expectedKeys, msg.toByteArray()); | 53 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
54 | + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); | ||
55 | + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | ||
56 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); | ||
57 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | ||
58 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
59 | + ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_ATTRIBUTES_PROTO_SCHEMA); | ||
60 | + DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); | ||
61 | + | ||
62 | + DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject"); | ||
63 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | ||
64 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | ||
65 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | ||
66 | + | ||
67 | + DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject"); | ||
68 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | ||
69 | + assertNotNull(jsonObjectBuilderDescriptor); | ||
70 | + DynamicMessage jsonObject = jsonObjectBuilder | ||
71 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | ||
72 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | ||
73 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | ||
74 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | ||
75 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | ||
76 | + .build(); | ||
77 | + | ||
78 | + DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes"); | ||
79 | + Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType(); | ||
80 | + assertNotNull(postAttributesMsgDescriptor); | ||
81 | + DynamicMessage postAttributesMsg = postAttributesBuilder | ||
82 | + .setField(postAttributesMsgDescriptor.findFieldByName("key1"), "value1") | ||
83 | + .setField(postAttributesMsgDescriptor.findFieldByName("key2"), true) | ||
84 | + .setField(postAttributesMsgDescriptor.findFieldByName("key3"), 3.0) | ||
85 | + .setField(postAttributesMsgDescriptor.findFieldByName("key4"), 4) | ||
86 | + .setField(postAttributesMsgDescriptor.findFieldByName("key5"), jsonObject) | ||
87 | + .build(); | ||
88 | + processAttributesTest(POST_DATA_ATTRIBUTES_TOPIC, expectedKeys, postAttributesMsg.toByteArray()); | ||
53 | } | 89 | } |
54 | 90 | ||
55 | @Test | 91 | @Test |
56 | public void testPushMqttAttributesGateway() throws Exception { | 92 | public void testPushMqttAttributesGateway() throws Exception { |
93 | + super.processBeforeTest("Test Post Attributes device", "Test Post Attributes gateway", TransportPayloadType.PROTOBUF, null, null); | ||
57 | TransportApiProtos.GatewayAttributesMsg.Builder gatewayAttributesMsgProtoBuilder = TransportApiProtos.GatewayAttributesMsg.newBuilder(); | 94 | TransportApiProtos.GatewayAttributesMsg.Builder gatewayAttributesMsgProtoBuilder = TransportApiProtos.GatewayAttributesMsg.newBuilder(); |
58 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 95 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
59 | String deviceName1 = "Device A"; | 96 | String deviceName1 = "Device A"; |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.telemetry.attributes.nosql; | 16 | package org.thingsboard.server.mqtt.telemetry.attributes.nosql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesJsonIntegrationTest; | 19 | import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesJsonIntegrationTest; |
21 | 20 | ||
22 | @DaoNoSqlTest | 21 | @DaoNoSqlTest |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.telemetry.attributes.nosql; | 16 | package org.thingsboard.server.mqtt.telemetry.attributes.nosql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; | 19 | import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; |
21 | 20 | ||
22 | @DaoNoSqlTest | 21 | @DaoNoSqlTest |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.telemetry.attributes.sql; | 16 | package org.thingsboard.server.mqtt.telemetry.attributes.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesJsonIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; | 19 | import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; |
21 | 20 | ||
22 | @DaoSqlTest | 21 | @DaoSqlTest |
@@ -27,7 +27,6 @@ import org.junit.After; | @@ -27,7 +27,6 @@ import org.junit.After; | ||
27 | import org.junit.Before; | 27 | import org.junit.Before; |
28 | import org.junit.Test; | 28 | import org.junit.Test; |
29 | import org.thingsboard.server.common.data.Device; | 29 | import org.thingsboard.server.common.data.Device; |
30 | -import org.thingsboard.server.common.data.TransportPayloadType; | ||
31 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 30 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
32 | import org.thingsboard.server.common.data.id.DeviceId; | 31 | import org.thingsboard.server.common.data.id.DeviceId; |
33 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; | 32 | import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest; |
@@ -27,7 +27,6 @@ import org.thingsboard.server.common.data.device.profile.MqttTopics; | @@ -27,7 +27,6 @@ import org.thingsboard.server.common.data.device.profile.MqttTopics; | ||
27 | import java.util.Arrays; | 27 | import java.util.Arrays; |
28 | import java.util.List; | 28 | import java.util.List; |
29 | 29 | ||
30 | -import static org.junit.Assert.assertEquals; | ||
31 | import static org.junit.Assert.assertNotNull; | 30 | import static org.junit.Assert.assertNotNull; |
32 | 31 | ||
33 | @Slf4j | 32 | @Slf4j |
@@ -15,33 +15,36 @@ | @@ -15,33 +15,36 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.mqtt.telemetry.timeseries; | 16 | package org.thingsboard.server.mqtt.telemetry.timeseries; |
17 | 17 | ||
18 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
19 | +import com.google.protobuf.Descriptors; | ||
20 | +import com.google.protobuf.DynamicMessage; | ||
21 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
18 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
19 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | 23 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
20 | import org.junit.After; | 24 | import org.junit.After; |
21 | -import org.junit.Before; | ||
22 | import org.junit.Test; | 25 | import org.junit.Test; |
23 | import org.thingsboard.server.common.data.Device; | 26 | import org.thingsboard.server.common.data.Device; |
27 | +import org.thingsboard.server.common.data.DeviceProfileProvisionType; | ||
24 | import org.thingsboard.server.common.data.TransportPayloadType; | 28 | import org.thingsboard.server.common.data.TransportPayloadType; |
29 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | ||
30 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
31 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
25 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
33 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
26 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 34 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
27 | import org.thingsboard.server.gen.transport.TransportProtos; | 35 | import org.thingsboard.server.gen.transport.TransportProtos; |
28 | 36 | ||
29 | import java.util.Arrays; | 37 | import java.util.Arrays; |
30 | import java.util.List; | 38 | import java.util.List; |
31 | 39 | ||
32 | -import static org.junit.Assert.assertEquals; | ||
33 | import static org.junit.Assert.assertNotNull; | 40 | import static org.junit.Assert.assertNotNull; |
41 | +import static org.junit.Assert.assertTrue; | ||
34 | 42 | ||
35 | @Slf4j | 43 | @Slf4j |
36 | public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends AbstractMqttTimeseriesIntegrationTest { | 44 | public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends AbstractMqttTimeseriesIntegrationTest { |
37 | 45 | ||
38 | private static final String POST_DATA_TELEMETRY_TOPIC = "proto/telemetry"; | 46 | private static final String POST_DATA_TELEMETRY_TOPIC = "proto/telemetry"; |
39 | 47 | ||
40 | - @Before | ||
41 | - public void beforeTest() throws Exception { | ||
42 | - processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null); | ||
43 | - } | ||
44 | - | ||
45 | @After | 48 | @After |
46 | public void afterTest() throws Exception { | 49 | public void afterTest() throws Exception { |
47 | processAfterTest(); | 50 | processAfterTest(); |
@@ -49,20 +52,127 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | @@ -49,20 +52,127 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | ||
49 | 52 | ||
50 | @Test | 53 | @Test |
51 | public void testPushMqttTelemetry() throws Exception { | 54 | public void testPushMqttTelemetry() throws Exception { |
55 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null); | ||
52 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 56 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
53 | - TransportProtos.TsKvListProto tsKvListProto = getTsKvListProto(expectedKeys, 0); | ||
54 | - processTelemetryTest(POST_DATA_TELEMETRY_TOPIC, expectedKeys, tsKvListProto.toByteArray(), false); | 57 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
58 | + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); | ||
59 | + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | ||
60 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); | ||
61 | + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); | ||
62 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
63 | + ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_TELEMETRY_PROTO_SCHEMA); | ||
64 | + DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema"); | ||
65 | + | ||
66 | + DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject"); | ||
67 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | ||
68 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | ||
69 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | ||
70 | + | ||
71 | + DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject"); | ||
72 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | ||
73 | + assertNotNull(jsonObjectBuilderDescriptor); | ||
74 | + DynamicMessage jsonObject = jsonObjectBuilder | ||
75 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | ||
76 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | ||
77 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | ||
78 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | ||
79 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | ||
80 | + .build(); | ||
81 | + | ||
82 | + DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry"); | ||
83 | + Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType(); | ||
84 | + assertNotNull(postTelemetryMsgDescriptor); | ||
85 | + DynamicMessage postTelemetryMsg = postTelemetryBuilder | ||
86 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key1"), "value1") | ||
87 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key2"), true) | ||
88 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key3"), 3.0) | ||
89 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key4"), 4) | ||
90 | + .setField(postTelemetryMsgDescriptor.findFieldByName("key5"), jsonObject) | ||
91 | + .build(); | ||
92 | + processTelemetryTest(POST_DATA_TELEMETRY_TOPIC, expectedKeys, postTelemetryMsg.toByteArray(), false); | ||
55 | } | 93 | } |
56 | 94 | ||
57 | @Test | 95 | @Test |
58 | public void testPushMqttTelemetryWithTs() throws Exception { | 96 | public void testPushMqttTelemetryWithTs() throws Exception { |
97 | + String schemaStr = "syntax =\"proto3\";\n" + | ||
98 | + "\n" + | ||
99 | + "package test;\n" + | ||
100 | + "\n" + | ||
101 | + "message PostTelemetry {\n" + | ||
102 | + " int64 ts = 1;\n" + | ||
103 | + " Values values = 2;\n" + | ||
104 | + " \n" + | ||
105 | + " message Values {\n" + | ||
106 | + " string key1 = 3;\n" + | ||
107 | + " bool key2 = 4;\n" + | ||
108 | + " double key3 = 5;\n" + | ||
109 | + " int32 key4 = 6;\n" + | ||
110 | + " JsonObject key5 = 7;\n" + | ||
111 | + " }\n" + | ||
112 | + " \n" + | ||
113 | + " message JsonObject {\n" + | ||
114 | + " int32 someNumber = 8;\n" + | ||
115 | + " repeated int32 someArray = 9;\n" + | ||
116 | + " NestedJsonObject someNestedObject = 10;\n" + | ||
117 | + " message NestedJsonObject {\n" + | ||
118 | + " string key = 11;\n" + | ||
119 | + " }\n" + | ||
120 | + " }\n" + | ||
121 | + "}"; | ||
122 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); | ||
59 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 123 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
60 | - TransportProtos.TsKvListProto tsKvListProto = getTsKvListProto(expectedKeys, 10000); | ||
61 | - processTelemetryTest(POST_DATA_TELEMETRY_TOPIC, expectedKeys, tsKvListProto.toByteArray(), true); | 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"); | ||
132 | + | ||
133 | + DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject"); | ||
134 | + Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); | ||
135 | + assertNotNull(nestedJsonObjectBuilderDescriptor); | ||
136 | + DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); | ||
137 | + | ||
138 | + DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject"); | ||
139 | + Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); | ||
140 | + assertNotNull(jsonObjectBuilderDescriptor); | ||
141 | + DynamicMessage jsonObject = jsonObjectBuilder | ||
142 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) | ||
143 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) | ||
144 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) | ||
145 | + .addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) | ||
146 | + .setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) | ||
147 | + .build(); | ||
148 | + | ||
149 | + | ||
150 | + DynamicMessage.Builder valuesBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.Values"); | ||
151 | + Descriptors.Descriptor valuesDescriptor = valuesBuilder.getDescriptorForType(); | ||
152 | + assertNotNull(valuesDescriptor); | ||
153 | + | ||
154 | + DynamicMessage valuesMsg = valuesBuilder | ||
155 | + .setField(valuesDescriptor.findFieldByName("key1"), "value1") | ||
156 | + .setField(valuesDescriptor.findFieldByName("key2"), true) | ||
157 | + .setField(valuesDescriptor.findFieldByName("key3"), 3.0) | ||
158 | + .setField(valuesDescriptor.findFieldByName("key4"), 4) | ||
159 | + .setField(valuesDescriptor.findFieldByName("key5"), jsonObject) | ||
160 | + .build(); | ||
161 | + | ||
162 | + DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry"); | ||
163 | + Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType(); | ||
164 | + assertNotNull(postTelemetryMsgDescriptor); | ||
165 | + DynamicMessage postTelemetryMsg = postTelemetryBuilder | ||
166 | + .setField(postTelemetryMsgDescriptor.findFieldByName("ts"), 10000L) | ||
167 | + .setField(postTelemetryMsgDescriptor.findFieldByName("values"), valuesMsg) | ||
168 | + .build(); | ||
169 | + | ||
170 | + processTelemetryTest(POST_DATA_TELEMETRY_TOPIC, expectedKeys, postTelemetryMsg.toByteArray(), true); | ||
62 | } | 171 | } |
63 | 172 | ||
64 | @Test | 173 | @Test |
65 | public void testPushMqttTelemetryGateway() throws Exception { | 174 | public void testPushMqttTelemetryGateway() throws Exception { |
175 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); | ||
66 | TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder(); | 176 | TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder(); |
67 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); | 177 | List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
68 | String deviceName1 = "Device A"; | 178 | String deviceName1 = "Device A"; |
@@ -76,6 +186,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | @@ -76,6 +186,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac | ||
76 | 186 | ||
77 | @Test | 187 | @Test |
78 | public void testGatewayConnect() throws Exception { | 188 | public void testGatewayConnect() throws Exception { |
189 | + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); | ||
79 | String deviceName = "Device A"; | 190 | String deviceName = "Device A"; |
80 | TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName); | 191 | TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName); |
81 | MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); | 192 | MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.telemetry.timeseries.sql; | 16 | package org.thingsboard.server.mqtt.telemetry.timeseries.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; | 19 | import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; |
21 | 20 | ||
22 | /** | 21 | /** |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.mqtt.telemetry.timeseries.sql; | 16 | package org.thingsboard.server.mqtt.telemetry.timeseries.sql; |
17 | 17 | ||
18 | import org.thingsboard.server.dao.service.DaoSqlTest; | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesJsonIntegrationTest; | ||
20 | import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesProtoIntegrationTest; | 19 | import org.thingsboard.server.mqtt.telemetry.timeseries.AbstractMqttTimeseriesProtoIntegrationTest; |
21 | 20 | ||
22 | /** | 21 | /** |
@@ -71,6 +71,14 @@ | @@ -71,6 +71,14 @@ | ||
71 | <artifactId>java-driver-core</artifactId> | 71 | <artifactId>java-driver-core</artifactId> |
72 | <scope>test</scope> | 72 | <scope>test</scope> |
73 | </dependency> | 73 | </dependency> |
74 | + <dependency> | ||
75 | + <groupId>com.squareup.wire</groupId> | ||
76 | + <artifactId>wire-schema</artifactId> | ||
77 | + </dependency> | ||
78 | + <dependency> | ||
79 | + <groupId>org.thingsboard</groupId> | ||
80 | + <artifactId>protobuf-dynamic</artifactId> | ||
81 | + </dependency> | ||
74 | </dependencies> | 82 | </dependencies> |
75 | 83 | ||
76 | <build> | 84 | <build> |
@@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.DeviceTransportType; | @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.DeviceTransportType; | ||
29 | property = "type") | 29 | property = "type") |
30 | @JsonSubTypes({ | 30 | @JsonSubTypes({ |
31 | @JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"), | 31 | @JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"), |
32 | - @JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"), | 32 | + @JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"), |
33 | @JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M")}) | 33 | @JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M")}) |
34 | public interface DeviceProfileTransportConfiguration { | 34 | public interface DeviceProfileTransportConfiguration { |
35 | 35 |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.device.profile; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.TransportPayloadType; | ||
20 | + | ||
21 | +@Data | ||
22 | +public class JsonTransportPayloadConfiguration implements TransportPayloadTypeConfiguration { | ||
23 | + | ||
24 | + @Override | ||
25 | + public TransportPayloadType getTransportPayloadType() { | ||
26 | + return TransportPayloadType.JSON; | ||
27 | + } | ||
28 | +} |
@@ -16,20 +16,27 @@ | @@ -16,20 +16,27 @@ | ||
16 | package org.thingsboard.server.common.data.device.profile; | 16 | package org.thingsboard.server.common.data.device.profile; |
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | -import org.thingsboard.server.common.data.TransportPayloadType; | ||
20 | import org.thingsboard.server.common.data.DeviceTransportType; | 19 | import org.thingsboard.server.common.data.DeviceTransportType; |
21 | 20 | ||
22 | @Data | 21 | @Data |
23 | public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration { | 22 | public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration { |
24 | 23 | ||
25 | - private TransportPayloadType transportPayloadType = TransportPayloadType.JSON; | ||
26 | - | ||
27 | private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC; | 24 | private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC; |
28 | private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC; | 25 | private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC; |
26 | + private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; | ||
29 | 27 | ||
30 | @Override | 28 | @Override |
31 | public DeviceTransportType getType() { | 29 | public DeviceTransportType getType() { |
32 | return DeviceTransportType.MQTT; | 30 | return DeviceTransportType.MQTT; |
33 | } | 31 | } |
34 | 32 | ||
33 | + public TransportPayloadTypeConfiguration getTransportPayloadTypeConfiguration() { | ||
34 | + if (transportPayloadTypeConfiguration != null) { | ||
35 | + return transportPayloadTypeConfiguration; | ||
36 | + } else { | ||
37 | + return new JsonTransportPayloadConfiguration(); | ||
38 | + } | ||
39 | + } | ||
40 | + | ||
41 | + | ||
35 | } | 42 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.device.profile; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import com.github.os72.protobuf.dynamic.DynamicSchema; | ||
20 | +import com.github.os72.protobuf.dynamic.EnumDefinition; | ||
21 | +import com.github.os72.protobuf.dynamic.MessageDefinition; | ||
22 | +import com.google.protobuf.Descriptors; | ||
23 | +import com.google.protobuf.DynamicMessage; | ||
24 | +import com.squareup.wire.schema.Location; | ||
25 | +import com.squareup.wire.schema.internal.parser.EnumConstantElement; | ||
26 | +import com.squareup.wire.schema.internal.parser.EnumElement; | ||
27 | +import com.squareup.wire.schema.internal.parser.FieldElement; | ||
28 | +import com.squareup.wire.schema.internal.parser.MessageElement; | ||
29 | +import com.squareup.wire.schema.internal.parser.OneOfElement; | ||
30 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
31 | +import com.squareup.wire.schema.internal.parser.ProtoParser; | ||
32 | +import com.squareup.wire.schema.internal.parser.TypeElement; | ||
33 | +import lombok.Data; | ||
34 | +import lombok.extern.slf4j.Slf4j; | ||
35 | +import org.thingsboard.server.common.data.TransportPayloadType; | ||
36 | + | ||
37 | +import java.util.ArrayList; | ||
38 | +import java.util.Collections; | ||
39 | +import java.util.List; | ||
40 | +import java.util.stream.Collectors; | ||
41 | + | ||
42 | +@Slf4j | ||
43 | +@Data | ||
44 | +public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeConfiguration { | ||
45 | + | ||
46 | + public static final Location LOCATION = new Location("", "", -1, -1); | ||
47 | + public static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; | ||
48 | + public static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; | ||
49 | + | ||
50 | + private String deviceTelemetryProtoSchema; | ||
51 | + private String deviceAttributesProtoSchema; | ||
52 | + | ||
53 | + @Override | ||
54 | + public TransportPayloadType getTransportPayloadType() { | ||
55 | + return TransportPayloadType.PROTOBUF; | ||
56 | + } | ||
57 | + | ||
58 | + public Descriptors.Descriptor getTelemetryDynamicMessageDescriptor(String deviceTelemetryProtoSchema) { | ||
59 | + return getDescriptor(deviceTelemetryProtoSchema, TELEMETRY_PROTO_SCHEMA); | ||
60 | + } | ||
61 | + | ||
62 | + public Descriptors.Descriptor getAttributesDynamicMessageDescriptor(String deviceAttributesProtoSchema) { | ||
63 | + return getDescriptor(deviceAttributesProtoSchema, ATTRIBUTES_PROTO_SCHEMA); | ||
64 | + } | ||
65 | + | ||
66 | + private Descriptors.Descriptor getDescriptor(String protoSchema, String schemaName) { | ||
67 | + try { | ||
68 | + ProtoFileElement protoFileElement = getTransportProtoSchema(protoSchema); | ||
69 | + DynamicSchema dynamicSchema = getDynamicSchema(protoFileElement, schemaName); | ||
70 | + String lastMsgName = getMessageTypes(protoFileElement.getTypes()).stream() | ||
71 | + .map(MessageElement::getName).reduce((previous, last) -> last).get(); | ||
72 | + DynamicMessage.Builder builder = dynamicSchema.newMessageBuilder(lastMsgName); | ||
73 | + return builder.getDescriptorForType(); | ||
74 | + } catch (Exception e) { | ||
75 | + log.warn("Failed to get Message Descriptor due to {}", e.getMessage()); | ||
76 | + return null; | ||
77 | + } | ||
78 | + } | ||
79 | + | ||
80 | + public DynamicSchema getDynamicSchema(ProtoFileElement protoFileElement, String schemaName) { | ||
81 | + DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder(); | ||
82 | + schemaBuilder.setName(schemaName); | ||
83 | + schemaBuilder.setPackage(!isEmptyStr(protoFileElement.getPackageName()) ? | ||
84 | + protoFileElement.getPackageName() : schemaName.toLowerCase()); | ||
85 | + List<TypeElement> types = protoFileElement.getTypes(); | ||
86 | + List<MessageElement> messageTypes = getMessageTypes(types); | ||
87 | + | ||
88 | + if (!messageTypes.isEmpty()) { | ||
89 | + List<EnumElement> enumTypes = getEnumElements(types); | ||
90 | + if (!enumTypes.isEmpty()) { | ||
91 | + enumTypes.forEach(enumElement -> { | ||
92 | + EnumDefinition enumDefinition = getEnumDefinition(enumElement); | ||
93 | + schemaBuilder.addEnumDefinition(enumDefinition); | ||
94 | + }); | ||
95 | + } | ||
96 | + List<MessageDefinition> messageDefinitions = getMessageDefinitions(messageTypes); | ||
97 | + messageDefinitions.forEach(schemaBuilder::addMessageDefinition); | ||
98 | + try { | ||
99 | + return schemaBuilder.build(); | ||
100 | + } catch (Descriptors.DescriptorValidationException e) { | ||
101 | + throw new RuntimeException("Failed to create dynamic schema due to: " + e.getMessage()); | ||
102 | + } | ||
103 | + } else { | ||
104 | + throw new RuntimeException("Failed to get Dynamic Schema! Message types is empty for schema:" + schemaName); | ||
105 | + } | ||
106 | + } | ||
107 | + | ||
108 | + public ProtoFileElement getTransportProtoSchema(String protoSchema) { | ||
109 | + return new ProtoParser(LOCATION, protoSchema.toCharArray()).readProtoFile(); | ||
110 | + } | ||
111 | + | ||
112 | + private List<MessageElement> getMessageTypes(List<TypeElement> types) { | ||
113 | + return types.stream() | ||
114 | + .filter(typeElement -> typeElement instanceof MessageElement) | ||
115 | + .map(typeElement -> (MessageElement) typeElement) | ||
116 | + .collect(Collectors.toList()); | ||
117 | + } | ||
118 | + | ||
119 | + private List<EnumElement> getEnumElements(List<TypeElement> types) { | ||
120 | + return types.stream() | ||
121 | + .filter(typeElement -> typeElement instanceof EnumElement) | ||
122 | + .map(typeElement -> (EnumElement) typeElement) | ||
123 | + .collect(Collectors.toList()); | ||
124 | + } | ||
125 | + | ||
126 | + private List<MessageDefinition> getMessageDefinitions(List<MessageElement> messageElementsList) { | ||
127 | + if (!messageElementsList.isEmpty()) { | ||
128 | + List<MessageDefinition> messageDefinitions = new ArrayList<>(); | ||
129 | + messageElementsList.forEach(messageElement -> { | ||
130 | + MessageDefinition.Builder messageDefinitionBuilder = MessageDefinition.newBuilder(messageElement.getName()); | ||
131 | + | ||
132 | + List<TypeElement> nestedTypes = messageElement.getNestedTypes(); | ||
133 | + if (!nestedTypes.isEmpty()) { | ||
134 | + List<EnumElement> nestedEnumTypes = getEnumElements(nestedTypes); | ||
135 | + if (!nestedEnumTypes.isEmpty()) { | ||
136 | + nestedEnumTypes.forEach(enumElement -> { | ||
137 | + EnumDefinition nestedEnumDefinition = getEnumDefinition(enumElement); | ||
138 | + messageDefinitionBuilder.addEnumDefinition(nestedEnumDefinition); | ||
139 | + }); | ||
140 | + } | ||
141 | + List<MessageElement> nestedMessageTypes = getMessageTypes(nestedTypes); | ||
142 | + List<MessageDefinition> nestedMessageDefinitions = getMessageDefinitions(nestedMessageTypes); | ||
143 | + nestedMessageDefinitions.forEach(messageDefinitionBuilder::addMessageDefinition); | ||
144 | + } | ||
145 | + List<FieldElement> messageElementFields = messageElement.getFields(); | ||
146 | + List<OneOfElement> oneOfs = messageElement.getOneOfs(); | ||
147 | + if (!oneOfs.isEmpty()) { | ||
148 | + for (OneOfElement oneOfelement : oneOfs) { | ||
149 | + MessageDefinition.OneofBuilder oneofBuilder = messageDefinitionBuilder.addOneof(oneOfelement.getName()); | ||
150 | + addMessageFieldsToTheOneOfDefinition(oneOfelement.getFields(), oneofBuilder); | ||
151 | + } | ||
152 | + } | ||
153 | + if (!messageElementFields.isEmpty()) { | ||
154 | + addMessageFieldsToTheMessageDefinition(messageElementFields, messageDefinitionBuilder); | ||
155 | + } | ||
156 | + messageDefinitions.add(messageDefinitionBuilder.build()); | ||
157 | + }); | ||
158 | + return messageDefinitions; | ||
159 | + } else { | ||
160 | + return Collections.emptyList(); | ||
161 | + } | ||
162 | + } | ||
163 | + | ||
164 | + private EnumDefinition getEnumDefinition(EnumElement enumElement) { | ||
165 | + List<EnumConstantElement> enumElementTypeConstants = enumElement.getConstants(); | ||
166 | + EnumDefinition.Builder enumDefinitionBuilder = EnumDefinition.newBuilder(enumElement.getName()); | ||
167 | + if (!enumElementTypeConstants.isEmpty()) { | ||
168 | + enumElementTypeConstants.forEach(constantElement -> enumDefinitionBuilder.addValue(constantElement.getName(), constantElement.getTag())); | ||
169 | + } | ||
170 | + return enumDefinitionBuilder.build(); | ||
171 | + } | ||
172 | + | ||
173 | + | ||
174 | + private void addMessageFieldsToTheMessageDefinition(List<FieldElement> messageElementFields, MessageDefinition.Builder messageDefinitionBuilder) { | ||
175 | + messageElementFields.forEach(fieldElement -> { | ||
176 | + String labelStr = null; | ||
177 | + if (fieldElement.getLabel() != null) { | ||
178 | + labelStr = fieldElement.getLabel().name().toLowerCase(); | ||
179 | + } | ||
180 | + messageDefinitionBuilder.addField( | ||
181 | + labelStr, | ||
182 | + fieldElement.getType(), | ||
183 | + fieldElement.getName(), | ||
184 | + fieldElement.getTag()); | ||
185 | + }); | ||
186 | + } | ||
187 | + | ||
188 | + private void addMessageFieldsToTheOneOfDefinition(List<FieldElement> oneOfsElementFields, MessageDefinition.OneofBuilder oneofBuilder) { | ||
189 | + oneOfsElementFields.forEach(fieldElement -> oneofBuilder.addField( | ||
190 | + fieldElement.getType(), | ||
191 | + fieldElement.getName(), | ||
192 | + fieldElement.getTag())); | ||
193 | + oneofBuilder.msgDefBuilder(); | ||
194 | + } | ||
195 | + | ||
196 | + private boolean isEmptyStr(String str) { | ||
197 | + return str == null || "".equals(str); | ||
198 | + } | ||
199 | + | ||
200 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.device.profile; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
20 | +import com.fasterxml.jackson.annotation.JsonSubTypes; | ||
21 | +import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
22 | +import org.thingsboard.server.common.data.TransportPayloadType; | ||
23 | + | ||
24 | +@JsonIgnoreProperties(ignoreUnknown = true) | ||
25 | +@JsonTypeInfo( | ||
26 | + use = JsonTypeInfo.Id.NAME, | ||
27 | + include = JsonTypeInfo.As.PROPERTY, | ||
28 | + property = "transportPayloadType") | ||
29 | +@JsonSubTypes({ | ||
30 | + @JsonSubTypes.Type(value = JsonTransportPayloadConfiguration.class, name = "JSON"), | ||
31 | + @JsonSubTypes.Type(value = ProtoTransportPayloadConfiguration.class, name = "PROTOBUF")}) | ||
32 | +public interface TransportPayloadTypeConfiguration { | ||
33 | + | ||
34 | + @JsonIgnore | ||
35 | + TransportPayloadType getTransportPayloadType(); | ||
36 | + | ||
37 | +} |
@@ -15,7 +15,11 @@ | @@ -15,7 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.mqtt.adaptors; | 16 | package org.thingsboard.server.transport.mqtt.adaptors; |
17 | 17 | ||
18 | +import com.google.gson.JsonParser; | ||
19 | +import com.google.protobuf.Descriptors; | ||
20 | +import com.google.protobuf.DynamicMessage; | ||
18 | import com.google.protobuf.InvalidProtocolBufferException; | 21 | import com.google.protobuf.InvalidProtocolBufferException; |
22 | +import com.google.protobuf.util.JsonFormat; | ||
19 | import io.netty.buffer.ByteBuf; | 23 | import io.netty.buffer.ByteBuf; |
20 | import io.netty.buffer.ByteBufAllocator; | 24 | import io.netty.buffer.ByteBufAllocator; |
21 | import io.netty.buffer.UnpooledByteBufAllocator; | 25 | import io.netty.buffer.UnpooledByteBufAllocator; |
@@ -29,10 +33,11 @@ import org.springframework.stereotype.Component; | @@ -29,10 +33,11 @@ import org.springframework.stereotype.Component; | ||
29 | import org.springframework.util.StringUtils; | 33 | import org.springframework.util.StringUtils; |
30 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 34 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
31 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 35 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
36 | +import org.thingsboard.server.common.transport.adaptor.JsonConverter; | ||
32 | import org.thingsboard.server.common.transport.adaptor.ProtoConverter; | 37 | import org.thingsboard.server.common.transport.adaptor.ProtoConverter; |
33 | import org.thingsboard.server.gen.transport.TransportApiProtos; | 38 | import org.thingsboard.server.gen.transport.TransportApiProtos; |
34 | import org.thingsboard.server.gen.transport.TransportProtos; | 39 | import org.thingsboard.server.gen.transport.TransportProtos; |
35 | -import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | 40 | +import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; |
36 | import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext; | 41 | import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext; |
37 | 42 | ||
38 | import java.util.Optional; | 43 | import java.util.Optional; |
@@ -45,20 +50,24 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -45,20 +50,24 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
45 | 50 | ||
46 | @Override | 51 | @Override |
47 | public TransportProtos.PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { | 52 | public TransportProtos.PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { |
53 | + DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx; | ||
48 | byte[] bytes = toBytes(inbound.payload()); | 54 | byte[] bytes = toBytes(inbound.payload()); |
55 | + Descriptors.Descriptor telemetryDynamicMsgDescriptor = getDescriptor(deviceSessionCtx.getTelemetryDynamicMsgDescriptor()); | ||
49 | try { | 56 | try { |
50 | - return ProtoConverter.convertToTelemetryProto(bytes); | ||
51 | - } catch (InvalidProtocolBufferException | IllegalArgumentException e) { | 57 | + return JsonConverter.convertToTelemetryProto(new JsonParser().parse(dynamicMsgToJson(bytes, telemetryDynamicMsgDescriptor))); |
58 | + } catch (Exception e) { | ||
52 | throw new AdaptorException(e); | 59 | throw new AdaptorException(e); |
53 | } | 60 | } |
54 | } | 61 | } |
55 | 62 | ||
56 | @Override | 63 | @Override |
57 | public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { | 64 | public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { |
65 | + DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx; | ||
58 | byte[] bytes = toBytes(inbound.payload()); | 66 | byte[] bytes = toBytes(inbound.payload()); |
67 | + Descriptors.Descriptor attributesDynamicMessage = getDescriptor(deviceSessionCtx.getAttributesDynamicMessageDescriptor()); | ||
59 | try { | 68 | try { |
60 | - return ProtoConverter.validatePostAttributeMsg(bytes); | ||
61 | - } catch (InvalidProtocolBufferException | IllegalArgumentException e) { | 69 | + return JsonConverter.convertToAttributesProto(new JsonParser().parse(dynamicMsgToJson(bytes, attributesDynamicMessage))); |
70 | + } catch (Exception e) { | ||
62 | throw new AdaptorException(e); | 71 | throw new AdaptorException(e); |
63 | } | 72 | } |
64 | } | 73 | } |
@@ -112,7 +121,6 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -112,7 +121,6 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
112 | @Override | 121 | @Override |
113 | public TransportProtos.ProvisionDeviceRequestMsg convertToProvisionRequestMsg(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException { | 122 | public TransportProtos.ProvisionDeviceRequestMsg convertToProvisionRequestMsg(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException { |
114 | byte[] bytes = toBytes(mqttMsg.payload()); | 123 | byte[] bytes = toBytes(mqttMsg.payload()); |
115 | - String topicName = mqttMsg.variableHeader().topicName(); | ||
116 | try { | 124 | try { |
117 | return ProtoConverter.convertToProvisionRequestMsg(bytes); | 125 | return ProtoConverter.convertToProvisionRequestMsg(bytes); |
118 | } catch (InvalidProtocolBufferException ex) { | 126 | } catch (InvalidProtocolBufferException ex) { |
@@ -207,4 +215,16 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -207,4 +215,16 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
207 | return Integer.parseInt(topicName.substring(topic.length())); | 215 | return Integer.parseInt(topicName.substring(topic.length())); |
208 | } | 216 | } |
209 | 217 | ||
218 | + private Descriptors.Descriptor getDescriptor(Descriptors.Descriptor descriptor) throws AdaptorException { | ||
219 | + if (descriptor == null) { | ||
220 | + throw new AdaptorException("Failed to get dynamic message descriptor!"); | ||
221 | + } | ||
222 | + return descriptor; | ||
223 | + } | ||
224 | + | ||
225 | + private String dynamicMsgToJson(byte[] bytes, Descriptors.Descriptor descriptor) throws InvalidProtocolBufferException { | ||
226 | + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(descriptor, bytes); | ||
227 | + return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage); | ||
228 | + } | ||
229 | + | ||
210 | } | 230 | } |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.mqtt.session; | 16 | package org.thingsboard.server.transport.mqtt.session; |
17 | 17 | ||
18 | +import com.google.protobuf.Descriptors; | ||
18 | import io.netty.channel.ChannelHandlerContext; | 19 | import io.netty.channel.ChannelHandlerContext; |
19 | import lombok.Getter; | 20 | import lombok.Getter; |
20 | import lombok.Setter; | 21 | import lombok.Setter; |
@@ -24,6 +25,8 @@ import org.thingsboard.server.common.data.DeviceTransportType; | @@ -24,6 +25,8 @@ import org.thingsboard.server.common.data.DeviceTransportType; | ||
24 | import org.thingsboard.server.common.data.TransportPayloadType; | 25 | import org.thingsboard.server.common.data.TransportPayloadType; |
25 | import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | 26 | import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
26 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | 27 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; |
28 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
29 | +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | ||
27 | import org.thingsboard.server.transport.mqtt.MqttTransportContext; | 30 | import org.thingsboard.server.transport.mqtt.MqttTransportContext; |
28 | import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; | 31 | import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; |
29 | import org.thingsboard.server.transport.mqtt.util.MqttTopicFilter; | 32 | import org.thingsboard.server.transport.mqtt.util.MqttTopicFilter; |
@@ -54,6 +57,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -54,6 +57,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
54 | private volatile MqttTopicFilter telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); | 57 | private volatile MqttTopicFilter telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); |
55 | private volatile MqttTopicFilter attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); | 58 | private volatile MqttTopicFilter attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); |
56 | private volatile TransportPayloadType payloadType = TransportPayloadType.JSON; | 59 | private volatile TransportPayloadType payloadType = TransportPayloadType.JSON; |
60 | + private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor; | ||
61 | + private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor; | ||
57 | 62 | ||
58 | @Getter | 63 | @Getter |
59 | @Setter | 64 | @Setter |
@@ -72,7 +77,9 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -72,7 +77,9 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
72 | return msgIdSeq.incrementAndGet(); | 77 | return msgIdSeq.incrementAndGet(); |
73 | } | 78 | } |
74 | 79 | ||
75 | - public boolean isDeviceTelemetryTopic(String topicName) { return telemetryTopicFilter.filter(topicName); } | 80 | + public boolean isDeviceTelemetryTopic(String topicName) { |
81 | + return telemetryTopicFilter.filter(topicName); | ||
82 | + } | ||
76 | 83 | ||
77 | public boolean isDeviceAttributesTopic(String topicName) { | 84 | public boolean isDeviceAttributesTopic(String topicName) { |
78 | return attributesTopicFilter.filter(topicName); | 85 | return attributesTopicFilter.filter(topicName); |
@@ -86,6 +93,14 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -86,6 +93,14 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
86 | return payloadType.equals(TransportPayloadType.JSON); | 93 | return payloadType.equals(TransportPayloadType.JSON); |
87 | } | 94 | } |
88 | 95 | ||
96 | + public Descriptors.Descriptor getTelemetryDynamicMsgDescriptor() { | ||
97 | + return telemetryDynamicMessageDescriptor; | ||
98 | + } | ||
99 | + | ||
100 | + public Descriptors.Descriptor getAttributesDynamicMessageDescriptor() { | ||
101 | + return attributesDynamicMessageDescriptor; | ||
102 | + } | ||
103 | + | ||
89 | @Override | 104 | @Override |
90 | public void setDeviceProfile(DeviceProfile deviceProfile) { | 105 | public void setDeviceProfile(DeviceProfile deviceProfile) { |
91 | super.setDeviceProfile(deviceProfile); | 106 | super.setDeviceProfile(deviceProfile); |
@@ -104,13 +119,22 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | @@ -104,13 +119,22 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { | ||
104 | if (transportConfiguration.getType().equals(DeviceTransportType.MQTT) && | 119 | if (transportConfiguration.getType().equals(DeviceTransportType.MQTT) && |
105 | transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { | 120 | transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { |
106 | MqttDeviceProfileTransportConfiguration mqttConfig = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | 121 | MqttDeviceProfileTransportConfiguration mqttConfig = (MqttDeviceProfileTransportConfiguration) transportConfiguration; |
107 | - payloadType = mqttConfig.getTransportPayloadType(); | 122 | + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttConfig.getTransportPayloadTypeConfiguration(); |
123 | + payloadType = transportPayloadTypeConfiguration.getTransportPayloadType(); | ||
108 | telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic()); | 124 | telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic()); |
109 | attributesTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic()); | 125 | attributesTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic()); |
126 | + if (TransportPayloadType.PROTOBUF.equals(payloadType)) { | ||
127 | + updateDynamicMessageDescriptors(transportPayloadTypeConfiguration); | ||
128 | + } | ||
110 | } else { | 129 | } else { |
111 | telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); | 130 | telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); |
112 | attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); | 131 | attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); |
113 | } | 132 | } |
114 | } | 133 | } |
115 | 134 | ||
135 | + private void updateDynamicMessageDescriptors(TransportPayloadTypeConfiguration transportPayloadTypeConfiguration) { | ||
136 | + ProtoTransportPayloadConfiguration protoTransportPayloadConfig = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; | ||
137 | + telemetryDynamicMessageDescriptor = protoTransportPayloadConfig.getTelemetryDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceTelemetryProtoSchema()); | ||
138 | + attributesDynamicMessageDescriptor = protoTransportPayloadConfig.getAttributesDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceAttributesProtoSchema()); | ||
139 | + } | ||
116 | } | 140 | } |
@@ -213,13 +213,7 @@ public class JsonConverter { | @@ -213,13 +213,7 @@ public class JsonConverter { | ||
213 | throw new JsonSyntaxException(CAN_T_PARSE_VALUE + value); | 213 | throw new JsonSyntaxException(CAN_T_PARSE_VALUE + value); |
214 | } | 214 | } |
215 | } else if (element.isJsonObject() || element.isJsonArray()) { | 215 | } else if (element.isJsonObject() || element.isJsonArray()) { |
216 | - result.add(KeyValueProto | ||
217 | - .newBuilder() | ||
218 | - .setKey(valueEntry | ||
219 | - .getKey()) | ||
220 | - .setType(KeyValueType.JSON_V) | ||
221 | - .setJsonV(element.toString()) | ||
222 | - .build()); | 216 | + result.add(KeyValueProto.newBuilder().setKey(valueEntry.getKey()).setType(KeyValueType.JSON_V).setJsonV(element.toString()).build()); |
223 | } else if (!element.isJsonNull()) { | 217 | } else if (!element.isJsonNull()) { |
224 | throw new JsonSyntaxException(CAN_T_PARSE_VALUE + element); | 218 | throw new JsonSyntaxException(CAN_T_PARSE_VALUE + element); |
225 | } | 219 | } |
@@ -15,6 +15,16 @@ | @@ -15,6 +15,16 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.device; | 16 | package org.thingsboard.server.dao.device; |
17 | 17 | ||
18 | +import com.squareup.wire.Syntax; | ||
19 | +import com.squareup.wire.schema.Field; | ||
20 | +import com.squareup.wire.schema.Location; | ||
21 | +import com.squareup.wire.schema.internal.parser.EnumElement; | ||
22 | +import com.squareup.wire.schema.internal.parser.FieldElement; | ||
23 | +import com.squareup.wire.schema.internal.parser.MessageElement; | ||
24 | +import com.squareup.wire.schema.internal.parser.OneOfElement; | ||
25 | +import com.squareup.wire.schema.internal.parser.ProtoFileElement; | ||
26 | +import com.squareup.wire.schema.internal.parser.ProtoParser; | ||
27 | +import com.squareup.wire.schema.internal.parser.TypeElement; | ||
18 | import lombok.extern.slf4j.Slf4j; | 28 | import lombok.extern.slf4j.Slf4j; |
19 | import org.apache.commons.lang3.StringUtils; | 29 | import org.apache.commons.lang3.StringUtils; |
20 | import org.hibernate.exception.ConstraintViolationException; | 30 | import org.hibernate.exception.ConstraintViolationException; |
@@ -35,7 +45,10 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileCon | @@ -35,7 +45,10 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileCon | ||
35 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; | 45 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; |
36 | import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm; | 46 | import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm; |
37 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | 47 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
48 | +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; | ||
38 | import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; | 49 | import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; |
50 | +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | ||
51 | +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | ||
39 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 52 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
40 | import org.thingsboard.server.common.data.id.TenantId; | 53 | import org.thingsboard.server.common.data.id.TenantId; |
41 | import org.thingsboard.server.common.data.page.PageData; | 54 | import org.thingsboard.server.common.data.page.PageData; |
@@ -51,6 +64,7 @@ import java.util.Arrays; | @@ -51,6 +64,7 @@ import java.util.Arrays; | ||
51 | import java.util.Collections; | 64 | import java.util.Collections; |
52 | import java.util.HashSet; | 65 | import java.util.HashSet; |
53 | import java.util.List; | 66 | import java.util.List; |
67 | +import java.util.stream.Collectors; | ||
54 | import java.util.Set; | 68 | import java.util.Set; |
55 | 69 | ||
56 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_PROFILE_CACHE; | 70 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_PROFILE_CACHE; |
@@ -64,6 +78,14 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -64,6 +78,14 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
64 | private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId "; | 78 | private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId "; |
65 | private static final String INCORRECT_DEVICE_PROFILE_NAME = "Incorrect deviceProfileName "; | 79 | private static final String INCORRECT_DEVICE_PROFILE_NAME = "Incorrect deviceProfileName "; |
66 | 80 | ||
81 | + private static final Location LOCATION = new Location("", "", -1, -1); | ||
82 | + private static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; | ||
83 | + private static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; | ||
84 | + | ||
85 | + private static String invalidSchemaProvidedMessage(String schemaName) { | ||
86 | + return "[Transport Configuration] invalid " + schemaName + " provided!"; | ||
87 | + } | ||
88 | + | ||
67 | @Autowired | 89 | @Autowired |
68 | private DeviceProfileDao deviceProfileDao; | 90 | private DeviceProfileDao deviceProfileDao; |
69 | 91 | ||
@@ -314,6 +336,22 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -314,6 +336,22 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
314 | throw new DataValidationException("Another default device profile is present in scope of current tenant!"); | 336 | throw new DataValidationException("Another default device profile is present in scope of current tenant!"); |
315 | } | 337 | } |
316 | } | 338 | } |
339 | + | ||
340 | + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); | ||
341 | + if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { | ||
342 | + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; | ||
343 | + if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { | ||
344 | + ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration = | ||
345 | + (ProtoTransportPayloadConfiguration) mqttTransportConfiguration.getTransportPayloadTypeConfiguration(); | ||
346 | + try { | ||
347 | + validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA); | ||
348 | + validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA); | ||
349 | + } catch (Exception exception) { | ||
350 | + throw new DataValidationException(exception.getMessage()); | ||
351 | + } | ||
352 | + } | ||
353 | + } | ||
354 | + | ||
317 | List<DeviceProfileAlarm> profileAlarms = deviceProfile.getProfileData().getAlarms(); | 355 | List<DeviceProfileAlarm> profileAlarms = deviceProfile.getProfileData().getAlarms(); |
318 | 356 | ||
319 | if (!CollectionUtils.isEmpty(profileAlarms)) { | 357 | if (!CollectionUtils.isEmpty(profileAlarms)) { |
@@ -327,8 +365,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -327,8 +365,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
327 | throw new DataValidationException(String.format("Can't create device profile with the same alarm rule types: \"%s\"!", alarmType)); | 365 | throw new DataValidationException(String.format("Can't create device profile with the same alarm rule types: \"%s\"!", alarmType)); |
328 | } | 366 | } |
329 | } | 367 | } |
330 | - | ||
331 | } | 368 | } |
369 | + | ||
332 | } | 370 | } |
333 | 371 | ||
334 | @Override | 372 | @Override |
@@ -352,6 +390,122 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -352,6 +390,122 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
352 | } | 390 | } |
353 | } | 391 | } |
354 | } | 392 | } |
393 | + | ||
394 | + private void validateTransportProtoSchema(String schema, String schemaName) throws IllegalArgumentException { | ||
395 | + ProtoParser schemaParser = new ProtoParser(LOCATION, schema.toCharArray()); | ||
396 | + ProtoFileElement protoFileElement; | ||
397 | + try { | ||
398 | + protoFileElement = schemaParser.readProtoFile(); | ||
399 | + } catch (Exception e) { | ||
400 | + throw new IllegalArgumentException("[Transport Configuration] failed to parse " + schemaName + " due to: " + e.getMessage()); | ||
401 | + } | ||
402 | + checkProtoFileSyntax(schemaName, protoFileElement); | ||
403 | + checkProtoFileCommonSettings(schemaName, protoFileElement.getOptions().isEmpty(), " Schema options don't support!"); | ||
404 | + checkProtoFileCommonSettings(schemaName, protoFileElement.getPublicImports().isEmpty(), " Schema public imports don't support!"); | ||
405 | + checkProtoFileCommonSettings(schemaName, protoFileElement.getImports().isEmpty(), " Schema imports don't support!"); | ||
406 | + checkProtoFileCommonSettings(schemaName, protoFileElement.getExtendDeclarations().isEmpty(), " Schema extend declarations don't support!"); | ||
407 | + checkTypeElements(schemaName, protoFileElement); | ||
408 | + } | ||
409 | + | ||
410 | + private void checkProtoFileSyntax(String schemaName, ProtoFileElement protoFileElement) { | ||
411 | + if (protoFileElement.getSyntax() == null || !protoFileElement.getSyntax().equals(Syntax.PROTO_3)) { | ||
412 | + throw new IllegalArgumentException("[Transport Configuration] invalid schema syntax: " + protoFileElement.getSyntax() + | ||
413 | + " for " + schemaName + " provided! Only " + Syntax.PROTO_3 + " allowed!"); | ||
414 | + } | ||
415 | + } | ||
416 | + | ||
417 | + private void checkProtoFileCommonSettings(String schemaName, boolean isEmptySettings, String invalidSettingsMessage) { | ||
418 | + if (!isEmptySettings) { | ||
419 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + invalidSettingsMessage); | ||
420 | + } | ||
421 | + } | ||
422 | + | ||
423 | + private void checkTypeElements(String schemaName, ProtoFileElement protoFileElement) { | ||
424 | + List<TypeElement> types = protoFileElement.getTypes(); | ||
425 | + if (!types.isEmpty()) { | ||
426 | + if (types.stream().noneMatch(typeElement -> typeElement instanceof MessageElement)) { | ||
427 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + " At least one Message definition should exists!"); | ||
428 | + } else { | ||
429 | + checkEnumElements(schemaName, getEnumElements(types)); | ||
430 | + checkMessageElements(schemaName, getMessageTypes(types)); | ||
431 | + } | ||
432 | + } else { | ||
433 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + " Type elements is empty!"); | ||
434 | + } | ||
435 | + } | ||
436 | + | ||
437 | + private void checkFieldElements(String schemaName, List<FieldElement> fieldElements) { | ||
438 | + if (!fieldElements.isEmpty()) { | ||
439 | + boolean hasRequiredLabel = fieldElements.stream().anyMatch(fieldElement -> { | ||
440 | + Field.Label label = fieldElement.getLabel(); | ||
441 | + return label != null && label.equals(Field.Label.REQUIRED); | ||
442 | + }); | ||
443 | + if (hasRequiredLabel) { | ||
444 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + " Required labels are not supported!"); | ||
445 | + } | ||
446 | + boolean hasDefaultValue = fieldElements.stream().anyMatch(fieldElement -> fieldElement.getDefaultValue() != null); | ||
447 | + if (hasDefaultValue) { | ||
448 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + " Default values are not supported!"); | ||
449 | + } | ||
450 | + } | ||
451 | + } | ||
452 | + | ||
453 | + private void checkEnumElements(String schemaName, List<EnumElement> enumTypes) { | ||
454 | + if (enumTypes.stream().anyMatch(enumElement -> !enumElement.getNestedTypes().isEmpty())) { | ||
455 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + " Nested types in Enum definitions are not supported!"); | ||
456 | + } | ||
457 | + if (enumTypes.stream().anyMatch(enumElement -> !enumElement.getOptions().isEmpty())) { | ||
458 | + throw new IllegalArgumentException(invalidSchemaProvidedMessage(schemaName) + " Enum definitions options are not supported!"); | ||
459 | + } | ||
460 | + } | ||
461 | + | ||
462 | + private void checkMessageElements(String schemaName, List<MessageElement> messageElementsList) { | ||
463 | + if (!messageElementsList.isEmpty()) { | ||
464 | + messageElementsList.forEach(messageElement -> { | ||
465 | + checkProtoFileCommonSettings(schemaName, messageElement.getGroups().isEmpty(), | ||
466 | + " Message definition groups don't support!"); | ||
467 | + checkProtoFileCommonSettings(schemaName, messageElement.getOptions().isEmpty(), | ||
468 | + " Message definition options don't support!"); | ||
469 | + checkProtoFileCommonSettings(schemaName, messageElement.getExtensions().isEmpty(), | ||
470 | + " Message definition extensions don't support!"); | ||
471 | + checkProtoFileCommonSettings(schemaName, messageElement.getReserveds().isEmpty(), | ||
472 | + " Message definition reserved elements don't support!"); | ||
473 | + checkFieldElements(schemaName, messageElement.getFields()); | ||
474 | + List<OneOfElement> oneOfs = messageElement.getOneOfs(); | ||
475 | + if (!oneOfs.isEmpty()) { | ||
476 | + oneOfs.forEach(oneOfElement -> { | ||
477 | + checkProtoFileCommonSettings(schemaName, oneOfElement.getGroups().isEmpty(), | ||
478 | + " OneOf definition groups don't support!"); | ||
479 | + checkFieldElements(schemaName, oneOfElement.getFields()); | ||
480 | + }); | ||
481 | + } | ||
482 | + List<TypeElement> nestedTypes = messageElement.getNestedTypes(); | ||
483 | + if (!nestedTypes.isEmpty()) { | ||
484 | + List<EnumElement> nestedEnumTypes = getEnumElements(nestedTypes); | ||
485 | + if (!nestedEnumTypes.isEmpty()) { | ||
486 | + checkEnumElements(schemaName, nestedEnumTypes); | ||
487 | + } | ||
488 | + List<MessageElement> nestedMessageTypes = getMessageTypes(nestedTypes); | ||
489 | + checkMessageElements(schemaName, nestedMessageTypes); | ||
490 | + } | ||
491 | + }); | ||
492 | + } | ||
493 | + } | ||
494 | + | ||
495 | + private List<MessageElement> getMessageTypes(List<TypeElement> types) { | ||
496 | + return types.stream() | ||
497 | + .filter(typeElement -> typeElement instanceof MessageElement) | ||
498 | + .map(typeElement -> (MessageElement) typeElement) | ||
499 | + .collect(Collectors.toList()); | ||
500 | + } | ||
501 | + | ||
502 | + private List<EnumElement> getEnumElements(List<TypeElement> types) { | ||
503 | + return types.stream() | ||
504 | + .filter(typeElement -> typeElement instanceof EnumElement) | ||
505 | + .map(typeElement -> (EnumElement) typeElement) | ||
506 | + .collect(Collectors.toList()); | ||
507 | + } | ||
508 | + | ||
355 | }; | 509 | }; |
356 | 510 | ||
357 | private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover = | 511 | private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover = |
@@ -106,6 +106,8 @@ | @@ -106,6 +106,8 @@ | ||
106 | <commons-collections.version>3.2.2</commons-collections.version> | 106 | <commons-collections.version>3.2.2</commons-collections.version> |
107 | <java-websocket.version>1.5.0</java-websocket.version> | 107 | <java-websocket.version>1.5.0</java-websocket.version> |
108 | <micrometer.version>1.5.2</micrometer.version> | 108 | <micrometer.version>1.5.2</micrometer.version> |
109 | + <protobuf-dynamic.version>1.0.2TB</protobuf-dynamic.version> | ||
110 | + <wire-schema.version>3.4.0</wire-schema.version> | ||
109 | </properties> | 111 | </properties> |
110 | 112 | ||
111 | <modules> | 113 | <modules> |
@@ -1369,6 +1371,16 @@ | @@ -1369,6 +1371,16 @@ | ||
1369 | <artifactId>micrometer-registry-prometheus</artifactId> | 1371 | <artifactId>micrometer-registry-prometheus</artifactId> |
1370 | <version>${micrometer.version}</version> | 1372 | <version>${micrometer.version}</version> |
1371 | </dependency> | 1373 | </dependency> |
1374 | + <dependency> | ||
1375 | + <groupId>org.thingsboard</groupId> | ||
1376 | + <artifactId>protobuf-dynamic</artifactId> | ||
1377 | + <version>${protobuf-dynamic.version}</version> | ||
1378 | + </dependency> | ||
1379 | + <dependency> | ||
1380 | + <groupId>com.squareup.wire</groupId> | ||
1381 | + <artifactId>wire-schema</artifactId> | ||
1382 | + <version>${wire-schema.version}</version> | ||
1383 | + </dependency> | ||
1372 | </dependencies> | 1384 | </dependencies> |
1373 | </dependencyManagement> | 1385 | </dependencyManagement> |
1374 | 1386 |
@@ -20,17 +20,6 @@ | @@ -20,17 +20,6 @@ | ||
20 | <fieldset class="fields-group"> | 20 | <fieldset class="fields-group"> |
21 | <legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend> | 21 | <legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend> |
22 | <div fxLayoutGap="8px" fxLayout="column"> | 22 | <div fxLayoutGap="8px" fxLayout="column"> |
23 | - <mat-form-field class="mat-block"> | ||
24 | - <mat-label translate>device-profile.mqtt-device-payload-type</mat-label> | ||
25 | - <mat-select formControlName="transportPayloadType" required> | ||
26 | - <mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type"> | ||
27 | - {{mqttTransportPayloadTypeTranslations.get(type) | translate}} | ||
28 | - </mat-option> | ||
29 | - </mat-select> | ||
30 | - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadType').hasError('required')"> | ||
31 | - {{ 'device-profile.mqtt-payload-type-required' | translate }} | ||
32 | - </mat-error> | ||
33 | - </mat-form-field> | ||
34 | <div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column"> | 23 | <div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column"> |
35 | <mat-form-field fxFlex> | 24 | <mat-form-field fxFlex> |
36 | <mat-label translate>device-profile.telemetry-topic-filter</mat-label> | 25 | <mat-label translate>device-profile.telemetry-topic-filter</mat-label> |
@@ -71,5 +60,42 @@ | @@ -71,5 +60,42 @@ | ||
71 | <div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div> | 60 | <div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div> |
72 | </div> | 61 | </div> |
73 | </fieldset> | 62 | </fieldset> |
63 | + <section formGroupName="transportPayloadTypeConfiguration"> | ||
64 | + <fieldset class="fields-group"> | ||
65 | + <legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend> | ||
66 | + <div fxLayoutGap="8px" fxLayout="column"> | ||
67 | + <mat-form-field class="mat-block"> | ||
68 | + <mat-select formControlName="transportPayloadType" required> | ||
69 | + <mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type"> | ||
70 | + {{mqttTransportPayloadTypeTranslations.get(type) | translate}} | ||
71 | + </mat-option> | ||
72 | + </mat-select> | ||
73 | + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').hasError('required')"> | ||
74 | + {{ 'device-profile.mqtt-payload-type-required' | translate }} | ||
75 | + </mat-error> | ||
76 | + </mat-form-field> | ||
77 | + <div *ngIf="protoPayloadType" fxLayout="column"> | ||
78 | + <mat-form-field fxFlex> | ||
79 | + <mat-label translate>device-profile.telemetry-proto-schema</mat-label> | ||
80 | + <textarea matInput required | ||
81 | + formControlName="deviceTelemetryProtoSchema" | ||
82 | + rows="5"></textarea> | ||
83 | + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')"> | ||
84 | + {{ 'device-profile.telemetry-proto-schema-required' | translate}} | ||
85 | + </mat-error> | ||
86 | + </mat-form-field> | ||
87 | + <mat-form-field fxFlex> | ||
88 | + <mat-label translate>device-profile.attributes-proto-schema</mat-label> | ||
89 | + <textarea matInput required | ||
90 | + formControlName="deviceAttributesProtoSchema" | ||
91 | + rows="5"></textarea> | ||
92 | + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')"> | ||
93 | + {{ 'device-profile.attributes-proto-schema-required' | translate}} | ||
94 | + </mat-error> | ||
95 | + </mat-form-field> | ||
96 | + </div> | ||
97 | + </div> | ||
98 | + </fieldset> | ||
99 | + </section> | ||
74 | </section> | 100 | </section> |
75 | </form> | 101 | </form> |
@@ -28,10 +28,11 @@ import { Store } from '@ngrx/store'; | @@ -28,10 +28,11 @@ import { Store } from '@ngrx/store'; | ||
28 | import { AppState } from '@app/core/core.state'; | 28 | import { AppState } from '@app/core/core.state'; |
29 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; | 29 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
30 | import { | 30 | import { |
31 | - MqttTransportPayloadType, | ||
32 | DeviceProfileTransportConfiguration, | 31 | DeviceProfileTransportConfiguration, |
33 | DeviceTransportType, | 32 | DeviceTransportType, |
34 | - MqttDeviceProfileTransportConfiguration, mqttTransportPayloadTypeTranslationMap | 33 | + MqttDeviceProfileTransportConfiguration, |
34 | + MqttTransportPayloadType, | ||
35 | + mqttTransportPayloadTypeTranslationMap | ||
35 | } from '@shared/models/device.models'; | 36 | } from '@shared/models/device.models'; |
36 | import { isDefinedAndNotNull } from '@core/utils'; | 37 | import { isDefinedAndNotNull } from '@core/utils'; |
37 | 38 | ||
@@ -85,9 +86,15 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | @@ -85,9 +86,15 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | ||
85 | configuration: this.fb.group({ | 86 | configuration: this.fb.group({ |
86 | deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], | 87 | deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], |
87 | deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], | 88 | deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], |
88 | - transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required] | 89 | + transportPayloadTypeConfiguration: this.fb.group({ |
90 | + transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required] | ||
91 | + }) | ||
89 | }, {validator: this.uniqueDeviceTopicValidator}) | 92 | }, {validator: this.uniqueDeviceTopicValidator}) |
90 | }); | 93 | }); |
94 | + this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').valueChanges.subscribe(payloadType => { | ||
95 | + this.updateTransportPayloadBasedControls(payloadType); | ||
96 | + this.mqttDeviceProfileTransportConfigurationFormGroup.updateValueAndValidity(); | ||
97 | + }); | ||
91 | this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { | 98 | this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { |
92 | this.updateModel(); | 99 | this.updateModel(); |
93 | }); | 100 | }); |
@@ -102,8 +109,14 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | @@ -102,8 +109,14 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | ||
102 | } | 109 | } |
103 | } | 110 | } |
104 | 111 | ||
112 | + get protoPayloadType(): boolean { | ||
113 | + let transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').value; | ||
114 | + return transportPayloadType === MqttTransportPayloadType.PROTOBUF; | ||
115 | + } | ||
116 | + | ||
105 | writeValue(value: MqttDeviceProfileTransportConfiguration | null): void { | 117 | writeValue(value: MqttDeviceProfileTransportConfiguration | null): void { |
106 | if (isDefinedAndNotNull(value)) { | 118 | if (isDefinedAndNotNull(value)) { |
119 | + this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration.transportPayloadType); | ||
107 | this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); | 120 | this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); |
108 | } | 121 | } |
109 | } | 122 | } |
@@ -117,6 +130,41 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | @@ -117,6 +130,41 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control | ||
117 | this.propagateChange(configuration); | 130 | this.propagateChange(configuration); |
118 | } | 131 | } |
119 | 132 | ||
133 | + private updateTransportPayloadBasedControls(type: MqttTransportPayloadType) { | ||
134 | + const transportPayloadTypeConfigurationFormGroup = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration') as FormGroup; | ||
135 | + if (type === MqttTransportPayloadType.PROTOBUF) { | ||
136 | + const defaultTelemetrySchema = "syntax =\"proto3\";\n" + | ||
137 | + "package telemetry;\n" + | ||
138 | + "\n" + | ||
139 | + "message SensorDataReading {\n" + | ||
140 | + "\n" + | ||
141 | + " double temperature = 1;\n" + | ||
142 | + " double humidity = 2;\n" + | ||
143 | + " InnerObject innerObject = 3;\n" + | ||
144 | + "\n" + | ||
145 | + " message InnerObject {\n" + | ||
146 | + " string key1 = 1;\n" + | ||
147 | + " bool key2 = 2;\n" + | ||
148 | + " double key3 = 3;\n" + | ||
149 | + " int32 key4 = 4;\n" + | ||
150 | + " string key5 = 5;\n" + | ||
151 | + " }\n" + | ||
152 | + "}\n"; | ||
153 | + const defaultAttributesSchema = "syntax =\"proto3\";\n" + | ||
154 | + "package attributes;\n" + | ||
155 | + "\n" + | ||
156 | + "message SensorConfiguration {\n" + | ||
157 | + " string firmwareVersion = 1;\n" + | ||
158 | + " string serialNumber = 2;\n" + | ||
159 | + "}"; | ||
160 | + transportPayloadTypeConfigurationFormGroup.registerControl('deviceTelemetryProtoSchema', this.fb.control(defaultTelemetrySchema, Validators.required)); | ||
161 | + transportPayloadTypeConfigurationFormGroup.registerControl('deviceAttributesProtoSchema', this.fb.control(defaultAttributesSchema, Validators.required)); | ||
162 | + } else { | ||
163 | + transportPayloadTypeConfigurationFormGroup.removeControl('deviceTelemetryProtoSchema'); | ||
164 | + transportPayloadTypeConfigurationFormGroup.removeControl('deviceAttributesProtoSchema'); | ||
165 | + } | ||
166 | + } | ||
167 | + | ||
120 | private validationMQTTTopic(): ValidatorFn { | 168 | private validationMQTTTopic(): ValidatorFn { |
121 | return (c: FormControl) => { | 169 | return (c: FormControl) => { |
122 | const newTopic = c.value; | 170 | const newTopic = c.value; |
@@ -148,6 +148,9 @@ export interface DefaultDeviceProfileTransportConfiguration { | @@ -148,6 +148,9 @@ export interface DefaultDeviceProfileTransportConfiguration { | ||
148 | export interface MqttDeviceProfileTransportConfiguration { | 148 | export interface MqttDeviceProfileTransportConfiguration { |
149 | deviceTelemetryTopic?: string; | 149 | deviceTelemetryTopic?: string; |
150 | deviceAttributesTopic?: string; | 150 | deviceAttributesTopic?: string; |
151 | + transportPayloadTypeConfiguration?: { | ||
152 | + transportPayloadType?: MqttTransportPayloadType; | ||
153 | + }; | ||
151 | [key: string]: any; | 154 | [key: string]: any; |
152 | } | 155 | } |
153 | 156 | ||
@@ -207,7 +210,7 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT | @@ -207,7 +210,7 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT | ||
207 | const mqttTransportConfiguration: MqttDeviceProfileTransportConfiguration = { | 210 | const mqttTransportConfiguration: MqttDeviceProfileTransportConfiguration = { |
208 | deviceTelemetryTopic: 'v1/devices/me/telemetry', | 211 | deviceTelemetryTopic: 'v1/devices/me/telemetry', |
209 | deviceAttributesTopic: 'v1/devices/me/attributes', | 212 | deviceAttributesTopic: 'v1/devices/me/attributes', |
210 | - transportPayloadType: MqttTransportPayloadType.JSON | 213 | + transportPayloadTypeConfiguration: {transportPayloadType: MqttTransportPayloadType.JSON} |
211 | }; | 214 | }; |
212 | transportConfiguration = {...mqttTransportConfiguration, type: DeviceTransportType.MQTT}; | 215 | transportConfiguration = {...mqttTransportConfiguration, type: DeviceTransportType.MQTT}; |
213 | break; | 216 | break; |
@@ -895,6 +895,10 @@ | @@ -895,6 +895,10 @@ | ||
895 | "telemetry-topic-filter-required": "Telemetry topic filter is required.", | 895 | "telemetry-topic-filter-required": "Telemetry topic filter is required.", |
896 | "attributes-topic-filter": "Attributes topic filter", | 896 | "attributes-topic-filter": "Attributes topic filter", |
897 | "attributes-topic-filter-required": "Attributes topic filter is required.", | 897 | "attributes-topic-filter-required": "Attributes topic filter is required.", |
898 | + "telemetry-proto-schema": "Telemetry proto schema", | ||
899 | + "telemetry-proto-schema-required": "Telemetry proto schema is required.", | ||
900 | + "attributes-proto-schema": "Attributes proto schema", | ||
901 | + "attributes-proto-schema-required": "Attributes proto schema is required.", | ||
898 | "rpc-response-topic-filter": "RPC response topic filter", | 902 | "rpc-response-topic-filter": "RPC response topic filter", |
899 | "rpc-response-topic-filter-required": "RPC response topic filter is required.", | 903 | "rpc-response-topic-filter-required": "RPC response topic filter is required.", |
900 | "not-valid-pattern-topic-filter": "Not valid pattern topic filter", | 904 | "not-valid-pattern-topic-filter": "Not valid pattern topic filter", |